【node实战系列】使用reqId跟踪全链路日志

avatar
前端开发工程师 @bigo

file

本文首发于:github.com/bigo-fronte… 欢迎关注、转载。

背景

bigo前端开始推广bff,hello农场作为首个bff落地项目,历经2个月,完成了从0-1的落地实践。

【node实战系列】按照小模块拆分,从开发者的角度讲叙,如何进行bff高可用编码。

本系列文章,基于eggjs框架编码,使用ts语法,为了提升阅读体验,建议大家先了解一下eggjs。

系列文章

欢迎大家关注我们的github blog,持续更新。 github.com/bigo-fronte…

使用reqId跟踪全链路日志

问题排查

接口怎么报错了?你这个字段的数据不对呀? 作为bff聚合层,测试或者前端同学对于接口异常,第一时间找到我们,需要我们快速定位问题,确定是业务逻辑异常,还是下游响应异常。

对于那种影响比较大的bug,处理时间是分秒必争的,慢几秒处理完,可能GMV就哗啦啦的掉了很多。

一个程序员是否优秀,其中一个判断维度就是:处理线上问题是否快狠准,而其中日志是帮我们快速定位问题的绝佳手段。

但是随着应用集群部署,微服务架构复杂,日志量大,做单个场景的全链路追踪就很重要。

reqId

reqId(或者叫traceId: 调用链id),在bff对当前请求生成随机reqId,日志打印需要包含reqId,同时在每个 RPC 方法里面传入 reqId,在返回给前端响应里面带上reqId。

排查问题时,就可以通过response的reqId查询所有下游日志,实现全链路追踪。

实现过程

// 返回指定长度的随机数
randomNum(len) {
  let str = '';
  const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  for(let i=0; i<len; i++){
    const pos = Math.round(Math.random() * (arr.length-1));
    str += arr[pos];
  }
  return Number(str);
}
// 首个 middleware 里面生成seqId
ctx.seqId = ctx.helper.randomNum(8);

// 日志方法里面默认打印 seqId
log(text, obj: PlainObject) {
  this.logger.info(`seqId=%j uid=%j ${text}`, this.seqId, this.loginuid || 0, obj);
}

// 约定透传给下游rpc
list.push({
  key: 'seqId', 
  value: String(this.ctx.seqId),
});

日志查询

如下图,基于seqId=87336202,就能快速查询日志了。

数据库日志查询: image.png

可视化时间轴展示: image.png

总结

日志追踪分析是解决生产问题的第一技术手段,甚至可以说是唯一的手段。通过seqId分析整个微服务的调用链,数据在不同服务节点的变更都一目了然,对于定位问题至关重要。好了,本文的简单介绍到这里就结束了。

欢迎大家留言讨论,祝工作顺利、生活愉快!

我是bigo前端,下期见。