是否有一种将Lithoxyl整合到flask.logger中的简洁方法?

时间:2016-08-30 12:55:31

标签: python logging flask

我喜欢lithoxyl的外观,并希望逐步替换flask.logger的当前用法。

是否有一种让两个日志记录框架共存的好方法?

到目前为止,我有以下内容:

from flask import current_app
from werkzeug.local import LocalProxy

logger = LocalProxy(lambda: current_app.logger)

class LogAdaptor(object):
    """file-like object that will write messages to the logger"""
    def write(self, msg):
        if msg.strip():
            logger.info(msg)

from lithoxyl import StreamEmitter, SensibleFormatter

emtr = StreamEmitter(LogAdaptor())

fmtr = SensibleFormatter('{level_name_upper} {module_name} {end_message}')

# ... the rest is basically the same as http://lithoxyl.readthedocs.io/en/latest/overview.html#logging-sensibly

这或多或少有效,但输出中的日志级别丢失,例如:

DEBUG backend: log message from app.logger.debug
INFO logger: CRITICAL "backend" "critical action failed"
INFO logger: DEBUG "backend" "action succeeded"
DEBUG backend: log message from app.logger.debug

我猜测所需的是一个更复杂的发射器,或者是一种在Flask.logger处理程序中访问底层流的.write的方法(绕过格式化等)。

或者这只是咆哮错误的树,我应该只使用拆分日志文件,直到它全部重构?

1 个答案:

答案 0 :(得分:1)

I've managed to make some improvements as I found https://github.com/mahmoud/lithoxyl/blob/master/lithoxyl/_syslog_emitter.py and created a similar class:

import logging
from lithoxyl.common import DEBUG, INFO, CRITICAL, get_level

class LoggerEmitter(object):
    priority_map = {DEBUG: {'success': logging.DEBUG,
                            'failure': logging.INFO,
                            'warn': logging.INFO,
                            'exception': logging.WARNING},
                    INFO: {'success': logging.INFO,
                           'failure': logging.WARNING,
                           'warn': logging.WARNING,
                           'exception': logging.ERROR},
                    CRITICAL: {'success': logging.WARNING,
                               'failure': logging.ERROR,
                               'warn': logging.ERROR,
                               'exception': logging.CRITICAL}}

    def __init__(self, logger):
        self.logger = logger

    def on_begin(self, begin_event, entry):
        level = self._get_level('begin', begin_event)
        self.logger.log(level, entry)

    def on_warn(self, warn_event, entry):
        level = self._get_level('warn', warn_event)
        self.logger.log(level, entry)

    def on_end(self, end_event, entry):
        level = self._get_level('end', end_event)
        self.logger.log(level, entry)

    def _get_level(self, event_name, action):
        level = get_level(action.level)

        if event_name == 'warn':
            status = 'warn'
        elif event_name == 'begin':
            status = 'begin'
        else:
            status = action.status

        return self.priority_map[level][status]

emtr = LoggerEmitter(logger)

The output is now something like:

DEBUG backend: log message from app.logger.debug
ERROR logger: "backend" "critical action failed"
DEBUG logger: "backend" "action succeeded"
DEBUG backend: log message from app.logger.debug

Which is better, but it would be nice if the module name was passed through properly too.