【问题标题】:Can I use the generic logging.Logger() in Celery tasks?我可以在 Celery 任务中使用通用 logging.Logger() 吗?
【发布时间】:2017-06-05 15:16:39
【问题描述】:

医生说

有一个名为“celery.task”的特殊记录器可用,您可以从该记录器继承以自动获取任务名称和唯一 ID 作为日志的一部分。

这还不够。有更详细的资料吗?具体来说,它默认定义了哪些处理程序和格式字符串?我为什么要继承它?我可以改用通用的logging.Logger() 吗?从 celery 任务(不是 Django)记录到文件的最佳实践是什么?等等。谢谢。

【问题讨论】:

    标签: python logging celery python-3.4


    【解决方案1】:

    我可以使用通用 logging.Logger() 来代替吗?

    是的,您可以使用通用 Python/Django 记录器。 而不是logger = get_task_logger(__name__),只需选择getLogger:

    import logging
    logger = logging.getLogger(__name__)
    

    我为什么要继承它?

    使用celery.task的好处是:

    自动获取任务名称和唯一 ID 作为日志的一部分。

    它本身使用标准 Python logging lib。


    这还不够。有更详细的资料吗? 具体来说,它默认定义了哪些处理程序和格式字符串?

    默认情况下,它使用来自logging.handlers 的WatchedFileHandler 您可以查看celery.app.log 文档,它是在setup_handler 方法中设置的。


    从 celery 任务记录到文件的最佳实践是什么 (不是姜戈)?等等

    1.直接在模块中 - 您可以简单地将所有内容放在模块的顶部 - 定义一个处理程序,并在获取记录器时分配它:

    import logging
    
    # ---- set up logging to file ---
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                        datefmt='%m-%d %H:%M',
                        filename='/temp/myapp.log',
                        filemode='w')
    # --- define a Handler ---
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    # --- set a format which is simpler for console use ---
    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
    # --- tell the handler to use this format ---
    console.setFormatter(formatter)
    # --- add the handler to the logger ---
    logging.getLogger('').addHandler(console)
    

    2。使用 logging_config 字典 - dictConfig:更好看的做法。

    import logging
    from logging.config import dictConfig
    
    logging_config = dict(
        version = 1,
        formatters = {
            'f': {'format':
                  '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
            },
        handlers = {
            'h': {'class': 'logging.StreamHandler',
                  'formatter': 'f',
                  'level': logging.DEBUG}
            },
        root = {
            'handlers': ['h'],
            'level': logging.DEBUG,
            },
    )
    
    dictConfig(logging_config)
    
    logger = logging.getLogger()
    logger.debug('often makes a very good meal of %s', 'visiting tourists')
    

    3.使用单独的日志记录格式文件 - *.ini:

    [loggers]
    # list of loggers
    keys=root,log02
    
    [handlers]
    # list of handlers    
    keys=hand01,hand02
    
    [formatters]
    # list of formatters    
    keys=form01,form02
    
    [logger_root]
    # config for 'root' logger    
    level=NOTSET
    handlers=hand01
    
    [handler_hand01]
    # config for handler hand01    
    class=StreamHandler
    level=NOTSET
    formatter=form01
    args=(sys.stdout,)
    
    [handler_hand02]
    ## config for handler hand02     
    class=FileHandler
    level=DEBUG
    formatter=form02
    args=('python.log', 'w')
    
    [formatter_form01]
    # config for formatter form01    
    format=F1 %(asctime)s %(levelname)s %(message)s
    datefmt=
    class=logging.Formatter
    

    4.一个单独的类 - 最后但同样重要的是,一个更优雅的解决方案是将所有这些作为单独的模块(类),并在需要时使用特定标志导入它:

    import logging
    from config import LOG, LOGGING
    
    class Logger:
        def __init__(self, logf=None, logger_name=None, debug=None, rotation=None):
            self.logfile = logf
            self.logger_name = logger_name if logger_name else logf
            self.logger = self.get_logger(rotation=rotation) if rotation else self.get_logger()
            self.debug = debug if debug else False
            self.debug = debug if debug else LOG["debug"]
    
        def logf(self, filename=None):
            if filename is None:
                filename = LOG["file"]
            return "%s%s" % (LOG["dir"], filename)
    
        def get_logger(self, rotation=False):
            logger = logging.getLogger(self.logger_name)
            logf = self.logf(self.logfile)
            if rotation:
                from logging.handlers import TimedRotatingFileHandler
                self.handler = TimedRotatingFileHandler(logf, when='midnight', interval=1, backupCount=10)
            else:
                self.handler = logging.FileHandler(logf)
            formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
            #formatter = "%(asctime)s - %(levelname)s - %(filename)s:%(funcName)s - %(message)s",
            self.handler.setFormatter(formatter)
            logger.addHandler(self.handler)
            logger.setLevel(logging.DEBUG)
            return logger
    

    【讨论】:

    • 非常感谢。不过,有几点我还不清楚。 1.“...获取任务名称...” - 我如何以及在哪里获得它?例如,如果我想更改格式。 2. 在最后一节(最佳实践)中,您不使用 celery 记录器。是首选吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2013-07-15
    • 2015-06-26
    • 1970-01-01
    • 2014-06-21
    • 2018-02-05
    • 2018-03-21
    相关资源
    最近更新 更多