← 中文资源

简体中文版本

Prom Client 计数器与直方图指标

用 prom-client 埋点服务指标:Counter 记录业务总量、Histogram 按桶记录延迟分布、默认指标端点供 Prometheus 抓取。

阅读英文原文

示例说明

可观测性三支柱里指标的成本收益比最高。Counter 只增不减,适合订单量这类累计语义,PromQL 的 rate 能算出速率;Histogram 把观测值落进预定义的延迟桶,聚合后可计算 P95 分位而无需存储每次样本。startTimer 返回闭包,finally 里调用保证异常路径也计入延迟。

技术要点

  • labelNames 限定维度防止标签基数爆炸
  • startTimer 闭包自动计时收尾
  • 独立 Registry 隔离自定义与默认指标

代码解读

checkout 处理器里订单计数按租户与渠道打标签,业务维度即刻可聚合;计时器在请求开始创建、finally 中结束,成败请求都进入延迟分布。/metrics 端点输出注册表的标准文本格式,Prometheus 定期抓取即可建立监控基线。

使用建议

标签值要有限集合,用户 ID 这类高基数值会拖垮 Prometheus。延迟桶按业务 SLO 划分边界才有意义。指标命名带单位后缀是社区约定。

代码示例

import promClient from 'prom-client';
import express from 'express';

const registry = new promClient.Registry();
promClient.collectDefaultMetrics({ register: registry, prefix: 'svc_' });

const ordersTotal = new promClient.Counter({
  name: 'orders_created_total',
  help: 'Total orders created',
  labelNames: ['tenant', 'channel'],
  registers: [registry],
});

const requestDuration = new promClient.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Request latency distribution',
  buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5],
  labelNames: ['route', 'method'],
  registers: [registry],
});

async function handleCheckout(req, res) {
  const end = requestDuration.startTimer({ route: '/checkout', method: 'POST' });
  try {
    ordersTotal.inc({ tenant: 'acme', channel: 'web' });
    res.json({ ok: true });
  } finally {
    end();
  }
}

const app = express();
app.post('/checkout', handleCheckout);
app.get('/metrics', async (req, res) => {
  res.set('content-type', registry.contentType);
  res.end(await registry.metrics());
});

app.listen(3000);