如何为OpenTelemetry Node.js SDK配置PrometheusExporter导出Trace数据
OpenTelemetry JS:将Trace数据转换为Metrics并导出到Prometheus
首先明确核心点:Prometheus是**指标(Metrics)**采集系统,不直接接收Trace(链路追踪)数据。@opentelemetry/exporter-prometheus是用于导出Metrics的组件,不能直接替换Trace的ConsoleSpanExporter。你需要将Trace数据转换为Metrics后,再通过该Exporter发送给Prometheus,具体流程如下:
一、核心配置流程
- 保留Trace采集链路,用
NodeTracerProvider处理Span数据 - 初始化
MeterProvider管理Metrics,关联PrometheusExporter - 通过自定义
SpanProcessor监听Span生命周期,将Trace数据转换为Metrics - 配置Prometheus抓取Metrics端点
二、完整代码示例(instrumentation.js)
先确认已安装依赖(若缺失请补充):
npm install @opentelemetry/sdk-trace-node @opentelemetry/sdk-metrics @opentelemetry/api @opentelemetry/exporter-prometheus @opentelemetry/exporter-trace-otlp-console
代码实现:
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node'); const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base'); const { ConsoleSpanExporter } = require('@opentelemetry/exporter-trace-otlp-console'); const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); const { trace } = require('@opentelemetry/api'); // 1. 配置Prometheus Metrics导出器 const prometheusExporter = new PrometheusExporter({ port: 9464, // 自定义端口,默认9464 }); // 2. 初始化MeterProvider并绑定导出器 const meterProvider = new MeterProvider(); meterProvider.addMetricReader(new PeriodicExportingMetricReader({ exporter: prometheusExporter, exportIntervalMillis: 10000, // 每10秒导出一次Metrics })); const meter = meterProvider.getMeter('trace-to-metrics-converter'); // 3. 自定义SpanProcessor:监听Span结束事件,转换为Metrics class TraceMetricsProcessor { constructor(meter) { // 定义需要的Metrics指标 this.requestCounter = meter.createCounter('app_requests_total', { description: 'Total number of traced requests', }); this.requestDurationHist = meter.createHistogram('app_request_duration_ms', { description: 'Duration of traced requests (milliseconds)', }); } // Span结束时触发,提取数据生成Metrics onEnd(span) { // 仅处理业务相关Span(示例:过滤HTTP请求Span) if (span.name.includes('HTTP')) { const method = span.attributes['http.method'] || 'unknown'; const statusCode = span.attributes['http.status_code'] || 'unknown'; const endpoint = span.attributes['http.target'] || 'unknown'; // 记录请求总数(带标签维度) this.requestCounter.add(1, { method, status_code: statusCode, endpoint, }); // 记录请求耗时(Span duration为纳秒,转毫秒) const durationMs = span.duration[0] * 1000 + span.duration[1] / 1e6; this.requestDurationHist.record(durationMs, { method, status_code: statusCode, endpoint, }); } } // 实现SpanProcessor接口的其他空方法 onStart(span, context) {} shutdown() { return Promise.resolve(); } forceFlush() { return Promise.resolve(); } } // 4. 初始化TracerProvider并绑定处理器 const tracerProvider = new NodeTracerProvider(); // 添加自定义Trace转Metrics处理器 tracerProvider.addSpanProcessor(new TraceMetricsProcessor(meter)); // 可选:保留ConsoleSpanExporter查看原始Trace数据 tracerProvider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); // 注册全局Tracer tracerProvider.register(); // 测试:模拟业务Span生成 const tracer = trace.getTracer('test-app-tracer'); setInterval(() => { const span = tracer.startSpan('HTTP GET /api/user'); span.setAttribute('http.method', 'GET'); span.setAttribute('http.target', '/api/user'); span.setAttribute('http.status_code', 200); setTimeout(() => span.end(), Math.random() * 1200); }, 2000);
三、关键细节说明
- SpanProcessor的作用:通过
onEnd钩子捕获每个Span的结束事件,提取Span的属性(如HTTP方法、状态码、耗时),转换为Prometheus支持的Metrics类型(计数器、直方图)。 - Metrics端点验证:启动应用后,访问
http://localhost:9464/metrics,能看到生成的app_requests_total和app_request_duration_ms指标。 - Prometheus抓取配置:在
prometheus.yml中添加以下配置,即可让Prometheus自动采集指标:
scrape_configs: - job_name: 'node-app-trace-metrics' scrape_interval: 15s static_configs: - targets: ['localhost:9464']
四、常见问题排查
- 无Metrics生成:检查Span的属性是否正确设置,自定义处理器中的过滤条件是否匹配你的Span名称/属性。
- Prometheus无法抓取:确认端口未被占用,防火墙允许访问,Prometheus配置的target地址正确。
- 版本兼容问题:确保所有
@opentelemetry/*依赖包版本一致,避免因版本差异导致的API不兼容。
内容的提问来源于stack exchange,提问作者Sergey
相关产品推荐
相关产品推荐

