Клиент Prometheus для Node.js, поддерживающий гистограммы, сводки, датчики и счетчики.
См. папку с примером использования. Библиотека не включает в себя какие-либо веб-фреймворки. Чтобы предоставить метрики, ответьте на запросы Prometheus на очистку с результатом await registry.metrics()
.
cluster
Node.js Модуль cluster
Node.js порождает несколько процессов и передает соединения сокетов этим воркерам. Возврат метрик из локального реестра работника покажет только метрики этого отдельного работника, что, как правило, нежелательно. Чтобы решить эту проблему, вы можете агрегировать все метрики рабочих в главном процессе. См. example/cluster.js
.
Метрики по умолчанию используют разумные методы агрегирования. (Однако обратите внимание, что среднее значение задержки цикла событий и процентили усредняются, что не совсем точно.) Пользовательские метрики по умолчанию суммируются для всех рабочих процессов. Чтобы использовать другой метод агрегирования, установите для свойства aggregator
в конфигурации метрики одно из следующих значений: «сумма», «первый», «мин», «макс», «среднее» или «опустить». (Пример см. в lib/metrics/version.js
.)
Если вам нужно предоставить метрики об отдельном работнике, вы можете включить в метку значение, уникальное для работника (например, идентификатор работника или идентификатор процесса). (См example/server.js
, где приведен пример использования worker_${cluster.worker.id}
в качестве значения метки.)
По умолчанию метрики агрегируются из глобального реестра. Чтобы использовать другой реестр, вызовите client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries)
из рабочих процессов.
Есть некоторые метрики по умолчанию, рекомендованные самим Prometheus. Чтобы собрать их, вызовите collectDefaultMetrics
. Кроме того, включены некоторые специфичные для Node.js метрики, такие как задержка цикла событий, активные дескрипторы, сборщик мусора и версия 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 ( ) ;
} ) ;
Гистограммы отслеживают размеры и частоту событий.
Корзины по умолчанию предназначены для обработки обычных веб-запросов/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 — версия 0.0.4 исходной метрики Prometheus, в настоящее время это тип реестра по умолчанию.
OPENMETRICS_CONTENT_TYPE — по умолчанию используется версия 1.0.0 стандарта OpenMetrics.
Строка 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 ] ) ;
Если вы хотите использовать несколько реестров или реестров, не являющихся стандартными, с модулем cluster
Node.js, вам необходимо настроить реестр/реестр для агрегирования из:
const AggregatorRegistry = client . AggregatorRegistry ;
AggregatorRegistry . setRegistries ( registry ) ;
// or for multiple registries:
AggregatorRegistry . setRegistries ( [ registry1 , registry2 ] ) ;
Вы можете получить все метрики, запустив await register.metrics()
, который вернет строку в формате представления Prometheus.
Если вам нужно вывести одну метрику в формате представления Prometheus, вы можете использовать await register.getSingleMetricAsString(*name of metric*)
, который вернет строку для использования Prometheus.
Если вам нужно получить ссылку на ранее зарегистрированную метрику, вы можете использовать register.getSingleMetric(*name of metric*)
.
Вы можете удалить все метрики, вызвав register.clear()
. Вы также можете удалить одну метрику, вызвав register.removeSingleMetric(*name of metric*)
.
Если вам нужно сбросить все метрики, вы можете использовать register.resetMetrics()
. Метрики останутся в реестре и могут использоваться без необходимости их повторного создания экземпляров, как это нужно было бы сделать после register.clear()
.
Вы можете получить агрегированные метрики для всех воркеров в кластере Node.js с помощью await register.clusterMetrics()
. Этот метод возвращает обещание, которое разрешается с помощью строки показателей, подходящей для использования 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 => {
/* ... */
} ) )