Source code for task_script_utils.workflow_logging
import logging
TS_LOG_LEVEL_MAP = {
"DEBUG": "debug",
"INFO": "info",
"WARNING": "warn",
"ERROR": "error",
"CRITICAL": "crit",
}
[docs]
def map_ts_log_level(log_level_name: str) -> str:
"""Convert Python's logging levels to TetraScience log levels
Arguments:
logging_level_name (str) - Python's logging level name ("DEBUG",
"WARNING", etc.)
Returns:
ts_log_level_name (str) - TetraScience log level string
"""
if log_level_name not in TS_LOG_LEVEL_MAP:
raise KeyError(
f"Log level `{log_level_name}` has no corresponding TetraScience level name"
)
return TS_LOG_LEVEL_MAP[log_level_name]
[docs]
class TSLogFormatter(logging.Formatter):
"""Log formatter to convert python logs into the TetraScience format"""
def __init__(self):
super().__init__()
[docs]
def format(self, record):
record.message = record.getMessage()
ts_log_record = {
"level": map_ts_log_level(record.levelname),
"message": record.message,
"funcName": record.module + "." + record.funcName,
}
return ts_log_record
[docs]
class TSLogHandler(logging.StreamHandler):
"""A log handler to redirect Python's logs to an external logger function"""
def __init__(self, external_logger: object) -> None:
"""Initialize a log handler with a pointer to the external logging
function, and a formatter to convert log into a dictionary expected
by the workflow object.
Arguments:
external_logger (object) - A TetraScience workflow logger object,
external_logger.log(log_record)
"""
super().__init__()
self.external_logger = external_logger
self.setFormatter(TSLogFormatter())
[docs]
def handle(self, record: logging.LogRecord) -> None:
"""Redirect log output to the external logger object's log function
A custom formatter structures the log into the form required by the
workflow logger.log function
Arguments:
record {logging.LogRecord} - Log record including message and level
"""
ts_record = self.format(record)
self.external_logger.log(ts_record)
[docs]
def setup_ts_log_handler(
external_logger: object, logger_scope: str = None
) -> logging.Logger:
"""Set up a handler to send Python logs to the TetraScience workflow logger
After setting up this log handler, any logger created within the same
logging hierarchy will have its logs sent to the external logger (see
logging.getLogger docs for more on logging heirarchy).
Arguments:
external_logger (object) - The external logging object to pass logs to.
external_logger.log(record) will be called with a record formatted
as a TetraScience log record.
logger_scope (str) - the name passed to logging.getLogger(logger_scope)
which defines the heirarchy of logs handled by the external logger.
"""
logger = logging.getLogger(logger_scope)
logger.setLevel(logging.INFO)
logger.addHandler(TSLogHandler(external_logger))