|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Module to convert log levels between Abseil Python, C++, and Python standard. |
|
|
|
This converter has to convert (best effort) between three different |
|
logging level schemes: |
|
|
|
* **cpp**: The C++ logging level scheme used in Abseil C++. |
|
* **absl**: The absl.logging level scheme used in Abseil Python. |
|
* **standard**: The python standard library logging level scheme. |
|
|
|
Here is a handy ascii chart for easy mental mapping:: |
|
|
|
LEVEL | cpp | absl | standard | |
|
---------+-----+--------+----------+ |
|
DEBUG | 0 | 1 | 10 | |
|
INFO | 0 | 0 | 20 | |
|
WARNING | 1 | -1 | 30 | |
|
ERROR | 2 | -2 | 40 | |
|
CRITICAL | 3 | -3 | 50 | |
|
FATAL | 3 | -3 | 50 | |
|
|
|
Note: standard logging ``CRITICAL`` is mapped to absl/cpp ``FATAL``. |
|
However, only ``CRITICAL`` logs from the absl logger (or absl.logging.fatal) |
|
will terminate the program. ``CRITICAL`` logs from non-absl loggers are treated |
|
as error logs with a message prefix ``"CRITICAL - "``. |
|
|
|
Converting from standard to absl or cpp is a lossy conversion. |
|
Converting back to standard will lose granularity. For this reason, |
|
users should always try to convert to standard, the richest |
|
representation, before manipulating the levels, and then only to cpp |
|
or absl if those level schemes are absolutely necessary. |
|
""" |
|
|
|
import logging |
|
|
|
STANDARD_CRITICAL = logging.CRITICAL |
|
STANDARD_ERROR = logging.ERROR |
|
STANDARD_WARNING = logging.WARNING |
|
STANDARD_INFO = logging.INFO |
|
STANDARD_DEBUG = logging.DEBUG |
|
|
|
|
|
|
|
|
|
ABSL_FATAL = -3 |
|
ABSL_ERROR = -2 |
|
ABSL_WARNING = -1 |
|
ABSL_WARN = -1 |
|
ABSL_INFO = 0 |
|
ABSL_DEBUG = 1 |
|
|
|
ABSL_LEVELS = {ABSL_FATAL: 'FATAL', |
|
ABSL_ERROR: 'ERROR', |
|
ABSL_WARNING: 'WARNING', |
|
ABSL_INFO: 'INFO', |
|
ABSL_DEBUG: 'DEBUG'} |
|
|
|
|
|
ABSL_NAMES = {'FATAL': ABSL_FATAL, |
|
'ERROR': ABSL_ERROR, |
|
'WARNING': ABSL_WARNING, |
|
'WARN': ABSL_WARNING, |
|
'INFO': ABSL_INFO, |
|
'DEBUG': ABSL_DEBUG} |
|
|
|
ABSL_TO_STANDARD = {ABSL_FATAL: STANDARD_CRITICAL, |
|
ABSL_ERROR: STANDARD_ERROR, |
|
ABSL_WARNING: STANDARD_WARNING, |
|
ABSL_INFO: STANDARD_INFO, |
|
ABSL_DEBUG: STANDARD_DEBUG} |
|
|
|
|
|
STANDARD_TO_ABSL = dict((v, k) for (k, v) in ABSL_TO_STANDARD.items()) |
|
|
|
|
|
def get_initial_for_level(level): |
|
"""Gets the initial that should start the log line for the given level. |
|
|
|
It returns: |
|
|
|
* ``'I'`` when: ``level < STANDARD_WARNING``. |
|
* ``'W'`` when: ``STANDARD_WARNING <= level < STANDARD_ERROR``. |
|
* ``'E'`` when: ``STANDARD_ERROR <= level < STANDARD_CRITICAL``. |
|
* ``'F'`` when: ``level >= STANDARD_CRITICAL``. |
|
|
|
Args: |
|
level: int, a Python standard logging level. |
|
|
|
Returns: |
|
The first initial as it would be logged by the C++ logging module. |
|
""" |
|
if level < STANDARD_WARNING: |
|
return 'I' |
|
elif level < STANDARD_ERROR: |
|
return 'W' |
|
elif level < STANDARD_CRITICAL: |
|
return 'E' |
|
else: |
|
return 'F' |
|
|
|
|
|
def absl_to_cpp(level): |
|
"""Converts an absl log level to a cpp log level. |
|
|
|
Args: |
|
level: int, an absl.logging level. |
|
|
|
Raises: |
|
TypeError: Raised when level is not an integer. |
|
|
|
Returns: |
|
The corresponding integer level for use in Abseil C++. |
|
""" |
|
if not isinstance(level, int): |
|
raise TypeError('Expect an int level, found {}'.format(type(level))) |
|
if level >= 0: |
|
|
|
return 0 |
|
else: |
|
return -level |
|
|
|
|
|
def absl_to_standard(level): |
|
"""Converts an integer level from the absl value to the standard value. |
|
|
|
Args: |
|
level: int, an absl.logging level. |
|
|
|
Raises: |
|
TypeError: Raised when level is not an integer. |
|
|
|
Returns: |
|
The corresponding integer level for use in standard logging. |
|
""" |
|
if not isinstance(level, int): |
|
raise TypeError('Expect an int level, found {}'.format(type(level))) |
|
if level < ABSL_FATAL: |
|
level = ABSL_FATAL |
|
if level <= ABSL_DEBUG: |
|
return ABSL_TO_STANDARD[level] |
|
|
|
return STANDARD_DEBUG - level + 1 |
|
|
|
|
|
def string_to_standard(level): |
|
"""Converts a string level to standard logging level value. |
|
|
|
Args: |
|
level: str, case-insensitive ``'debug'``, ``'info'``, ``'warning'``, |
|
``'error'``, ``'fatal'``. |
|
|
|
Returns: |
|
The corresponding integer level for use in standard logging. |
|
""" |
|
return absl_to_standard(ABSL_NAMES.get(level.upper())) |
|
|
|
|
|
def standard_to_absl(level): |
|
"""Converts an integer level from the standard value to the absl value. |
|
|
|
Args: |
|
level: int, a Python standard logging level. |
|
|
|
Raises: |
|
TypeError: Raised when level is not an integer. |
|
|
|
Returns: |
|
The corresponding integer level for use in absl logging. |
|
""" |
|
if not isinstance(level, int): |
|
raise TypeError('Expect an int level, found {}'.format(type(level))) |
|
if level < 0: |
|
level = 0 |
|
if level < STANDARD_DEBUG: |
|
|
|
return STANDARD_DEBUG - level + 1 |
|
elif level < STANDARD_INFO: |
|
return ABSL_DEBUG |
|
elif level < STANDARD_WARNING: |
|
return ABSL_INFO |
|
elif level < STANDARD_ERROR: |
|
return ABSL_WARNING |
|
elif level < STANDARD_CRITICAL: |
|
return ABSL_ERROR |
|
else: |
|
return ABSL_FATAL |
|
|
|
|
|
def standard_to_cpp(level): |
|
"""Converts an integer level from the standard value to the cpp value. |
|
|
|
Args: |
|
level: int, a Python standard logging level. |
|
|
|
Raises: |
|
TypeError: Raised when level is not an integer. |
|
|
|
Returns: |
|
The corresponding integer level for use in cpp logging. |
|
""" |
|
return absl_to_cpp(standard_to_absl(level)) |
|
|