All Projects → immobiliare → fastify-metrics

immobiliare / fastify-metrics

Licence: MIT license
📊 Fastify plugin that integrates metrics collection and dispatch to statsd

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects
shell
77523 projects

Projects that are alternatives of or similar to fastify-metrics

Netdata
Real-time performance monitoring, done right! https://www.netdata.cloud
Stars: ✭ 57,056 (+91925.81%)
Mutual labels:  grafana, statsd
dokku-graphite
a graphite, grafana, statsd, carbon plugin for dokku
Stars: ✭ 47 (-24.19%)
Mutual labels:  grafana, statsd
grafana-stack
Tiny docker images for graphite, grafana and statsdly
Stars: ✭ 28 (-54.84%)
Mutual labels:  grafana, statsd
Docker Statsd Influxdb Grafana
Docker Image with Telegraf (StatsD), InfluxDB and Grafana
Stars: ✭ 352 (+467.74%)
Mutual labels:  grafana, statsd
Graphite Stack Ansible Vagrant
Provision a complete Graphite, StatsD & Grafana install using Ansible and (optionally) Vagrant
Stars: ✭ 62 (+0%)
Mutual labels:  grafana, statsd
Tgres
Time Series in Go and PostgreSQL
Stars: ✭ 481 (+675.81%)
Mutual labels:  grafana, statsd
docker-graphite
Run Graphite with Docker
Stars: ✭ 15 (-75.81%)
Mutual labels:  grafana, statsd
Redis Timeseries
Future development of redis-timeseries is at github.com/RedisLabsModules/redis-timeseries.
Stars: ✭ 197 (+217.74%)
Mutual labels:  grafana, statsd
docker grafana statsd elk
Docker repo for a general purpose graphing and logging container - includes graphite+carbon, grafana, statsd, elasticsearch, kibana, nginx, logstash indexer (currently using redis as an intermediary)
Stars: ✭ 19 (-69.35%)
Mutual labels:  grafana, statsd
mlapp
ML model serving app based on APIs
Stars: ✭ 70 (+12.9%)
Mutual labels:  grafana
grafana-plugin-sdk-go
A Go SDK for building backend plugins for Grafana
Stars: ✭ 151 (+143.55%)
Mutual labels:  grafana
fastify-autoroutes
fastest way to map directories to URLs in fastify
Stars: ✭ 70 (+12.9%)
Mutual labels:  fastify
statsd.cr
A statsd client library for Crystal.
Stars: ✭ 32 (-48.39%)
Mutual labels:  statsd
go-zero-looklook
🔥基于go-zero(go zero) 微服务全技术栈开发最佳实践项目。Develop best practice projects based on the full technology stack of go zero (go zero) microservices.
Stars: ✭ 2,691 (+4240.32%)
Mutual labels:  grafana
jmx-monitoring-stacks
No description or website provided.
Stars: ✭ 170 (+174.19%)
Mutual labels:  grafana
ecs-container-exporter
AWS ECS side car that exports ECS container level docker stats metrics to Prometheus as well as publish it via Statsd.
Stars: ✭ 22 (-64.52%)
Mutual labels:  statsd
fullstack-graphql-app
An opinionated fullstack GraphQL monorepo boilerplate using pnpm, Turborepo, Prisma, GraphQL Yoga 2, Fastify, Nextjs, urql, and React
Stars: ✭ 90 (+45.16%)
Mutual labels:  fastify
enviroplus exporter
Prometheus exporter for enviroplus module by Pimoroni
Stars: ✭ 70 (+12.9%)
Mutual labels:  grafana
perfmetrics
A library for sending software performance metrics from Python libraries and apps to statsd.
Stars: ✭ 26 (-58.06%)
Mutual labels:  statsd
grafana-dashboards
Collection of reusable Grafana dashboards
Stars: ✭ 55 (-11.29%)
Mutual labels:  grafana

logo

fastify-metrics

Release code style: prettier semantic-release npm (scoped) license

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!

Table of Content

Fastify Version Support

Node.js fastify @immobiliarelabs/fastify-metrics
<14 3 3
>14 4 4

Installation

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

Migrating from version 1

See the migration guide if you have to migrate from the version 1 to 2 of this plugin.

Usage

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);

Route Configuration

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.

Note

The plugin internally uses the routeId key in the metrics object of the Request.routeConfig or Reply.request.routeConfig object to build the label of the metric of a route.

See

Metrics collected

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.

Decorators

The plugin adds some decorators to both the fastify instance and the reply object.

Fastify decorators

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.

Request and Reply decorators

getMetricLabel()

  • Returns <string> The computed metric label of the route.

sendTimingMetric(name[, value])

  • name <string> The name of the metric
  • value <number> The value of the metric

It 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])

  • name <string> The name of the metric
  • value <number> The value of the metric

It 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)

  • name <string> The name of the metric
  • value <number> The value of the metric

It 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)

  • name <string> The name of the metric
  • value <number> The value of the metric

It 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.

Hooks

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 time
  • onError: to count errors

Request and Reply routeConfig

The plugin adds a metrics object to the Request.routeConfig and Reply.request.routeConfig for convenience with the following properties:

  • routeId <string> The id for the current route
  • fastifyPrefix <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.

API

This module exports a plugin registration function.

Configuration 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.

Routes labels generation modes

There are two different modes to generate the label for each route:

  • static
  • dynamic
computedPrefix

In both modes by default the plugin generates a prefix using:

  • the fastify prefix used to register the plugin (normalized replacing / with .), we call it fastifyPrefix
  • the routes prefix passed to the plugin option routes.prefix, we call it routesPrefix

Generating a computed prefix like this:

<fastifyPrefix>.<routesPrefix>

static mode

In this mode a onRoute hook is registered in the fastify instance and the plugin generates a label at startup time combining the following strings:

  • the fastify prefix used to register the plugin, accessible via the prefix key of the route registration options.
  • the routes prefix passed in the plugin options, accessible as a parameter of the internal getLabel function.
  • the 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.
  • Returns: <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 mode

In 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:

  • the fastify prefix used to register the plugin, accessible via the prefix key of the fastify instance.
  • the routes prefix passed in the plugin options, accessible via the metricsRoutesPrefix decorator of the fastify instance.
  • the 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
  • Returns: <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.

Example
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.routeConfig.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);

Powered Apps

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.

Support & Contribute

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.

License

fastify-metrics is licensed under the MIT license.
See the LICENSE file for more information.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].