gpt4 book ai didi

Python 记录器在未捕获异常后停止记录

转载 作者:太空狗 更新时间:2023-10-29 17:51:27 25 4
gpt4 key购买 nike

我们的 flask 应用程序使用的 native python 记录器似乎在发生异常后停止写入日志。每次停止之前记录的最后一个条目是一条描述异常的消息。通常下一条消息是由 after_request 中的代码编写的,但对于记录器停止的情况,after_request 消息永远不会写出。

知道是什么原因造成的吗?

注意:我最初在 Serverfault ( https://serverfault.com/questions/655683/python-logger-stops-logging ) 上发布了这个问题,认为这是一个基础设施问题。但现在我们已经将问题缩小到在异常之后发生,这个问题可能更适合 Stackoverflow。

更新 [12/22/2015]:

记录器实例化:

logging.addLevelName(Config.LOG_AUDIT_LEVEL_NUM, Config.LOG_AUDIT_LEVEL_NAME)

logger = logging.getLogger(Config.LOGGER_NAME)
logger.setLevel(Config.LOG_LEVEL)

handler = SysLogHandler(address='/dev/log', facility=SysLogHandler.LOG_LOCAL3)
handler.setLevel(Config.LOG_LEVEL)

formatter = log_formatter()
handler.setFormatter(formatter)
logger.addHandler(handler)

日志格式器:

class log_formatter(logging.Formatter):

def __init__(self,
fmt=None,
datefmt=None,
json_cls=None,
json_default=_default_json_default):
"""
:param fmt: Config as a JSON string, allowed fields;
extra: provide extra fields always present in logs
source_host: override source host name
:param datefmt: Date format to use (required by logging.Formatter
interface but not used)
:param json_cls: JSON encoder to forward to json.dumps
:param json_default: Default JSON representation for unknown types,
by default coerce everything to a string
"""

if fmt is not None:
self._fmt = json.loads(fmt)
else:
self._fmt = {}
self.json_default = json_default
self.json_cls = json_cls

if 'extra' not in self._fmt:
self.defaults = {}
else:
self.defaults = self._fmt['extra']

try:
self.source_host = socket.gethostname()
except:
self.source_host = ""

def format(self, record):
"""
Format a log record to JSON, if the message is a dict
assume an empty message and use the dict as additional
fields.
"""

fields = record.__dict__.copy()
aux_fields = [
'relativeCreated', 'process', 'args', 'module', 'funcName', 'name',
'thread', 'created', 'threadName', 'msecs', 'filename', 'levelno',
'processName', 'pathname', 'lineno', 'levelname'
]
for k in aux_fields:
del fields[k]

if isinstance(record.msg, dict):
fields.update(record.msg)
fields.pop('msg')
msg = ""
else:
msg = record.getMessage()

if 'msg' in fields:
fields.pop('msg')

if 'exc_info' in fields:
if fields['exc_info']:
formatted = tb.format_exception(*fields['exc_info'])
fields['exception'] = formatted
fields.pop('exc_info')

if 'exc_text' in fields and not fields['exc_text']:
fields.pop('exc_text')

logr = self.defaults.copy()

logr = {
'timestamp': datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
'host': self.source_host,
}
logr.update(self._build_fields(logr, fields))

if msg:
logr['message'] = msg

something = json.dumps(logr, default=self.json_default, cls=self.json_cls)
return something

def _build_fields(self, defaults, fields):
return dict(defaults.get('fields', {}).items() + fields.items())

更新 [01/03/2015]:

回答发布的问题:

异常发生后应用程序是否还在运行?

是的,应用程序继续运行。

引发了哪种类型的异常,其原因是什么?

内部/自定义异常。由于不同类型的异常,记录器已停止。

您在应用程序中使用线程吗?

是的,该应用程序由 gunicorn 提供线程。

日志库是如何使用的?

我们使用默认的 FileHandler、SysLogHandler 和自定义格式化程序(输出 JSON)

它是否登录文件?它是否使用日志轮换?

是的,它记录到一个文件,但没有轮换。

最佳答案

关于 after_request,来自文档:

As of Flask 0.7 this function might not be executed at the end of the request in case an unhandled exception occurred.

至于您的日志记录问题,可能是您的调试标志设置为 true,这会导致调试器启动并可能停止日志记录。

引用资料:
( http://flask.pocoo.org/docs/0.10/api/#flask.Flask.after_request )
( http://flask.pocoo.org/docs/0.10/errorhandling/#working-with-debuggers )

关于Python 记录器在未捕获异常后停止记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27751805/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com