Source code for zfit.util.logging
"""
This module controls the zfit logging.
The base logger for zfit is called `zfit`, and all loggers created by this module
have the form `zfit.XX`, where `XX` is their name.
By default, time, name of the logger and message with the default
colorlog color scheme are printed.
"""
import os
import logging
import colorlog
[docs]def get_logger(name, stdout_level=None, file_level=None, file_name=None):
"""Get and configure logger.
This logger has two handlers:
- A stdout handler is always configured with `colorlog`.
- A file handler is configured if `file_name` is given. Once it has been configure, it is not
necessary to give it to modify its properties.
Once the logger has been created, `get_logger` can be called again to modify its log levels,
independently for the stream and file handlers.
Note:
If the logger name doesn't start with "zfit", it is automatically added.
Note:
Default logging level at first instantiation is WARNING.
Arguments:
name (str): Name of the logger.
stdout_level (int, optional): Logging level for the stream handler. Defaults to `logging.WARNING`.
file_level (int, optional): Logging level for the file handler. Defaults to `logging.WARNING`.
file_name (str, optional): File to log to. If not given, no file logging is performed.
Return:
`logging.Logger`: The requested logger.
Raise:
ValueError if `file_level` has been specified without having configured the output file.
"""
if not name.startswith('zfit'):
name = 'zfit.{}'.format(name.rstrip('.'))
if stdout_level is None:
stdout_level = logging.WARNING
format_stream = ("%(asctime)s - %(name)s | "
"%(log_color)s%(levelname)-8s%(reset)s | "
"%(log_color)s%(message)s%(reset)s")
format_file = ("%(asctime)s - %(name)s | "
"%(levelname)-8s | "
"%(message)s")
logger = logging.getLogger(name)
if not logger.handlers:
# Add Stream handler
formatter = colorlog.ColoredFormatter(format_stream)
stream = logging.StreamHandler()
stream.setFormatter(formatter)
logger.addHandler(stream)
# The first handler is always the stream
logger.handlers[0].setLevel(stdout_level)
# Now the file handler
file_handler = None
# Find the file handler
for handler in logger.handlers:
if isinstance(handler, logging.FileHandler):
if not file_name or \
os.path.abspath(file_name) == handler.baseFilename:
file_handler = handler
break
# If requested, create one
if file_name and file_handler is None:
formatter = colorlog.ColoredFormatter(format_file)
file_handler = logging.FileHandler(file_name)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Set its level
if file_level is not None and file_handler is None:
raise ValueError("Requested change in file log level but no file logger has been configured")
if file_level is None:
file_level = logging.WARNING
if file_handler is not None:
file_handler.setLevel(file_level)
# Set the logging level to the lowest level
logger_level = min(stdout_level, file_level)
logger.setLevel(logger_level)
return logger