python⽇志输出的内容修改为json格式
业务中要求,python项⽬的⽇志输出为json串,同时包括异常;经过查看python logging相关的源码,发现还不能完全的兼容;⽐如异常的源码那⾥:
class Formatter(object):
"""省略"""
def format(self, record):
if self.usesTime():
record.asctime = self.formatTime(record, self.datefmt)
s = self.formatMessage(record)
_info:
python格式化输出format# Cache the traceback text to avoid converting it multiple times
# (it's constant anyway)
if _text:
<_text = self._info)
_text:
if s[-1:] != "\n":
s = s + "\n"
s = s + _text
if record.stack_info:
if s[-1:] != "\n":
s = s + "\n"
s = s + self.formatStack(record.stack_info)
return s
logging.Formatter的format⽅法,⾸先会按照格式化串格式化message,然后如果出现异常,是直接再message后⾯加上异常;此时格式已经不是指定的格式,因此这⾥需要修⾃定义。
# -*- coding:utf-8 -*-
import json
import logging
import os
import traceback
BASE_DIR = os.path.wd())
LOG_DIR = os.path.join(BASE_DIR,  "logs")
host_ip ="localhost"
JSON_LOGGING_FORMAT = json.dumps({
"ip": "%(ip)s",
"app": "%(app)s",
"level": "%(levelname)s",
"trace": "%(stack_msg)s",
"filepath": "%(pathname)s",
"line_number": "%(lineno)s",
"time": "%(asctime)s",
"message": "%(message)s",
"stack_trace": "%(exc_text)s"
})
class JsonLoggingFilter(logging.Filter):
def__init__(self, name, ip, app):
logging.Filter.__init__(self, name=name)
self.ip = ip
self.app = app
def filter(self, record):
record.ip = self.ip
record.app = self.app
# 为record 添加异常堆栈信息字段; 当有多个handler 的时候,这⾥会判断多次
if hasattr(record, "stack_msg") and hasattr(record, "stack_trace"):
return True
_info:
ex_type, ex_val, ex_stack = _info
stack_list = []
for stack act_tb(ex_stack):
stack_list.append("%s" % stack)
record.stack_msg = ex_val
record.stack_trace = "#".join(stack_list)
else:
record.stack_msg, record.stack_trace = "", ""
return True
class JsonFormatter(logging.Formatter):
def__init__(self, fmt=None):
logging.Formatter.__init__(self, fmt=fmt)
def format(self, record):
if self.usesTime():
record.asctime = self.formatTime(record, self.datefmt)
_info:
# Cache the traceback text to avoid converting it multiple times
# (it's constant anyway)
if _text:
<_text = self._info).replace("\n", "").replace("\"", "'")        s = self.formatMessage(record)
return s
class JsonLogger(logging.Logger):
logger = None
level = None
mode = None
def__init__(self, app_name, level=logging.DEBUG, console_level=logging.INFO, mode="w"):
self.name = app_name
self.app_name = app_name
logging.Logger.__init__(self, name=app_name)
self.logger = logging.Logger(name=app_name)
self.logger.setLevel(level)
if not ists(LOG_DIR):
os.makedirs(LOG_DIR)
log_file_path = os.path.join(LOG_DIR, "%s.json" % app_name)
json_logging_filter = JsonLoggingFilter(app_name, ip=host_ip, app=app_name)
json_formatter = JsonFormatter(JSON_LOGGING_FORMAT)
# ⽂件⽇志
file_handle = logging.FileHandler(log_file_path, mode=mode)
file_handle.setLevel(level)
file_handle.setFormatter(json_formatter)
file_handle.addFilter(json_logging_filter)
# 控制台⽇志
console_handle = logging.StreamHandler()
console_handle.setLevel(console_level)
console_handle.setFormatter(json_formatter)
console_handle.addFilter(json_logging_filter)
self.logger.addHandler(file_handle)
self.logger.addHandler(console_handle)
def getLogger(self):
return self.logger
def setLevel(self, level):
self.logger.level = level
if__name__ == '__main__':
my_logger = JsonLogger("python-common").getLogger()
my_logger.info("info  level log")
try:
open('/path/to/does/not/exist', 'rb')
except FileNotFoundError as e:
ption("file exception", exc_info=e)
参考:
关于异常
⽇志输出 json串

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。