不论运行程序的平台是 docker 还是 k8s,采集日志有两种计划:
- 计划一:采集程序的规范输入
- 计划二:程序把日志写文件中,而后采集日志文件
在先来剖析一下计划一和二的好坏
计划一的害处就是:『多行日志采集』
不论是用『行首正则表达式』还是『json 化』都不是优雅的解决方案
『行首正则表达式』,不是所有模块的日志都有固定格局,当然,想要强制统一也有方法;『json 化』:没有格式化的 json 是人类不可读的,『json 化』不便了程序,然而恶心了程序员的眼睛
所以,pass
计划二:没有毛病
我怎么用的:程序,即打印日志到规范输入,又写入日志文件
- 打印日志到规范输入:这是给人看到,能够间接应用 docker logs、docker-compose logs、kubectl logs 间接看,不便
- 写入日志文件:应用 loguru 的 serialize=’json’ 将单条日志写入日志文件
所以这些日志输入计划,及满足了程序员间接查看日志,也不便程序的采集。
那具体如何实现呢?间接上代码
from loguru import logger
from mark import BASE_DIR
import settings
import os
import json
from loguru._handler import Handler
from loguru._recattrs import RecordException
log_path = BASE_DIR/'logs'
if not os.path.exists(log_path):
os.makedirs(log_path)
def _serialize_record(text: str, record: dict):
exception: RecordException = record["exception"]
if exception is not None:
exception = {
"type": None if exception.type is None else exception.type.__name__,
"value": exception.value,
"traceback": bool(exception.traceback),
}
serializable = {
"text": text,
"record": {"extra": record["extra"],
},
}
return json.dumps(serializable, default=str, ensure_ascii=False) + "\n"
Handler._serialize_record = staticmethod(_serialize_record)
logger.add(
log_path/'run.log',
serialize='json',
rotation='100 MB',
retention=1
)
最重要的就是上面这段,咱们增加一个日志处理器,用于将日志写到文件中
第一个参数指定,写哪里
第二个参数指定,用什么格局写,这里用 json,因为这样能够防止『打印堆栈谬误会多行』的问题
第三、四个参数指定,示意日志轮换规定,写慢 100 MB,就备份一下,而后从 0MB 从新开始,总共有 1 份
logger.add(
log_path/'run.log',
serialize='json',
rotation='100 MB',
retention=1
)
loguru 应用 serialize=’json’ 默认输入的字段太多了,所以咱们应用猴子补丁,替换 _serialize_record
函数,去掉不须要的字段,节约日志存储老本
参考文章:
loguru 如何轮换日志
loguru serialize 缩小字段
如何应用 loguru 接管程序的所有日志输入