"""Logging configuration.The Celery instances logging section: ``Celery.log``.Sets up logging for the worker and other programs,redirects standard outs, colors log output, patches loggingrelated compatibility fixes, and so on."""importloggingimportosimportsysimportwarningsfromlogging.handlersimportWatchedFileHandlerfromkombu.utils.encodingimportset_default_encoding_filefromceleryimportsignalsfromcelery._stateimportget_current_taskfromcelery.exceptionsimportCDeprecationWarning,CPendingDeprecationWarningfromcelery.localimportclass_propertyfromcelery.platformsimportisattyfromcelery.utils.logimport(ColorFormatter,LoggingProxy,get_logger,get_multiprocessing_logger,mlevel,reset_multiprocessing_logger)fromcelery.utils.nodenamesimportnode_formatfromcelery.utils.termimportcolored__all__=('TaskFormatter','Logging')MP_LOG=os.environ.get('MP_LOG',False)
[文档]classTaskFormatter(ColorFormatter):"""Formatter for tasks, adding the task name and id."""
[文档]classLogging:"""Application logging setup (app.log)."""#: The logging subsystem is only configured once per process.#: setup_logging_subsystem sets this flag, and subsequent calls#: will do nothing._setup=Falsedef__init__(self,app):self.app=appself.loglevel=mlevel(logging.WARN)self.format=self.app.conf.worker_log_formatself.task_format=self.app.conf.worker_task_log_formatself.colorize=self.app.conf.worker_log_color
[文档]defsetup_logging_subsystem(self,loglevel=None,logfile=None,format=None,colorize=None,hostname=None,**kwargs):ifself.already_setup:returniflogfileandhostname:logfile=node_format(logfile,hostname)Logging._setup=Trueloglevel=mlevel(loglevelorself.loglevel)format=formatorself.formatcolorize=self.supports_color(colorize,logfile)reset_multiprocessing_logger()receivers=signals.setup_logging.send(sender=None,loglevel=loglevel,logfile=logfile,format=format,colorize=colorize,)ifnotreceivers:root=logging.getLogger()ifself.app.conf.worker_hijack_root_logger:root.handlers=[]get_logger('celery').handlers=[]get_logger('celery.task').handlers=[]get_logger('celery.redirected').handlers=[]# Configure root loggerself._configure_logger(root,logfile,loglevel,format,colorize,**kwargs)# Configure the multiprocessing loggerself._configure_logger(get_multiprocessing_logger(),logfile,loglevelifMP_LOGelselogging.ERROR,format,colorize,**kwargs)signals.after_setup_logger.send(sender=None,logger=root,loglevel=loglevel,logfile=logfile,format=format,colorize=colorize,)# then setup the root task logger.self.setup_task_loggers(loglevel,logfile,colorize=colorize)try:stream=logging.getLogger().handlers[0].streamexcept(AttributeError,IndexError):passelse:set_default_encoding_file(stream)# This is a hack for multiprocessing's fork+exec, so that# logging before Process.run works.logfile_name=logfileifisinstance(logfile,str)else''os.environ.update(_MP_FORK_LOGLEVEL_=str(loglevel),_MP_FORK_LOGFILE_=logfile_name,_MP_FORK_LOGFORMAT_=format)returnreceivers
[文档]defsetup_task_loggers(self,loglevel=None,logfile=None,format=None,colorize=None,propagate=False,**kwargs):"""Setup the task logger. If `logfile` is not specified, then `sys.stderr` is used. Will return the base task logger object. """loglevel=mlevel(loglevelorself.loglevel)format=formatorself.task_formatcolorize=self.supports_color(colorize,logfile)logger=self.setup_handlers(get_logger('celery.task'),logfile,format,colorize,formatter=TaskFormatter,**kwargs)logger.setLevel(loglevel)# this is an int for some reason, better to not question why.logger.propagate=int(propagate)signals.after_setup_task_logger.send(sender=None,logger=logger,loglevel=loglevel,logfile=logfile,format=format,colorize=colorize,)returnlogger
[文档]defredirect_stdouts_to_logger(self,logger,loglevel=None,stdout=True,stderr=True):"""Redirect :class:`sys.stdout` and :class:`sys.stderr` to logger. Arguments: logger (logging.Logger): Logger instance to redirect to. loglevel (int, str): The loglevel redirected message will be logged as. """proxy=LoggingProxy(logger,loglevel)ifstdout:sys.stdout=proxyifstderr:sys.stderr=proxyreturnproxy
[文档]defsupports_color(self,colorize=None,logfile=None):colorize=self.colorizeifcolorizeisNoneelsecolorizeifself.app.IS_WINDOWS:# Windows does not support ANSI color codes.returnFalseifcolorizeorcolorizeisNone:# Only use color if there's no active log file# and stderr is an actual terminal.returnlogfileisNoneandisatty(sys.stderr)returncolorize
def_detect_handler(self,logfile=None):"""Create handler from filename, an open stream or `None` (stderr)."""logfile=sys.__stderr__iflogfileisNoneelselogfileifhasattr(logfile,'write'):returnlogging.StreamHandler(logfile)returnWatchedFileHandler(logfile,encoding='utf-8')def_has_handler(self,logger):returnany(notisinstance(h,logging.NullHandler)forhinlogger.handlersor[])def_is_configured(self,logger):returnself._has_handler(logger)andnotgetattr(logger,'_rudimentary_setup',False)