示例说明
可观测性三支柱里指标的成本收益比最高。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);