comparison sat/core/log.py @ 3988:760f563b1243

core (log): `log.exception` is now usable
author Goffi <goffi@goffi.org>
date Thu, 24 Nov 2022 10:08:47 +0100
parents 8289ac1b34f4
children 1b7c6ee080b9
comparison
equal deleted inserted replaced
3987:9089cf6c9684 3988:760f563b1243
20 """High level logging functions""" 20 """High level logging functions"""
21 # XXX: this module use standard logging module when possible, but as SàT can work in different cases where logging is not the best choice (twisted, pyjamas, etc), it is necessary to have a dedicated module. Additional feature like environment variables and colors are also managed. 21 # XXX: this module use standard logging module when possible, but as SàT can work in different cases where logging is not the best choice (twisted, pyjamas, etc), it is necessary to have a dedicated module. Additional feature like environment variables and colors are also managed.
22 # TODO: change formatting from "%s" style to "{}" when moved to Python 3 22 # TODO: change formatting from "%s" style to "{}" when moved to Python 3
23 23
24 from typing import TYPE_CHECKING, Any, Optional 24 from typing import TYPE_CHECKING, Any, Optional
25 from typing_extensions import TypedDict
26 25
27 if TYPE_CHECKING: 26 if TYPE_CHECKING:
28 from logging import _ExcInfoType 27 from logging import _ExcInfoType
29 else: 28 else:
30 _ExcInfoType = Any 29 _ExcInfoType = Any
41 COLOR_END = '%(color_end)s' 40 COLOR_END = '%(color_end)s'
42 41
43 42
44 class Filtered(Exception): 43 class Filtered(Exception):
45 pass 44 pass
46
47
48 class KWArgs(TypedDict):
49 exc_info: _ExcInfoType
50 45
51 46
52 class Logger: 47 class Logger:
53 """High level logging class""" 48 """High level logging class"""
54 fmt = None # format option as given by user (e.g. SAT_LOG_LOGGER) 49 fmt = None # format option as given by user (e.g. SAT_LOG_LOGGER)
66 self.fmt = other.fmt 61 self.fmt = other.fmt
67 self.Filter_name = other.fmt 62 self.Filter_name = other.fmt
68 self.post_treat = other.post_treat 63 self.post_treat = other.post_treat
69 self._name = other._name 64 self._name = other._name
70 65
71 def addTraceback(self, message): 66 def add_traceback(self, message):
72 tb = traceback.format_exc() 67 tb = traceback.format_exc()
73 return message + "\n==== traceback ====\n" + tb 68 return message + "\n==== traceback ====\n" + tb
74 69
75 def out(self, message: object, level: Optional[str] = None, **kwargs: KWArgs) -> None: 70 def out(
71 self,
72 message: object,
73 level: Optional[str] = None,
74 exc_info: _ExcInfoType = False,
75 **kwargs
76 ) -> None:
76 """Actually log the message 77 """Actually log the message
77 78
78 @param message: formatted message 79 @param message: formatted message
79 """ 80 """
80 if kwargs.get('exc_info', False): 81 if exc_info:
81 message = self.addTraceback(message) 82 message = self.add_traceback(message)
82 print(message) 83 print(message)
83 84
84 def log(self, level: str, message: object, **kwargs: KWArgs) -> None: 85 def log(
86 self,
87 level: str,
88 message: object,
89 exc_info: _ExcInfoType = False,
90 **kwargs
91 ) -> None:
85 """Print message 92 """Print message
86 93
87 @param level: one of C.LOG_LEVELS 94 @param level: one of C.LOG_LEVELS
88 @param message: message to format and print 95 @param message: message to format and print
89 """ 96 """
97 if exc_info:
98 message = self.add_traceback(message)
90 try: 99 try:
91 formatted = self.format(level, message) 100 formatted = self.format(level, message)
92 if self.post_treat is None: 101 if self.post_treat is None:
93 self.out(formatted, level, **kwargs) 102 self.out(formatted, level, **kwargs)
94 else: 103 else:
127 record['profile'] = configure_cls[backend].getProfile() 136 record['profile'] = configure_cls[backend].getProfile()
128 return self.fmt % record 137 return self.fmt % record
129 else: 138 else:
130 raise e 139 raise e
131 140
132 def debug(self, msg: object, **kwargs: KWArgs) -> None: 141 def debug(self, msg: object, **kwargs) -> None:
133 self.log(C.LOG_LVL_DEBUG, msg, **kwargs) 142 self.log(C.LOG_LVL_DEBUG, msg, **kwargs)
134 143
135 def info(self, msg: object, **kwargs: KWArgs) -> None: 144 def info(self, msg: object, **kwargs) -> None:
136 self.log(C.LOG_LVL_INFO, msg, **kwargs) 145 self.log(C.LOG_LVL_INFO, msg, **kwargs)
137 146
138 def warning(self, msg: object, **kwargs: KWArgs) -> None: 147 def warning(self, msg: object, **kwargs) -> None:
139 self.log(C.LOG_LVL_WARNING, msg, **kwargs) 148 self.log(C.LOG_LVL_WARNING, msg, **kwargs)
140 149
141 def error(self, msg: object, **kwargs: KWArgs) -> None: 150 def error(self, msg: object, **kwargs) -> None:
142 self.log(C.LOG_LVL_ERROR, msg, **kwargs) 151 self.log(C.LOG_LVL_ERROR, msg, **kwargs)
143 152
144 def critical(self, msg: object, **kwargs: KWArgs) -> None: 153 def critical(self, msg: object, **kwargs) -> None:
145 self.log(C.LOG_LVL_CRITICAL, msg, **kwargs) 154 self.log(C.LOG_LVL_CRITICAL, msg, **kwargs)
155
156 def exception(self, msg: object, exc_info=True, **kwargs) -> None:
157 self.log(C.LOG_LVL_ERROR, msg, exc_info=exc_info, **kwargs)
146 158
147 159
148 class FilterName(object): 160 class FilterName(object):
149 """Filter on logger name according to a regex""" 161 """Filter on logger name according to a regex"""
150 162