prometheus-client_js

repository·main·Indexed 25 days ago

https://github.com/prometheus/client_js

A Prometheus client for Node.js supporting core metric types: counters, gauges, histograms, and summaries. It includes features for collecting default Node.js metrics, pushing to a Pushgateway, and aggregating metrics across Node.js cluster workers using AggregatorRegistry. The library allows for custom registries, label-based dimensions, and configurable bucket generation via linearBuckets and exponentialBuckets.

Tokens
6.6K
Snippets
6
Records
57
Agent score
83%

What's inside @prometheus/client

  1. Use metrics with Node.js's `cluster` module

    main

    When using the cluster module, metrics from individual workers are isolated. To provide a unified view, use ClusterRegistry to aggregate metrics in the primary process.

    Key requirements:

    1. Initialization: Instantiate ClusterRegistry before branching on cluster.isPrimary.
    2. IPC Listener: The ClusterRegistry constructor automatically installs the necessary IPC listeners in each process. If you only instantiate it in the primary process, workers will not be able to respond to aggregation requests, causing clusterMetrics() to time out.
    3. Aggregation Methods:
      • Custom metrics are summed across workers by default.
      • You can change the aggregation method by setting the aggregator property in the metric configuration to one of: 'sum', 'first', 'min', 'max', 'average', or 'omit'.
      • Note: Default metrics (like event loop lag) use sensible aggregation, but mean and percentiles are averaged, which may not be perfectly accurate.
    4. Worker-specific metrics: To track individual workers, include a unique identifier (like cluster.worker.id or the process ID) as a label.
    5. Registry Configuration: Metrics are aggregated from the global registry by default. To use different registries, call client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries) from the worker processes.
  2. Collect default Node.js metrics

    main

    To collect standard Prometheus and Node.js-specific metrics (like event loop lag, active handles, GC, and Node.js version), call collectDefaultMetrics(). These metrics are collected during a scrape, not on an interval.

    You can pass a configuration object to customize the collection:

    • prefix: String prefix for metric names.
    • register: The registry to register metrics to (defaults to the global default registry).
    • gcDurationBuckets: Custom buckets for GC duration histogram.
    • eventLoopMonitoringPrecision: Sampling rate in ms (default: 10).
    • eventLoopUtilizationTimeout: Interval in ms to calculate utilization (default: 100).
    • eventLoopUtilizationBuckets: Custom buckets for event loop utilization histogram.
    • eventLoopUtilizationPercentiles: Custom percentiles for event loop utilization summary.
    • eventLoopUtilizationMaxAgeSeconds: Summary sliding window time in seconds (default: 60).
    • eventLoopUtilizationAgeBuckets: Summary sliding window buckets (default: 5).
    • labels: Object containing generic labels to apply to all default metrics (useful for clustered environments).

    To see all available default metrics, inspect client.collectDefaultMetrics.metricsList.

    const client = require('@prometheus/client');
    const collectDefaultMetrics = client.collectDefaultMetrics;
    
    collectDefaultMetrics();
  3. Expose metrics to Prometheus

    main
    The library does not include a built-in web framework. To expose your metrics to a Prometheus scrape request, you must implement a web server (e.g., using Express, Fastify, or the native http module) and respond to the scrape request with the output of await registry.metrics().
  4. Aggregate metrics across Node.js cluster workers using AggregatorRegistry

    main

    When using Node.js's cluster module, standard registries only collect metrics for the local process. To collect and aggregate metrics from all workers into a single view, use the AggregatorRegistry class.

    In a cluster setup:

    1. The Primary (Master) process should instantiate AggregatorRegistry and call .clusterMetrics() to retrieve the combined metrics from all connected workers.
    2. The Workers automatically listen for requests from the primary process and respond with their local metrics.

    Note: The clusterMetrics() method has a default timeout of 5000ms.

  5. Create a Counter metric

    main

    Counters are cumulative metrics that only increase and reset to zero when the process restarts. They require a name and help string.

    const client = require('@prometheus/client');
    const counter = new client.Counter({
      name: 'metric_name',
      help: 'metric_help',
    });
    counter.inc(); // Increment by 1
    counter.inc(10); // Increment by 10
  6. Push metrics to a Pushgateway

    main

    Use the Pushgateway class to push metrics to a Prometheus Pushgateway.

    Methods:

    • pushAdd({ jobName: '...', groupings: { ... } }): Adds metrics and overwrites old ones for the job.
    • push({ jobName: '...' }): Overwrites all metrics for the job (uses PUT).
    • delete({ jobName: '...' }): Deletes all metrics for the job.

    Configuration:

    • jobName: Required unless requireJobName: false is set in options.
    • groupings: An object of additional labels for the push request.
    • timeout: Request timeout in ms.
    • agent: A Node.js HTTP/HTTPS agent (e.g., for keepAlive).
  7. Create a Summary metric

    main

    Summaries calculate percentiles of observed values.

    Configuration:

    • percentiles: An array of percentiles (defaults to [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999]).
    • maxAgeSeconds: Enables sliding window functionality by defining how old a bucket can be before being reset.
    • ageBuckets: Configures the number of buckets in the sliding window.
    • pruneAgedBuckets: If true, empty buckets are not exported. If false (default), they are exported with 0 values.

    Utility methods:

    • observe(value): Records a new observation.
    • startTimer(): Returns a function that, when called, returns the duration in seconds.
    const client = require('@prometheus/client');
    
    // Basic summary
    const summary = new client.Summary({ name: 'metric_name', help: 'metric_help' });
    summary.observe(10);
    
    // Summary with sliding window
    new client.Summary({
      name: 'metric_name',
      help: 'metric_help',
      maxAgeSeconds: 600,
      ageBuckets: 5,
      pruneAgedBuckets: false,
    });
  8. Create a Gauge metric

    main

    Gauges represent a single numerical value that can arbitrarily go up or down.

    Point-in-time observations: If the gauge represents a value that should be sampled at the moment of a scrape (e.g., current memory usage), provide a collect() function. This function can be synchronous or return a Promise. Do not use arrow functions for collect as they will not bind this correctly.

    Utility methods:

    • set(value): Set the gauge to a specific value.
    • inc(value): Increment the gauge.
    • dec(value): Decrement the gauge.
    • setToCurrentTime(): Set the value to the current time in seconds.
    • startTimer(): Returns a function that, when called, records the duration since the timer started.
    const client = require('@prometheus/client');
    
    // Standard usage
    const gauge = new client.Gauge({ name: 'metric_name', help: 'metric_help' });
    gauge.set(10);
    
    // Point-in-time observation using collect()
    new client.Gauge({
      name: 'metric_name',
      help: 'metric_help',
      collect() {
        this.set(/* the current value */);
      },
    });
    
    // Async version
    new client.Gauge({
      name: 'metric_name',
      help: 'metric_help',
      async collect() {
        const currentValue = await somethingAsync();
        this.set(currentValue);
      },
    });
  9. Create a Histogram metric

    main

    Histograms track the frequency of events within specified buckets.

    Configuration: You can provide custom buckets in the constructor. Use client.linearBuckets() or client.exponentialBuckets() to generate them.

    Utility methods:

    • observe(value): Records a new observation.
    • startTimer(): Returns a function that, when called, returns the duration of the observed event in seconds.
  10. Use Labels with metrics

    main

    Labels allow you to add dimensions to your metrics. All label names must be declared in the labelNames property during metric creation.

    Setting label values:

    1. metric.set({ label1: 'val1' }, value)
    2. metric.labels({ label1: 'val1' }).set(value)
    3. metric.labels('val1').set(value)

    Timers with labels: You can set labels when starting a timer, or when ending it.

    Zeroing metrics: Metrics with labels are not exported until they have been observed at least once. For Histograms, you can explicitly initialize expected label values using .zero({ labelName: 'value' }).

    const client = require('@prometheus/client');
    
    const gauge = new client.Gauge({
      name: 'metric_name',
      help: 'metric_help',
      labelNames: ['method', 'statusCode'],
    });
    
    // Ways to set values with labels
    gauge.set({ method: 'GET', statusCode: '200' }, 100);
    gauge.labels({ method: 'GET', statusCode: '200' }).set(100);
    gauge.labels('GET', '200').set(100);
    
    // Timers with labels
    const end = gauge.startTimer({ method: 'GET' });
    // ... later ...
    end({ statusCode: '200' });
    
    // Zeroing histogram labels to ensure they are exported
    const histogram = new client.Histogram({
      name: 'metric_name',
      help: 'metric_help',
      labelNames: ['method'],
    });
    histogram.zero({ method: 'GET' });
  11. Manage multiple Registries

    main

    By default, metrics are registered to the global registry (require('@prometheus/client').register).

    Custom Registries:

    • To use a custom registry, pass it in the registers array in the metric constructor.
    • To register a metric manually, use registry.registerMetric(metric).
    • To merge multiple registries into one, use client.Registry.merge([reg1, reg2]).

    Note: When merging, ensure all registries use the same type (Prometheus or OpenMetrics). Merging different types is undefined.

    Cluster Support: If using Node.js cluster module, use AggregatorRegistry to aggregate metrics from workers:

    const AggregatorRegistry = client.AggregatorRegistry;
    AggregatorRegistry.setRegistries([registry1, registry2]);
    const client = require('@prometheus/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
    
    const mergedRegistries = client.Registry.merge([registry, client.register]);
  12. Enable Exemplars in Histograms

    main

    Exemplars allow you to attach specific observations (like a Trace ID) to a histogram bucket. To use this feature, you must set enableExemplars: true in the Histogram configuration object.

    When enabled, the observe method accepts an object with exemplarLabels, and startTimer accepts an additional argument for exemplar labels.