跳转到主要内容

半结构化日志消息的基础设施。

项目描述

gocept.logging

https://github.com/gocept/gocept.logging/workflows/tests/badge.svg https://coveralls.io/repos/github/gocept/gocept.logging/badge.svg

本包提供半结构化日志消息的基础设施。

这意味着在自由文本日志消息之后附加易于解析的信息,以便稍后分析日志。Python标准库中的logging模块已经通过extra参数支持此功能。gocept.logging提供了一个Formatter,该Formatter提取这些extra值,将它们格式化为key=value对,并将其附加到消息上

>>> import gocept.logging
>>> import logging
>>> import sys

>>> handler = logging.StreamHandler(sys.stdout)
>>> handler.setFormatter(gocept.logging.SyslogKeyValueFormatter())
>>> log = logging.getLogger('example')
>>> log.addHandler(handler)
>>> log.warning('Hello, world!', extra={'foo': 'bar'})
Aug 24 12:10:08 localhost example: Hello, world! foo=bar

本软件包经过测试,与Python 2.7和3.3版本兼容。

高级用法

如果您有一些始终希望传递给日志消息的额外值(例如当前用户、会话ID等),您可以使用预填充这些值的LoggerAdapter包装您的记录器。gocept.logging提供了一种允许堆叠适配器并覆盖预填充值的适配器。

>>> from gocept.logging.adapter import StaticDefaults
>>> import logging

>>> log = logging.getLogger('advanced')
>>> log = StaticDefaults(log, {'foo': 'bar', 'qux': 'baz'})
>>> log = StaticDefaults(log, {'blam': 'splat'})
>>> log.warning('Hello, world!', extra={'foo': 'override'})
    # yields {'foo': 'override', 'qux': 'baz', 'blam': 'splat'}

测试支持

为了帮助检查额外值,gocept.logging附带了一个专门用于测试的处理程序。

>>> import gocept.logging
>>> import logging

>>> log = logging.getLogger('testing')
>>> handler = gocept.logging.TestingHandler()
>>> log.addHandler(handler)
>>> log.warning('Hello, world!', extra={'foo': 'bar'})
>>> handler.messages[0].extra['foo']
'bar'

TestingHandler将每个日志消息记录为类型为gocept.logging.testing.LogMessage的namedtuple,因此您可以轻松访问消息的所有部分。

示例配置

创建半结构化日志消息是问题的一半,而分析它们是另一半。我们为此目的使用logstash

推荐的设置是

application -> syslogd on localhost -> logstash on central host (via UDP syslog input)

对于开发,您可能希望省略中间人,并将应用程序配置为通过syslog协议直接将日志消息发送到logstash。

使用ini文件设置

如果您有应用程序的paste.ini,您可能可以使用以下内容

[loggers]
keys = root

[handlers]
keys = console, syslog

[formatters]
keys = generic, keyvalue

[logger_root]
level = INFO
handlers = console, syslog

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(asctime)s %(levelname)-5.5s %(name)s: %(message)s

[handler_syslog]
class = logging.handlers.SysLogHandler
args = ()
formatter = keyvalue

[formatter_keyvalue]
class = gocept.logging.SyslogKeyValueFormatter

使用ZConfig设置

如果您有Zope应用程序,您可能可以使用以下内容

<eventlog>
  <logfile>
    formatter zope.exceptions.log.Formatter
    format %(asctime)s %(levelname)-5.5s %(name)s: %(message)s
    path STDOUT
  </logfile>
  <syslog>
    formatter gocept.logging.SyslogKeyValueFormatter
  </syslog>
</eventlog>

syslogd配置

rsyslog

$EscapeControlCharactersOnReceive off
$MaxMessageSize 64k
user.* @localhost:5140

前两行是为了支持多行且可能占用一些空间的跟踪回溯。最后一行告诉rsyslogd将user设施的所有消息(这是stdlib logging默认使用的)通过syslog UDP协议转发到本机的5140端口(logstash可能在此端口上监听)。

logstash配置

input {
        tcp {
                host => "localhost"
                port => 5140
                type => syslog
        }
        udp {
                host => "localhost"
                port => 5140
                type => syslog
        }
}

filter {
        grok {
                type => "syslog"
                pattern => [ "(?m)<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" ]
        }
        syslog_pri {
                type => "syslog"
        }
        date {
                type => "syslog"
                match => [ "syslog_timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]
        }
        mutate {
                type => "syslog"
                exclude_tags => "_grokparsefailure"
                replace => [ "@source_host", "%{syslog_hostname}" ]
                replace => [ "@message", "%{syslog_program}: %{syslog_message}" ]
        }
        mutate {
                type => "syslog"
                remove => [ "syslog_hostname", "syslog_timestamp" ]
        }
        kv {
                exclude_tags => "_grokparsefailure"
                type => "syslog"
        }
}

output {
        elasticsearch { embedded => true }
}

其他功能

ArgumentParser

提供的gocept.logging.ArgumentParser提供了在运行脚本中设置logging级别的功能。

from gocept.logging import ArgumentParser
parser = ArgumentParser()
# Optionally set a custom log format, defaults to ``logging.BASIC_FORMAT``
parser.LOG_FORMAT = 'LOG:%(message)s'
# add your arguments with parser.add_argument() here
options = parser.parse_args()

使用your_run_script --help查看有关可以传递以设置日志级别的参数的帮助信息。

已知错误

如果您以Unicode格式记录消息,例如log.info(u'foo'),SyslogHandler将(不正确地)预置一个字节顺序标记,这会混淆logstash解析器,导致“_grokparsefailure”。这是Python标准库中的一个已知问题,已在Python-2.7.4中修复。

开发gocept.logging

作者:

gocept <mail@gocept.com>

PyPI页面:

http://pypi.python.org/pypi/gocept.logging/

问题:

通过电子邮件报告

源代码:

https://github.com/gocept/gocept.logging

当前变更日志:

https://raw.githubusercontent.com/gocept/gocept.logging/master/CHANGES.rst

gocept.logging变更日志

1.0 (2023-07-18)

  • 停止支持Python 2.7、3.3、3.4、3.5、3.6。

  • 增加对Python 3.7、3.8、3.9、3.10、3.11的支持。

  • StaticDefaults添加一个别名.warn(#1)。

0.8.1 (2017-01-09)

  • 修复setup.py以使用相对路径。

0.8 (2016-03-17)

  • 声明与PyPy和PyPy3的兼容性。

0.7 (2015-09-29)

  • 声明Python 3.5兼容性。

0.6 (2015-09-17)

  • 声明Python 3.4兼容性。

  • ArgumentParser.parse_args()现在在返回值的log_level属性上存储计算出的日志级别。

0.5 (2014-02-07)

  • 允许更改ArgumentParser的日志格式。

0.4 (2013-09-24)

  • 正确处理非字符串日志消息。

0.3 (2013-09-04)

  • 添加了一个专门的argparse.ArgumentParser,允许用户默认设置logging级别。

0.2 (2013-08-24)

  • 将时间戳和主机名添加到syslog消息中,这允许直接将SyslogKeyValueFormatter连接到logstash,而无需中间syslogd。

0.1 (2013-08-16)

  • 首次发布

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分布

gocept.logging-1.0.tar.gz (12.9 kB 查看哈希值)

上传时间 源代码

构建分布

gocept.logging-1.0-py2.py3-none-any.whl (11.5 kB 查看哈希值)

上传时间 Python 2 Python 3

支持者