-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathlogging.py
87 lines (71 loc) · 2.92 KB
/
logging.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#
# Copyright (c) 2020-2021 Arm Limited and Contributors. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
"""Helpers for logging errors according to severity of the exception."""
from typing import Type, Optional, cast
from types import TracebackType
import logging
from mbed_tools.lib.exceptions import ToolsError
LOGGING_FORMAT = "%(levelname)s: %(message)s"
VERBOSITY_HELP = {
logging.CRITICAL: "-v",
logging.ERROR: "-v",
logging.WARNING: "-vv",
logging.INFO: "-vvv",
logging.DEBUG: "--traceback",
}
def _exception_message(err: BaseException, log_level: int, traceback: bool) -> str:
"""Generate a user facing message with help on how to get more information from the logs."""
error_msg = str(err)
if log_level != logging.DEBUG or not traceback:
cli_option = VERBOSITY_HELP.get(log_level, "-v")
error_msg += f"\n\nMore information may be available by using the command line option '{cli_option}'."
return error_msg
class MbedToolsHandler:
"""Context Manager to catch Mbed Tools exceptions and generate a helpful user facing message."""
def __init__(self, logger: logging.Logger, traceback: bool = False):
"""Keep track of the logger to use and whether or not a traceback should be generated."""
self._logger = logger
self._traceback = traceback
self.exit_code = 0
def __enter__(self) -> "MbedToolsHandler":
"""Return the Context Manager."""
return self
def __exit__(
self,
exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException],
exc_traceback: Optional[TracebackType],
) -> bool:
"""Handle any raised exceptions, suppressing Tools errors and generating an error message instead."""
if exc_type and issubclass(exc_type, ToolsError):
error_msg = _exception_message(cast(BaseException, exc_value), logging.root.level, self._traceback)
self._logger.error(error_msg, exc_info=self._traceback)
# Do not propagate exceptions derived from ToolsError
self.exit_code = 1
return True
# Propagate all other exceptions
return False
def log_exception(logger: logging.Logger, exception: Exception, show_traceback: bool = False) -> None:
"""Logs an exception in both normal and verbose forms.
Args:
logger: logger
exception: exception to log
show_traceback: show the full traceback.
"""
logger.error(exception, exc_info=show_traceback)
def set_log_level(verbose_count: int) -> None:
"""Sets the log level.
Args:
verbose_count: number of `-v` flags used
"""
if verbose_count > 2:
log_level = logging.DEBUG
elif verbose_count == 2:
log_level = logging.INFO
elif verbose_count == 1:
log_level = logging.WARNING
else:
log_level = logging.ERROR
logging.basicConfig(level=log_level, format=LOGGING_FORMAT)