Node.js 的 Prometheus 客户端,支持直方图、摘要、仪表和计数器。
请参阅示例文件夹以获取示例用法。该库不捆绑任何 Web 框架。要公开指标,请使用await registry.metrics()
的结果响应Prometheus的抓取请求。
cluster
模块一起使用Node.js 的cluster
模块会生成多个进程,并将套接字连接交给这些工作人员。从工作人员的本地注册表返回指标只会显示单个工作人员的指标,这通常是不可取的。为了解决这个问题,您可以聚合主进程中所有工作线程的指标。有关示例,请参阅example/cluster.js
。
默认指标使用合理的聚合方法。 (但请注意,事件循环滞后平均值和百分位数是平均的,这并不完全准确。)默认情况下,自定义指标会在工作人员之间求和。要使用不同的聚合方法,请将指标配置中的aggregator
属性设置为“sum”、“first”、“min”、“max”、“average”或“omit”之一。 (有关示例,请参阅lib/metrics/version.js
。)
如果您需要公开有关单个工作线程的指标,则可以在标签中包含该工作线程唯一的值(例如工作线程 ID 或进程 ID)。 (有关使用worker_${cluster.worker.id}
作为标签值的示例,请参阅example/server.js
。)
默认情况下,指标是从全局注册表聚合的。要使用不同的注册表,请从工作进程中调用client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries)
。
Prometheus 本身推荐了一些默认指标。要收集这些,请调用collectDefaultMetrics
。此外,还包括一些特定于 Node.js 的指标,例如事件循环延迟、活动句柄、GC 和 Node.js 版本。有关所有指标的列表,请参阅 lib/metrics。
注意:一些有关文件描述符和内存的指标仅在 Linux 上可用。
collectDefaultMetrics
可以选择接受具有以下条目的配置对象:
prefix
度量标准名称的可选前缀。默认值:无前缀。register
指标应注册到哪个注册表。默认值:全局默认注册表。gcDurationBuckets
带有用于 GC 持续时间直方图的自定义存储桶。 GC 持续时间直方图的默认存储桶为[0.001, 0.01, 0.1, 1, 2, 5]
(以秒为单位)。eventLoopMonitoringPrecision
采样率以毫秒为单位。必须大于零。默认值:10。要将指标注册到另一个注册表,请将其作为register
传入:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
const Registry = client . Registry ;
const register = new Registry ( ) ;
collectDefaultMetrics ( { register } ) ;
要使用自定义存储桶作为 GC 持续时间直方图,请将其作为gcDurationBuckets
传入:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( { gcDurationBuckets : [ 0.1 , 0.2 , 0.3 ] } ) ;
要使用您自己的任意字符串为指标名称添加前缀,请传入prefix
:
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
const prefix = 'my_application_' ;
collectDefaultMetrics ( { prefix } ) ;
要将通用标签应用于所有默认指标,请将对象传递给labels
属性(如果您在集群环境中工作,则很有用):
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( {
labels : { NODE_APP_INSTANCE : process . env . NODE_APP_INSTANCE } ,
} ) ;
您可以通过检查client.collectDefaultMetrics.metricsList
来获取完整的指标列表。
默认指标是在指标端点上收集的,而不是按时间间隔收集的。
const client = require ( 'prom-client' ) ;
const collectDefaultMetrics = client . collectDefaultMetrics ;
collectDefaultMetrics ( ) ;
所有指标类型都有两个强制参数: name
和help
。有关命名指标的指南,请参阅 https://prometheus.io/docs/practices/naming/。
对于基于时间点观察的指标(例如当前内存使用情况,而不是在直方图中连续观察到的 HTTP 请求持续时间),您应该提供一个collect()
函数,当 Prometheus 抓取您的指标端点时将调用该函数。 collect()
可以是同步的,也可以返回一个承诺。请参阅下面的仪表示例。 (请注意,您不应在setInterval
回调中更新指标值;而是在此collect
函数中执行此操作。)
有关如何为所有指标类型配置标签的信息,请参阅标签。
计数器上升,并在进程重新启动时重置。
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
仪表与计数器类似,但仪表的值可以减小。
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
如果仪表用于时间点观察,您应该提供一个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 ) ;
} ,
} ) ;
请注意,您不应使用箭头函数来collect
,因为箭头函数不会为this
提供正确的值。
// Set value to current time in seconds:
gauge . setToCurrentTime ( ) ;
// Record durations:
const end = gauge . startTimer ( ) ;
http . get ( 'url' , res => {
end ( ) ;
} ) ;
直方图跟踪事件的大小和频率。
默认存储桶旨在涵盖常见的 Web/RPC 请求,但它们可以被覆盖。 (另请参阅桶生成器。)
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
} ) ;
摘要计算观察值的百分位数。
默认百分位数为:0.01、0.05、0.5、0.9、0.95、0.99、0.999。但可以通过指定percentiles
数组来覆盖它们。 (另请参阅桶生成器。)
const client = require ( 'prom-client' ) ;
new client . Summary ( {
name : 'metric_name' ,
help : 'metric_help' ,
percentiles : [ 0.01 , 0.1 , 0.9 , 0.99 ] ,
} ) ;
要启用摘要的滑动窗口功能,您需要将maxAgeSeconds
和ageBuckets
添加到配置中,如下所示:
const client = require ( 'prom-client' ) ;
new client . Summary ( {
name : 'metric_name' ,
help : 'metric_help' ,
maxAgeSeconds : 600 ,
ageBuckets : 5 ,
pruneAgedBuckets : false ,
} ) ;
maxAgeSeconds
将告诉存储桶在重置之前可以有多久,而ageBuckets
配置我们在滑动窗口中将有多少个存储桶用于摘要。如果pruneAgedBuckets
为false
(默认),则指标值将始终存在,即使为空(其百分位值为0
)。如果您不想在它为空时导出它,请将pruneAgedBuckets
设置为true
。
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
} ) ;
所有指标都可以采用配置对象中的labelNames
属性。指标支持的所有标签名称都需要在此处声明。有两种方法可以向标签添加值:
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 ) ;
还可以在创建计时器之前和之后使用带标签的计时器:
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
}
} ) ;
带标签的指标在至少被观察一次之前无法导出,因为在观察之前可能不知道可能的标签值。
对于直方图,可以通过显式将所有预期标签值归零来解决:
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 还可以使用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 } ) ;
静态标签可以应用于注册表发出的每个指标:
const client = require ( 'prom-client' ) ;
const defaultLabels = { serviceName : 'api-v1' } ;
client . register . setDefaultLabels ( defaultLabels ) ;
这将以下列方式输出指标:
# 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
如果存在名称冲突,默认标签将被覆盖。
register.clear()
将清除默认标签。
OpenMetrics 规范中定义的示例可以在计数器和直方图指标类型上启用。默认指标支持 OpenTelemetry,它们将使用标签{traceId, spanId}
及其相应值填充示例。
如果启用了范例,则inc()
和observe()
调用的格式会有所不同。他们获得格式为{labels, value, exemplarLabels}
的单个对象。
使用示例时,用于指标的注册表应设置为 OpenMetrics 类型(如果未指定注册表,则包括全局或默认注册表)。
该库支持旧的 Prometheus 格式和 OpenMetrics 格式。可以根据注册表设置格式。对于默认指标:
const Prometheus = require ( 'prom-client' ) ;
Prometheus . register . setContentType (
Prometheus . Registry . OPENMETRICS_CONTENT_TYPE ,
) ;
当前可用的注册表类型由内容类型定义:
PROMETHEUS_CONTENT_TYPE - 原始 Prometheus 指标的版本 0.0.4,这是当前默认的注册表类型。
OPENMETRICS_CONTENT_TYPE - 默认为 OpenMetrics 标准版本 1.0.0。
每个注册表类型的 HTTP Content-Type 字符串都在模块级别( prometheusContentType
和openMetricsContentType
)公开,并作为Registry
对象上的静态属性公开。
模块暴露的contentType
常量在创建新注册表时返回默认的内容类型,当前默认为 Prometheus 类型。
默认情况下,指标会自动注册到全局注册表(位于require('prom-client').register
)。您可以通过在度量构造函数配置中指定registers: []
来防止这种情况。
使用非全局注册表需要创建一个注册表实例并将其传递到指标配置对象的registers
内。或者,您可以传递一个空registers
数组并手动注册它。
注册表具有merge
功能,使您能够在同一端点上公开多个注册表。如果两个注册表中存在相同的指标名称,则会引发错误。
不同类型的合并注册表是未定义的。用户需要确保所有使用的注册表具有相同的类型(Prometheus 或 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 ] ) ;
如果您想在 Node.js cluster
模块中使用多个或非默认注册表,则需要将注册表设置为从以下位置聚合:
const AggregatorRegistry = client . AggregatorRegistry ;
AggregatorRegistry . setRegistries ( registry ) ;
// or for multiple registries:
AggregatorRegistry . setRegistries ( [ registry1 , registry2 ] ) ;
您可以通过运行await register.metrics()
来获取所有指标,这将返回Prometheus exposition格式的字符串。
如果需要以 Prometheus 展示格式输出单个指标,可以使用await register.getSingleMetricAsString(*name of metric*)
,它将返回一个字符串供 Prometheus 使用。
如果您需要获取对先前注册的指标的引用,可以使用register.getSingleMetric(*name of metric*)
。
您可以通过调用register.clear()
删除所有指标。您还可以通过调用register.removeSingleMetric(*name of metric*)
删除单个指标。
如果需要重置所有指标,可以使用register.resetMetrics()
。这些指标将保留在寄存器中,并且无需再次实例化即可使用,就像您在register.clear()
之后需要做的那样。
您可以使用await register.clusterMetrics()
获取 Node.js 集群中所有工作线程的聚合指标。此方法返回一个承诺,该承诺使用适合 Prometheus 使用的指标字符串进行解析。
const metrics = await register . clusterMetrics ( ) ;
// - or -
register
. clusterMetrics ( )
. then ( metrics => {
/* ... */
} )
. catch ( err => {
/* ... */
} ) ;
可以通过 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 => {
/* ... */
} ) )