Ein Prometheus-Client für Node.js, der Histogramme, Zusammenfassungen, Messgeräte und Zähler unterstützt.
Eine Beispielverwendung finden Sie im Beispielordner. Die Bibliothek bündelt kein Web-Framework. Um die Metriken verfügbar zu machen, antworten Sie auf die Scrape-Anfragen von Prometheus mit dem Ergebnis von await registry.metrics()
.
cluster
von Node.js Das cluster
von Node.js erzeugt mehrere Prozesse und übergibt Socket-Verbindungen an diese Worker. Durch die Rückgabe von Kennzahlen aus dem lokalen Register eines Arbeitnehmers werden nur die Kennzahlen dieses einzelnen Arbeitnehmers angezeigt, was im Allgemeinen unerwünscht ist. Um dieses Problem zu lösen, können Sie alle Arbeitsmetriken im Masterprozess aggregieren. Ein Beispiel finden Sie example/cluster.js
.
Standardmetriken verwenden sinnvolle Aggregationsmethoden. (Beachten Sie jedoch, dass der Mittelwert und die Perzentile der Ereignisschleifenverzögerung gemittelt werden, was nicht ganz genau ist.) Benutzerdefinierte Metriken werden standardmäßig über alle Worker hinweg summiert. Um eine andere Aggregationsmethode zu verwenden, legen Sie die aggregator
Eigenschaft in der Metrikkonfiguration auf „sum“, „first“, „min“, „max“, „average“ oder „omit“ fest. (Ein Beispiel finden Sie unter lib/metrics/version.js
.)
Wenn Sie Metriken zu einem einzelnen Worker offenlegen müssen, können Sie einen für den Worker eindeutigen Wert (z. B. die Worker-ID oder die Prozess-ID) in eine Bezeichnung aufnehmen. (Siehe example/server.js
für ein Beispiel mit worker_${cluster.worker.id}
als Labelwert.)
Metriken werden standardmäßig aus der globalen Registrierung aggregiert. Um eine andere Registrierung zu verwenden, rufen Sie client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries)
aus den Arbeitsprozessen auf.
Es gibt einige von Prometheus selbst empfohlene Standardmetriken. Um diese zu sammeln, rufen Sie collectDefaultMetrics
auf. Darüber hinaus sind einige Node.js-spezifische Metriken enthalten, z. B. Ereignisschleifenverzögerung, aktive Handles, GC und Node.js-Version. Eine Liste aller Metriken finden Sie unter lib/metrics.
HINWEIS: Einige der Metriken bezüglich Dateideskriptoren und Speicher sind nur unter Linux verfügbar.
collectDefaultMetrics
akzeptiert optional ein Konfigurationsobjekt mit folgenden Einträgen:
prefix
ein optionales Präfix für Metriknamen. Standard: kein Präfix.register
, in welcher Registry die Metriken registriert werden sollen. Standard: die globale Standardregistrierung.gcDurationBuckets
mit benutzerdefinierten Buckets für das Histogramm der GC-Dauer. Die Standardbereiche des GC-Dauerhistogramms sind [0.001, 0.01, 0.1, 1, 2, 5]
(in Sekunden).eventLoopMonitoringPrecision
mit Abtastrate in Millisekunden. Muss größer als Null sein. Standard: 10. Um Metriken in einer anderen Registry zu registrieren, übergeben Sie sie als register
:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
const Registry = client . Registry ;
const register = new Registry ( ) ;
collectDefaultMetrics ( { register } ) ;
Um benutzerdefinierte Buckets für das GC-Dauerhistogramm zu verwenden, übergeben Sie es als gcDurationBuckets
:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( { gcDurationBuckets : [ 0.1 , 0.2 , 0.3 ] } ) ;
Um Metriknamen Ihre eigene beliebige Zeichenfolge voranzustellen, übergeben Sie ein prefix
:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
const prefix = 'my_application_' ;
collectDefaultMetrics ( { prefix } ) ;
Um generische Labels auf alle Standardmetriken anzuwenden, übergeben Sie ein Objekt an die labels
Eigenschaft (nützlich, wenn Sie in einer Clusterumgebung arbeiten):
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( {
labels : { NODE_APP_INSTANCE : process . env . NODE_APP_INSTANCE } ,
} ) ;
Sie können die vollständige Liste der Metriken erhalten, indem Sie client.collectDefaultMetrics.metricsList
überprüfen.
Standardmetriken werden auf dem Scrape-of-Metrics-Endpunkt erfasst, nicht in einem Intervall.
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( ) ;
Alle Metriktypen verfügen über zwei obligatorische Parameter: name
und help
. Hinweise zur Benennung von Metriken finden Sie unter https://prometheus.io/docs/practices/naming/.
Für Metriken, die auf punktuellen Beobachtungen basieren (z. B. aktuelle Speichernutzung, im Gegensatz zu kontinuierlich in einem Histogramm beobachteten HTTP-Anforderungsdauern), sollten Sie eine Funktion collect()
bereitstellen, die aufgerufen wird, wenn Prometheus Ihren Metrikendpunkt durchsucht. collect()
kann entweder synchron sein oder ein Versprechen zurückgeben. Ein Beispiel finden Sie unter Messgerät unten. (Beachten Sie, dass Sie Metrikwerte nicht in einem setInterval
-Rückruf aktualisieren sollten; tun Sie dies stattdessen in dieser collect
.)
Informationen zum Konfigurieren von Labels für alle Metriktypen finden Sie unter Labels .
Die Zähler steigen und werden zurückgesetzt, wenn der Prozess neu startet.
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
Messgeräte ähneln Zählern, der Wert eines Messgeräts kann jedoch verringert werden.
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
Wenn das Messgerät für eine punktuelle Beobachtung verwendet wird, sollten Sie eine collect
bereitstellen:
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 ) ;
} ,
} ) ;
Beachten Sie, dass Sie zum collect
keine Pfeilfunktionen verwenden sollten, da die Pfeilfunktionen this
nicht den richtigen Wert haben.
// Set value to current time in seconds:
gauge . setToCurrentTime ( ) ;
// Record durations:
const end = gauge . startTimer ( ) ;
http . get ( 'url' , res => {
end ( ) ;
} ) ;
Histogramme verfolgen die Größe und Häufigkeit von Ereignissen.
Die Standard-Buckets sollen normale Web-/RPC-Anfragen abdecken, können aber überschrieben werden. (Siehe auch Eimergeneratoren .)
const client = require ( 'prom-client' ) ;
new client . Histogram ( {
name : 'metric_name' ,
help : 'metric_help' ,
buckets : [ 0.1 , 5 , 15 , 50 , 100 , 500 ] ,
} ) ;
const client = require ( 'prom-client' ) ;
const histogram = new client . Histogram ( {
name : 'metric_name' ,
help : 'metric_help' ,
} ) ;
histogram . observe ( 10 ) ; // Observe value in histogram
const end = histogram . startTimer ( ) ;
xhrRequest ( function ( err , res ) {
const seconds = end ( ) ; // Observes and returns the value to xhrRequests duration in seconds
} ) ;
Zusammenfassungen berechnen Perzentile der beobachteten Werte.
Die Standardperzentile sind: 0,01, 0,05, 0,5, 0,9, 0,95, 0,99, 0,999. Sie können jedoch durch Angabe eines percentiles
Arrays überschrieben werden. (Siehe auch Eimergeneratoren .)
const client = require ( 'prom-client' ) ;
new client . Summary ( {
name : 'metric_name' ,
help : 'metric_help' ,
percentiles : [ 0.01 , 0.1 , 0.9 , 0.99 ] ,
} ) ;
Um die Schiebefensterfunktion für Zusammenfassungen zu aktivieren, müssen Sie maxAgeSeconds
und ageBuckets
wie folgt zur Konfiguration hinzufügen:
const client = require ( 'prom-client' ) ;
new client . Summary ( {
name : 'metric_name' ,
help : 'metric_help' ,
maxAgeSeconds : 600 ,
ageBuckets : 5 ,
pruneAgedBuckets : false ,
} ) ;
maxAgeSeconds
gibt an, wie alt ein Bucket sein kann, bevor er zurückgesetzt wird, und ageBuckets
konfiguriert, wie viele Buckets wir in unserem Schiebefenster für die Zusammenfassung haben werden. Wenn pruneAgedBuckets
false
(Standard) ist, ist der Metrikwert immer vorhanden, auch wenn er leer ist (seine Perzentilwerte sind 0
). Setzen Sie pruneAgedBuckets
auf true
, wenn Sie es nicht exportieren möchten, wenn es leer ist.
const client = require ( 'prom-client' ) ;
const summary = new client . Summary ( {
name : 'metric_name' ,
help : 'metric_help' ,
} ) ;
summary . observe ( 10 ) ;
const end = summary . startTimer ( ) ;
xhrRequest ( function ( err , res ) {
end ( ) ; // Observes the value to xhrRequests duration in seconds
} ) ;
Alle Metriken können eine labelNames
Eigenschaft im Konfigurationsobjekt annehmen. Alle Labelnamen, die die Metrik unterstützen muss, müssen hier deklariert werden. Es gibt zwei Möglichkeiten, den Beschriftungen Werte hinzuzufügen:
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 ) ;
Es ist auch möglich, Timer mit Labels zu verwenden, sowohl vor als auch nach der Erstellung des Timers:
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
}
} ) ;
Metriken mit Labels können nicht exportiert werden, bevor sie mindestens einmal beobachtet wurden, da die möglichen Labelwerte vor der Beobachtung nicht bekannt sind.
Bei Histogrammen kann dies gelöst werden, indem alle erwarteten Beschriftungswerte explizit auf Null gesetzt werden:
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' } ) ;
Typescript kann auch Label-Namen mit as const
erzwingen
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 } ) ;
Statische Labels können auf jede von einer Registrierung ausgegebene Metrik angewendet werden:
const client = require ( 'prom-client' ) ;
const defaultLabels = { serviceName : 'api-v1' } ;
client . register . setDefaultLabels ( defaultLabels ) ;
Dadurch werden Metriken wie folgt ausgegeben:
# 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
Bei einem Namenskonflikt werden die Standardbezeichnungen überschrieben.
register.clear()
löscht Standardbeschriftungen.
Die in der OpenMetrics-Spezifikation definierten Exemplare können für die Metriktypen „Zähler“ und „Histogramm“ aktiviert werden. Die Standardmetriken unterstützen OpenTelemetry. Sie füllen die Exemplare mit den Bezeichnungen {traceId, spanId}
und ihren entsprechenden Werten.
Das Format für inc()
und observe()
Aufrufe unterscheidet sich, wenn Exemplare aktiviert sind. Sie erhalten ein einzelnes Objekt mit dem Format {labels, value, exemplarLabels}
.
Bei der Verwendung von Exemplaren sollte die für Metriken verwendete Registrierung auf den OpenMetrics-Typ eingestellt sein (einschließlich der globalen oder Standardregistrierung, wenn keine Registrierungen angegeben sind).
Die Bibliothek unterstützt sowohl das alte Prometheus-Format als auch das OpenMetrics-Format. Das Format kann pro Registry eingestellt werden. Für Standardmetriken:
const Prometheus = require ( 'prom-client' ) ;
Prometheus . register . setContentType (
Prometheus . Registry . OPENMETRICS_CONTENT_TYPE ,
) ;
Derzeit verfügbare Registrierungstypen werden durch die Inhaltstypen definiert:
PROMETHEUS_CONTENT_TYPE – Version 0.0.4 der ursprünglichen Prometheus-Metriken, dies ist derzeit der Standard-Registrierungstyp.
OPENMETRICS_CONTENT_TYPE – standardmäßig Version 1.0.0 des OpenMetrics-Standards.
Die HTTP-Content-Type-Zeichenfolge für jeden Registrierungstyp wird sowohl auf Modulebene ( prometheusContentType
und openMetricsContentType
) als auch als statische Eigenschaften im Registry
verfügbar gemacht.
Die vom Modul bereitgestellte contentType
Konstante gibt beim Erstellen einer neuen Registrierung den Standardinhaltstyp zurück, derzeit ist der Standardtyp Prometheus.
Standardmäßig werden Metriken automatisch in der globalen Registrierung registriert (zu finden unter require('prom-client').register
). Sie können dies verhindern, indem Sie in der Konfiguration des Metrikkonstruktors registers: []
angeben.
Die Verwendung nicht-globaler Register erfordert das Erstellen einer Registrierungsinstanz und deren Übergabe innerhalb registers
im Metrikkonfigurationsobjekt. Alternativ können Sie ein leeres registers
übergeben und es manuell registrieren.
Registry verfügt über eine merge
, mit der Sie mehrere Registrys auf demselben Endpunkt verfügbar machen können. Wenn in beiden Registern derselbe Metrikname vorhanden ist, wird ein Fehler ausgegeben.
Das Zusammenführen von Registern verschiedener Typen ist nicht definiert. Der Benutzer muss sicherstellen, dass alle verwendeten Registrierungen denselben Typ haben (Prometheus- oder OpenMetrics-Versionen).
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 ] ) ;
Wenn Sie mehrere oder nicht standardmäßige Registrierungen mit dem Node.js- cluster
verwenden möchten, müssen Sie die Registrierung(en) so einstellen, dass sie aggregiert von:
const AggregatorRegistry = client . AggregatorRegistry ;
AggregatorRegistry . setRegistries ( registry ) ;
// or for multiple registries:
AggregatorRegistry . setRegistries ( [ registry1 , registry2 ] ) ;
Sie können alle Metriken abrufen, indem Sie await register.metrics()
ausführen, wodurch eine Zeichenfolge im Prometheus-Expositionsformat zurückgegeben wird.
Wenn Sie eine einzelne Metrik im Prometheus-Expositionsformat ausgeben müssen, können Sie await register.getSingleMetricAsString(*name of metric*)
verwenden, wodurch eine Zeichenfolge zurückgegeben wird, die Prometheus verarbeiten kann.
Wenn Sie einen Verweis auf eine zuvor registrierte Metrik benötigen, können Sie register.getSingleMetric(*name of metric*)
verwenden.
Sie können alle Metriken entfernen, indem Sie register.clear()
aufrufen. Sie können auch eine einzelne Metrik entfernen, indem Sie register.removeSingleMetric(*name of metric*)
aufrufen.
Wenn Sie alle Metriken zurücksetzen müssen, können Sie register.resetMetrics()
verwenden. Die Metriken bleiben im Register vorhanden und können verwendet werden, ohne dass sie erneut instanziiert werden müssen, wie Sie es nach register.clear()
tun müssten.
Mit await register.clusterMetrics()
können Sie aggregierte Metriken für alle Worker in einem Node.js-Cluster abrufen. Diese Methode gibt ein Versprechen zurück, das mit einer Metrikzeichenfolge aufgelöst wird, die für Prometheus geeignet ist.
const metrics = await register . clusterMetrics ( ) ;
// - or -
register
. clusterMetrics ( )
. then ( metrics => {
/* ... */
} )
. catch ( err => {
/* ... */
} ) ;
Es ist möglich, Metriken über ein Pushgateway zu pushen.
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 => {
/* ... */
} ) )