用于python标准库日志记录模块的gelf格式化程序。
gelf-formatter的Python项目详细描述
凝胶形成剂
Graylog Extended Log Format (GELF)用于
Python标准库logging模块的格式化程序
动机
有几个包提供了标准库日志模块的handlers,该模块可以通过tcp/udp/http将应用程序日志发送到Graylog(py-gelf是一个很好的例子)。尽管这些功能很有用,但是仅仅为了传递日志而使应用程序的性能依赖于网络请求并不理想。
或者,您可以简单地登录到一个文件或stdout
,让一个收集器(比如Fluentd)处理并异步地将这些日志发送到远程服务器(而不仅仅是graylog,因为gelf可以用作通用的日志格式),这是容器化应用程序的常见模式。在这样的场景中,我们只需要一个GELF日志formatter
功能
- 支持任意附加字段;
- 支持将保留的^{
} 属性包含为附加字段 - 带有回溯格式的异常检测
- 零依赖和微小的足迹。
安装
pip
$ pip install gelf-formatter
来源
$ python setup.py install
用法
只需创建一个gelfformatter.GelfFormatter
实例并将其作为参数传递给^{
importsysimportloggingfromgelfformatterimportGelfFormatterformatter=GelfFormatter()handler=logging.StreamHandler(sys.stdout)handler.setFormatter(formatter)
使用^{
logging.basicConfig(level=logging.DEBUG,handlers=[handler])
logger=logging.getLogger('my-app')logger.addHandler(handler)
就这样。现在可以像往常一样使用日志模块,所有记录都将格式化为GELF消息
标准字段
格式化程序将输出GELF Payload Specification (version 1.1):
version
:字符串,始终设置为1.1
;host
:字符串,初始化时^{} 的输出;short_message
:字符串,日志记录消息full_message
(可选):字符串,格式化的异常回溯(如果有);timestamp
:数字,以秒为单位的时间,从纪元开始作为浮点level
:整数,syslog严重级别
不能忽略、重命名或重写这些字段
示例
logging.info("Some message")
{"version":"1.1","host":"my-server","short_message":"Some message","timestamp":1557342545.1067393,"level":6}
例外情况
full_message
字段用于存储异常的回溯你只需要用^{
示例
importurllib.requestreq=urllib.request.Request('http://www.pythonnn.org')try:urllib.request.urlopen(req)excepturllib.error.URLErrorase:logging.exception(e.reason)
{"version": "1.1", "short_message": "[Errno -2] Name or service not known", "timestamp": 1557342714.0695107, "level": 3, "host": "my-server", "full_message": "Traceback (most recent call last):\n ...(truncated)... raise URLError(err)\nurllib.error.URLError: <urlopen error [Errno -2] Name or service not known>"}
其他字段
GELF规范允许任意附加字段,键的前缀为下划线
要包含其他字段,请使用标准的loggingextra
关键字。键将自动以下划线作为前缀(如果还没有)。
示例
logging.info("request received",extra={"path":"/orders/1","method":"GET"})
{"version": "1.1", "short_message": "request received", "timestamp": 1557343604.5892842, "level": 6, "host": "my-server", "_path": "/orders/1", "_method": "GET"}
保留字段
默认情况下,格式化程序忽略所有^{
为此,只需在初始化GelfFormatter
时将LogRecord
属性名的列表作为allowed_reserved_attrs
关键字的值传递。您还可以修改已经初始化的格式化程序的allowed_reserved_attrs
实例变量。
示例
attrs=["lineno","module","filename"]formatter=GelfFormatter(allowed_reserved_attrs=attrs)# orformatter.allowed_reserved_attrs=attrslogging.debug("starting application...")
{"version": "1.1", "short_message": "starting application...", "timestamp": 1557346554.989846, "level": 6, "host": "my-server", "_lineno": 175, "_module": "myapp", "_filename": "app.py"}
您可以选择使用^{
上下文字段
能够一次性定义一组附加字段并将它们包含在所有日志消息中,对于避免重复的键/值对和启用上下文日志记录非常有用。
python的日志模块提供了几个选项来向日志添加上下文,其中我们突出显示了^{
在这两者之间,我们建议logging.Filter
,它更简单,可以直接附加到^{logging.basicConfig
)使用logging.Filter
。如果您选择LoggerAdapter
,则需要logging.Logger
来包装
您还可以使用logging.Filter
来重用/重命名任何保留的logging.LogRecord
属性
示例
classContextFilter(logging.Filter):deffilter(self,record):# Add any number of arbitrary additional fieldsrecord.app="my-app"record.app_version="1.2.3"record.environment=os.environ.get("APP_ENV")# Reuse any reserved `logging.LogRecord` attributesrecord.file=record.filenamerecord.line=record.linenoreturnTrueformatter=GelfFormatter()handler=logging.StreamHandler(sys.stdout)handler.setFormatter(formatter)handler.addFilter(ContextFilter())logging.basicConfig(level=logging.DEBUG,handlers=[handler])logging.info("hi",extra=dict(foo="bar"))
{"version": "1.1", "short_message": "hi", "timestamp": 1557431642.189755, "level": 6, "host": "my-server", "_foo": "bar", "_app": "my-app", "_app_version": "1.2.3", "_environment": "development", "_file": "app.py", "_line": 159}
漂亮的印花
要找一个漂亮的盖尔夫日志打印机吗?如果是,请看gelf-pretty:fire:
贡献
这个项目遵守贡献者契约code of conduct。通过参与,您将遵守本准则。请参阅我们的contributing guide了解更多信息。