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

2019-11-19 14:55:24 +08:00
 NeverBelieveMe

-- 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 这种混在一起打印的情况。想知道有没有什么办法解决

4875 次点击
所在节点    Python
19 条回复
valkyrja
2019-11-19 15:04:48 +08:00
用 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
2019-11-19 15:08:53 +08:00
楼上+1,两个请求本来就是并发的,给每个请求分配一个唯一 ID
panyanyany
2019-11-19 15:10:10 +08:00
logger 最好是一个模块用一个 logger = logging.getLogger(__name__),不要一个 logger 在不同的模块引用来引用去的
locoz
2019-11-19 15:11:56 +08:00
我的接口服务在打日志的时候是用的 JSONLogger,然后每个日志里面都带上了一个请求初始化时生成的 request_id,在 Kibana 里查的时候直接搜 request_id 就能看到某一次请求的所有日志了。
itskingname
2019-11-19 15:26:45 +08:00
使用第三方库 loguru,不要用自带的 logging 模块,就能解决你这个问题。
forrestchang
2019-11-19 15:28:16 +08:00
日志统一放到一个消息队列里,然后开一个 job 来处理这些日志。
Roney
2019-11-19 16:21:25 +08:00
@forrestchang 正解
TypeErrorNone
2019-11-19 16:30:29 +08:00
在中间件里给每个请求加上 request_id,打日志的时候记录 request_id
flyingghost
2019-11-19 16:39:46 +08:00
日志汇总吧,并发请求就会交错起来,不方便跟踪一个请求(一个业务)的日志。
按请求分开吧,日志之间的时序关系就会丢失,不方便观察服务器状态,尤其是一些请求无关的全局的状态和资源。

各有利弊。

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

```
[2019-11-19 16:45:05 472][DEBUG][7e42d668] logger
```
tiedan
2019-11-19 17:41:47 +08:00
加 trace_id 想找哪个请求,用 trace_id 过滤即可
kaid97
2019-11-19 17:42:45 +08:00
并行肯定会的阿。。你要不封装一层加个队列,不然无解
sunhk25
2019-11-19 17:52:07 +08:00
学习,顺便问一下这种日志放到文件里好还是放到 db 中好呢
1462326016
2019-11-19 18:42:00 +08:00
要么单例要么队列
NeverBelieveMe
2019-11-20 09:47:33 +08:00
@valkyrja request id 在 logging.Formatter 里面能定义这个字段么?还是自己在打印的时候加上去?
NeverBelieveMe
2019-11-20 09:49:18 +08:00
@flyingghost 关键业务日志独立是怎么做到的?
mxy940127
2019-11-20 10:03:02 +08:00
flask 不是有个 before_request 和 after_request 的钩子么,为什么不在那个钩子里写日志呢. trace_id 或者 request_id 自己建一个 uuid,写入日志就行

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/621041

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX