Node/Express服务日志生成Span但Jaeger UI无服务名称问题求助
我之前也碰到过完全一样的情况——日志明明显示Span已经生成,但Jaeger UI里就是找不到我的服务。咱们一步步来定位问题:
1. 先盯紧tracing.js里的服务名配置
这是最容易踩的坑:必须明确指定serviceName,Jaeger UI完全靠这个字段识别你的服务。检查你的tracing.js,确保初始化Tracer时有清晰的配置:
const { initTracer } = require('jaeger-client'); const config = { serviceName: 'my-express-microservice', // 这里绝对不能留空或者用默认值! sampler: { type: 'const', param: 1, // 开发环境用全量采样,确保Span都能上报 }, reporter: { logSpans: true, agentHost: 'localhost', // 和Jaeger Agent的地址保持一致 agentPort: 6832, // 默认UDP端口,别写错 }, }; const options = { logger: { info(msg) { console.log('INFO', msg); }, error(msg) { console.log('ERROR', msg); }, }, }; const tracer = initTracer(config, options); module.exports = tracer;
如果这里的serviceName没设置或者拼写错误,Jaeger UI根本不知道该把你的Span归到哪个服务下。
2. 确认Span被正确结束(finish())
日志里显示"Reporting span"不代表Span一定被成功上报——必须调用span.finish(),Jaeger才会把这个Span发送给Agent。检查你的server.js请求处理器:
const express = require('express'); const tracer = require('./tracing'); const { expressMiddleware } = require('jaeger-client/dist/middleware/express'); const app = express(); // 先挂载Jaeger的Express中间件,自动为每个请求生成根Span app.use(expressMiddleware(tracer)); app.get('/test', (req, res) => { // 如果手动创建子Span,一定要关联根Span的上下文 const childSpan = tracer.startSpan('process-test-request', { childOf: req.spanContext }); // 你的业务逻辑 res.send('OK'); childSpan.finish(); // 关键!忘记调用的话,这个Span永远不会被上报 }); app.listen(3000);
就算是中间件自动生成的根Span,也要确保请求正常结束(比如没有未处理的错误导致进程挂掉),否则根Span也可能无法完成上报。
3. 检查Jaeger服务的连通性
日志显示"Reporting span"只是客户端层面的日志,还要确认Agent/Collector是否真的收到了Span:
- 如果用Docker部署Jaeger,先确认
jaeger-agent容器在运行:docker ps | grep jaeger-agent - 查看Jaeger Agent的日志,看是否有接收Span的记录:
docker logs <jaeger-agent-container-id> - 确保
tracing.js里的reporter配置的agentHost和agentPort和Jaeger Agent的监听地址完全匹配(默认是localhost:6832)
4. 别忽略Jaeger UI的时间范围
有时候Span已经成功上报了,但Jaeger UI默认只显示最近15分钟的数据。如果你的测试请求是在更早的时间发起的,调整UI右上角的时间范围(比如选"Last hour"或者自定义区间)再试试。
5. 版本兼容性排查
如果你的Jaeger客户端版本和服务端(Agent/Collector/UI)版本差异过大,可能会出现协议不兼容的问题。比如旧版本客户端用Thrift协议,而新版本Jaeger默认启用GRPC,这种情况下要么调整客户端配置指定协议,要么升级/降级到匹配的版本。
先从前面两个点开始排查——服务名配置和Span结束调用,这两个是最常见的原因。
内容的提问来源于stack exchange,提问作者Abhishek

