V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
NeverBelieveMe
V2EX  ›  Python

多接口写日志的时候,日志会重叠起来,怎么解决

  •  
  •   NeverBelieveMe · 2019-11-19 14:55:24 +08:00 · 5091 次点击
    这是一个创建于 1838 天前的主题,其中的信息可能已经有所发展或是发生改变。

    -- coding: utf-8 --

    import logging import os class Log(object):

    def __init__(self, name, ):
        self.name = name
        self.path = os.getcwd() + "/logs/"
        self.formatter = logging.Formatter("%(asctime)s - %(filename)s -[line:%(lineno)d] - %(levelname)s: %(message)s",
                                           "%Y-%m-%d %H:%M:%S")
    
    def getLogger(self):
        logger = logging.getLogger(self.name)
        logger.setLevel(logging.DEBUG)
    
        logger.addHandler(self.get_console_handler())
        return logger
    
    def get_console_handler(self):
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.DEBUG)
        console_handler.setFormatter(self.formatter)
        return console_handler
    

    flask_logger = Log(name="flask").getLogger()

    上面是代码。 遇到的情况是在 a.pyb.py 文件分别引入了 flask_logger,接口 A 和接口 B 分别是 logger.info(“A start")...logger.info(“A end")和 logger.info(“B start")...logger.info(“B end"),在接口被频繁调用的时候,就会出现 A start B start B end A end 这种混在一起打印的情况。想知道有没有什么办法解决

    19 条回复    2019-11-20 10:03:02 +08:00
    valkyrja
        1
    valkyrja  
       2019-11-19 15:04:48 +08:00   ❤️ 2
    用 nginx 的话,可以使用 nginx 的 request id,应用通过 request id 串联请求内的日志: https://www.nginx.com/blog/application-tracing-nginx-plus/

    不用 nginx 就自己生成 request id 放到 flask 上下文: https://flask.palletsprojects.com/en/1.0.x/appcontext/
    conn4575
        2
    conn4575  
       2019-11-19 15:08:53 +08:00 via Android
    楼上+1,两个请求本来就是并发的,给每个请求分配一个唯一 ID
    panyanyany
        3
    panyanyany  
       2019-11-19 15:10:10 +08:00
    logger 最好是一个模块用一个 logger = logging.getLogger(__name__),不要一个 logger 在不同的模块引用来引用去的
    locoz
        4
    locoz  
       2019-11-19 15:11:56 +08:00
    我的接口服务在打日志的时候是用的 JSONLogger,然后每个日志里面都带上了一个请求初始化时生成的 request_id,在 Kibana 里查的时候直接搜 request_id 就能看到某一次请求的所有日志了。
    itskingname
        5
    itskingname  
       2019-11-19 15:26:45 +08:00
    使用第三方库 loguru,不要用自带的 logging 模块,就能解决你这个问题。
    forrestchang
        6
    forrestchang  
       2019-11-19 15:28:16 +08:00
    日志统一放到一个消息队列里,然后开一个 job 来处理这些日志。
    Roney
        7
    Roney  
       2019-11-19 16:21:25 +08:00
    @forrestchang 正解
    TypeErrorNone
        8
    TypeErrorNone  
       2019-11-19 16:30:29 +08:00
    在中间件里给每个请求加上 request_id,打日志的时候记录 request_id
    flyingghost
        9
    flyingghost  
       2019-11-19 16:39:46 +08:00   ❤️ 1
    日志汇总吧,并发请求就会交错起来,不方便跟踪一个请求(一个业务)的日志。
    按请求分开吧,日志之间的时序关系就会丢失,不方便观察服务器状态,尤其是一些请求无关的全局的状态和资源。

    各有利弊。

    我的做法是:
    1,默认日志按时序,需要的时候用 requestID 来过滤就可以方便的按照请求来查看日志序列。全局时序也方便日志切割、轮转、储存、查找等大部分场景。
    2,关键业务日志独立,按业务来冗余记录。比如一个用户 /一个订单的所有日志。
    3,以上两点结合也比较方便。输入还是正常输入,输出独立多个 Adapter,按不同规则去路由到不同文件即可。
    robinlovemaggie
        10
    robinlovemaggie  
       2019-11-19 17:27:43 +08:00
    a.py --> a stream--> a.log
    b.py --> b stream -->b.log
    Varobjs
        11
    Varobjs  
       2019-11-19 17:39:44 +08:00
    1. 并发写日志肯定会窜行
    2. 可以先把日志写到内存,生命周期结束统一刷到磁盘,减少窜行可能性
    3. 最后就是,每个生命周期,完全可以加个 reqId 的静态变量,每行日志加上[reqId] 前缀
    Varobjs
        12
    Varobjs  
       2019-11-19 17:41:45 +08:00
    类似这种

    ```
    [2019-11-19 16:45:05 472][DEBUG][7e42d668] logger
    ```
    tiedan
        13
    tiedan  
       2019-11-19 17:41:47 +08:00
    加 trace_id 想找哪个请求,用 trace_id 过滤即可
    kaid97
        14
    kaid97  
       2019-11-19 17:42:45 +08:00
    并行肯定会的阿。。你要不封装一层加个队列,不然无解
    sunhk25
        15
    sunhk25  
       2019-11-19 17:52:07 +08:00 via Android
    学习,顺便问一下这种日志放到文件里好还是放到 db 中好呢
    1462326016
        16
    1462326016  
       2019-11-19 18:42:00 +08:00
    要么单例要么队列
    NeverBelieveMe
        17
    NeverBelieveMe  
    OP
       2019-11-20 09:47:33 +08:00
    @valkyrja request id 在 logging.Formatter 里面能定义这个字段么?还是自己在打印的时候加上去?
    NeverBelieveMe
        18
    NeverBelieveMe  
    OP
       2019-11-20 09:49:18 +08:00
    @flyingghost 关键业务日志独立是怎么做到的?
    mxy940127
        19
    mxy940127  
       2019-11-20 10:03:02 +08:00
    flask 不是有个 before_request 和 after_request 的钩子么,为什么不在那个钩子里写日志呢. trace_id 或者 request_id 自己建一个 uuid,写入日志就行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   970 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:16 · PVG 04:16 · LAX 12:16 · JFK 15:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.