← 中文资源

简体中文版本

构建 Prometheus 指标导出服务

一个完整的 Prometheus 导出器:计数器、仪表、直方图、标签纪律、拉取端点,以及断言指标名与分桶的测试。

阅读英文原文

项目概述

本项目实现 Prometheus 指标导出服务:以一致命名暴露应用与业务指标,限制标签基数,并选用契合负载的分桶。指标只有在命名稳定且标签基数有界时才有用,而这两点在首个计数器之后很容易丢失。

架构与关键决策

注册表以类型化助手创建计数器、仪表与直方图,使指标总以固定标签键集创建;抓取端点从内存状态渲染为曝光格式,计算廉价而不触数据库。HTTP 中间件一次性记录方法、路由模板与状态,避免用原始路径制造无界标签值。直方图分桶按预期分布选择,因为不契合负载的分桶会产生无法回答问题的直方图。

实施与测试

抓取端点断言预期指标名与标签键存在;驱动一次请求断言计数器递增;断言直方图桶单调且求和等于观测数;断言大量不同路径不会产生无界标签值。

限制与后续

  • 覆盖计数器、仪表与直方图,不含客户端分位摘要。
  • 无运行时基数上限,纪律依靠助手签名与评审。
  • 在内存中,重启即重置,跨重启的速率需按重置处理。

代码示例

pnpm init
pnpm add prom-client express
pnpm add -D typescript tsx vitest
metrics-exporter/
├── src/registry.ts
├── src/http-metrics.ts
├── src/render.ts
├── src/business.ts
├── tests/metrics.test.ts
└── package.json
const requests = new Counter({ name: 'http_requests_total', labelNames: ['route', 'status'] });
const latency = new Histogram({ name: 'http_request_seconds', buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5] });
const routeLabel = routeFromTemplate(req);
latency.observe({ route: routeLabel }, seconds);
res.set('Content-Type', registry.contentType).send(await registry.metrics());
queueDepth.set({ queue: 'email' }, await queue.size());
pnpm vitest run