我当前的格式字符串是:
formatter = logging.Formatter('%(asctime)s : %(message)s')
Run Code Online (Sandbox Code Playgroud)
我想添加一个名为app_name的新字段,它将在包含此格式化程序的每个脚本中具有不同的值.
import logging
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.addHandler(syslog)
Run Code Online (Sandbox Code Playgroud)
但我不知道如何将该app_name值传递给记录器以插入格式字符串.我显然可以让它出现在日志消息中,但每次都传递它,但这很麻烦.
我试过了:
logging.info('Log message', app_name='myapp')
logging.info('Log message', {'app_name', 'myapp'})
logging.info('Log message', 'myapp')
Run Code Online (Sandbox Code Playgroud)
但没有工作.
unu*_*tbu 104
您可以使用LoggerAdapter,因此您不必在每次日志记录调用时传递额外信息:
import logging
extra = {'app_name':'Super App'}
logger = logging.getLogger(__name__)
syslog = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.setLevel(logging.INFO)
logger.addHandler(syslog)
logger = logging.LoggerAdapter(logger, extra)
logger.info('The sky is so blue')
Run Code Online (Sandbox Code Playgroud)
日志(类似的东西)
2013-07-09 17:39:33,596 Super App : The sky is so blue
Run Code Online (Sandbox Code Playgroud)
过滤器还可用于添加上下文信息.
import logging
class AppFilter(logging.Filter):
def filter(self, record):
record.app_name = 'Super App'
return True
logger = logging.getLogger(__name__)
logger.addFilter(AppFilter())
syslog = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.setLevel(logging.INFO)
logger.addHandler(syslog)
logger.info('The sky is so blue')
Run Code Online (Sandbox Code Playgroud)
产生类似的日志记录.
mr2*_*ert 42
你需要将dict作为参数传递给extra,以便那样做.
logging.info('Log message', extra={'app_name': 'myapp'})
Run Code Online (Sandbox Code Playgroud)
证明:
>>> import logging
>>> logging.basicConfig(format="%(foo)s - %(message)s")
>>> logging.warning('test', extra={'foo': 'bar'})
bar - test
Run Code Online (Sandbox Code Playgroud)
另外,作为注释,如果您尝试在不传递dict的情况下记录消息,那么它将失败.
>>> logging.warning('test')
Traceback (most recent call last):
File "/usr/lib/python2.7/logging/__init__.py", line 846, in emit
msg = self.format(record)
File "/usr/lib/python2.7/logging/__init__.py", line 723, in format
return fmt.format(record)
File "/usr/lib/python2.7/logging/__init__.py", line 467, in format
s = self._fmt % record.__dict__
KeyError: 'foo'
Logged from file <stdin>, line 1
Run Code Online (Sandbox Code Playgroud)
Ahm*_*mad 36
从 Python3.2 开始,您现在可以使用LogRecordFactory
import logging
logging.basicConfig(format="%(custom_attribute)s - %(message)s")
old_factory = logging.getLogRecordFactory()
def record_factory(*args, **kwargs):
record = old_factory(*args, **kwargs)
record.custom_attribute = "my-attr"
return record
logging.setLogRecordFactory(record_factory)
Run Code Online (Sandbox Code Playgroud)
>>> logging.info("hello")
my-attr - hello
Run Code Online (Sandbox Code Playgroud)
当然,record_factory可以自定义为任何可调用对象,custom_attribute如果您保留对工厂可调用对象的引用,则可以更新的值。
logger = logging.getLogger(..))的3rd 方库现在具有相同的日志格式。(过滤器/适配器不是这种情况,您需要使用相同的记录器对象)另一种方法是创建自定义LoggerAdapter.当您无法更改格式时,或者如果您的格式与不发送唯一键的代码共享(在您的案例中为app_name),这将非常有用:
class LoggerAdapter(logging.LoggerAdapter):
def __init__(self, logger, prefix):
super(LoggerAdapter, self).__init__(logger, {})
self.prefix = prefix
def process(self, msg, kwargs):
return '[%s] %s' % (self.prefix, msg), kwargs
Run Code Online (Sandbox Code Playgroud)
在您的代码中,您将像往常一样创建并初始化您的记录器:
logger = logging.getLogger(__name__)
# Add any custom handlers, formatters for this logger
myHandler = logging.StreamHandler()
myFormatter = logging.Formatter('%(asctime)s %(message)s')
myHandler.setFormatter(myFormatter)
logger.addHandler(myHandler)
logger.setLevel(logging.INFO)
Run Code Online (Sandbox Code Playgroud)
最后,您将创建包装器适配器以根据需要添加前缀:
logger = LoggerAdapter(logger, 'myapp')
logger.info('The world bores you when you are cool.')
Run Code Online (Sandbox Code Playgroud)
输出看起来像这样:
2013-07-09 17:39:33,596 [myapp] The world bores you when you are cool.
Run Code Online (Sandbox Code Playgroud)
我自己实现后发现了这个SO问题。希望它能帮助某人。在下面的代码中,我引入了一个claim_id以记录器格式调用的额外键。claim_id只要环境中存在密钥,它就会记录 Claim_id 。在我的用例中,我需要记录 AWS Lambda 函数的此信息。
import logging
import os
LOG_FORMAT = '%(asctime)s %(name)s %(levelname)s %(funcName)s %(lineno)s ClaimID: %(claim_id)s: %(message)s'
class AppLogger(logging.Logger):
# Override all levels similarly - only info overriden here
def info(self, msg, *args, **kwargs):
return super(AppLogger, self).info(msg, extra={"claim_id": os.getenv("claim_id", "")})
def get_logger(name):
""" This function sets log level and log format and then returns the instance of logger"""
logging.setLoggerClass(AppLogger)
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
logger = logging.getLogger(name)
logger.setLevel(logging.INFO)
return logger
LOGGER = get_logger(__name__)
LOGGER.info("Hey")
os.environ["claim_id"] = "12334"
LOGGER.info("Hey")
Run Code Online (Sandbox Code Playgroud)
要点:https://gist.github.com/ygivenx/306f2e4e1506f302504fb67abef50652
小智 5
接受的答案没有在日志文件中记录格式,而格式反映在系统输出中。或者,我使用了一种更简单的方法并担任:
logging.basicConfig(filename="mylogfile.test",
filemode="w+",
format='%(asctime)s: ' +app_name+': %(message)s ',
level=logging.DEBUG)Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
40430 次 |
| 最近记录: |