为了配合LogStash日志收集服务,需要将线上服务的日志输出改为json格式。python日志标准库中并没有json格式的formatter,网上虽然已经有一些json相关的formatter,但不是很满意,就自己开发了一个并放到了github和pypi,目前仅支持Python3,现已支持python2.7和python3,能够很方便的解决自定义名映射属性问题,也支持新增自定义属性。
欢迎到我的github点星星、提问题:
https://github.com/MyColorfulDays/jsonformatter
LogRecord属性介绍可参考Python官网地址:
https://docs.python.org/3/library/logging.html#logrecord-attributes
# 自定义属性
# key代表LogRecord新增/替换的属性名称
# value必须`callable`类型,且不支持参数
CUSTOM_ATTRS = {
"session_id": lambda : str(random.random())[2:10]
}
# 输出格式配置
# 支持json字符串,OrderedDict,dict(由于Python3.7之前dict是无序的,所以3.7之前的版本推荐使用OrderedDict或json字符串)
# key的值可任意
# value必须是LogRecord的属性或新增的自定义属性
# value也可以是“%(attribute)s/d/f”,它将被转为字符串格式输出,不再保持LogRecord属性的原类型
# value如果包含多个LogRecord的属性,必须为“%(attribute)s/d/f”格式拼接
# message若不属于`str, int, float, bool, type(None)`,会自动被转为字符串(防止输出日志时报错:xxx type is not JSON serializable.)
STRING_FORMAT = '''{
"@timestamp": "asctime",
"Module": "module",
"Lineno": "lineno",
"Str Lineno": "%(lineno)d",
"Level": "levelname",
"Session Id": "session_id",
"Multi Attrs": "%(module)s - %(lineno)d: %(funcName)s ",
"Message": "message"
}'''
$ python test_jsonformatter.py
{
"@timestamp": "2019-07-12 16:43:36,889",
"Module": "test_jsonformatter",
"Lineno": 46,
"Str Lineno": "46",
"Level": "INFO",
"Session Id": "51916201",
"Multi Attrs": "test_jsonformatter - 46: test_logger ",
"Message": 1
}
{
"@timestamp": "2019-07-12 16:43:36,889",
"Module": "test_jsonformatter",
"Lineno": 47,
"Str Lineno": "47",
"Level": "INFO",
"Session Id": "10761601",
"Multi Attrs": "test_jsonformatter - 47: test_logger ",
"Message": "{}"
}
{
"@timestamp": "2019-07-12 16:43:36,889",
"Module": "test_jsonformatter",
"Lineno": 48,
"Str Lineno": "48",
"Level": "INFO",
"Session Id": "42298281",
"Multi Attrs": "test_jsonformatter - 48: test_logger ",
"Message": "测试参数: arg1"
}
test_jsonformatter.py
import logging
import random
from jsonformatter import JsonFormatter
# 自定义属性
# key代表LogRecord新增/替换的属性名称
# value必须`callable`类型,且不支持参数
CUSTOM_ATTRS = {
"session_id": lambda : str(random.random())[2:10]
}
# 输出格式配置
# 支持json字符串,OrderedDict,dict(由于Python3.7之前dict是无序的,所以3.7之前的版本推荐使用OrderedDict或json字符串)
# key的值可任意
# value必须是LogRecord的属性或新增的自定义属性
# value也可以是“%(attribute)s/d/f”,它将被转为字符串格式输出,不再保持LogRecord属性的原类型
# value如果包含多个LogRecord的属性,必须为“%(attribute)s/d/f”格式拼接
# message属性若不属于`str, int, float, bool, type(None)`,会自动被转为字符串(防止输出日志是报错:xxx type is not JSON serializable.)
STRING_FORMAT = '''{
"@timestamp": "asctime",
"Module": "module",
"Lineno": "lineno",
"Str Lineno": "%(lineno)d",
"Level": "levelname",
"Session Id": "session_id",
"Multi Attrs": "%(module)s - %(lineno)d: %(funcName)s ",
"Message": "message"
}'''
def config_logger():
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# JsonFormatter支持`json.dumps`的所有可选参数
formatter = JsonFormatter(STRING_FORMAT, record_custom_attrs=CUSTOM_ATTRS, indent=4, ensure_ascii=False)
sh = logging.StreamHandler()
sh.setFormatter(formatter)
sh.setLevel(logging.INFO)
logger.addHandler(sh)
def test_logger():
logger = logging.getLogger()
logger.info(1)
logger.info({})
logger.info("测试参数: %s", 'arg1')
if __name__=='__main__':
config_logger()
test_logger()
日志的配置也支持通过配置文件方式设置,可以到我的github查看。
$ pip install jsonformatter
$ git clone https://github.com/MyColorfulDays/jsonformatter.git
$ cd jsonformatter
$ python setup.py install