[譯]Prometheus監控NodeJS SDK(prom-client)使用說明

weixin_33766168發表於2019-03-04

github地址:https://github.com/siimon/prom-client

(此文為尚不熟悉時所譯,如有錯誤煩請指出修改)

Readme:

這是一個支援histogram, summaries, gauges and counters四種數值格式的prometheus nodejs客戶端。

用法

在example資料夾中有用法示例。這個庫不會繫結任何web框架,只會在registry中返回metrics()函式來顯示metrics。

通過nodejs的cluster模式使用

nodejs的cluster模式產生了多程式並且不會干涉socket連線其他workers。從一個worker的本地registry返回metrics只會顯示那個worker自己的metrics,這一般是不可取的。為了解決這點,你可以在主程式合併所有worker的metrics。檢視example/cluster.js獲取示例。

預設的metrics使用合理的聚合方法。自定義metrics預設會按照workers求和。要使用不同的合併方法,需要在metric配置中設定aggregator屬性為'sum', 'first', 'min', 'max', 'average' or 'omit'的其中一個。(檢視lib/metrics/version.js獲取示例。)

如果你想要顯示一個worker的metrics,可以包含一個只屬於這個worker的值(比如worker ID或者程式ID)在標籤中。(檢視example/server.js獲取使用worker_${cluster.worker.id}作為標籤值的示例。)

metrics預設會通過全域性registry來聚合。要使用不同的registry,就在worker程式中呼叫client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries)。

API

配置

所有的metrics型別都有兩個強制的引數:name和help。

預設metrics

有一些Prometheus自身推薦的預設metrics。要採集這些,就呼叫collectDefaultMetrics

注意:有些metrics,關於檔案描述符和記憶體的,只在Linux可獲取。

此外,包含了一些node特有的metrics,比如事件迴圈滯後( event loop lag),active handles和nodejs版本。在 lib/metrics 檢視有哪些metrics。

collectDefaultMetrics 獲取一個有三個條目的選項物件,一個指定探測多久執行一次的timeout引數,一個表示metric名稱的可選字首和一個表示哪個metrics需要被註冊的註冊器。預設為每10秒探測一次,但這可以像這樣修改:

const client = require('prom-client');

const collectDefaultMetrics = client.collectDefaultMetrics;

// Probe every 5th second.
collectDefaultMetrics({ timeout: 5000 });

註冊metrics到其他註冊器,傳遞一個註冊器進來:

const client = require('prom-client');

const collectDefaultMetrics = client.collectDefaultMetrics;
const Registry = client.Registry;
const register = new Registry();

collectDefaultMetrics({ register });

傳入一個字首來以任意字串作為metrics字首名:

const client = require('prom-client');

const collectDefaultMetrics = client.collectDefaultMetrics;

// Probe every 5th second.
collectDefaultMetrics({ prefix: 'my_application_' });

你可以通過檢查client.collectDefaultMetrics.metricsList來獲取metrcis的所有條目。

collectDefaultMetrics 會在呼叫時返回一個身份標識,這是一個依賴於Timer的,用來保持探測進行。要停止所有的探測,可以傳入clearInterval 。

注意:現有的間隔會在呼叫collectDefaultMetrics時自動清除。

const client = require('prom-client');

const collectDefaultMetrics = client.collectDefaultMetrics;

const interval = collectDefaultMetrics();

// ... some time later

clearInterval(interval);

注意:unref 會在interval 內部呼叫,所以它不會在作為唯一保持避免停止的程式時保持你的node程式執行。

停止輪詢預設metrics

要停止採集預設metrics,你需要呼叫呼叫函式並傳給clearInterval。

const client = require('prom-client');

clearInterval(client.collectDefaultMetrics());

// Clear the register
client.register.clear();

Counter數值

Counter會持續增長,並在程式重啟時重置。

const client = require('prom-client');
const counter = new client.Counter({
  name: 'metric_name',
  help: 'metric_help'
});
counter.inc(); // Inc with 1
counter.inc(10); // Inc with 10

Gauge數值

Gauge類似Counter,但Gauge值可以減少。

const client = require('prom-client');
const gauge = new client.Gauge({ name: 'metric_name', help: 'metric_help' });
gauge.set(10); // Set to 10
gauge.inc(); // Inc with 1
gauge.inc(10); // Inc with 10
gauge.dec(); // Dec with 1
gauge.dec(10); // Dec with 10

有一些公用的工具案例:

gauge.setToCurrentTime(); // Sets value to current time

const end = gauge.startTimer();
xhrRequest(function(err, res) {
  end(); // Sets value to xhrRequests duration in seconds
});

Histogram數值

Histogram追蹤事件的尺寸和頻率

配置

預設的桶用來覆蓋常規的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');
new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  labelNames: ['status_code'],
  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) {
  end(); // Observes the value to xhrRequests duration in seconds
});

Summary數值

Summary用來計算觀察值的百分數。

配置
預設百分數為0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999。但他們可以這樣改寫:

const client = require('prom-client');
new client.Summary({
  name: 'metric_name',
  help: 'metric_help',
  percentiles: [0.01, 0.1, 0.9, 0.99]
});

為了確保summary的滑動視窗功能,你需要像這樣在配置中新增maxAgeSeconds 和ageBuckets :

const client = require('prom-client');
new client.Summary({
  name: 'metric_name',
  help: 'metric_help',
  maxAgeSeconds: 600,
  ageBuckets: 5
});

maxAgeSeconds會指定一個bucket多久之後會重置,ageBuckets指定在我們的summary滑動視窗中有多少buckets。

使用示例:

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
});

Labels

所有的metrics都可以在配置物件中設定一個標籤名屬性。所有metric支援的標籤名都需要在這申明。有兩個方法來新增標籤:

const client = require('prom-client');
const gauge = new client.Gauge({
  name: 'metric_name',
  help: 'metric_help',
  labelNames: ['method', 'statusCode']
});

gauge.set({ method: 'GET', statusCode: '200' }, 100); // 1st version, Set value 100 with method set to GET and statusCode to 200
gauge.labels('GET', '200').set(100); // 2nd version, Same as above

也可能通過標籤使用計時器,在即使前前後都會建立:

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
  }
});

預設標籤(按註冊器分割)
靜態的標籤可能應用於一個註冊器下的每個metric:

const client = require('prom-client');
const defaultLabels = { serviceName: 'api-v1' };
client.register.setDefaultLabels(defaultLabels);

這會按下面的方式輸出所有metrics:

# 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()會清除預設標籤。

時間戳

Counter和Gauge metrics可以在值引數後接收一個時間戳引數。這個引數必須是一個Date或者一個數字(milliseconds since Unix epoch, i.e. 1970-01-01 00:00:00 UTC,不計跳躍秒數)。

gauge.set(100, 1485531442231); // Set gauge value and timestamp as milliseconds since Unix epoch
gauge.set(100, Date.now()); // Set gauge value and timestamp as milliseconds since Unix epoch
gauge.set(100, new Date()); // Set gauge value and timestamp as Date
gauge.set({ method: 'GET', statusCode: '200' }, 100, new Date()); // Set gauge value and timestamp with labels
gauge.labels('GET', '200').set(100, new Date()); // Same as above

counter.inc(1, new Date()); // Increment counter with timestamp

多註冊器

預設情況下,metrics是自動註冊到全域性註冊器(require('prom-client').register)的。你可以在建立metric時通過設定最後一個引數為false(依賴於metric,這可能是第四或第五個引數)來避免這樣做。

使用非全域性註冊器需要建立註冊器例項並新增它到配置物件的registers中。或者你可以傳入一個空registers陣列並手動去註冊它。

註冊器有一個merge函式可以用來在同一個端點暴露多個註冊器。如果同一個metric名在不同註冊器中存在,會丟擲一個錯誤。

const client = require('prom-client');
const registry = new client.Registry();
const counter = new client.Counter({
  name: 'metric_name',
  help: 'metric_help',
  registers: [registry]
});
const histogram = new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  registers: []
});
registry.registerMetric(histogram);
counter.inc();

const mergedRegistries = client.Registry.merge([registry, client.register]);

如果你想要在nodejs cluster模式下使用多個或非預設註冊器,需要設定註冊器合併:

const AggregatorRegistry = client.AggregatorRegistry;
AggregatorRegistry.setRegistries(registry);
// or for multiple registries:
AggregatorRegistry.setRegistries([registry1, registry2]);

註冊器

你可以通過執行register.metrics()獲取所有的metrics,這會輸出一個字串給prometheus。

register.metrics()接受一個時間戳範圍的可選物件。將之設為false會將字串的時間戳去除。

獲取單個metric供prometheus展示

如果你需要輸出單個metric給prometheus,可以使用register.getSingleMetricAsString(name of metric),這會輸出一個字串給prometheus。

獲取單個metric

如果你需要獲取一個之前註冊的metric,可以使用register.getSingleMetric(name of metric)。

移除metrics

你可以呼叫register.clear()移除所有metrics。還可以呼叫register.removeSingleMetric(name of metric)移除單個metric。

重置metrics
如果你需要重置所有metrics,可以使用register.resetMetrics()。這些metrics會保留在註冊器中,並無需再次例項化它們就能使用,但在register.clear()之後你需要例項化。

Cluster metrics

你可以在nodejs cluster中通過register.clusterMetrics()獲取所有workers的聚合metrics。該方法返回一個promise並接收一個callback,這兩者都解決一個適合傳給prometheus的metrics字串。

register
  .clusterMetrics()
  .then(metrics => {
    /* ... */
  })
  .catch(err => {
    /* ... */
  });

// - or -

register.clusterMetrics((err, metrics) => {
  // ...
});

Pushgateway

可以通過Pushgateway來push metrics。

注意時間戳會在metrics被push前被剝奪,因為Pushgateway >= 0.4 將不接受時間戳。

const client = require('prom-client');
let gateway = new client.Pushgateway('http://127.0.0.1:9091');

gateway.pushAdd({ jobName: 'test' }, function(err, resp, body) {}); //Add metric and overwrite old ones
gateway.push({ jobName: 'test' }, function(err, resp, body) {}); //Overwrite all metrics (use PUT)
gateway.delete({ jobName: 'test' }, function(err, resp, body) {}); //Delete all metrics for jobName

//All gateway requests can have groupings on it
gateway.pushAdd({ jobName: 'test', groupings: { key: 'value' } }, function(
  err,
  resp,
  body
) {});

//It's possible to extend the Pushgateway with request options from nodes core http/https library
gateway = new client.Pushgateway('http://127.0.0.1:9091', { timeout: 5000 }); //Set the request timeout to 5000ms

Utilites

為了方便,有兩個桶生成器函式——線性和指數的。

const client = require('prom-client');
new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  buckets: client.linearBuckets(0, 10, 20) //Create 20 buckets, starting on 0 and a width of 10
});

new client.Histogram({
  name: 'metric_name',
  help: 'metric_help',
  buckets: client.exponentialBuckets(1, 2, 5) //Create 5 buckets, starting on 1 and with a factor of 2
});

在註冊器和本工程的主檔案中,prometheus期待的內類型別都是作為常量輸出的,稱為contentType。


檢視作者首頁

相關文章