uber-statsd-client

Yet another client for Etsy's statsd

Usage no npm install needed!

<script type="module">
  import uberStatsdClient from 'https://cdn.skypack.dev/uber-statsd-client';
</script>

README

uber-statsd-client

Node.js client for statsd.

Example

var createStatsd = require('uber-statsd-client');

var sdc = createStatsd({
    host: 'statsd.example.com'
});

var timer = new Date();
sdc.increment('some.counter'); // Increment by one.
sdc.gauge('some.gauge', 10); // Set gauge to 10
sdc.timing('some.timer', timer); // Calculates time diff

sdc.close(); // Optional - stop NOW

Caveats

Apparently a udp based statsd client does not work with cluster in node0.10 or node0.12. I'd recommend finding a tcp based statsd client or not using cluster.

Docs

var createStatsd = require('uber-statsd-client')
var sdc = createStatsd({
    host: 'statsd.example.com',
    port: 8124
});

Available options:

options.prefix

type: String, default: ""

Prefix all stats written by the client with a particular string prefix value. This defaults to ""

options.host

type: String, default: ""

The hostname where stats should be send. Defaults to "localhost"

options.port

type: Number, default: 8125

The port where stats should be send. Defaults to 8125

options.socket_timeout

type: Number, default: 1000

The UDP socket will auto-close if it has not been written to within the socket_timeout period. Defaults to 1000 milliseconds.

If socket_timeout is set to 0 then the UDP socket will never auto close.

options.highWaterMark

type: Number, default: 100

The UDP socket implementation has an internal highWaterMark. There is a known issue in node core where it will buffer packets being written to the UDP socket if it's currently in the "resolving DNS host" state.

When the highWaterMark is reached all packets are dropped and ignored.

options.packetQueue

{
    block?: Number,
    flush?: Number,
    trailingNewLine?: Boolean
}

The UDP socket uses an internal packet queue that can be configured.

The semantics of the packet queue is that it will write to the UDP socket if it has buffered at least block amount of bytes OR it has elapsed at least flush amount of milliseconds.

By default the packet queue will join multiple messages with a new line. It will also append a trailing new line, however you can opt out of the trailing new line by setting trailingNewLine field to false.

The block field defaults to 1440 bytes. The flush field defaults to 1000 milliseconds. The trailingNewLine field defaults to true.

options.dnsResolver

{
    timeToLive?: Number,
    seedIP?: String,
    backoffSettings?: {
        maxDelay?: Number,
        minDelay?: Number,
        retries?: Number,
        factor?: Number
    }
}

The UDP socket will optionally use a DNS resolver to resolve DNS once instead of resolving it for every UDP packet being written.

It's strongly recommended you use the DNS resolver.

The DNS resolver will resolve its DNS lookup based on the configured timeToLive. i.e. it caches the DNS host for at least that amount of time.

The DNS resolver takes a seedIP value, this is used when it cannot resolve DNS due to DNS failures and will fallback to the static IP you gave it.

The DNS resolver retries DNS lookups on DNS failures based on the backoffSettings you supply.

The timeToLive field defaults to five minutes (in milliseconds) The seedIP field has no default. The backoffSettings.maxDelay field defaults to Infinity The backoffSettings.minDelay field defaults to 500 milliseconds The backoffSettings.retries field defaults to 10 retries The backoffSettings.factor field defaults to 2.

options.isDisabled

isDisabled is an optional predicate function. You can pass in a predicate function that allows you to disabled the statsd client at run time.

When this predicate function returns true the EphemeralSocket will stop writing to the statsd UDP server.

Counting stuff

Counters are supported, both as raw .counter(metric, delta) and with the shortcuts .increment(metric, [delta=1]) and .decrement(metric, [delta=-1]):

sdc.increment('systemname.subsystem.value'); // Increment by one
sdc.decrement('systemname.subsystem.value', -10); // Decrement by 10
sdc.counter('systemname.subsystem.value, 100); // Indrement by 100

Gauges

Sends an arbitrary number to the back-end:

sdc.gauge('what.you.gauge', 100);

Delays

Keep track of how fast (or slow) your stuff is:

var start = new Date();
setTimeout(function () {
        sdc.timing('random.timeout', start);
}, 100 * Math.random());

If it is given a Date, it will calculate the difference, and anything else will be passed straight through.

And don't let the name (or nifty interface) fool you - it can measure any kind of number, where you want to see the distribution (content lengths, list items, query sizes, ...)

Stopping gracefully

By default, the socket is closed if it hasn't been used for a second (see socket_timeout in the init-options), but it can also be force-closed with .close():

var start = new Date();
setTimeout(function () {
    sdc.timing('random.timeout', start); // 2 - implicitly re-creates socket.
    sdc.close(); // 3 - Closes socket after last use.
}, 100 * Math.random());
sdc.close(); // 1 - Closes socket early.

The call is idempotent, so you can call it "just to be sure". And if you submit new metrics later, the socket will automatically be re-created, and a new timeout-timer started.

Prefix-magic

The library supports getting "child" clients with extra prefixes, to help with making sane name-spacing in apps:

// Create generic client
var sdc = createSDC({host: 'statsd.example.com', prefix: 'systemname');
sdc.increment('foo'); // Increments 'systemname.foo'
... do great stuff ...

// Subsystem A
var sdcA = sdc.getChildClient('a');
sdcA.increment('foo'); // Increments 'systemname.a.foo'

// Subsystem B
var sdcB = sdc.getChildClient('b');
sdcB.increment('foo'); // Increments 'systemname.b.foo'

Internally, they all use the same socket, so calling .close() on any of them will allow the entire program to stop gracefully.

What's broken

Check the GitHub issues.

LICENSE

ISC - see LICENSE.txt.