Un cliente prometheus para Node.js que admite histogramas, resúmenes, indicadores y contadores.
Consulte la carpeta de ejemplo para ver un ejemplo de uso. La biblioteca no incluye ningún marco web. Para exponer las métricas, responda a las solicitudes de extracción de Prometheus con el resultado de await registry.metrics()
.
cluster
de Node.js El módulo cluster
de Node.js genera múltiples procesos y transfiere conexiones de socket a esos trabajadores. La devolución de métricas del registro local de un trabajador sólo revelará las métricas de ese trabajador individual, lo cual generalmente no es deseable. Para resolver esto, puede agregar todas las métricas de los trabajadores en el proceso maestro. Consulte example/cluster.js
para ver un ejemplo.
Las métricas predeterminadas utilizan métodos de agregación sensatos. (Tenga en cuenta, sin embargo, que la media del retraso del bucle de eventos y los percentiles se promedian, lo cual no es perfectamente exacto). Las métricas personalizadas se suman entre los trabajadores de forma predeterminada. Para utilizar un método de agregación diferente, establezca la propiedad aggregator
en la configuración de métrica en uno de "suma", "primero", "mínimo", "máximo", "promedio" u "omitir". (Consulte lib/metrics/version.js
para ver un ejemplo).
Si necesita exponer métricas sobre un trabajador individual, puede incluir un valor que sea exclusivo del trabajador (como el ID del trabajador o el ID del proceso) en una etiqueta. (Consulte example/server.js
para ver un ejemplo que utiliza worker_${cluster.worker.id}
como valor de etiqueta).
Las métricas se agregan desde el registro global de forma predeterminada. Para utilizar un registro diferente, llame client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries)
desde los procesos de trabajo.
Hay algunas métricas predeterminadas recomendadas por el propio Prometheus. Para recopilarlos, llame collectDefaultMetrics
. Además, se incluyen algunas métricas específicas de Node.js, como el retraso del bucle de eventos, identificadores activos, GC y la versión de Node.js. Consulte lib/metrics para obtener una lista de todas las métricas.
NOTA: Algunas de las métricas relacionadas con los descriptores de archivos y la memoria solo están disponibles en Linux.
collectDefaultMetrics
acepta opcionalmente un objeto de configuración con las siguientes entradas:
prefix
un prefijo opcional para nombres de métricas. Valor predeterminado: sin prefijo.register
en qué registro se deben registrar las métricas. Predeterminado: el registro predeterminado global.gcDurationBuckets
con depósitos personalizados para el histograma de duración de GC. Los depósitos predeterminados del histograma de duración de GC son [0.001, 0.01, 0.1, 1, 2, 5]
(en segundos).eventLoopMonitoringPrecision
con frecuencia de muestreo en milisegundos. Debe ser mayor que cero. Predeterminado: 10. Para registrar métricas en otro registro, páselo como register
:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
const Registry = client . Registry ;
const register = new Registry ( ) ;
collectDefaultMetrics ( { register } ) ;
Para usar depósitos personalizados para el histograma de duración de GC, páselo como gcDurationBuckets
:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( { gcDurationBuckets : [ 0.1 , 0.2 , 0.3 ] } ) ;
Para anteponer nombres de métricas con su propia cadena arbitraria, pase un prefix
:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
const prefix = 'my_application_' ;
collectDefaultMetrics ( { prefix } ) ;
Para aplicar etiquetas genéricas a todas las métricas predeterminadas, pase un objeto a la propiedad labels
(útil si trabaja en un entorno agrupado):
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( {
labels : { NODE_APP_INSTANCE : process . env . NODE_APP_INSTANCE } ,
} ) ;
Puede obtener la lista completa de métricas inspeccionando client.collectDefaultMetrics.metricsList
.
Las métricas predeterminadas se recopilan en el punto final de extracción de métricas, no en un intervalo.
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( ) ;
Todos los tipos de métricas tienen dos parámetros obligatorios: name
y help
. Consulte https://prometheus.io/docs/practices/naming/ para obtener orientación sobre cómo nombrar métricas.
Para las métricas basadas en observaciones de un momento dado (por ejemplo, el uso actual de la memoria, a diferencia de las duraciones de las solicitudes HTTP observadas continuamente en un histograma), debe proporcionar una función de collect()
, que se invocará cuando Prometheus extraiga el punto final de sus métricas. collect()
puede ser sincrónico o devolver una promesa. Consulte el indicador a continuación para ver un ejemplo. (Tenga en cuenta que no debe actualizar los valores de métricas en una devolución de llamada setInterval
; en su lugar, hágalo en esta función collect
).
Consulte Etiquetas para obtener información sobre cómo configurar etiquetas para todos los tipos de métricas.
Los contadores aumentan y se reinician cuando se reinicia el proceso.
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
Los indicadores son similares a los contadores, pero el valor de un indicador se puede disminuir.
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
Si el medidor se utiliza para una observación de un momento determinado, debe proporcionar una función collect
:
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 ) ;
} ,
} ) ;
Tenga en cuenta que no debe utilizar funciones de flecha para collect
porque las funciones de flecha no tendrán el valor correcto para this
.
// Set value to current time in seconds:
gauge . setToCurrentTime ( ) ;
// Record durations:
const end = gauge . startTimer ( ) ;
http . get ( 'url' , res => {
end ( ) ;
} ) ;
Los histogramas rastrean los tamaños y la frecuencia de los eventos.
Los depósitos predeterminados están destinados a cubrir las solicitudes web/RPC habituales, pero se pueden anular. (Ver también Generadores de cangilones ).
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
} ) ;
Los resúmenes calculan percentiles de los valores observados.
Los percentiles predeterminados son: 0,01, 0,05, 0,5, 0,9, 0,95, 0,99, 0,999. Pero se pueden anular especificando una matriz percentiles
. (Ver también Generadores de cangilones ).
const client = require ( 'prom-client' ) ;
new client . Summary ( {
name : 'metric_name' ,
help : 'metric_help' ,
percentiles : [ 0.01 , 0.1 , 0.9 , 0.99 ] ,
} ) ;
Para habilitar la funcionalidad de ventana deslizante para resúmenes, debe agregar maxAgeSeconds
y ageBuckets
a la configuración de esta manera:
const client = require ( 'prom-client' ) ;
new client . Summary ( {
name : 'metric_name' ,
help : 'metric_help' ,
maxAgeSeconds : 600 ,
ageBuckets : 5 ,
pruneAgedBuckets : false ,
} ) ;
maxAgeSeconds
indicará la antigüedad de un depósito antes de restablecerlo y ageBuckets
configura cuántos depósitos tendremos en nuestra ventana deslizante para el resumen. Si pruneAgedBuckets
es false
(predeterminado), el valor de la métrica siempre estará presente, incluso cuando esté vacío (sus valores percentiles serán 0
). Establezca pruneAgedBuckets
en true
si no desea exportarlo cuando esté vacío.
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
} ) ;
Todas las métricas pueden tomar una propiedad labelNames
en el objeto de configuración. Todos los nombres de etiquetas que la métrica admite deben declararse aquí. Hay dos formas de agregar valores a las etiquetas:
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 ) ;
También es posible utilizar temporizadores con etiquetas, tanto antes como después de crear el temporizador:
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
}
} ) ;
Las métricas con etiquetas no se pueden exportar antes de que se hayan observado al menos una vez, ya que los posibles valores de las etiquetas no se conocen antes de que se observen.
Para los histogramas, esto se puede resolver poniendo a cero explícitamente todos los valores de etiqueta esperados:
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' } ) ;
Typecript también puede imponer nombres de etiquetas usando 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 } ) ;
Se pueden aplicar etiquetas estáticas a cada métrica emitida por un registro:
const client = require ( 'prom-client' ) ;
const defaultLabels = { serviceName : 'api-v1' } ;
client . register . setDefaultLabels ( defaultLabels ) ;
Esto generará métricas de la siguiente manera:
# 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
Las etiquetas predeterminadas se anularán si hay un conflicto de nombres.
register.clear()
borrará las etiquetas predeterminadas.
Los ejemplos definidos en la especificación OpenMetrics se pueden habilitar en los tipos de métricas Contador e Histograma. Las métricas predeterminadas son compatibles con OpenTelemetry y completarán los ejemplos con las etiquetas {traceId, spanId}
y sus valores correspondientes.
El formato para las llamadas inc()
y observe()
es diferente si los ejemplos están habilitados. Obtienen un único objeto con el formato {labels, value, exemplarLabels}
.
Cuando se utilizan ejemplos, el registro utilizado para las métricas debe establecerse en el tipo OpenMetrics (incluido el registro global o predeterminado si no se especifica ningún registro).
La biblioteca admite tanto el antiguo formato Prometheus como el formato OpenMetrics. El formato se puede configurar por registro. Para métricas predeterminadas:
const Prometheus = require ( 'prom-client' ) ;
Prometheus . register . setContentType (
Prometheus . Registry . OPENMETRICS_CONTENT_TYPE ,
) ;
Los tipos de registro disponibles actualmente se definen por los tipos de contenido:
PROMETHEUS_CONTENT_TYPE : versión 0.0.4 de las métricas originales de Prometheus, este es actualmente el tipo de registro predeterminado.
OPENMETRICS_CONTENT_TYPE : por defecto es la versión 1.0.0 del estándar OpenMetrics.
La cadena HTTP Content-Type para cada tipo de registro se expone tanto a nivel de módulo ( prometheusContentType
y openMetricsContentType
) como como propiedades estáticas en el objeto Registry
.
La constante contentType
expuesta por el módulo devuelve el tipo de contenido predeterminado al crear un nuevo registro; actualmente el valor predeterminado es el tipo Prometheus.
De forma predeterminada, las métricas se registran automáticamente en el registro global (ubicado en require('prom-client').register
). Puede evitar esto especificando registers: []
en la configuración del constructor de métricas.
El uso de registros no globales requiere crear una instancia de Registro y pasarla dentro de registers
en el objeto de configuración de métrica. Alternativamente, puede pasar una matriz registers
vacía y registrarla manualmente.
El registro tiene una función merge
que le permite exponer varios registros en el mismo punto final. Si existe el mismo nombre de métrica en ambos registros, se generará un error.
La fusión de registros de diferentes tipos no está definida. El usuario debe asegurarse de que todos los registros utilizados sean del mismo tipo (versiones Prometheus u OpenMetrics).
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 ] ) ;
Si desea utilizar registros múltiples o no predeterminados con el módulo cluster
de Node.js, deberá configurar el registro/registros para que se agreguen desde:
const AggregatorRegistry = client . AggregatorRegistry ;
AggregatorRegistry . setRegistries ( registry ) ;
// or for multiple registries:
AggregatorRegistry . setRegistries ( [ registry1 , registry2 ] ) ;
Puede obtener todas las métricas ejecutando await register.metrics()
, que devolverá una cadena en el formato de exposición de Prometheus.
Si necesita generar una única métrica en el formato de exposición de Prometheus, puede usar await register.getSingleMetricAsString(*name of metric*)
, que devolverá una cadena para que Prometheus la consuma.
Si necesita obtener una referencia a una métrica registrada previamente, puede usar register.getSingleMetric(*name of metric*)
.
Puede eliminar todas las métricas llamando register.clear()
. También puede eliminar una sola métrica llamando register.removeSingleMetric(*name of metric*)
.
Si necesita restablecer todas las métricas, puede usar register.resetMetrics()
. Las métricas permanecerán presentes en el registro y se podrán usar sin la necesidad de crear una instancia nuevamente, como lo haría después de register.clear()
.
Puede obtener métricas agregadas para todos los trabajadores en un clúster de Node.js con await register.clusterMetrics()
. Este método devuelve una promesa que se resuelve con una cadena de métricas adecuada para que la consuma Prometheus.
const metrics = await register . clusterMetrics ( ) ;
// - or -
register
. clusterMetrics ( )
. then ( metrics => {
/* ... */
} )
. catch ( err => {
/* ... */
} ) ;
Es posible impulsar métricas a través de 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 => {
/* ... */
} ) )