syslogformat/src/syslogformat/helpers.py

55 lines
2.0 KiB
Python

import logging as _logging
from syslog import LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG
from typing import Union
LevelT = Union[str, int]
def check_level(level: LevelT) -> int:
"""
Custom implementation of the logging module's _checkLevel(...) function.
Returns the numeric representation of a log level.
Args:
level: Either a string such as 'DEBUG' or 'WARNING' or an integer.
Returns:
If an integer is passed, it is returned unchanged;
if a string is passed, the corresponding numeric log level is returned.
Raises:
TypeError if something other than a string or an integer is passed.
ValueError if the string has no corresponding level in the logging module.
"""
if isinstance(level, int):
return level
if str(level) != level:
raise TypeError(f"Level not an integer or a valid string: {level}")
output = getattr(_logging, level)
if output is None:
raise ValueError(f"Unknown level: {level}")
return output
def py_to_sys_lvl(level_num: int) -> int:
"""
Maps a (numeric) log level as defined in Python stdlib logging module to the syslog module's log levels.
The output number corresponds to a syslog `PRI` without the enclosing angle brackets.
Even though there are more levels available to syslog, the `EMERG` (num. 0) and `NOTICE` (num. 5) levels are
omitted here, i.e. it goes straight from `INFO` (num. 6) to `WARNING` (num. 4) because there is no equivalent
in the Python logging module to `NOTICE`, and `EMERG` is unnecessary because no Python script should be able to
cause such severe problems.
"""
if level_num <= _logging.DEBUG:
return LOG_DEBUG
if level_num <= _logging.INFO:
return LOG_INFO
if level_num <= _logging.WARNING:
return LOG_WARNING
if level_num <= _logging.ERROR:
return LOG_ERR
if level_num <= _logging.CRITICAL:
return LOG_CRIT
return LOG_ALERT