히스토그램, 요약, 게이지 및 카운터를 지원하는 Node.js용 Prometheus 클라이언트입니다.
샘플 사용법은 예제 폴더를 참조하세요. 라이브러리는 웹 프레임워크를 번들로 제공하지 않습니다. 측정항목을 노출하려면 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
호출하세요. 또한 이벤트 루프 지연, 활성 핸들, GC 및 Node.js 버전과 같은 일부 Node.js 관련 측정항목이 포함됩니다. 모든 메트릭 목록은 lib/metrics를 참조하세요.
참고: 파일 설명자 및 메모리와 관련된 일부 측정항목은 Linux에서만 사용할 수 있습니다.
collectDefaultMetrics
선택적으로 다음 항목이 포함된 구성 객체를 허용합니다.
prefix
지표 이름에 대한 선택적 접두사입니다. 기본값: 접두어 없음.register
. 기본값: 전역 기본 레지스트리입니다.gcDurationBuckets
입니다. GC 기간 히스토그램의 기본 버킷은 [0.001, 0.01, 0.1, 1, 2, 5]
(초)입니다.eventLoopMonitoringPrecision
. 0보다 커야 합니다. 기본값: 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 요청 기간과 반대되는 현재 메모리 사용량)을 기반으로 하는 메트릭의 경우 Prometheus가 메트릭 엔드포인트를 스크랩할 때 호출되는 collect()
함수를 제공해야 합니다. 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 ) ;
} ,
} ) ;
화살표 함수에는 this
에 대한 올바른 값이 없기 때문에 collect
에 화살표 함수를 사용하면 안 됩니다.
// 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
}
} ) ;
관찰되기 전에는 가능한 라벨 값을 알 수 없으므로 라벨이 있는 측정항목은 한 번 이상 관찰되기 전에는 내보낼 수 없습니다.
히스토그램의 경우 예상되는 모든 레이블 값을 명시적으로 0으로 설정하면 이 문제를 해결할 수 있습니다.
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 콘텐츠 유형 문자열은 모듈 수준( 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 ] ) ;
Prometheus 설명 형식의 문자열을 반환하는 await register.metrics()
실행하여 모든 지표를 얻을 수 있습니다.
Prometheus 설명 형식으로 단일 지표를 출력해야 하는 경우, Prometheus가 사용할 문자열을 반환하는 await register.getSingleMetricAsString(*name of metric*)
을 사용할 수 있습니다.
이전에 등록된 측정항목에 대한 참조를 가져와야 하는 경우 register.getSingleMetric(*name of metric*)
사용할 수 있습니다.
register.clear()
호출하여 모든 측정항목을 제거할 수 있습니다. register.removeSingleMetric(*name of metric*)
호출하여 단일 메트릭을 제거할 수도 있습니다.
모든 측정항목을 재설정해야 하는 경우, register.resetMetrics()
사용할 수 있습니다. 메트릭은 레지스터에 남아 있으며, register.clear()
이후에 수행해야 하는 것처럼 다시 인스턴스화할 필요 없이 사용할 수 있습니다.
await register.clusterMetrics()
사용하면 Node.js 클러스터의 모든 작업자에 대해 집계된 측정항목을 얻을 수 있습니다. 이 메서드는 Prometheus가 사용하기에 적합한 측정항목 문자열로 확인되는 Promise를 반환합니다.
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 => {
/* ... */
} ) )