Source code for ophyd_async.core._log
import logging
import sys
import colorlog
__all__ = (
"config_ophyd_async_logging",
"logger",
"set_handler",
)
DEFAULT_FORMAT = (
"%(log_color)s[%(levelname)1.1s %(asctime)s.%(msecs)03d "
"%(module)s:%(lineno)d] %(message)s"
)
DEFAULT_DATE_FORMAT = "%y%m%d %H:%M:%S"
DEFAULT_LOG_COLORS = {
"DEBUG": "cyan",
"INFO": "green",
"WARNING": "yellow",
"ERROR": "red",
"CRITICAL": "red,bg_white",
}
class ColoredFormatterWithDeviceName(colorlog.ColoredFormatter):
def format(self, record):
message = super().format(record)
if hasattr(record, "ophyd_async_device_name"):
message = f"[{record.ophyd_async_device_name}]{message}" # type: ignore
return message
def _validate_level(level) -> int:
"""Return an int for level comparison."""
if isinstance(level, int):
levelno = level
elif isinstance(level, str):
levelno = logging.getLevelName(level)
else:
raise TypeError(f"Level {level!r} is not an int or str")
if isinstance(levelno, int):
return levelno
else:
raise ValueError(
"Your level is illegal, please use "
"'CRITICAL', 'FATAL', 'ERROR', 'WARNING', 'INFO', or 'DEBUG'."
)
logger = logging.getLogger("ophyd_async")
current_handler = None # overwritten below
[docs]
def config_ophyd_async_logging(
file=sys.stdout,
fmt=DEFAULT_FORMAT,
datefmt=DEFAULT_DATE_FORMAT,
color=True,
level="WARNING",
):
"""
Set a new handler on the ``logging.getLogger('ophyd_async')`` logger.
If this is called more than once, the handler from the previous invocation
is removed (if still present) and replaced.
Parameters
----------
file : object with ``write`` method or filename string
Default is ``sys.stdout``.
fmt : Overall logging format
datefmt : string
Date format. Default is ``'%H:%M:%S'``.
color : boolean
Use ANSI color codes. True by default.
level : str or int
Python logging level, given as string or corresponding integer.
Default is 'WARNING'.
Returns
-------
handler : logging.Handler
The handler, which has already been added to the 'ophyd_async' logger.
Examples
--------
Log to a file.
config_ophyd_async_logging(file='/tmp/what_is_happening.txt')
Include the date along with the time. (The log messages will always include
microseconds, which are configured separately, not as part of 'datefmt'.)
config_ophyd_async_logging(datefmt="%Y-%m-%d %H:%M:%S")
Turn off ANSI color codes.
config_ophyd_async_logging(color=False)
Increase verbosity: show level DEBUG or higher.
config_ophyd_async_logging(level='DEBUG')
"""
global current_handler
if isinstance(file, str):
handler = logging.FileHandler(file)
formatter = ColoredFormatterWithDeviceName(
fmt=fmt, datefmt=datefmt, no_color=True
)
else:
handler = colorlog.StreamHandler(file)
formatter = ColoredFormatterWithDeviceName(
fmt=fmt, datefmt=datefmt, log_colors=DEFAULT_LOG_COLORS, no_color=color
)
levelno = _validate_level(level)
handler.setFormatter(formatter)
handler.setLevel(levelno)
if current_handler in logger.handlers:
logger.removeHandler(current_handler)
logger.addHandler(handler)
current_handler = handler
if logger.getEffectiveLevel() > levelno:
logger.setLevel(levelno)
try:
return handler
finally:
handler.close()
set_handler = config_ophyd_async_logging # for back-compat