Node.js中OpenTelemetry工具库Trace数据无法同步至Grafana求助
问题
我在Node.js应用中使用OpenTelemetry收集数据时遇到了问题,以下是我的配置:
tracing.js
const { logs, SeverityNumber } = require('@opentelemetry/api-logs'); let otelLogs = logs.getLogger("publisher", "1.1") const traceExporter = new OTLPTraceExporter({ url: 'http://localhost:4318/v1/traces', headers: { hello: 'OTLPTraceExporter' }, }); const logExporter = new OTLPLogExporter({ url: 'http://localhost:4318/v1/logs', headers: { hello: 'OTLPLogExporter' }, }); const provider = new BasicTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: process.env.SERVICE, }), }); provider.addSpanProcessor(new SimpleSpanProcessor(traceExporter)); provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); provider.register() const sdk = new opentelemetry.NodeSDK({ logRecordProcessor: new SimpleLogRecordProcessor(logExporter), traceExporter, // http instrumentations: [ new HttpInstrumentation() ], resource: new Resource({ [ SemanticResourceAttributes.SERVICE_NAME ]: process.env.SERVICE, [ SemanticResourceAttributes.SERVICE_NAMESPACE ]: "test", [ SemanticResourceAttributes.SERVICE_VERSION ]: "1.0", [ SemanticResourceAttributes.SERVICE_INSTANCE_ID ]: `my-instance-id-1 ${Date.now() }`, }), serviceName: "SERVICE" }); const getTracer = () => { return trace.getTracer("default") } sdk.start() module.exports = { getTracer }
publisher.js
const express = require('express') const app = express() const port = process.env.PORT || 3001 const { logs, SeverityNumber } = require('@opentelemetry/api-logs'); const otelLogs = logs.getLogger("publisher", "1.1") const tracer = tracing.getTracer() app.get('/a', async (req, res) => { const message = { pattern: {cmd: 'add-recipe'}, data: { id: Date.now().toString(), title: "adgadgadgdag", description: "aadfadfadfeeeee111", creationDate: Date(), ingredients: ["adfadf","adfadf"] } } res.send(message) }) app.listen(port, () => { console.log(`${process.env.SERVICE} Running ${port}`) }) otelLogs.emit({ severityNumber: SeverityNumber.INFO, body: "test publisher otelLogs", attributes : {test:"attribute"} })
当我发起GET请求到localhost:3001/a时,控制台能看到如下Trace输出:
{ traceId: '55245fd1400262e3774bd2c4ece669b7', parentId: undefined, traceState: undefined, name: 'GET', id: 'd93da19364db5f55', kind: 1, timestamp: 1699968631970000, duration: 59399.224, attributes: { 'http.url': 'http://localhost:3001/a', 'http.host': 'localhost:3001', 'net.host.name': 'localhost', 'http.method': 'GET', 'http.scheme': 'http', 'http.target': '/a', 'http.user_agent': 'curl/7.81.0', 'http.flavor': '1.1', 'net.transport': 'ip_tcp', 'net.host.ip': '::ffff:127.0.0.1', 'net.host.port': 3001, 'net.peer.ip': '::ffff:127.0.0.1', 'net.peer.port': 42138, 'http.status_code': 200, 'http.status_text': 'OK' }, status: { code: 0 }, events: [], links: [] }
但这条Trace记录没有出现在Grafana中,直接调用otelLogs.emit生成的日志却能正常显示。请问如何让工具库生成的所有数据都同步到Grafana?
解决方案
核心问题是重复初始化了Tracer Provider,导致Http Instrumentation生成的Span无法被NodeSDK正确处理并导出到Grafana。
问题分析
你在tracing.js中手动创建并注册了BasicTracerProvider,之后又初始化了opentelemetry.NodeSDK。NodeSDK会自动创建并管理独立的Tracer Provider,两个实例完全分离:
- 控制台输出的Span来自手动创建的Provider(你给它配置了
ConsoleSpanExporter) - 手动Provider的
OTLPTraceExporter因资源配置冲突、初始化顺序问题,无法将数据正确发送到Grafana - 日志能正常显示,是因为日志导出逻辑仅由NodeSDK管理,没有冲突
修复步骤
- 删除手动创建的
BasicTracerProvider代码块,完全由NodeSDK统一管理Tracer Provider、导出器和Instrumentation - 明确配置NodeSDK的Span处理器,同时保留控制台输出
- 确保
getTracer使用SDK初始化后的全局Tracer实例
修改后的tracing.js示例:
const { logs, SeverityNumber } = require('@opentelemetry/api-logs'); const { trace } = require('@opentelemetry/api'); const { NodeSDK } = require('@opentelemetry/sdk-node'); const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http'); const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http'); const { SimpleSpanProcessor, ConsoleSpanExporter } = require('@opentelemetry/sdk-trace-base'); const { SimpleLogRecordProcessor } = require('@opentelemetry/sdk-logs'); const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http'); const { Resource } = require('@opentelemetry/resources'); const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions'); const traceExporter = new OTLPTraceExporter({ url: 'http://localhost:4318/v1/traces', headers: { hello: 'OTLPTraceExporter' }, }); const logExporter = new OTLPLogExporter({ url: 'http://localhost:4318/v1/logs', headers: { hello: 'OTLPLogExporter' }, }); const sdk = new NodeSDK({ spanProcessor: new SimpleSpanProcessor(traceExporter), additionalSpanProcessors: [new SimpleSpanProcessor(new ConsoleSpanExporter())], logRecordProcessor: new SimpleLogRecordProcessor(logExporter), instrumentations: [new HttpInstrumentation()], resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: process.env.SERVICE, [SemanticResourceAttributes.SERVICE_NAMESPACE]: "test", [SemanticResourceAttributes.SERVICE_VERSION]: "1.0", [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: `my-instance-id-1 ${Date.now()}`, }), }); const getTracer = () => { return trace.getTracer("default") } sdk.start().catch((err) => { console.error('OpenTelemetry SDK初始化失败', err); }); process.on('SIGTERM', () => { sdk.shutdown() .then(() => console.log('OpenTelemetry SDK已正常关闭')) .catch((err) => console.error('OpenTelemetry SDK关闭出错', err)); }); module.exports = { getTracer }
验证要点
- 重启应用后发起请求,确认控制台仍有Span输出
- 检查Grafana的Trace面板,确认Http请求的Span已正常显示
- 日志导出不受影响,依然能正常出现在Grafana中
内容的提问来源于stack exchange,提问作者Midnight Guest
相关产品推荐
相关产品推荐

