你写过Python程序吧。写完后跑起来,发现报错了。你打开控制台,看到一堆刷屏的信息。时间戳看不懂,日志级别也混在一起,根本分不清哪些是错误,哪些是普通输出。你只好一句一句看,最后发现要找的那条错误信息藏在几百行无关日志里。这种感觉糟透了。
很多人在Python里写日志,就是print('开始处理数据'),print('处理完成')。看起来挺简单。等程序一上线,数据量大了,问题就全出来了。print出来的东西没有格式,没有时间,没有文件位置。出问题时你根本不知道是哪一行代码打出来的,也不知道这个日志是多久前的。
给你看一个真实案例。我去年帮一个团队排查线上问题。他们的日志是这么写的:
import logging
logging.basicConfig(level=logging.INFO)
logging.info('用户登录成功')
看着没什么问题对吧。可当系统每秒处理几百次登录时,控制台全是'用户登录成功'。哪天某个用户登录失败,那条错误信息就被淹没在其他成功日志里。他们查了整整两天,最后发现是数据库连接超时。
好的日志配置,应该让问题自己跳出来。我用了几年时间,反复调整,找到了一套很实用的配置。你把这段代码复制到项目里,线上排查时间至少能省一半。
第一步,设置日志格式。别用默认格式。你得加上时间戳、文件名、行号、日志级别。这样哪行代码出的问题,几秒前出的,一眼就能看出来。配置长这样:
import logging
logging.basicConfig(
format='%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
这个格式出来后,每条日志都带着精确的时间。比如 2024-03-15 14:32:17 - ERROR - user_service.py:42 - 数据库连接失败。你一看就知道是哪个文件的第42行出了问题,时间也精确到秒。
第二步,区分日志级别。很多人习惯只用info和error。不够。你需要用上debug, info, warning, error, critical这五级。日常运行只输出info及以上,debug信息留在开发环境。线上出问题时,临时调成debug级别,就能看到所有细节。不用每次都改代码。
import logging
import sys
控制台输出warning及以上
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.WARNING)
文件记录所有级别
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)
这么设置后,控制台只显示警告和错误,不会被正常日志刷屏。同时所有信息都写入文件,方便事后回头看。
第三步,日志文件要轮转。你肯定遇到过日志文件越来越大,最后打不开的情况。用TimedRotatingFileHandler,按天或者按文件大小拆分。比如每天一个日志文件,保留30天。
from logging.handlers import TimedRotatingFileHandler
import logging
handler = TimedRotatingFileHandler(
'app.log',
when='midnight',
backupCount=30
)
这样每天零点自动生成新文件,旧文件压缩归档。你随时可以查看某一天的完整日志,查完就删,不占空间。
第四步,加上请求ID。如果是web服务,最好给每个请求生成一个唯一ID。这样你能把同一次请求的所有日志串起来。比如用户A发起一个请求,它经过接口、数据库、缓存,每一步的日志都会带上相同的请求ID。出问题时,你只需要搜这个ID,就能看到完整的调用链。
import uuid
import logging
class RequestIdFilter(logging.Filter):
def filter(self, record):
record.request_id = getattr(threading.current_thread(), 'request_id', 'N/A')
return True
把这个filter加到你logger上,每条日志自动带上请求ID。排查问题时,用grep搜这个ID,结果一目了然。
这套配置我用在不同项目上,效果都很好。以前排查问题要翻半小时日志,现在五分钟找到根因。你拿去用,稍微调整下时间格式和日志路径就行。
有个小提醒。别在生产环境打印敏感信息。密码、身份证号、银行卡号,这些都不能写到日志里。你可以在配置里加个过滤器,自动替换敏感字段。安全第一。
还是那句话,日志不是为了写而写,是为了排查问题而写。配置好了,它能帮你省下大把时间。下次你程序崩了,不用再对着满屏的print抓狂了。