V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
xrlin
V2EX  ›  程序员

请教下日志打印的最佳实践

  •  
  •   xrlin · May 24, 2018 · 5234 views
    This topic created in 2896 days ago, the information mentioned may be changed or developed.

    无论是线上还是开发环境,log 打印对排查 bug 都很有帮助,但是这就遇到个问题,如果要打印详细的 log 就会侵入到方法的实现,特别是如果调用链很常的时候,比如

    controller -> validator -> serviceA -> serviceB -> model

    这时如果要打印出详细的日志就必须在 controller、service、model .... 中都要加上打印语句,这样显得很麻烦,有没有更好的实现方式?虽然可以用类似 AOP 的方法,但是如果要精细一些还是要在方法实现中主动调用。

    15 replies    2018-12-11 03:56:17 +08:00
    kslr
        1
    kslr  
       May 24, 2018 via Android
    发出事件监听呢
    billwsy
        2
    billwsy  
       May 24, 2018 via iPhone
    glog https://github.com/google/glog 可以在某些时候打印 stack trace
    gaoyulong
        3
    gaoyulong  
       May 24, 2018
    mark
    ppyybb
        4
    ppyybb  
       May 24, 2018 via iPhone
    我在 rails 里面的简易做法是:
    抛出异常
    打出到 controller 层为止的 stack trace
    打出需要的当前环境的状态
    严重的发短信报警

    另外,你 log 的目的是针对可能出现的异常情况做记录,方便出问题的时候查找。
    还是已经发现比较奇怪的现象,但是找不到原因,准备打 log 排查?如果是后者,log 只是临时的,处理好有问题的调用链上的 log,专门写一个 logger 类来打出一整条链上的状态,事后清理即可
    ksupertu
        5
    ksupertu  
       May 24, 2018
    sentry 了解一下
    jorneyr
        6
    jorneyr  
       May 24, 2018
    很多日志都是根据业务逻辑进行打印,就必须侵入到不同层的代码里。AOP 只能打印一些通用的日志,例如访问方法的顺序,参数,执行的时间等。
    hilow
        7
    hilow  
       May 24, 2018 via Android
    在每个函数中返回 自定义的 *exerror.Error 类型变量。
    此 err 变量中包含错误的上下文信息,如 userId, zerror 和 [email protected]:108 这样的 zcallstack
    在调用函数时,如果返回非 nil 的 err,就能打印日志,日志中包含所有上下文信息。
    实际业务中在不同代码中调用相同函数,可能出现同样错误,都返回了 err,这时能根据要求灵活决定是否打印出日志。
    日志打印格式推荐“结构化日志信息”,比如`level=info msg="Recv RestRequest"` ,主要优点是,方便使用 grep awk 等工具过滤日志,详情参考[logrus]( https://github.com/sirupsen/logrus)
    另外每行日志中增加一个`ReqId`,此 ID 全局唯一,用于关联同一会议的 ID

    ```log
    cat log/server.log | grep ExtHwyApi_QLlUyYd9To
    time="2018-05-24T09:42:02+08:00" level=info msg="Recv RestRequest" ReqHeader=map[Date:[2018-03-29T09:32:35+08:00] Accept:[application/json]] ReqId="ExtHwyApi_QLlUyYd9To" Url="/ext/api/product"
    time="2018-05-24T09:42:02+08:00" level=warning msg="AuthTimeOut Disable" AuthTimeOutSeconds=0 ReqId="ExtHwyApi_QLlUyYd9To"
    time="2018-05-24T09:42:03+08:00" level=error msg="RestDispatch Fail" ReqBody="{"seq":"ExtHwyApi_QLlUyYd9To","var":1}}" ReqId="ExtHwyApi_QLlUyYd9To" ResBody="{"Code":"812018","Msg":"发送失败"}" Tag="out_ccm" zcallstack="[email protected]:43 Handler@ext_hwy_api.go:44" zerror="dial tcp 127.0.0.1:5010: connectex: No connection could be made because the target machine actively refused it."
    ```
    xrlin
        8
    xrlin  
    OP
       May 24, 2018
    @ppyybb 异常的话一般都会记录下,就是一些问题追踪比较难以排查,特别是遇到一些不常遇到的问题,这时如果没有记录下日志不好分析。
    xrlin
        9
    xrlin  
    OP
       May 24, 2018
    @ppyybb 不过再想想,遇到不是异常而是某些逻辑分支的情况,即便的打上 log,也是设定为 info,在线上也不会启用,遇到问题出现时才启用记录。
    lolizeppelin
        10
    lolizeppelin  
       May 24, 2018 via Android
    Python 可以看看 openstack 的做法

    配置里可以控制每个模块代码块的日志等级
    EmdeBoas
        11
    EmdeBoas  
       May 24, 2018
    平时都是无脑用 CAT...没想过这个问题..回头好好看看 CAT 里面怎么实现的
    ywind
        12
    ywind  
       May 24, 2018 via Android
    m
    zj299792458
        13
    zj299792458  
       May 24, 2018 via iPhone
    我想问问如果日志过多,比如播放视频的每一帧信息都记入日志,微秒级别记录,直接往文件操作符里写会阻塞正常逻辑么?还是一般自己实现 cache ?
    yhding
        14
    yhding  
       May 24, 2018
    我一直有个想法但是没有具体实现,就是在打印日志的时候写的详细一些,
    比如: 文件路径 + 行数 + 想输出的信息.
    大佬看如何啊
    lxml
        15
    lxml  
       Dec 11, 2018
    @yhding #14 调用 runtime 包就行了,缺点是性能差成狗
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3605 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 65ms · UTC 11:14 · PVG 19:14 · LAX 04:14 · JFK 07:14
    ♥ Do have faith in what you're doing.