ไคลเอ็นต์ 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 ไว้ด้วย เช่น เหตุการณ์หน่วงเวลาของลูป ตัวจัดการที่ใช้งานอยู่ เวอร์ชัน GC และ Node.js ดู lib/เมตริกสำหรับรายการเมตริกทั้งหมด
หมายเหตุ: ตัวชี้วัดบางส่วนที่เกี่ยวข้องกับ File Descriptors และ Memory มีเฉพาะบน 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 ( ) ;
ประเภทเมตริกทั้งหมดมีพารามิเตอร์บังคับ 2 รายการ ได้แก่ 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 ปกติ แต่สามารถแทนที่ได้ (ดูเพิ่มเติมที่ Bucket Generators )
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
(ดูเพิ่มเติมที่ Bucket Generators )
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 สำหรับรีจิสทรีแต่ละประเภทจะแสดงทั้งที่ระดับโมดูล ( 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 => {
/* ... */
} ) )