Node.js OpenTelemetry 监控实战:指标采集与导出完整教程
用 OpenTelemetry 为 Node.js 应用建立指标监控:自动 HTTP 指标、Counter/UpDownCounter/Gauge/Histogram 四种仪器用法、指标命名规范,以及通过 OTLP 导出到观测云实现看板与告警。附 Express 完整代码示例。
Node.js 的 OpenTelemetry 指标接入以 @opentelemetry/sdk-metrics 为核心,配合自动埋点包即可获得 HTTP 层指标,再用四种仪器补充业务指标——JS 生态的自动埋点覆盖 Express、Fastify、Koa 等主流框架,接入成本极低。
核心要点速览
- 自动埋点包一行注册,HTTP 请求数、耗时自动产出;
- 业务指标四种仪器:Counter 计数、UpDownCounter 水位、Gauge 瞬时、Histogram 分布;
- 指标经 OTLP 周期性导出(默认 60s);
- 端点指向观测云 DataKit 即完成监控闭环。
初始化指标 SDK
const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http');
const { Resource } = require('@opentelemetry/resources');
const exporter = new OTLPMetricExporter({
url: 'http://datakit-host:4318/v1/metrics',
});
const meterProvider = new MeterProvider({
resource: new Resource({ 'service.name': 'web-frontend' }),
readers: [new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 30000 })],
});
const meter = meterProvider.getMeter('web-frontend');
注意 NodeSDK(@opentelemetry/sdk-node)可以一行同时初始化链路+指标,新项目推荐直接使用。
自动 HTTP 指标
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const sdk = new NodeSDK({
metricReader: new PeriodicExportingMetricReader({ exporter }),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
Express 的每个路由自动产生请求计数与耗时分布指标,路由参数自动低基数化(/user/:id 而非 /user/12345)。
四种业务指标写法
// Counter:注册总数
const signups = meter.createCounter('user.signups.total');
signups.add(1, { plan: 'pro' });
// UpDownCounter:当前活跃会话
const sessions = meter.createUpDownCounter('sessions.active');
sessions.add(1); // 登录
sessions.add(-1); // 登出
// Gauge:当前配置版本之类的瞬时值
const queueDepth = meter.createGauge('jobs.queue.depth');
// 或用 Observable Gauge 回调采集:observableQueue.observe(result => ...)
// Histogram:任务处理耗时分布
const jobDuration = meter.createHistogram('jobs.duration', { unit: 's' });
jobDuration.record(elapsedSeconds, { job_type: 'email' });
命名纪律:点分小写、带单位、属性只放聚合维度(套餐、任务类型),用户 ID 这类高基数值永远不进指标——留给链路与日志。
Node.js 特有的注意点
- 异步上下文:Promise 链、async/await 由 AsyncLocalStorage 自动跟踪,但事件发射器(EventEmitter)跨边界时需检查上下文是否延续;
- 进程退出:
process.on('SIGTERM', () => sdk.shutdown())必须加,否则最后一波指标丢失; - 单进程多实例:PM2 集群模式下每个进程独立上报,后端按实例标签区分,聚合时留意。
观测云落地:从指标到告警一站完成
exporter 的 URL 指向观测云 DataKit(HTTP 4318),指标自动进入观测云:指标模块查数、场景视图搭看板、监控器配阈值/突变告警,通知走钉钉/企微/飞书。Node.js 应用同时开启链路追踪后,指标异常可直接下钻到具体请求链路。
常见问题(FAQ)
Q:自动埋点和我手写的指标会冲突吗? 不会,自动指标走框架层,手写指标走业务层,名称空间不同;但注意别对同一件事重复计数。
Q:exportIntervalMillis 设多少? 默认 60s,业务监控够用;告警敏感场景可降到 15-30s,再低收益递减。
Q:可以只导出指标不导出链路吗? 可以,分别配置 reader 与 tracer provider,互不影响。
Q:TypeScript 项目有额外配置吗? 类型定义齐全,直接 import 即可;自动埋点需在应用代码之前加载(--require ./tracing.js 启动参数)。