python输出json格式log,方便LogStash收集

韦宏朗
2023-12-01

为了配合LogStash日志收集服务,需要将线上服务的日志输出改为json格式。python日志标准库中并没有json格式的formatter,网上虽然已经有一些json相关的formatter,但不是很满意,就自己开发了一个并放到了github和pypi,目前仅支持Python3,现已支持python2.7python3,能够很方便的解决自定义名映射属性问题,也支持新增自定义属性

欢迎到我的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安装:

$ pip install jsonformatter

克隆github源码手工安装:

$ git clone https://github.com/MyColorfulDays/jsonformatter.git
$ cd jsonformatter
$ python setup.py install
 类似资料: