Source code for server.web.log_config

"""Configure Logging for structlogs, syslog, etc."""

import logging.config
from typing import Dict, List, Optional

import structlog

# from jobmon.server import __version__


[docs] def configure_structlog(extra_processors: Optional[List] = None) -> None: """Configure logging format, handlers, etc.""" if extra_processors is None: extra_processors = [] structlog.configure( processors=[ # bring in threadlocal context structlog.contextvars.merge_contextvars, # This performs the initial filtering, so we don't # evaluate e.g. DEBUG when unnecessary structlog.stdlib.filter_by_level, # Adds logger=module_name (e.g __main__) structlog.stdlib.add_logger_name, # Adds level=info, debug, etc. structlog.stdlib.add_log_level, # add jobmon version to json object *extra_processors, # Performs the % string interpolation as expected structlog.stdlib.PositionalArgumentsFormatter(), # add datetime to our logs structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S"), # Include the stack when stack_info=True structlog.processors.StackInfoRenderer(), # Include the exception when exc_info=True # e.g log.exception() or log.warning(exc_info=True)'s behavior structlog.processors.format_exc_info, # Creates the necessary args, kwargs for log() structlog.stdlib.ProcessorFormatter.wrap_for_formatter, ], # Our "event_dict" is explicitly a dict context_class=dict, # Provides the logging.Logger for the underlaying log call logger_factory=structlog.stdlib.LoggerFactory(), # Provides predefined methods - log.debug(), log.info(), etc. wrapper_class=structlog.stdlib.BoundLogger, # Caching of our logger cache_logger_on_first_use=True, )
[docs] default_formatters: Dict = { # copied formatter from here: https://github.com/hynek/structlog/issues/235 "text": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(), "keep_exc_info": True, "keep_stack_info": True, }, "json": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.JSONRenderer(), }, }
[docs] default_handlers: Dict = { "console_text": { "level": "INFO", "class": "logging.StreamHandler", "formatter": "text", }, "console_json": { "level": "INFO", "class": "logging.StreamHandler", "formatter": "json", }, }
[docs] default_loggers: Dict = { # only configure loggers of given name "jobmon.server.web": { "handlers": ["console_json"], "level": "INFO", }, "werkzeug": { "handlers": ["console_json"], "level": "WARN", }, "sqlalchemy": { "handlers": ["console_json"], "level": "WARN", }, # enable SQL debug # 'sqlalchemy.engine': { # 'level': 'INFO', # } }
[docs] def configure_logging( loggers_dict: Optional[Dict] = None, handlers_dict: Optional[Dict] = None, formatters_dict: Optional[Dict] = None, ) -> None: """Setup logging with default handlers.""" if formatters_dict is None: formatters_dict = default_formatters if handlers_dict is None: handlers_dict = default_handlers if loggers_dict is None: loggers_dict = default_loggers dict_config = { "version": 1, "disable_existing_loggers": False, "formatters": formatters_dict, "handlers": handlers_dict, "loggers": loggers_dict, } logging.config.dictConfig(dict_config)