1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2025-11-13 17:39:16 +01:00
lodel2_mirror/lodel/logger.py
2016-04-13 11:41:14 +02:00

117 lines
4.8 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#-*- coding: utf-8 -*-
import logging, logging.handlers
import os.path
from lodel.settings import Settings
# Variables & constants definitions
default_format = '%(asctime)-15s %(levelname)s %(_pathname)s:%(_lineno)s:%(_funcName)s() : %(message)s'
simple_format = '%(asctime)-15s %(levelname)s : %(message)s'
SECURITY_LOGLEVEL = 35
logging.addLevelName(SECURITY_LOGLEVEL, 'SECURITY')
handlers = dict() # Handlers list (generated from settings)
# Fetching default root logger
logger = logging.getLogger()
# Setting options from Lodel.settings.Settings.logging
def __init_from_settings():
# capture warning disabled, because the custom format raises error (unable
# to give the _ preffixed arguments to logger resulting into a KeyError
# exception )
#logging.captureWarnings(True) # Log warnings
logger.setLevel(logging.DEBUG)
for name in Settings.logging._fields:
add_handler(name, getattr(Settings.logging, name))
##@brief Add an handler, identified by a name, to a given logger
#
# logging_opt is a dict with logger option. Allowed keys are :
# - filename : take a filepath as value and cause the use of a logging.handlers.RotatingFileHandler
# - level : the minimum logging level for a logger, takes values [ 'DEBUG', 'INFO', 'WARNING', 'SECURITY', 'ERROR', 'CRITICAL' ]
# - format : DONT USE THIS OPTION (or if you use it be sure to includes %(_pathname)s %(_lineno)s %(_funcName)s format variables in format string
# - context : boolean, if True include the context (module:lineno:function_name) in the log format
# @todo Move the logging_opt documentation somewhere related with settings
#
# @param name str : The handler name
# @param logging_opt dict : dict containing options ( see above )
def add_handler(name, logging_opt):
logger = logging.getLogger()
if name in handlers:
raise KeyError("A handler named '%s' allready exists")
logging_opt = logging_opt._asdict()
if 'filename' in logging_opt and logging_opt['filename'] is not None:
maxBytes = (1024 * 10) if 'maxbytes' not in logging_opt else logging_opt['maxbytes']
backupCount = 10 if 'backupcount' not in logging_opt else logging_opt['backupcount']
handler = logging.handlers.RotatingFileHandler(
logging_opt['filename'],
maxBytes = maxBytes,
backupCount = backupCount,
encoding = 'utf-8')
else:
handler = logging.StreamHandler()
if 'level' in logging_opt:
handler.setLevel(getattr(logging, logging_opt['level'].upper()))
if 'format' in logging_opt:
formatter = logging.Formatter(logging_opt['format'])
else:
if 'context' in logging_opt and not logging_opt['context']:
formatter = logging.Formatter(simple_format)
else:
formatter = logging.Formatter(default_format)
handler.setFormatter(formatter)
handlers[name] = handler
logger.addHandler(handler)
##@brief Remove an handler generated from configuration (runtime logger configuration)
# @param name str : handler name
def remove_handler(name):
if name in handlers:
logger.removeHandler(handlers[name])
# else: can we do anything ?
##@brief Utility function that disable unconditionnaly handlers that implies console output
# @note In fact, this function disables handlers generated from settings wich are instances of logging.StreamHandler
def remove_console_handlers():
for name, handler in handlers.items():
if isinstance(handler, logging.StreamHandler):
remove_handler(name)
# Utility functions
##@brief Generic logging function
# @param lvl int : Log severity
# @param msg str : log message
# @param *args : additional positionnal arguments
# @param **kwargs : additional named arguments
def log(lvl, msg, *args, **kwargs):
caller = logger.findCaller() # Opti warning : small overhead
extra = {
'_pathname': os.path.relpath(
caller[0],
start=Settings.lib_path
), # os.path.relpath add another small overhead
'_lineno': caller[1],
'_funcName': caller[2],
}
logger.log(lvl, msg, extra = extra, *args, **kwargs)
def debug(msg, *args, **kwargs): log(logging.DEBUG, msg, *args, **kwargs)
def info(msg, *args, **kwargs): log(logging.INFO, msg, *args, **kwargs)
def warning(msg, *args, **kwargs): log(logging.WARNING, msg, *args, **kwargs)
def security(msg, *args, **kwargs): log(SECURITY_LOGLEVEL, msg, *args, **kwargs)
def error(msg, *args, **kwargs): log(logging.ERROR, msg, *args, **kwargs)
def critical(msg, *args, **kwargs): log(logging.CRITICAL, msg, *args, **kwargs)
# Initialisation triggering
if len(handlers) == 0:
__init_from_settings()