How do you put the TimedRotatingFileHandler in configuration?



  • I've got a logistics configuration:

    "file_handler": {
        "class": "logging.handlers.TimedRotatingFileHandler",
        "level": "DEBUG",
        "formatter": "simple",
        "filename": "development.log",
         "encoding": "utf8"
    }
    

    The configuration, as illustrated by the example, is JSON- an object. Loading and application of the configuration is banal and simple: first reading of the file, then interpretation of the module json from the standard library call dict_config

    I don't like the name of the log file after rotation. It is very uncomfortable with the fact that there is a time mark as an expansion of the file. I really want to put it in the base name, and the extension will be 'log'.

    I found a solution to my problem, it's written on an enSO: https://stackoverflow.com/questions/338450/timedrotatingfilehandler-changing-file-name ♪ But I don't really like that decision. It's for runtime, and I'd like to file a declarative, that's the configuration.

    Is it possible and if so, how?



  • In due course, it was a similar task to the following:

    my_logging.py:

    import os
    import datetime
    import errno
    import logging.config
    import logging.handlers
    

    import yaml

    def mkdir_p(path):
    try:
    os.makedirs(path, exist_ok=True) # Python>3.2
    except TypeError:
    try:
    os.makedirs(path)
    except OSError as exc: # Python >2.5
    if exc.errno == errno.EEXIST and os.path.isdir(path):
    pass
    else: raise

    class EvalFileHandler(logging.FileHandler):
    def init(self, **kwargs):
    fn = eval(os.path.expandvars(kwargs['filename']))
    mkdir_p(os.path.dirname(fn))
    kwargs['filename'] = fn
    logging.FileHandler.init(self, **kwargs)

    def setup_logging(
    config_file='logging.yml',
    default_level=logging.INFO,
    env_key_config='LOGGING_CONFIG'
    ):
    """Setup logging configuration

    """
    path = config_file
    value = os.getenv(env_key_config, None)
    if value:
        path = value
    if os.path.exists(path):
        with open(path, 'rt') as f:
            config = yaml.load(f.read())
        logging.config.dictConfig(config)
    else:
        logging.basicConfig(level=default_level)
    

    logging.yml:

    ---
    version: 1
    disable_existing_loggers: False
    formatters:
    default:
    format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    simple:
    format: "%(asctime)s - %(levelname)-8s - %(message)s"
    short:
    format: "%(asctime)s - %(message)s"
    message_only:
    format: "%(message)s"

    handlers:
    console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple
    stream: ext://sys.stdout

    debug_file_handler:
        class: my_logging.EvalFileHandler
        level: DEBUG            
        formatter: simple
        filename: "__import__('datetime').datetime.now().strftime('$HOME/log/%Y/%m/%Y%m%d-db_jiramatic-debug.log')"
        encoding: utf8
    
    info_file_handler:
        class: my_logging.EvalFileHandler
        level: INFO            
        formatter: simple
        filename: "__import__('datetime').datetime.now().strftime('$HOME/log/%Y/%m/%Y%m%d-db_jiramatic.log')"
        encoding: utf8
    
    error_file_handler:
        class: my_logging.EvalFileHandler
        level: ERROR            
        formatter: simple
        filename: "__import__('datetime').datetime.now().strftime('$HOME/log/%Y/%m/%Y%m%d-db_jiramatic-errors.log')"
        encoding: utf8
    

    loggers:
    my_project:
    level: INFO

    handlers: [console, info_file_handler, error_file_handler, debug_file_handler]

        handlers: [console, info_file_handler, error_file_handler]
        propagate: no
    

    root:
    level: INFO
    handlers: [console, info_file_handler, error_file_handler]

    Then basically squeak.

    import my_logging

    my_logging.setup_logging(config_file='/path/to/logging.yml')
    logger = logging.getLogger('my_project')




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2