ヒストグラム、要約、ゲージ、カウンターをサポートする 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
を呼び出します。さらに、イベント ループ ラグ、アクティブ ハンドル、GC、Node.js バージョンなど、Node.js 固有のメトリクスもいくつか含まれています。すべてのメトリックのリストについては、lib/metrics を参照してください。
注: ファイル記述子とメモリに関するメトリクスの一部は、Linux でのみ使用できます。
collectDefaultMetrics
、オプションで次のエントリを含む構成オブジェクトを受け入れます。
prefix
メトリック名のオプションの接頭辞。デフォルト: プレフィックスなし。register
。デフォルト: グローバルなデフォルトのレジストリ。gcDurationBuckets
。 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
という 2 つの必須パラメータがあります。メトリクスの命名に関するガイダンスについては、https://prometheus.io/docs/practices/naming/ を参照してください。
ポイントインタイムの観察に基づくメトリクス (ヒストグラムで継続的に観察される HTTP リクエストの継続時間ではなく、現在のメモリ使用量など) の場合は、 collect()
関数を提供する必要があります。この関数は、Prometheus がメトリクス エンドポイントを収集するときに呼び出されます。 collect()
同期することも、Promise を返すこともできます。例については、以下の「ゲージ」を参照してください。 ( 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 ( ) ;
} ) ;
ヒストグラムはイベントのサイズと頻度を追跡します。
デフォルトのバケットは通常の 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
プロパティを取得できます。メトリックがサポートするすべてのラベル名をここで宣言する必要があります。ラベルに値を追加するには 2 つの方法があります。
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
}
} ) ;
ラベル付きのメトリクスは、観察されるまでは可能なラベル値が不明であるため、少なくとも 1 回観察されるまではエクスポートできません。
ヒストグラムの場合、これは、予想されるすべてのラベル値を明示的にゼロにすることで解決できます。
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 の説明形式で文字列が返されます。
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 が消費するのに適したメトリクス文字列で解決される 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 => {
/* ... */
} ) )