18.5. Logging Handlers

  • Stdout and Stderr

  • File

  • Network

  • System Log

  • Memory

  • Dummy

18.5.1. Stdout and Stderr

  • StreamHandler - instances send messages to streams (file-like objects).

18.5.2. File

  • FileHandler - Output to file

  • TimedRotatingFileHandler - Output to file with rotation based on time

  • RotatingFileHandler - Output to file with rotation based on file size

  • WatchedFileHandler - Output to file with monitoring for external changes

18.5.3. Network

  • SocketHandler - Output to TCP/IP socket

  • DatagramHandler - Output to UDP socket

  • HTTPHandler - Output to HTTP server

  • SMTPHandler - Output to email address via SMTP

18.5.4. System Log

  • SysLogHandler - Output to Unix syslog daemon

  • NTEventLogHandler - Output to Windows event log

18.5.5. Memory

  • MemoryHandler - Output to memory buffer

  • QueueHandler - Output to queue

18.5.6. Dummy

  • NullHandler - Do not display output

18.5.7. Log Colors

>>> import logging
>>>
>>>
>>> class LogFormatter(logging.Formatter):
...     COLORS = {
...         'CRITICAL': '\033[91;1m',
...         'ERROR': '\033[91m',
...         'INFO': '\033[36m',
...         'WARNING': '\033[33m',
...         'DEBUG': '\033[32m',
...         'RESET': '\033[0m'
...     }
...
...     def format(self, record):
...         message = super().format(record)
...         reset = self.COLORS['RESET']
...         color = self.COLORS[record.levelname]
...         return f"{color}{message}{reset}"
>>>
>>>
>>> handler = logging.StreamHandler()
>>> handler.setFormatter(LogFormatter('{levelname} {message}', style='{'))
>>>
>>> log = logging.getLogger('myapp')
>>> log.addHandler(handler)
>>> log.setLevel(logging.DEBUG)
>>>
>>> log.critical('This is a log message')
>>> log.error('This is a log message')
>>> log.info('This is a log message')
>>> log.warning('This is a log message')
>>> log.debug('This is a log message')

18.5.8. Datetime Conversion

  • Server has different timezone than the users

  • Server timezone is UTC

  • User timezone is (e.g. Poland)

>>> import logging
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo
>>>
>>>
>>> UTC = ZoneInfo('UTC')
>>> LOCAL = ZoneInfo('Poland')
>>>
>>> class LogFormatter(logging.Formatter):
...     def format(self, record):
...         utc = datetime.fromtimestamp(record.created, tz=UTC)
...         local = utc.astimezone(LOCAL)
...         message = super().format(record)
...         return f"UTC: {utc:%Y-%m-%d %H:%M}, Local: {local:%Y-%m-%d %H:%M}, {message}"
>>>
>>>
>>> handler = logging.StreamHandler()
>>> handler.setFormatter(LogFormatter('{levelname} {message}', style='{'))
>>>
>>> log = logging.getLogger('myapp')
>>> log.addHandler(handler)
>>> log.setLevel(logging.DEBUG)
>>>
>>> log.critical('This is a log message')
>>> log.error('This is a log message')
>>> log.info('This is a log message')
>>> log.warning('This is a log message')
>>> log.debug('This is a log message')

18.5.9. Further Reading