[译]Prometheus监控NodeJS SDK(prom-client)使用说明

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。


查看作者首页

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容