Search code examples
pythonloggingyamlsyslog

How to set output for logging.handlers.SysLogHandler in YAML file in python


I have following config file:

[loggers]
keys=MYLogger

[handlers]
keys=fileHandler,streamHandler,sysHandler

[formatters]
keys=simpleFormatter

[logger_MYLogger]
level=INFO
handlers=fileHandler
qualname=MYLogger
propagate=0

[handler_fileHandler]
class=FileHandler
formatter=simpleFormatter
args=('mylog.log',)

[handler_streamHandler]
class=StreamHandler
formatter=simpleFormatter
args=(sys.stdout,)

[handler_sysHandler]
class=logging.handlers.SysLogHandler
formatter=simpleFormatter
args=('/dev/log',)


[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s : %(message)s
datefmt=%Y-%m-%d %H:%M:%S

I need to convert it to the YAML file. I've done it successfully, except part for sysHandler:

  version: 1
  formatters:
    simpleFormatter:
      format: '%(asctime)s - %(name)s - %(levelname)s : %(message)s'
      datefmt: '%Y-%m-%d %H:%M:%S'
  handlers:
    stream:
      class: logging.StreamHandler
      formatter: simpleFormatter
      stream: ext://sys.stdout
    file:
      class: logging.FileHandler
      formatter: simpleFormatter
      filename: mylog.log
    # sys:
    #   class: logging.handlers.SysLogHandler
    #   formatter: simpleFormatter
    #   stream: /dev/log
  loggers: 
    MYLogger:
      level: INFO
      handlers: [stream, file]

How to provide arguments for sysHandler in yaml format? Why it was ok to simply put args in original config file and here I have to specify stream / filename?


Solution

  • The logging dictionary schema details have the following to say about handlers:

    handlers - the corresponding value will be a dict in which each key is a handler 
    id and each value is a dict describing how to configure the corresponding Handler
    instance.
    
    The configuring dict is searched for the following keys:
    
        class (mandatory). This is the fully qualified name of the handler class.
        level (optional). The level of the handler.
        formatter (optional). The id of the formatter for this handler.
        filters (optional). A list of ids of the filters for this handler.
    
    All other keys are passed through as keyword arguments to the handler’s
    constructor.
    

    The SysLogHandler has the following signature:

    SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)
    

    The key stream, which is not a mandatory or optional key for a handler, is passed as keyword argument to SysLogHandler() and that is not a keyword you can use to instantiate an instance of that class.

    The non-mandatory/optional keys for the StreamHandler (i.e. stream) and FileHandler (i.e. filename) match the respective signatures).

    I assume you really have to supply to suppy the address with the tuple argument as sequence, to get this accepted:

    sys:
        class: logging.handlers.SysLogHandler
        formatter: simpleFormatter
        address: [localhost, /dev/log]
    

    (Please note that the args entry for [handler_sysHandler] in your INI style config file should start with a tuple. From the logging documentation:

    args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)