dats
Minimalistic zero-dependencies UDP/TCP statsd client for Node.js
There are times when you have to gather metrics and you want something simple without writing too much boilerplate, dats
to your aid!
This client aims to have a simple statsd compliant API with some optional flavour for advanced usage, like: buffered metrics and either UDP/TCP transports!
Supports Node.js >=14.0.0
, if you are a Node.js v12
user refer to dats@2.x.x
.
Table of Content
Installation
The package is available at npm.
You can install it with npm
$ npm i -S @immobiliarelabs/dats
$ npm i -S @immobiliarelabs/dats@next
or yarn
$ yarn add @immobiliarelabs/dats
$ yarn @immobiliarelabs/dats@next
Usage
Generic
import Client from '@immobiliarelabs/dats';
const stats = new Client({
host: 'udp://someip:someport',
namespace: 'myGrafanaNamespace',
onError: (error) => {
processError(error);
},
});
stats.counter('some.toCount', 3);
stats.counter('some.toCount');
stats.counter('some.toCount', 1, 10);
stats.timing('some.toTime', 10);
stats.timing('some.toTime', 10, 0.1);
stats.gauge('some.toGauge', 23);
stats.set('some.set', 765);
Namespacing with Hostname/PID
import Client from '@immobiliarelabs/dats';
const stats = new Client({
host: 'udp://someip:someport',
namespace: 'myGrafanaNamespace.${hostname}.${pid}',
});
stats.counter('some.toCount', 3);
If the hostname contains any .
, the client will replace them with _
.
TCP Client
import Client from '@immobiliarelabs/dats';
const stats = new Client({
host: 'tcp://someip:someport',
namespace: 'myGrafanaNamespace.${hostname}.${pid}',
});
await stats.connect();
stats.counter('some.toCount', 3);
API
This module exports:
Client
The statsd client
new Client(options)
options
: configuration object.
host
: statsd host (udp://{ip}:{port}
or tcp://{ip}:{port}
), you can use also ipv6. If you want to force udp6 usage use: udp6://{host}:{port}
, when using TCP, you have to call the Client.connect
method.namespace
: Optional. Prefix to use for the metrics. The metric will be sent as namespace.
+ the metric string. Optionally you can use ${hostname}
and ${pid}
placeholders in the namespace and have them substituted with the machine hostname and the process id.bufferSize
: Optional. Default is 0
. Setting this value to a number greather than zero will activate buffered mode, which instead of sending metrics on each call, it will buffer them and send them when one of this conditions occurs: the buffer is full, or the bufferFlushTimeout
has expired. Using this approach is more performant, but you must be careful to use a value compatible to the MTU available on your network, otherwise your packets might get dropped silently. See multi-metric-packets.bufferFlushTimeout
: Optional. Default is 100
. Timeout in milliseconds to wait before flushing the metrics buffer.debug
: Optional. Default debuglog('dats')
. The logger function.udpDnsCache
: Optional. Default true. Activate the cache DNS lookup for udp.udpDnsCacheTTL
: Optional. Default 120
. Dns cache Time to live in seconds.onError
: Optional. Default (err) => void
. Called when there is an error. Allows you to check also send errors.customSocket
: Optional. Default null
. Custom socket used by the client, this is a feature for mocking we do not recommend using it in production.tags
: Optional Default null
. If provided, metrics will include tags in the form #key1:value1,key2:value2
.
Client.close([cb])
close the client socket
cb
: optional. A callback function to call when the socket is closed. If no cb
is provided a Promise
is returned.
Returns: a Promise
if no cb
is passed.
Client.connect()
connect the TCP socket. Calling this function is required only on TCP.
Returns: a Promise
.
Client.counter(string[, value, sampling])
send a metric of type counter
string
: The metric stringvalue
: Optional. The metric value (Number
). Defaults to 1
.sampling
: Optional. The metric sampling.
All sending errors are handled by the onError
callback.
Client.timing(string, value[, sampling])
send a metric of type timing
string
: The metric stringvalue
: The metric value (Number
).sampling
: Optional. The metric sampling.
All sending errors are handled by the onError
callback.
Client.gauge(string, value)
send a metric of type gauge
string
: The metric stringvalue
: The metric value (Number
).
All sending errors are handled by the onError
callback.
Client.set(string, value)
send a metric of type set
string
: The metric stringvalue
: The metric value (Number
).
All sending errors are handled by the onError
callback.
Dats Mock
Dats exports his mock, you can use it as follow:
import ClientMock from '@immobiliarelabs/dats/dist/mock';
const host = new URL(`udp://127.0.0.1:8232`);
const namespace = 'ns1';
const client = new ClientMock({ host, namespace });
client.gauge('some.metric', 100);
client.set('some.metric', 100);
// metrics is an array with all metrics sent
console.log(client.metrics);
/* stdout:
[
'ns1.some.metric:100|g',
'ns1.some.metric:100|s',
]
*/
// Check if a metric is in the metrics array
client.hasSent('ns1.some.metric:100|s'); // -> true
client.hasSent('ns1.some.metric:10|s'); // -> false
client.hasSent(/ns1\.some\.metric:\d+\|s/); // -> true
client.hasSent(/ns1\.some\.test:\d+\|s/); // -> false
// Clean the metrics array with
client.cleanMetrics();
console.log(client.metrics);
/* stdout:
[]
*/
CLI Interface
dats is also exposed as a CLI that can both be installed as a npm global package or a precompiled binary.
The precompile binary can be found in the release section for Linux, MacOS or Windows.
CLI Usage
$ npm i -g @immobiliarelabs/dats
dats --help
datsrc
Every command flag can also be specified in JSON format in the file .datsrc
, the process at runtime will search it in the current working directory and merge both file config and flags before running!
{
"host": "123.123.123.123",
"port": "1234",
"prefix": "my_metric_prefix"
}
Pre-compiled binary
If you want to use the precompiled binary get the correct link for your OS in the release section and do the following:
curl https://github.com/immobiliare/dats/releases/download/v{{VERSION_TAG}}/dats-cli-{{VERSION_OS}} -L -o dats-cli
chmod +x dats-cli
./dats-cli
Benchmarks
The automatic benchmarking for every commit can be found at the following links: next and
main.
The tests were done using autocannon pointing to an HTTP node.js Server that sends at each request a count metric.
With this kind of test, we evaluate how much the library influences the application performance.
Below are reported the benchmarks with the most famous node.js statsd clients:
Base is the HTTP server without metrics.
Powered Apps
dats was created by the amazing Node.js team at ImmobiliareLabs, the Tech dept of Immobiliare.it, the #1 real estate company in Italy.
We are currently using dats in our products as well as our internal toolings.
If you are using dats in production drop us a message.
Support & Contribute
Made with ❤️ by ImmobiliareLabs & Contributors
We'd love for you to contribute to dats!
If you have any questions on how to use dats, bugs and enhancement please feel free to reach out by opening a GitHub Issue.
License
dats is licensed under the MIT license.
See the LICENSE file for more information.