Why MetricsJS?
With Metrics JS, it’s possible to instrument a Node.js module, measuring the things you feel are important such as operation timing or counts, without needing to know which system the metrics will be collected into. It’s up to the final consumer to decide whether the metrics will be pushed to Prometheus, Data Dog or something else.
Resilient design
MetricsJS is designed in a way that’s immune to the problem posed by a global registry.
The problem we solve
Take for instance this simplified implementation of a metrics class:
This approach works as long as there is only ever one version of this module. Why? Let’s look at how npm
and other package managers handles dependencies.
Imagine you have a dependency tree somewhat like this:
Your app is not the only one using my-metrics-client
. What happens when installing is that npm
is that the shared dependencies will be flattened:
So far, so good. All code that produces metrics use the same version, and push metrics to the same shared REGISTRY
singleton.
Problems start happening when your dependency tree looks like this:
At this point, my-metrics-client
can’t be flattened to one shared instance. Each of the @my-corp
modules that are producing metrics will not add their entries to your app’s REGISTRY
. You will have no access to the metrics generated by your dependencies.
Solving dependency mismatch
MetricsJS solves the problem by treating metrics as a stream of data.
In MetricsJS we define a standard metric object:
Each producer of metrics has its own instance of the metrics client, which mimics the API of prom-client
. The metrics client is also Node stream. Each method on the client produces a metric object on the stream.
Back to the dependency tree, it doesn’t matter if it looks like this:
All the modules in @my-corp
expose their metrics stream. The app composes the streams, and has access to all metrics.