Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@immobiliarelabs/fastify-metrics
Advanced tools
A minimalistic and opinionated Fastify plugin that collects metrics and dispatches them to statsd
A slighlty opinionated Fastify plugin that collects metrics and dispatches them to statsd.
If you write your services and apps using Fastify
and also use statsd
, this plugin might be for you!
It automatically collects Node.js process metrics along with routes stats like hit count, timings and errors and uses the Dats
client to send them to a stasd
collector.
⚠️ Fastify 4 introduced some breaking changes, please refer to this version support table to find what works best for you!
Node.js | fastify | @immobiliarelabs/fastify-metrics |
---|---|---|
<14 | 3 | 3 |
>14 | 4 | 4 |
npm
# lastest stable version
$ npm i -S @immobiliarelabs/fastify-metrics
# latest development version
$ npm i -S @immobiliarelabs/fastify-metrics@next
yarn
# lastest stable version
$ yarn add @immobiliarelabs/fastify-metrics
# latest development version
$ yarn @immobiliarelabs/fastify-metrics@next
See the migration guide if you have to migrate from the version 1 to 2 of this plugin.
const fastify = require('fastify')();
await fastify.register(require('@immobiliarelabs/fastify-metrics'), {
client: {
host: 'udp://someip:someport',
namespace: 'ns',
},
});
const route = {
// This is required in order to associate a metric to a route
// If an object `metrics` with a `routeId` is not passed the route stats will be
// ignored.
config: {
metrics: {
routeId: 'root.getStatus',
},
},
url: '/',
method: 'GET',
handler(request, reply) {
reply.send({ ok: true });
},
};
fastify.route(route);
fastify.listen(3000);
To configure a route, you have to pass a metrics
object with the routeId
key set with a not empty string.
If the routeId
is not passed or is set with a falsy value, the route will not be metricated, and all route metrics methods will be disabled.
There are more usage examples in the examples
folder.
The plugin internally uses the routeId
key in the metrics
object of the Request.routeOptions
or Reply.request.routeOptions
object to build the label of the metric of a route.
See
These are the metrics that can be collected with their respective label.
Name | Type | Unit of measure | Description |
---|---|---|---|
<METRICS_NAMESPACE>.process.cpu | gauge | percentage | process cpu usage |
<METRICS_NAMESPACE>.process.mem.external | gauge | bytes | process external memory |
<METRICS_NAMESPACE>.process.mem.rss | gauge | bytes | process rss memory |
<METRICS_NAMESPACE>.process.mem.heapUsed | gauge | bytes | process heap used memory |
<METRICS_NAMESPACE>.process.mem.heapTotal | gauge | bytes | process heap total memory |
<METRICS_NAMESPACE>.process.eventLoopDelay | gauge | milliseconds | process event loop delay |
<METRICS_NAMESPACE>.process.eventLoopUtilization | gauge | absolute number between 0 and 1 | process event loop utilization |
<METRICS_NAMESPACE>.<computedPrefix>.<routeId>.requests | counter | unit | requests count per service |
<METRICS_NAMESPACE>.<computedPrefix>.<routeId>.errors.<statusCode> | counter | unit | errors count per service |
<METRICS_NAMESPACE>.<computedPrefix>.<routeId>.request_size | timing | bytes | request size |
<METRICS_NAMESPACE>.<computedPrefix>.<routeId>.response_time | timing | milliseconds | response time |
<METRICS_NAMESPACE>.<computedPrefix>.<routeId>.response_size | timing | bytes | response size |
To know more about how the computedPrefix
and the route label are built see here.
The plugin adds some decorators to both the fastify instance and the reply object.
metrics
object
>An object containing the following properties:
metrics.namespace
string
>The namespace
passed to the plugin configuration option.
metrics.fastifyPrefix
string
>The normalized fastify instance prefix
.
metrics.routesPrefix
string
>The normalized routes prefix
passed to the routes.prefix
option.
metrics.client
The Dats instance.
metrics.sampler
The sampler instance used to sample process metrics, if options.health
is true
.
metrics.hrtime2us
A utility function to convert the legacy process.hrtime([time])
value to microseconds.
See hrtime-utils.
metrics.hrtime2ns
A utility function to convert the legacy process.hrtime([time])
value to nanoseconds.
See hrtime-utils.
metrics.hrtime2ms
A utility function to convert the legacy process.hrtime([time])
value to milliseconds.
See hrtime-utils.
metrics.hrtime2s
A utility function to convert the legacy process.hrtime([time])
value to seconds.
See hrtime-utils.
getMetricLabel()
string
> The computed metric label of the route.sendTimingMetric(name[, value])
string
> The name of the metricnumber
> The value of the metricIt sends a timing metric. It automatically prepends the route label to the passed name
. It is just a small wrapper of the native Dats
client method.
sendCounterMetric(name[, value])
string
> The name of the metricnumber
> The value of the metricIt sends a counter metric. It automatically prepends the route label to the passed name
. It is just a small wrapper of the native Dats
client method.
sendGaugeMetric(name, value)
string
> The name of the metricnumber
> The value of the metricIt sends a gauge metric. It automatically prepends the route label to the passed name
. It is just a small wrapper of the native Dats
client method.
sendSetMetric(name, value)
string
> The name of the metricnumber
> The value of the metricIt sends a timing metric. It automatically prepends the route label to the passed name
. It is just a small wrapper of the native Dats
client method.
The plugin uses the following hooks:
onRoute
: to generate the route labels at startup time if routes.mode
is set to 'static'
.onClose
: to close the Dats instance and the sampler instance.onRequest
: it registers a hook to count requests and, if routes.mode
is set to 'dynamic'
, it adds another one to generate the route label.onResponse
: to measure response timeonError
: to count errorsThe plugin adds a metrics
object to the Request.routeOptions
and Reply.request.routeOptions
for convenience with the following properties:
routeId
<string
> The id for the current routefastifyPrefix
<string
> The prefix of the fastify instance registering the route, with the /
replaced with .
and without the .
at the beginning.routesPrefix
<string
> The routes prefix passed to the plugin options and without .
at the beginning and end.These properties can be useful when using a custom getLabel
function.
This module exports a plugin registration function.
options
The plugin is configured with an object with the following properties
client
<Object
|Client
> The statsd client configuration object or a Client
instance. When using the options object, a default onError
function is used to log with level error
the event with the app logger.routes
<boolean
|Object
> Routes metrics configuration. If set to false
it disables the collection of all the default routes metrics.
mode
<'static'
|'dynamic'
> The strategy to generate the route metric label.prefix
<string
> The prefix to use for the routes labels (<METRICS_NAMESPACE>.<computedPrefix>.<routeId>.*
). It defaults to ''
(no prefix).getLabel
<Function
> A custom function to generate the route label. It has a different signature depending on the mode.timing
<boolean
> Collect response timings (<METRICS_NAMESPACE>.<computedPrefix>.<routeId>
). Default: true
.requestSize
<boolean
> Collect request size (<METRICS_NAMESPACE>.<computedPrefix>.requests.<routeId>
). Default: false
.responseSize
<boolean
> Collect response size (<METRICS_NAMESPACE>.<computedPrefix>.requests.<routeId>
). Default: false
.hits
<boolean
> Collect requests count (<METRICS_NAMESPACE>.<computedPrefix>.requests.<routeId>
). Default: true
.errors
<boolean
> Collect errors count (<METRICS_NAMESPACE>.<computedPrefix>.errors.<routeId>.<statusCode>
). Default: true
.health
<boolean
|Object
> Flag to enable/disable the collection of the process health data(<METRICS_NAMESPACE>.process.*
) or an object to configure a subset of the health metrics provided by the sampler. Default: true
.
sampleInterval
<number
> The number of milliseconds of the interval to get the metrics sample.eventLoopOptions
<Object
> The options object used to configure the core monitorEventLoopDelay
.There are two different modes to generate the label for each route:
static
dynamic
In both modes by default the plugin generates a prefix using:
fastify
prefix used to register the plugin (normalized replacing /
with .
), we call it fastifyPrefix
routes.prefix
, we call it routesPrefix
Generating a computed prefix like this:
<fastifyPrefix>.<routesPrefix>
static
modeIn this mode a onRoute
hook is registered in the fastify
instance and the plugin generates a label at startup time combining the following strings:
fastify
prefix used to register the plugin, accessible via the prefix
key of the route registration options.getLabel
function.config.metrics.routeId
string used to configure the route, acessible via the config
key of the route registration options.The getLabel
function in this mode will have the following signature:
getLabel(options)
options
<Object
> The route registration
config
metrics
routeId
<string
> The id used to initialize the route.fastifyPrefix
<string
> The normalized prefix of the fastify instance registering the route.routesPrefix
<string
> The normalized routes prefix passed to the plugin options.string
> The route label string without any .
at the beginning or end.Pay attention to avoid returing empty strings or strings with leading and trailing .
.
dynamic
modeIn this mode a onRequest
hook is registerd in the fastify
instance and the plugin generates a label and attaches it to each request and reply combining the following strings:
fastify
prefix used to register the plugin, accessible via the prefix
key of the fastify
instance.metricsRoutesPrefix
decorator of the fastify
instance.config.metrics.routeId
string used to configure the route, acessible via the config
key of the request
or reply
context.The getLabel
function in this mode will have the following signature:
getLabel(request, reply)
request
reply
string
> The route label string without any .
at the beginning or end.The this
context of the function is bound to the fastify instance of the request. Pay attention to avoid returing empty strings or strings with leading and trailing .
. Also, don't use arrow functions otherwhise the this
context won't refer to the fastify instance.
If you don't pass your custom function, the default one returns the same string computed in static
mode. Hence, the dynamic
mode is not very useful if you don't define your own getLabel
function.
const fastify = require('fastify')();
await fastify.register(require('@immobiliarelabs/fastify-metrics'), {
client: {
host: 'udp://someip:someport',
namespace: 'ns',
},
routes: {
mode: 'dynamic',
getLabel: function (request, reply) {
const auth = request.user ? 'user' : 'anonim';
const { metrics } = request.routeOptions.config;
const routesPrefix = metrics.routesPrefix
? `${metrics.routesPrefix}.`
: '';
const fastifyPrefix = metrics.fastifyPrefix
? `${metrics.fastifyPrefix}.`
: '';
const routeId = metrics.routeId ? `${metrics.routeId}.` : '';
return `${fastifyPrefix}${routesPrefix}${routeId}${auth}`;
},
},
});
const route = {
config: {
metrics: {
routeId: 'root.getStatus',
},
},
url: '/',
method: 'GET',
handler(request, reply) {
reply.send({ ok: true });
},
};
fastify.route(route);
fastify.listen(3000);
fastify-metrics
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 fastify-metrics
in our products as well as our internal toolings.
If you are using fastify-metrics in production drop us a message.
Made with ❤️ by ImmobiliareLabs & Contributors
We'd love for you to contribute to fastify-metrics
!
If you have any questions on how to use fastify-metrics
, bugs and enhancement please feel free to reach out by opening a GitHub Issue.
fastify-metrics
is licensed under the MIT license.
See the LICENSE file for more information.
FAQs
A minimalistic and opinionated Fastify plugin that collects metrics and dispatches them to statsd
We found that @immobiliarelabs/fastify-metrics demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.