nestjs 日志问题 traceId - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zzh2036
V2EX    Node.js

nestjs 日志问题 traceId

  •  
  •   zzh2036 2023-08-11 17:26:10 +08:00 3302 次点击
    这是一个创建于 866 天前的主题,其中的信息可能已经有所发展或是发生改变。

    nestjs(express)做了一个简单的服务
    目前用 winston替换了 nestjs的默认日志及 typeorm的日志
    有时候需要查看日志定位问题,所以想在日志中添加 traceId用于追踪一次 request的完整链路,最好是无代码侵入的
    有查到使用 Async hooks进行 request上下文保存的
    大家有没有已实现的方案?

    23 条回复    2023-08-22 13:55:33 +08:00
    lzgshsj
        1
    lzgshsj  
       2023-08-11 17:50:43 +08:00
    没用 winston ,用的 pino ,自带了 genReqId 的方法
    NessajCN
        2
    NessajCN  
       2023-08-11 17:51:15 +08:00
    既然是你自己做的服务那你就在 logger.log()的时候把你要的 traceId 加进去呗....
    没怎么看懂你有什么进一步需求
    zzh2036
        3
    zzh2036  
    OP
       2023-08-11 17:57:59 +08:00
    @NessajCN 需要调用其他函数的时候,traceId 要当做参数继续传递下去吗?因为之前没有做过 traceId 这些,所以想知道一些详细的方案。traceId 的生成能和 jwt 中的 userId 做一些关联吗?
    zzh2036
        4
    zzh2036  
    OP
       2023-08-11 18:00:20 +08:00
    @lzgshsj 你是用了 fastify 还是 express 配合 pino 使用的?
    NessajCN
        5
    NessajCN  
       2023-08-11 18:05:02 +08:00
    @zzh2036 哦所以你问的是 tracerId 的生成问题而不是怎么在日志里加 id 的问题是吧?
    这个讲道理没有什么固定规则呀当然你怎么看得顺眼怎么来。要我的话函数名加个时间戳么差不多了...最多再加个 api 名
    thynson
        6
    thynson  
       2023-08-11 18:05:40 +08:00
    nestjs 是不太好做的,所以我自己实现了一个类似的框架 sensejs
    进一步了解: https://sensejs.io 或者 https://github.com/sensejs/sensejs
    thynson
        7
    thynson  
       2023-08-11 18:07:05 +08:00
    zzh2036
        8
    zzh2036  
    OP
       2023-08-11 18:10:34 +08:00
    @NessajCN 有如何在日志中加 id 的疑问,刚才说的 logger.log()直接加 traceId ,那如果调用其它函数,traceId 要当做参数继续往下传递是吧?
    thynson
        9
    thynson  
       2023-08-11 18:14:30 +08:00
    @zzh2036 NestJS 印象中我是这么做的,在依赖注入框架下,然后在每个类初始化的时候用,可以把 requestId 注入进来,并关联到 Logger 上,requestId 的产生需要定义一个 provider 。当然这种做法还是有一定的侵入性
    NessajCN
        10
    NessajCN  
       2023-08-11 18:16:07 +08:00 via Android
    @zzh2036 这个都是你自己决定的…你想接着用这个 id 就往下传,想用个新的就再生成一个呗
    zzh2036
        11
    zzh2036  
    OP
       2023-08-11 18:19:22 +08:00
    @thynson 感谢大佬,我去试试
    zzh2036
        12
    zzh2036  
    OP
       2023-08-11 18:19:47 +08:00
    @NessajCN 感谢大佬,大概了解一些了
    victimsss
        13
    victimsss  
       2023-08-11 18:19:54 +08:00
    @NessajCN 大概是在中间件使用 continuation-local-storage 或者 cls-hooked 记录 jwt 的 id 或者 生产的 reqId 然后供上下文使用,然后 logger 记录的时候不需要显式传参。
    crysislinux
        14
    crysislinux  
       2023-08-11 18:27:11 +08:00 via Android
    async hooks 不是 100%可靠的。这点比较坑,打日志可以用,但是不要做业务,比如存储 tenant id 之类的
    zzh2036
        15
    zzh2036  
    OP
       2023-08-11 18:27:29 +08:00
    @victimsss 总结的太棒了
    Helios0
        16
    Helios0  
       2023-08-11 21:20:13 +08:00
    nestjs-cls https://papooch.github.io/nestjs-cls/
    或者自己实现一个中间件也是一样的
    zurmokeeper
        17
    zurmokeeper  
       2023-08-11 21:32:06 +08:00
    个人暂时还是比较笨的方法实现,把 logger 对象挂在 req 上,请求的开头自己生成一个 traceid,挂上去,后续这个 req ,在 nestjs 的生命周期里都是能拿到的,然后用类似 req.logger.debug() 这种方式打印,整个生命周期就都是用 traceid 关联的了。如果还有其他服务,也可以把这个 traceid 放到请求头或者其他地方,一路传下去,也可以实现多个服务被一个 traceid 串起来的功能
    owen800q
        18
    owen800q  
       2023-08-12 00:25:39 +08:00 via iPhone
    @z
    @zurmokeeper 把 logger 放到 req 是不的想法,反正 req 都要一直往下的
    zzh2036
        19
    zzh2036  
    OP
       2023-08-14 10:09:29 +08:00
    @Helios0 感谢大佬,这个 nestjs-cls 中 requestID 的 case ,比较符合我想要的效果
    zzh2036
        20
    zzh2036  
    OP
       2023-08-14 10:13:26 +08:00
    @zurmokeeper 很实用的想法,我之前想到在请求拦截中生成 traceId ,挂在 req 对象上,controller 里解出来,后续一直在 service 中做传递。但觉得应该有更优雅的实现
    guiling
        21
    guiling  
       2023-08-22 10:59:54 +08:00
    当初网上确实找不到成熟方案,所以自己实现的,核心就是利用 AsyncLocalStorage
    1 使用 express-request-id 作为日志的 traceid
    2 基于 AsyncLocalStorage 自己写一个中间件,获取请求头里的 traceid 并赋值到 AsyncLocalStorage 的实例中,这个是最核心的,代码不多,node 版本好想要 14 以上,网上有相关教程
    3 重写 console 的 log 合 error 方法,日志就用这两个,没用第三方 logger ,这样所有请求默认的日志就会带 traceid
    4 关于定时任务因为不走请求所以没有 traceid ,需要自己随机生成一个然后在最外层包进去(我是机器时间+任务名)

    最终效果大概这样
    https://s2.loli.net/2023/08/22/9EOeUzQD5XvAqWj.png
    定时任务的
    https://s2.loli.net/2023/08/22/x4dHy8wcLiM5mP3.png

    理论上最终可以做成想 java 那样的把模块方法名也打印出来
    zzh2036
        22
    zzh2036  
    OP
       2023-08-22 12:21:36 +08:00
    @guiling 不错的实现方式。我目前直接引用了 nestjs-cls 这个包,全局注册时自定义了 traceid 生成规则,在 winston logger 的 printf 方法中通过 cls 取出 traceid 进行打印。
    guiling
        23
    guiling  
       2023-08-22 13:55:33 +08:00
    @zzh2036 看了下原理一样的,也是基于 AsyncLocalStorage ,可惜当初做的时候这包还没出来,不然就省事了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2981 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 13:10 PVG 21:10 LAX 05:10 JFK 08:10
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86