A streaming metric producer. Allows producing counters, gauges, time series in a way that is independent of your metrics system so that you can produce metrics and let consumers decide how to consume them. Additionally, you can pipe together different metrics streams before finally consuming them all in a single location.
The client is intended to be used in the following way:
Instantiate a new client
const client = new Metrics();
Use the client for instrumentation
client.metric({
name: 'unique_metic_name',
description: 'Description of metric being collected',
value: 10,
});
Pipe collected metrics to a collector
client.pipe(consumer);
The client supports 2 types of metric creation use cases. 1. timers (via client.timer
) and 2. Non timers (via client.metric
)
- Histograms are supported by using the timer functionality.
- Gauges are supported via setting the
value
property. - Counters are implicit. ie. Each metric added can be counted by a consumer.
- Timestamps are always generated by default for all metrics.
- By default the client will only buffer up 100 metrics items before it starts dropping the oldest metric from the stream for each new metric it adds. This should prevent any memory leaks associated with not consuming the stream.
A metric to be used in a counter
client.metric({
name: 'my_counter',
description: 'Counter description',
});
Setting a value to be used in a gauge
client.metric({
name: 'my_gauge',
description: 'Gauge description',
value: 123,
});
A timer to be used in a histogram
const end = client.timer({
name: 'my_histogram',
description: 'Histogram description'
});
await something();
end();
A timer to be used in a histogram and a gauge
const end = client.timer({
name: 'my_histogram_gauge',
description: 'Histogram gauge example'
});
await something();
end({ value: 123 });
One of the goals of @metrics/client
is to allow any number of modules to produce their own metrics, not know about
where they might be consumed.
This can be achieved by including and instantiating a @metrics/client
client in each module, using it to create metrics and then exposing the client for consumption elsewhere.
Example
// module-1
const Metrics = require('@metrics/client');
const client = new Metrics();
client.metric({...})
module.exports.metrics = client;
// module-2
const Metrics = require('@metrics/client');
const client = new Metrics();
client.metric({...})
module.exports.metrics = client;
// consuming module
const module1 = require('module-1');
const module2 = require('module-2');
const consumer = require('some-consumer');
module1.pipe(module2).pipe(consumer);
In order to consume metrics produced by @metrics/client
you just need to listen for data and use your favourite metrics client to convert our data format into something usable by your system of choice.
Example: Prometheus using prom-client
const { Counter } = require('prom-client');
const { Writable } = require('stream');
class Consumer extends Writable {
constructor() {
super({ objectMode: true });
this.counter = new Counter({
name: 'my_metric_counter',
help: 'Counts http request type things',
labelNames: ['url', 'method'],
});
}
_write(metric, enc, cb) {
this.counter.labels(metric.meta.url, metric.meta.method).inc(1);
cb();
}
}
Creates a new instance of the metrics client.
options
name | description | type | default |
---|---|---|---|
maxBuffer |
Max number of metrics to retain if not consumed. Keeps most recent. | number |
100 |
Example
const client = new Metrics(options);
return: Duplex Stream
Collects a metric. As a minimum, a name and description for the metric must be provided.
options
name | description | type | default | required |
---|---|---|---|---|
name |
Metric name. valid characters: a-z,A-Z,0-9,_ | string |
null | true |
description |
Metric description | string |
null | true |
value |
Arbitrary value for the metric (used for gauges) | string|number |
null | false |
meta |
Available to be used to hold any misc data. | object |
null | false |
n.b. In practice, meta
can be used as a way to label metrics. Use each key of the meta object as the label name and the value as the label value
return: void
client.metric({
name: '',
description: '',
});
Starts a metric timer and returns and end function to be called when the measurement should be considered finished.
options
name | description | type | default | required |
---|---|---|---|---|
name |
Metric name. valid characters: a-z,A-Z,0-9,_ | string |
null | true |
description |
Metric description | string |
null | true |
value |
Arbitrary value for the metric (used for gauges) | string|number |
null | false |
meta |
Available to be used to hold any misc data | object |
null | false |
n.b. In practice, meta
can be used as a way to label metrics. Use each key of the meta object as the label name and the value as the label value
return: function
Returns an end function (see below) to be used to indicate that the timer measurement is finished.
Example
const end = client.timer(options);
Stops a previously started timer, merges timers options
with end options
and and sets the measured time
value.
options
name | description | type | default | required |
---|---|---|---|---|
name |
Metric name. valid characters: a-z,A-Z,0-9,_ | string |
null | true |
description |
Metric description | string |
null | true |
value |
Arbitrary value for the metric (used for gauges) | string|number |
null | false |
meta |
Available to be used to hold any misc data | object |
null | false |
n.b. In practice, meta
can be used as a way to label metrics. Use each key of the meta object as the label name and the value as the label value
return: void
Example
const end = client.timer(options);
// ... thing to be measured
end(options);