SkillAgentSearch skills...

Promster

โฐA Prometheus exporter for Hapi, express, Apollo, undici and Marble.js servers to automatically measure request timings ๐Ÿ“Š

Install / Use

/learn @tdeekens/Promster
About this skill

Quality Score

0/100

Category

Operations

Supported Platforms

Universal

README

<p align="center"> <img alt="Logo" height="150" src="https://raw.githubusercontent.com/tdeekens/promster/main/logo.png" /><br /><br /> </p> <h2 align="center">โฐ Promster - Measure metrics from Hapi, express, Marble.js, Apollo or Fastify servers with Prometheus ๐Ÿšฆ</h2> <p align="center"> <b>Promster is a Prometheus Exporter for Node.js servers written for Express, Hapi, Marble.js, Apollo or Fastify.</b> </p> <p align="center"> <sub> โค๏ธ Hapi ยท Express ยท Marble.js ยท Fastify ยท Apollo ยท TypeScript ยท Vitest ยท oxlint ยท Changesets ยท Prometheus ๐Ÿ™ </sub> </p> <p align="center"> <a href="https://github.com/tdeekens/promster/actions/workflows/test.yml"> <img alt="Test & build status" src="https://github.com/tdeekens/promster/actions/workflows/test.yml/badge.svg"> </a> <a href="https://codecov.io/gh/tdeekens/promster"> <img alt="Codecov Coverage Status" src="https://img.shields.io/codecov/c/github/tdeekens/promster.svg?style=flat-square"> </a> <a href="https://app.fossa.io/projects/git%2Bgithub.com%2Ftdeekens%2Fpromster?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Ftdeekens%2Fpromster.svg?type=shield"/></a> <a href="https://snyk.io/test/github/tdeekens/promster"><img src="https://snyk.io/test/github/tdeekens/promster/badge.svg" alt="Known Vulnerabilities" data-canonical-src="https://snyk.io/test/github/{username}/{repo}" style="max-width:100%;"/></a> <img alt="Made with Coffee" src="https://img.shields.io/badge/made%20with-%E2%98%95%EF%B8%8F%20coffee-yellow.svg"> </p>

Table of Contents

โฏ Why another Prometheus exporter for Express and Hapi?

These packages are a combination of observations and experiences I have had with other exporters which I tried to fix.

  1. ๐ŸŽ Use process.hrtime.bigint() for high-resolution real time in metrics in seconds (converting from nanoseconds)
    • process.hrtime.bigint() calls libuv's uv_hrtime, without system call like new Date
  2. โš”๏ธ Allow normalization of all pre-defined label values
  3. ๐Ÿ–ฅ Expose Garbage Collection among other metric of the Node.js process by default
  4. ๐Ÿšจ Expose a built-in server to expose metrics quickly (on a different port) while also allowing users to integrate with existing servers
  5. ๐Ÿ“Š Define two metrics one histogram for buckets and a summary for percentiles for performant graphs in e.g. Grafana
  6. ๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง One library to integrate with Hapi, Express and potentially more (managed as a mono repository)
  7. ๐Ÿฆ„ Allow customization of labels while sorting them internally before reporting
  8. ๐Ÿผ Expose Prometheus client on Express locals or Hapi app to easily allow adding more app metrics

โฏ Package Status

| Package | Version | Downloads | | ----------------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------- | | promster/hapi | [![hapi Version][hapi-icon]][hapi-version] | [![hapi Downloads][hapi-downloads]][hapi-downloads] | | promster/express | [![express Version][express-icon]][express-version] | [![express Downloads][express-downloads]][express-downloads] | | promster/marblejs | [![marblejs Version][marblejs-icon]][marblejs-version] | [![marblejs Downloads][marblejs-downloads]][marblejs-downloads] | | promster/fastify | [![fastify Version][fastify-icon]][fastify-version] | [![fastify Downloads][fastify-downloads]][fastify-downloads] | | promster/apollo | [![apollo Version][apollo-icon]][apollo-version] | [![apollo Downloads][apollo-downloads]][apollo-downloads] | | promster/undici | [![undici Version][undici-icon]][undici-version] | [![undici Downloads][undici-downloads]][undici-downloads] | | promster/server | [![server Version][server-icon]][server-version] | [![server Downloads][server-downloads]][server-downloads] | | promster/metrics | [![metrics Version][metrics-icon]][metrics-version] | [![metrics Downloads][metrics-downloads]][metrics-downloads] | | promster/types | [![types Version][types-icon]][types-version] | [![types Downloads][types-downloads]][types-downloads] |

โฏ Installation

This is a mono repository maintained using changesets. It contains multiple packages including framework integrations (express, hapi, fastify, marblejs, apollo, undici), a core metrics library, a standalone server for exposing metrics, and shared types.

Depending on the preferred integration use:

yarn add @promster/express or npm i @promster/express --save

or

yarn add @promster/hapi or npm i @promster/hapi --save

Please additionally make sure you have prom-client installed. It is a peer dependency of @promster as some projects might already have an existing prom-client installed, which otherwise would result in different default registries.

yarn add prom-client or npm i prom-client --save

โฏ Getting Started

Promster has to be set up with your server -- either as an Express middleware, a Hapi plugin, a Fastify plugin, or similar. You can expose the gathered metrics via a built-in small server or through your own.

Note: Do not be scared by the variety of options. @promster can be set up without any additional configuration options and has sensible defaults. However, trying to suit many needs and different existing setups (e.g. metrics having recording rules over histograms) it comes with all those options listed in Configuration.

Express

import app from './your-express-app';
import { createMiddleware } from '@promster/express';

// Note: This should be done BEFORE other routes
// Pass 'app' as middleware parameter to additionally expose Prometheus under 'app.locals'
app.use(createMiddleware({ app, options }));

Passing the app into the createMiddleware call attaches the internal prom-client to your Express app's locals. This may come in handy as later you can:

// Create an e.g. custom counter
const counter = new app.locals.Prometheus.Counter({
  name: 'metric_name',
  help: 'metric_help',
});

// to later increment it
counter.inc();

Fastify

import app from './your-fastify-app';
import { plugin as promsterPlugin } from '@promster/fastify';

fastify.register(promsterPlugin);

The plugin attaches the internal prom-client to your Fastify instance. This may come in handy as later you can:

// Create an e.g. custom counter
const counter = new fastify.Prometheus.Counter({
  name: 'metric_name',
  help: 'metric_help',
});

// to later increment it
counter.inc();

Hapi

import { createPlugin } from '@promster/hapi';
import app from './your-hapi-app';

app.register(createPlugin({ options }));

Here you do not have to pass in the app into the createPlugin call as the internal prom-client will be exposed onto Hapi as in:

// Create an e.g. custom counter
const counter = new app.Prometheus.Counter({
  name: 'metric_name',
  help: 'metric_help',
});

// to later increment it
counter.inc();

Marble.js

import {
  createMiddleware,
  getContentType,
  getSummary,
} from '@promster/marblejs';

const middlewares = [
  createMiddleware(),
  //...
];

const serveMetrics$ = r
  .matchPath('/metrics')
  .matchType('GET')
  .use(async (req$) =>
    req$.pipe(
      mapTo({
        headers: { 'Content-Type': getContentType() },
        body: await getSummary(),
      }),
    ),
  );

Apollo

import { createPlugin as createPromsterMetricsPlugin } from '@promster/apollo';

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [createPromsterMetricsPlugin()],
});

await server.listen();

Undici

Depending on the undici version used you have to use a pool metrics exporter or can use the agent metrics exporter.

Agent metrics (undici v7.9.0 or later)

import { createAgentMetricsExporter } from '@promster/undici';

createAgentMetricsExporter([agentA, agentB]);

You can then also always add additional agents:

import { addObservedAgent } from '@promster/undici';

addObservedAgent(agent);

Pool metrics (undici before v7.9.0)

import { createPoolMetricsExporter } from '@promster/undici';

createPoolMetricsExporter({ poolA, poolB });

You can then also always add additional pools:

import { addObservedPool } from '@promster/undici';

addObservedPool(origin, pool);

To integrate this with an undici agent you can use the factory function:

const agent = new Agent({
  factory(origin: s
View on GitHub
GitHub Stars226
CategoryOperations
Updated1d ago
Forks30

Languages

TypeScript

Security Score

100/100

Audited on Mar 30, 2026

No findings