prom-client vs opentracing vs datadog-metrics vs newrelic vs elastic-apm-node vs loggly vs sentry vs raygun
Application Monitoring and Observability Tools for Node.js
prom-clientopentracingdatadog-metricsnewrelicelastic-apm-nodelogglysentryraygunSimilar Packages:

Application Monitoring and Observability Tools for Node.js

These eight packages represent different approaches to application monitoring, logging, and observability in the JavaScript ecosystem. datadog-metrics, elastic-apm-node, newrelic, and prom-client focus on metrics and performance tracking. loggly specializes in log aggregation and search. opentracing provides a vendor-neutral tracing API. raygun and sentry concentrate on error tracking and crash reporting. While most are Node.js-focused, several offer browser counterparts for full-stack observability.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
prom-client8,774,0323,481126 kB562 years agoApache-2.0
opentracing8,061,3611,083195 kB35-Apache-2.0
datadog-metrics2,638,51714793.9 kB72 years agoMIT
newrelic1,296,4271,0002.93 MB604 days agoApache-2.0
elastic-apm-node465,140595909 kB363a month agoBSD-2-Clause
loggly53,400233-2210 years agoMIT
sentry38,45511515.5 MB1132 days agoFSL-1.1-Apache-2.0
raygun23,76632123 kB320 days ago-

Application Monitoring and Observability Tools: A Technical Deep-Dive

When building production JavaScript applications, you need visibility into what's happening — errors, performance bottlenecks, and system health. The eight packages we're comparing (datadog-metrics, elastic-apm-node, loggly, newrelic, opentracing, prom-client, raygun, sentry) each solve different parts of the observability puzzle. Let's break down how they work and when to use each one.

šŸŽÆ Primary Focus: What Each Tool Actually Does

These packages fall into three main categories:

Metrics & Performance Tracking — datadog-metrics, elastic-apm-node, newrelic, prom-client

Log Aggregation — loggly

Error Tracking — raygun, sentry

Distributed Tracing — opentracing

Understanding this distinction matters because you'll often need tools from multiple categories for complete observability.

šŸ“Š Metrics Collection: Four Different Approaches

datadog-metrics sends custom metrics to Datadog's DogStatsD server. You define what to measure and push it to their infrastructure.

// datadog-metrics: Push custom metrics
const metrics = require('datadog-metrics');
metrics.init({ host: 'localhost', prefix: 'myapp.' });

const gauge = metrics.gauge('requests.per.second');
gauge(150);

elastic-apm-node automatically instruments your Node.js app and sends performance data to Elastic APM. Less manual setup, more automatic coverage.

// elastic-apm-node: Automatic instrumentation
const apm = require('elastic-apm-node').start({
  serviceName: 'my-app',
  serverUrl: 'http://localhost:8200'
});

// Transactions are captured automatically
app.get('/users', (req, res) => {
  // APM tracks this request automatically
  res.json({ users: [] });
});

newrelic also provides automatic instrumentation but sends data to New Relic's commercial platform. Requires minimal code changes.

// newrelic: Auto-instrumentation via require
require('newrelic');

const express = require('express');
const app = express();

// New Relic automatically tracks requests, errors, and performance
app.get('/products', (req, res) => {
  res.json({ products: [] });
});

prom-client exposes metrics in Prometheus format for you to scrape. You control the metrics server and storage.

// prom-client: Expose metrics endpoint
const client = require('prom-client');
const register = new client.Registry();

const requestCounter = new client.Counter({
  name: 'http_requests_total',
  help: 'Total HTTP requests'
});

register.registerMetric(requestCounter);

app.get('/metrics', async (req, res) => {
  res.set('Content-Type', register.contentType);
  res.end(await register.metrics());
});

šŸ› Error Tracking: Sentry vs Raygun

sentry captures errors with rich context — stack traces, user data, breadcrumbs, and performance data. Has excellent browser and Node.js support.

// sentry: Capture exceptions with context
const Sentry = require('@sentry/node');

Sentry.init({
  dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
  environment: 'production'
});

try {
  riskyOperation();
} catch (error) {
  Sentry.captureException(error, {
    tags: { feature: 'checkout' },
    user: { id: '123' }
  });
}

raygun also captures errors but with a simpler setup. Good for teams that want error tracking without the full observability platform.

// raygun: Simple error reporting
const raygun = require('raygun');
const client = new raygun.Client();

client.init({ apiKey: 'YOUR_API_KEY' });

client.send(new Error('Something went wrong'), {
  tags: ['production'],
  user: { identifier: 'user-123' }
});

šŸ“ Log Aggregation: Loggly's Approach

loggly sends logs to their cloud service for search and analysis. Works with popular logging libraries like Winston.

// loggly: Send logs to cloud
const winston = require('winston');
const Loggly = require('winston-loggly-bulk');

const logger = winston.createLogger({
  transports: [
    new winston.transports.Loggly({
      token: 'YOUR_TOKEN',
      subdomain: 'your-subdomain',
      tags: ['NodeJS']
    })
  ]
});

logger.info('Application started');

šŸ”— Distributed Tracing: OpenTracing's Role

opentracing provides a vendor-neutral API for distributed tracing. You need to pair it with a specific implementation (like Jaeger or Zipkin).

// opentracing: Vendor-neutral tracing API
const opentracing = require('opentracing');

const tracer = new opentracing.Tracer();
const span = tracer.startSpan('database-query');

span.setTag('db.type', 'postgresql');

// Do database work...

span.finish();

āš ļø Important Note: OpenTracing has been merged into OpenTelemetry. For new projects, use @opentelemetry/api instead. OpenTracing is in maintenance mode.

// OpenTelemetry (recommended for new projects)
const api = require('@opentelemetry/api');

const tracer = api.trace.getTracer('my-app');
const span = tracer.startSpan('database-query');

// ... work ...

span.end();

🌐 Frontend vs Backend: Critical Distinction

Most packages listed here are Node.js/backend focused. For frontend monitoring, you need different packages:

Backend PackageFrontend Alternative
datadog-metrics@datadog/browser-rum
elastic-apm-node@elastic/apm-rum
newrelicnewrelic-browser
sentry (Node)@sentry/browser
raygun (Node)raygun4js
// @sentry/browser: Frontend error tracking
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
});

Sentry.captureMessage('Frontend error occurred');

āš ļø Deprecation and Maintenance Status

opentracing — In maintenance mode. OpenTelemetry has replaced it. Do not use for new projects.

loggly — SolarWinds (owner) has shifted focus. Evaluate current maintenance before committing to new projects.

Recommended for new projects: sentry, prom-client, elastic-apm-node

Evaluate carefully: loggly, opentracing

Commercial solutions: datadog-metrics, newrelic, raygun (require paid subscriptions for full features)

šŸ”§ Integration Complexity Comparison

Lowest Setup Effort — newrelic, sentry

  • Drop in the package
  • Add API key
  • Start receiving data
// newrelic: Minimal setup
require('newrelic'); // That's it for basic tracking

// sentry: Simple initialization
Sentry.init({ dsn: 'your-dsn' });

Medium Setup Effort — datadog-metrics, elastic-apm-node, raygun

  • Need infrastructure configuration
  • Some manual instrumentation for custom metrics
// datadog-metrics: Configure connection
metrics.init({
  host: 'statsd-host',
  prefix: 'myapp.'
});

Highest Setup Effort — prom-client, opentracing

  • Need to run your own infrastructure (Prometheus, Jaeger, etc.)
  • More configuration but more control
// prom-client: Full control over metrics
const register = new client.Registry();
// Define each metric manually
// Set up scraping endpoint
// Configure Prometheus server separately

šŸ’° Cost Considerations

Open Source / Self-Hosted — prom-client, opentracing

  • No licensing costs
  • You pay for infrastructure and maintenance

Freemium — sentry, raygun

  • Free tiers available
  • Paid plans for higher volume or advanced features

Commercial — datadog-metrics, newrelic, elastic-apm-node (with Elastic Cloud)

  • Typically require paid subscriptions for production use
  • elastic-apm-node can be self-hosted with Elastic Stack

Uncertain — loggly

  • Pricing and maintenance status should be verified before commitment

šŸ“‹ Feature Comparison Matrix

PackageAuto-InstrumentCustom MetricsError TrackingLog AggregationDistributed TracingFrontend Support
datadog-metricsāŒāœ…āŒāŒāŒVia separate SDK
elastic-apm-nodeāœ…āœ…āœ…āŒāœ…Via @elastic/apm-rum
logglyāŒāŒāŒāœ…āŒVia separate SDK
newrelicāœ…āœ…āœ…āœ…āœ…Via newrelic-browser
opentracingāŒāŒāŒāŒāœ…Via separate SDK
prom-clientāŒāœ…āŒāŒāŒVia separate SDK
raygunāŒāŒāœ…āŒāŒVia raygun4js
sentryāœ…āœ…āœ…āŒāœ…Via @sentry/browser

šŸŽÆ Real-World Selection Scenarios

Scenario 1: Startup with Limited Budget

Best choice: sentry + prom-client

  • Sentry's free tier covers error tracking
  • prom-client gives you metrics without vendor lock-in
  • Total cost: $0 for infrastructure you manage yourself
// Combined setup
import * as Sentry from '@sentry/node';
const client = require('prom-client');

Sentry.init({ dsn: process.env.SENTRY_DSN });

const httpRequestDuration = new client.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Duration of HTTP requests'
});

Scenario 2: Enterprise with Existing Datadog Investment

Best choice: datadog-metrics + sentry

  • Leverage existing Datadog dashboards
  • Sentry for detailed error tracking (better DX than Datadog Errors)
// datadog-metrics: Send business metrics
metrics.gauge('checkout.completed', 1, ['environment:production']);

// sentry: Track errors separately
Sentry.captureException(error);

Scenario 3: Full Elastic Stack Shop

Best choice: elastic-apm-node + loggly (or Elastic logs)

  • Unified observability across logs, metrics, and traces
  • Single platform for all monitoring data
// elastic-apm-node: Full APM
const apm = require('elastic-apm-node').start({
  serviceName: 'my-service',
  captureBody: 'all'
});

Scenario 4: Maximum Control, Self-Hosted Everything

Best choice: prom-client + opentelemetry (not opentracing)

  • Complete ownership of monitoring infrastructure
  • No vendor dependencies
// prom-client + OpenTelemetry
const client = require('prom-client');
const api = require('@opentelemetry/api');

// Metrics via Prometheus
// Tracing via OpenTelemetry

🚫 Common Mistakes to Avoid

Mistake 1: Using backend packages for frontend monitoring

// WRONG: This is Node.js only
const apm = require('elastic-apm-node'); // Won't work in browser

// RIGHT: Use browser SDK
import { init } from '@elastic/apm-rum';
init({ serviceName: 'my-app' });

Mistake 2: Choosing OpenTracing for new projects

// WRONG: OpenTracing is in maintenance
const opentracing = require('opentracing');

// RIGHT: Use OpenTelemetry
const api = require('@opentelemetry/api');

Mistake 3: Not sampling in high-traffic apps

// WRONG: Send every transaction
Sentry.init({ dsn: '...', tracesSampleRate: 1.0 });

// RIGHT: Sample appropriately
Sentry.init({ 
  dsn: '...', 
  tracesSampleRate: 0.1 // 10% of transactions
});

šŸ’” Final Recommendations

For most teams starting fresh: sentry provides the best balance of features, ease of use, and cost. Add prom-client if you need custom metrics.

For enterprises with budget: newrelic or datadog-metrics offer comprehensive platforms with less operational overhead.

For self-hosted enthusiasts: prom-client + OpenTelemetry gives maximum control without vendor lock-in.

Avoid for new projects: opentracing (use OpenTelemetry instead), loggly (verify current maintenance status first).

Remember: These are primarily backend tools. For complete observability, pair them with their frontend counterparts to get full-stack visibility.

How to Choose: prom-client vs opentracing vs datadog-metrics vs newrelic vs elastic-apm-node vs loggly vs sentry vs raygun

  • prom-client:

    Choose prom-client if you're using Prometheus for metrics collection and want open-source, self-hosted monitoring. It's lightweight and gives you full control over metric definitions. Best for teams comfortable managing their own Prometheus infrastructure and Grafana dashboards.

  • opentracing:

    Choose opentracing if you need vendor-neutral distributed tracing and want to avoid lock-in. However, note that OpenTelemetry has largely superseded OpenTracing — consider @opentelemetry/api for new projects instead. Only use if you have existing OpenTracing infrastructure.

  • datadog-metrics:

    Choose datadog-metrics if your team already uses Datadog for infrastructure monitoring and you need tight integration with their ecosystem. It works best for backend metrics collection in Node.js services. Not suitable for browser-side monitoring — use @datadog/browser-sdk instead for frontend applications.

  • newrelic:

    Choose newrelic if you want comprehensive APM with minimal configuration and your budget allows for a commercial solution. It offers automatic instrumentation and strong Node.js support. Best for teams that prefer managed services over self-hosted monitoring infrastructure.

  • elastic-apm-node:

    Choose elastic-apm-node if you're running the Elastic Stack (Elasticsearch, Logstash, Kibana) and want unified observability across your infrastructure. It provides automatic instrumentation for many Node.js frameworks. For frontend monitoring, pair it with @elastic/apm-rum for complete distributed tracing.

  • loggly:

    Choose loggly if you need centralized log aggregation with search capabilities and your team prefers a dedicated logging service. Note that Loggly has shifted focus over time — evaluate current maintenance status before committing. Consider alternatives like Winston + cloud storage for more control.

  • sentry:

    Choose sentry if you want the most comprehensive error tracking with strong frontend support, performance monitoring, and release tracking. It has excellent JavaScript/TypeScript integration and active maintenance. Best for teams that prioritize developer experience and want both error and performance monitoring in one platform.

  • raygun:

    Choose raygun if you need straightforward error tracking with good JavaScript support and prefer a simpler pricing model than competitors. It offers both frontend and backend monitoring. Consider if you need less complexity than Sentry but more features than basic logging.

README for prom-client

Prometheus client for node.js Actions Status

A prometheus client for Node.js that supports histogram, summaries, gauges and counters.

Usage

See example folder for a sample usage. The library does not bundle any web framework. To expose the metrics, respond to Prometheus's scrape requests with the result of await registry.metrics().

Usage with Node.js's cluster module

Node.js's cluster module spawns multiple processes and hands off socket connections to those workers. Returning metrics from a worker's local registry will only reveal that individual worker's metrics, which is generally undesirable. To solve this, you can aggregate all of the workers' metrics in the master process. See example/cluster.js for an example.

Default metrics use sensible aggregation methods. (Note, however, that the event loop lag mean and percentiles are averaged, which is not perfectly accurate.) Custom metrics are summed across workers by default. To use a different aggregation method, set the aggregator property in the metric config to one of 'sum', 'first', 'min', 'max', 'average' or 'omit'. (See lib/metrics/version.js for an example.)

If you need to expose metrics about an individual worker, you can include a value that is unique to the worker (such as the worker ID or process ID) in a label. (See example/server.js for an example using worker_${cluster.worker.id} as a label value.)

Metrics are aggregated from the global registry by default. To use a different registry, call client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries) from the worker processes.

API

Default metrics

There are some default metrics recommended by Prometheus itself. To collect these, call collectDefaultMetrics. In addition, some Node.js-specific metrics are included, such as event loop lag, active handles, GC and Node.js version. See lib/metrics for a list of all metrics.

NOTE: Some of the metrics, concerning File Descriptors and Memory, are only available on Linux.

collectDefaultMetrics optionally accepts a config object with following entries:

  • prefix an optional prefix for metric names. Default: no prefix.
  • register to which registry the metrics should be registered. Default: the global default registry.
  • gcDurationBuckets with custom buckets for GC duration histogram. Default buckets of GC duration histogram are [0.001, 0.01, 0.1, 1, 2, 5] (in seconds).
  • eventLoopMonitoringPrecision with sampling rate in milliseconds. Must be greater than zero. Default: 10.

To register metrics to another registry, pass it in as register:

const client = require('prom-client');
const collectDefaultMetrics = client.collectDefaultMetrics;
const Registry = client.Registry;
const register = new Registry();
collectDefaultMetrics({ register });

To use custom buckets for GC duration histogram, pass it in as gcDurationBuckets:

const client = require('prom-client');
const collectDefaultMetrics = client.collectDefaultMetrics;
collectDefaultMetrics({ gcDurationBuckets: [0.1, 0.2, 0.3] });

To prefix metric names with your own arbitrary string, pass in a prefix:

const client = require('prom-client');
const collectDefaultMetrics = client.collectDefaultMetrics;
const prefix = 'my_application_';
collectDefaultMetrics({ prefix });

To apply generic labels to all default metrics, pass an object to the labels property (useful if you're working in a clustered environment):

const client = require('prom-client');
const collectDefaultMetrics = client.collectDefaultMetrics;
collectDefaultMetrics({
  labels: { NODE_APP_INSTANCE: process.env.NODE_APP_INSTANCE },
});

You can get the full list of metrics by inspecting client.collectDefaultMetrics.metricsList.

Default metrics are collected on scrape of metrics endpoint, not on an interval.

const client = require('prom-client');

const collectDefaultMetrics = client.collectDefaultMetrics;

collectDefaultMetrics();

Custom Metrics

All metric types have two mandatory parameters: name and help. Refer to https://prometheus.io/docs/practices/naming/ for guidance on naming metrics.

For metrics based on point-in-time observations (e.g. current memory usage, as opposed to HTTP request durations observed continuously in a histogram), you should provide a collect() function, which will be invoked when Prometheus scrapes your metrics endpoint. collect() can either be synchronous or return a promise. See Gauge below for an example. (Note that you should not update metric values in a setInterval callback; do so in this collect function instead.)

See Labels for information on how to configure labels for all metric types.

Counter

Counters go up, and reset when the process restarts.

const client = require('prom-client');
const counter = new client.Counter({
  name: 'metric_name',
  help: 'metric_help',
});
counter.inc(); // Increment by 1
counter.inc(10); // Increment by 10

Gauge

Gauges are similar to Counters but a Gauge's value can be decreased.

const client = require('prom-client');
const gauge = new client.Gauge({ name: 'metric_name', help: 'metric_help' });
gauge.set(10); // Set to 10
gauge.inc(); // Increment 1
gauge.inc(10); // Increment 10
gauge.dec(); // Decrement by 1
gauge.dec(10); // Decrement by 10
Configuration

If the gauge is used for a point-in-time observation, you should provide a collect function:

const client = require('prom-client');
new client.Gauge({
  name: 'metric_name',
  help: 'metric_help',
  collect() {
    // Invoked when the registry collects its metrics' values.
    // This can be synchronous or it can return a promise/be an async function.
    this.set(/* the current value */);
  },
});
// Async version:
const client = require('prom-client');
new client.Gauge({
  name: 'metric_name',
  help: 'metric_help',
  async collect() {
    // Invoked when the registry collects its metrics' values.
    const currentValue = await somethingAsync();
    this.set(currentValue);
  },
});

Note that you should not use arrow functions for collect because arrow functions will not have the correct value for this.

Utility Functions
// Set value to current time in seconds:
gauge.setToCurrentTime();

// Record durations:
const end = gauge.startTimer();
http.get('url', res => {
  end();
});

Histogram

Histograms track sizes and frequency of events.

Configuration

The defaults buckets are intended to cover usual web/RPC requests, but they can be overridden. (See also Bucket Generators.)

const client = require('prom-client');
new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  buckets: [0.1, 5, 15, 50, 100, 500],
});
Examples
const client = require('prom-client');
const histogram = new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
});
histogram.observe(10); // Observe value in histogram
Utility Methods
const end = histogram.startTimer();
xhrRequest(function (err, res) {
  const seconds = end(); // Observes and returns the value to xhrRequests duration in seconds
});

Summary

Summaries calculate percentiles of observed values.

Configuration

The default percentiles are: 0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999. But they can be overridden by specifying a percentiles array. (See also Bucket Generators.)

const client = require('prom-client');
new client.Summary({
  name: 'metric_name',
  help: 'metric_help',
  percentiles: [0.01, 0.1, 0.9, 0.99],
});

To enable the sliding window functionality for summaries you need to add maxAgeSeconds and ageBuckets to the config like this:

const client = require('prom-client');
new client.Summary({
  name: 'metric_name',
  help: 'metric_help',
  maxAgeSeconds: 600,
  ageBuckets: 5,
  pruneAgedBuckets: false,
});

The maxAgeSeconds will tell how old a bucket can be before it is reset and ageBuckets configures how many buckets we will have in our sliding window for the summary. If pruneAgedBuckets is false (default), the metric value will always be present, even when empty (its percentile values will be 0). Set pruneAgedBuckets to true if you don't want to export it when it is empty.

Examples
const client = require('prom-client');
const summary = new client.Summary({
  name: 'metric_name',
  help: 'metric_help',
});
summary.observe(10);
Utility Methods
const end = summary.startTimer();
xhrRequest(function (err, res) {
  end(); // Observes the value to xhrRequests duration in seconds
});

Labels

All metrics can take a labelNames property in the configuration object. All label names that the metric support needs to be declared here. There are two ways to add values to the labels:

const client = require('prom-client');
const gauge = new client.Gauge({
  name: 'metric_name',
  help: 'metric_help',
  labelNames: ['method', 'statusCode'],
});

// 1st version: Set value to 100 with "method" set to "GET" and "statusCode" to "200"
gauge.set({ method: 'GET', statusCode: '200' }, 100);
// 2nd version: Same effect as above
gauge.labels({ method: 'GET', statusCode: '200' }).set(100);
// 3rd version: And again the same effect as above
gauge.labels('GET', '200').set(100);

It is also possible to use timers with labels, both before and after the timer is created:

const end = startTimer({ method: 'GET' }); // Set method to GET, we don't know statusCode yet
xhrRequest(function (err, res) {
  if (err) {
    end({ statusCode: '500' }); // Sets value to xhrRequest duration in seconds with statusCode 500
  } else {
    end({ statusCode: '200' }); // Sets value to xhrRequest duration in seconds with statusCode 200
  }
});

Zeroing metrics with Labels

Metrics with labels can not be exported before they have been observed at least once since the possible label values are not known before they're observed.

For histograms, this can be solved by explicitly zeroing all expected label values:

const histogram = new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  buckets: [0.1, 5, 15, 50, 100, 500],
  labels: ['method'],
});
histogram.zero({ method: 'GET' });
histogram.zero({ method: 'POST' });

Strongly typed Labels

Typescript can also enforce label names using as const

import * as client from 'prom-client';

const counter = new client.Counter({
  name: 'metric_name',
  help: 'metric_help',
  // add `as const` here to enforce label names
  labelNames: ['method'] as const,
});

// Ok
counter.inc({ method: 1 });

// this is an error since `'methods'` is not a valid `labelName`
// @ts-expect-error
counter.inc({ methods: 1 });

Default Labels (segmented by registry)

Static labels may be applied to every metric emitted by a registry:

const client = require('prom-client');
const defaultLabels = { serviceName: 'api-v1' };
client.register.setDefaultLabels(defaultLabels);

This will output metrics in the following way:

# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes{serviceName="api-v1"} 33853440 1498510040309

Default labels will be overridden if there is a name conflict.

register.clear() will clear default labels.

Exemplars

The exemplars defined in the OpenMetrics specification can be enabled on Counter and Histogram metric types. The default metrics have support for OpenTelemetry, they will populate the exemplars with the labels {traceId, spanId} and their corresponding values.

The format for inc() and observe() calls are different if exemplars are enabled. They get a single object with the format {labels, value, exemplarLabels}.

When using exemplars, the registry used for metrics should be set to OpenMetrics type (including the global or default registry if no registries are specified).

Registry type

The library supports both the old Prometheus format and the OpenMetrics format. The format can be set per registry. For default metrics:

const Prometheus = require('prom-client');
Prometheus.register.setContentType(
  Prometheus.Registry.OPENMETRICS_CONTENT_TYPE,
);

Currently available registry types are defined by the content types:

PROMETHEUS_CONTENT_TYPE - version 0.0.4 of the original Prometheus metrics, this is currently the default registry type.

OPENMETRICS_CONTENT_TYPE - defaults to version 1.0.0 of the OpenMetrics standard.

The HTTP Content-Type string for each registry type is exposed both at module level (prometheusContentType and openMetricsContentType) and as static properties on the Registry object.

The contentType constant exposed by the module returns the default content type when creating a new registry, currently defaults to Prometheus type.

Multiple registries

By default, metrics are automatically registered to the global registry (located at require('prom-client').register). You can prevent this by specifying registers: [] in the metric constructor configuration.

Using non-global registries requires creating a Registry instance and passing it inside registers in the metric configuration object. Alternatively you can pass an empty registers array and register it manually.

Registry has a merge function that enables you to expose multiple registries on the same endpoint. If the same metric name exists in both registries, an error will be thrown.

Merging registries of different types is undefined. The user needs to make sure all used registries have the same type (Prometheus or OpenMetrics versions).

const client = require('prom-client');
const registry = new client.Registry();
const counter = new client.Counter({
  name: 'metric_name',
  help: 'metric_help',
  registers: [registry], // specify a non-default registry
});
const histogram = new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  registers: [], // don't automatically register this metric
});
registry.registerMetric(histogram); // register metric manually
counter.inc();

const mergedRegistries = client.Registry.merge([registry, client.register]);

If you want to use multiple or non-default registries with the Node.js cluster module, you will need to set the registry/registries to aggregate from:

const AggregatorRegistry = client.AggregatorRegistry;
AggregatorRegistry.setRegistries(registry);
// or for multiple registries:
AggregatorRegistry.setRegistries([registry1, registry2]);

Register

You can get all metrics by running await register.metrics(), which will return a string in the Prometheus exposition format.

Getting a single metric value in Prometheus exposition format

If you need to output a single metric in the Prometheus exposition format, you can use await register.getSingleMetricAsString(*name of metric*), which will return a string for Prometheus to consume.

Getting a single metric

If you need to get a reference to a previously registered metric, you can use register.getSingleMetric(*name of metric*).

Removing metrics

You can remove all metrics by calling register.clear(). You can also remove a single metric by calling register.removeSingleMetric(*name of metric*).

Resetting metrics

If you need to reset all metrics, you can use register.resetMetrics(). The metrics will remain present in the register and can be used without the need to instantiate them again, like you would need to do after register.clear().

Cluster metrics

You can get aggregated metrics for all workers in a Node.js cluster with await register.clusterMetrics(). This method returns a promise that resolves with a metrics string suitable for Prometheus to consume.

const metrics = await register.clusterMetrics();

// - or -

register
  .clusterMetrics()
  .then(metrics => {
    /* ... */
  })
  .catch(err => {
    /* ... */
  });

Pushgateway

It is possible to push metrics via a Pushgateway.

const client = require('prom-client');
let gateway = new client.Pushgateway('http://127.0.0.1:9091');

gateway.pushAdd({ jobName: 'test' })
	.then(({resp, body}) => {
		/* ... */
	})
	.catch(err => {
		/* ... */
	})); //Add metric and overwrite old ones
gateway.push({ jobName: 'test' })
	.then(({resp, body}) => {
		/* ... */
	})
	.catch(err => {
		/* ... */
	})); //Overwrite all metrics (use PUT)
gateway.delete({ jobName: 'test' })
	.then(({resp, body}) => {
		/* ... */
	})
	.catch(err => {
		/* ... */
	})); //Delete all metrics for jobName

//All gateway requests can have groupings on it
gateway.pushAdd({ jobName: 'test', groupings: { key: 'value' } })
	.then(({resp, body}) => {
		/* ... */
	})
	.catch(err => {
		/* ... */
	}));

// It's possible to extend the Pushgateway with request options from nodes core
// http/https library. In particular, you might want to provide an agent so that
// TCP connections are reused.
gateway = new client.Pushgateway('http://127.0.0.1:9091', {
  timeout: 5000, //Set the request timeout to 5000ms
  agent: new http.Agent({
    keepAlive: true,
    keepAliveMsec: 10000,
    maxSockets: 5,
  }),
});

Some gateways such as Gravel Gateway do not support grouping by job name, exposing a plain /metrics endpoint instead of /metrics/job/<jobName>. It's possible to configure a gateway instance to not require a jobName in the options argument.

gravelGateway = new client.Pushgateway('http://127.0.0.1:9091', {
  timeout: 5000,
  requireJobName: false,
});
gravelGateway.pushAdd();

Bucket Generators

For convenience, there are two bucket generator functions - linear and exponential.

const client = require('prom-client');
new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  buckets: client.linearBuckets(0, 10, 20), //Create 20 buckets, starting on 0 and a width of 10
});

new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  buckets: client.exponentialBuckets(1, 2, 5), //Create 5 buckets, starting on 1 and with a factor of 2
});

Garbage Collection Metrics

To avoid native dependencies in this module, GC statistics for bytes reclaimed in each GC sweep are kept in a separate module: https://github.com/SimenB/node-prometheus-gc-stats. (Note that that metric may no longer be accurate now that v8 uses parallel garbage collection.)