py.lib
43:6f8bea109183 Browse Files
. Наведение порядка в коде логирования
log/log_confile.py log/log_syslog.py log/slog_console.py log/slog_syslogger.py log/tiny_slog.py
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/log/log_confile.py Sat Jan 28 16:39:53 2023 +0300 1.3 @@ -0,0 +1,246 @@ 1.4 +# coding: utf-8 1.5 +""" Логирование на консоль 1.6 + 1.7 +Метки в журнале о уровне сообщения: 1.8 + "`": Debug 1.9 + ".": Info 1.10 + "*": Warning 1.11 + "!": Error 1.12 + "#": Alert 1.13 + 1.14 +""" 1.15 + 1.16 +from time import monotonic, ctime 1.17 +from datetime import timedelta, date 1.18 +from traceback import extract_tb, extract_stack 1.19 +from sys import exc_info, stderr, stdout 1.20 +from typing import Optional, TextIO, Any 1.21 +from os.path import join as p_join, abspath 1.22 +from threading import RLock 1.23 + 1.24 + 1.25 +TIME_TO_FLUSH: int = 120 # Время по умолчанию с момента прошлого сброса лога, 1.26 + # после которого, выполняется принудительный сброс буферов 1.27 + 1.28 + 1.29 +class Timing(object): 1.30 + def __init__(self, name: Optional[str] = None): 1.31 + if name is None: 1.32 + self.prefix = '' 1.33 + 1.34 + else: 1.35 + self.prefix = f'{name} :: ' 1.36 + 1.37 + self.tsAll = monotonic() 1.38 + self.ts = self.tsAll 1.39 + 1.40 + def get_time(self): 1.41 + return monotonic() - self.ts 1.42 + 1.43 + def reset(self): 1.44 + self.ts = monotonic() 1.45 + self.tsAll = self.ts 1.46 + 1.47 + def __str__(self): 1.48 + ts = monotonic() 1.49 + return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts) 1.50 + 1.51 + def __call__(self, msg): 1.52 + _buf = f'{self} | {msg}' 1.53 + self.ts = monotonic() 1.54 + return _buf 1.55 + 1.56 + 1.57 +class NullLog(object): 1.58 + def __init__(self, prefix: str = 'main'): 1.59 + self.prefix = prefix 1.60 + 1.61 + @staticmethod 1.62 + def _write(mark: str, msg: Any): 1.63 + pass # cat > /dev/null 1.64 + 1.65 + def __call__(self, msg): 1.66 + self._write('.', msg) 1.67 + 1.68 + def err(self, msg): 1.69 + self._write('!', msg) 1.70 + 1.71 + def warn(self, msg): 1.72 + self._write('*', msg) 1.73 + 1.74 + def alert(self, msg): 1.75 + self._write('#', msg) 1.76 + 1.77 + def debug(self, msg): 1.78 + self._write('`', msg) 1.79 + 1.80 + @staticmethod 1.81 + def get_timing(name: Optional[str] = None): 1.82 + return Timing(name) 1.83 + 1.84 + def sub_log(self, name: str): 1.85 + return self.__class__(f'{self.prefix}/{name}') 1.86 + 1.87 + def excpt(self, msg, e_class=None, e_obj=None, e_tb=None, stack_skip=0): 1.88 + if e_class is None: 1.89 + e_class, e_obj, e_tb = exc_info() 1.90 + 1.91 + tb_data_tb = list(extract_tb(e_tb))[::-1] 1.92 + tb_data_stack = list(extract_stack())[::-1][(2 + stack_skip):] 1.93 + self.err(msg) 1.94 + self.err('--- EXCEPTION ---') 1.95 + self.err(f' {e_class.__name__} ({e_obj})') 1.96 + self.err('--- TRACEBACK ---') 1.97 + for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_tb: 1.98 + self.err(f'File: {_tb_file}, line {_tb_line} in {_tb_func}') 1.99 + self.err(f' {_tb_text}') 1.100 + 1.101 + self.err('>>> Exception Handler <<<') 1.102 + for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_stack: 1.103 + self.err(f'File: {_tb_file}, line {_tb_line} in {_tb_func}') 1.104 + self.err(f' {_tb_text}') 1.105 + 1.106 + self.err('--- END EXCEPTION ---') 1.107 + 1.108 + 1.109 +class FileLog(NullLog): 1.110 + @staticmethod 1.111 + def _open_file(file_name: str): 1.112 + return open(file_name, 'a', encoding='utf-8') 1.113 + 1.114 + def __init__(self, prefix: str = 'main', 1.115 + file_name: Optional[str] = None, 1.116 + file_obj: Optional[TextIO] = None, 1.117 + time_to_flush: int = TIME_TO_FLUSH 1.118 + ): 1.119 + 1.120 + super().__init__(prefix=prefix) 1.121 + self.fd: Optional[TextIO] = None 1.122 + 1.123 + self.flush_time = monotonic() 1.124 + self.time_to_flush = time_to_flush # Время с момента прошлого сброса лога, 1.125 + # после которого, выполняется принудительный сброс буферов 1.126 + 1.127 + if file_name is not None: 1.128 + self.fd = self._open_file(file_name) 1.129 + 1.130 + else: 1.131 + self.fd = file_obj 1.132 + 1.133 + if self.fd is None: 1.134 + raise ValueError(f'Не задан файл для записи журналов') 1.135 + 1.136 + def flush(self, time_mark: float = None): 1.137 + if time_mark is None: 1.138 + time_mark = monotonic() 1.139 + 1.140 + self.flush_time = time_mark 1.141 + self.fd.flush() 1.142 + 1.143 + def close(self): 1.144 + self.fd.flush() 1.145 + self.fd.close() 1.146 + self.fd = None 1.147 + 1.148 + def __del__(self): 1.149 + if self.fd is not None: 1.150 + self.fd.flush() 1.151 + self.fd.close() 1.152 + self.fd = None 1.153 + 1.154 + def flush_event(self): 1.155 + t = monotonic() 1.156 + if t - self.flush_time >= self.time_to_flush: 1.157 + self.flush(t) 1.158 + 1.159 + def _write(self, mark: str, msg: Any): 1.160 + if self.fd is None: 1.161 + raise ValueError('Попытка использовать закрытый файл журнала') 1.162 + 1.163 + t = ctime() 1.164 + for l in str(msg).splitlines(): 1.165 + self.fd.write(f'{t} | {mark} {self.prefix} | {l}') 1.166 + 1.167 + self.flush_event() 1.168 + 1.169 + def sub_log(self, name: str): 1.170 + if self.fd is None: 1.171 + raise ValueError('Попытка использовать закрытый файл журнала') 1.172 + 1.173 + return self.__class__(f'{self.prefix}/{name}', file_obj=self.fd, time_to_flush=self.time_to_flush) 1.174 + 1.175 + 1.176 +class StderrLog(FileLog): 1.177 + def __init__(self, prefix: str = 'main'): 1.178 + super().__init__(prefix, file_obj=stderr) 1.179 + 1.180 + def flush_event(self): 1.181 + pass # нет необходимости сбрасывать буферы в консоли 1.182 + 1.183 + 1.184 +class StdoutLog(FileLog): 1.185 + def __init__(self, prefix: str = 'main'): 1.186 + super().__init__(prefix, file_obj=stdout) 1.187 + 1.188 + def flush_event(self): 1.189 + pass # нет необходимости сбрасывать буферы в консоли 1.190 + 1.191 + 1.192 +class LogrotateFile(FileLog): 1.193 + def __init__(self, directory: str = '.', prefix: str = 'main', time_to_flush: int = TIME_TO_FLUSH): 1.194 + d = date.today() 1.195 + directory = abspath(directory) 1.196 + file_name = p_join(directory, f'{prefix}-{d}.log') 1.197 + 1.198 + super().__init__(prefix, file_name=file_name, time_to_flush=time_to_flush) 1.199 + self.logrotate_base = p_join(directory, f'{prefix}') 1.200 + self.logrotate_date = d 1.201 + 1.202 + def flush(self, time_mark: float = None, no_rotate: bool = False): 1.203 + if not no_rotate: 1.204 + d = date.today() 1.205 + if self.logrotate_date != d: 1.206 + self.logrotate_rotate() 1.207 + return 1.208 + 1.209 + super().flush(time_mark=time_mark) 1.210 + 1.211 + def logrotate_rotate(self): 1.212 + d = date.today() 1.213 + file_name = f'{self.logrotate_base}-{d}.log' 1.214 + self.fd.flush() 1.215 + self.fd = self._open_file(file_name) 1.216 + self.logrotate_date = d 1.217 + self.flush(no_rotate=True) 1.218 + 1.219 + 1.220 +class ThreadSafeFileLog(FileLog): 1.221 + def __int__(self, *a, **kwa): 1.222 + super().__init__(*a, **kwa) 1.223 + self.thread_safe_lock = RLock() 1.224 + 1.225 + def _write(self, mark: str, msg: Any): 1.226 + with self.thread_safe_lock: 1.227 + super()._write(mark, msg) 1.228 + 1.229 + def flush(self, time_mark: float = None): 1.230 + with self.thread_safe_lock: 1.231 + super().flush(time_mark) 1.232 + 1.233 + 1.234 +class ThreadSafeLogrotateFile(LogrotateFile): 1.235 + def __init__(self, directory: str = '.', prefix: str = 'main', time_to_flush: int = TIME_TO_FLUSH): 1.236 + super().__init__(directory=directory, prefix=prefix, time_to_flush=time_to_flush) 1.237 + self.thread_safe_lock = RLock() 1.238 + 1.239 + def _write(self, mark: str, msg: Any): 1.240 + with self.thread_safe_lock: 1.241 + super()._write(mark, msg) 1.242 + 1.243 + def flush(self, time_mark: float = None, no_rotate: bool = False): 1.244 + with self.thread_safe_lock: 1.245 + super().flush(time_mark=time_mark, no_rotate=no_rotate) 1.246 + 1.247 + def logrotate_rotate(self): 1.248 + with self.thread_safe_lock: 1.249 + super().logrotate_rotate()
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/log/log_syslog.py Sat Jan 28 16:39:53 2023 +0300 2.3 @@ -0,0 +1,105 @@ 2.4 +# coding: utf-8 2.5 +""" 2.6 +Тривиальная реализация сислоггера без блэк-джека и поэтесс 2.7 + 2.8 +Метки в журнале о уровне сообщения: 2.9 + "`": Debug 2.10 + ".": Info 2.11 + "*": Warning 2.12 + "!": Error 2.13 + "#": Alert 2.14 + 2.15 +""" 2.16 +from time import monotonic 2.17 +from datetime import timedelta 2.18 + 2.19 +import syslog 2.20 +from traceback import extract_tb, extract_stack 2.21 +from sys import exc_info 2.22 + 2.23 + 2.24 +class Timing(object): 2.25 + def __init__(self, name=None): 2.26 + if name is None: 2.27 + self.prefix = '' 2.28 + 2.29 + else: 2.30 + self.prefix = f'{name} :: ' 2.31 + 2.32 + self.tsAll = monotonic() 2.33 + self.ts = self.tsAll 2.34 + 2.35 + def get_time(self): 2.36 + return monotonic() - self.ts 2.37 + 2.38 + def reset(self): 2.39 + self.ts = monotonic() 2.40 + self.tsAll = self.ts 2.41 + 2.42 + def __str__(self): 2.43 + ts = monotonic() 2.44 + return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts) 2.45 + 2.46 + def __call__(self, msg): 2.47 + _buf = f'{self} | {msg}' 2.48 + self.ts = monotonic() 2.49 + return _buf 2.50 + 2.51 + 2.52 +class SysLogger(object): 2.53 + @staticmethod 2.54 + def init_syslog(ident): 2.55 + syslog.openlog(ident, syslog.LOG_PID) 2.56 + 2.57 + @staticmethod 2.58 + def get_timing(name=None): 2.59 + return Timing(name) 2.60 + 2.61 + def __init__(self, prefix='main', facility=syslog.LOG_USER): 2.62 + self.prefix = str(prefix) 2.63 + self.facility = facility 2.64 + 2.65 + def _write(self, flag, mark, msg): 2.66 + for l in str(msg).splitlines(): 2.67 + syslog.syslog(self.facility | flag, f'{mark} {self.prefix} | {l}') 2.68 + 2.69 + def __call__(self, msg): 2.70 + self._write(syslog.LOG_INFO, '.', msg) 2.71 + 2.72 + def err(self, msg): 2.73 + self._write(syslog.LOG_ERR, '!', msg) 2.74 + 2.75 + def warn(self, msg): 2.76 + self._write(syslog.LOG_WARNING, '*', msg) 2.77 + 2.78 + def debug(self, msg): 2.79 + self._write(syslog.LOG_DEBUG, '`', msg) 2.80 + 2.81 + def alert(self, msg): 2.82 + self._write(syslog.LOG_ALERT, '#', msg) 2.83 + 2.84 + def sub_log(self, prefix): 2.85 + return self.__class__(f'{self.prefix}/{prefix}', self.facility) 2.86 + 2.87 + def excpt(self, msg, e_class=None, e_obj=None, e_tback=None, stack_skip=0): 2.88 + if e_class is None: 2.89 + e_class, e_obj, e_tback = exc_info() 2.90 + 2.91 + tb_data_tb = list(extract_tb(e_tback))[::-1] 2.92 + tb_data_stack = list(extract_stack())[::-1][(2 + stack_skip):] 2.93 + 2.94 + self.err(msg) 2.95 + self.err('--- EXCEPTION ---') 2.96 + self.err(f' {e_class.__name__} ({e_obj})') 2.97 + 2.98 + self.err('--- TRACEBACK ---') 2.99 + for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_tb: 2.100 + self.err(f'File: {_tb_file}, line {_tb_line} in {_tb_func}') 2.101 + self.err(f' {_tb_text}') 2.102 + 2.103 + self.err('>>> Exception Handler <<<') 2.104 + for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_stack: 2.105 + self.err(f'File: {_tb_file}, line {_tb_line} in {_tb_func}') 2.106 + self.err(f' {_tb_text}') 2.107 + 2.108 + self.err('--- END EXCEPTION ---')
3.1 --- a/log/slog_console.py Sat Aug 27 17:56:21 2022 +0300 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,123 +0,0 @@ 3.4 -# coding: utf-8 3.5 -""" Логирование на консоль 3.6 - 3.7 -Метки в журнале о уровне сообщения: 3.8 - "`": Debug 3.9 - ".": Info 3.10 - "*": Warning 3.11 - "!": Error 3.12 - "#": Alert 3.13 -""" 3.14 - 3.15 -from time import monotonic 3.16 -from datetime import timedelta 3.17 -from sys import exc_info, stderr, stdout 3.18 -from traceback import extract_tb, extract_stack 3.19 - 3.20 - 3.21 -class Timing(object): 3.22 - def __init__(self, name=None): 3.23 - if name is None: 3.24 - self.prefix = '' 3.25 - else: 3.26 - self.prefix = '%s :: ' % name 3.27 - self.tsAll = monotonic() 3.28 - self.ts = self.tsAll 3.29 - 3.30 - def getTime(self): 3.31 - return monotonic() - self.ts 3.32 - 3.33 - def reset(self): 3.34 - self.ts = monotonic() 3.35 - self.tsAll = self.ts 3.36 - 3.37 - def __str__(self): 3.38 - ts = monotonic() 3.39 - return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts) 3.40 - 3.41 - def __call__(self, msg): 3.42 - _buf = '%s | %s' % (self, msg) 3.43 - self.ts = monotonic() 3.44 - return _buf 3.45 - 3.46 - 3.47 -class ConsoleLog(object): 3.48 - def __init__(self, appname='main'): 3.49 - self.appname = appname 3.50 - 3.51 - @staticmethod 3.52 - def _write(ItrCntnt): 3.53 - for l in ItrCntnt: 3.54 - print(l) 3.55 - 3.56 - def __call__(self, msg): 3.57 - self._write(map( 3.58 - lambda x: '%3s | %s :: %s' % ('.', self.appname, x), 3.59 - str(msg).splitlines() 3.60 - )) 3.61 - 3.62 - def err(self, msg): 3.63 - self._write(map( 3.64 - lambda x: '%3s | %s :: %s' % ('!', self.appname, x), 3.65 - str(msg).splitlines() 3.66 - )) 3.67 - 3.68 - def warn(self, msg): 3.69 - self._write(map( 3.70 - lambda x: '%3s | %s :: %s' % ('*', self.appname, x), 3.71 - str(msg).splitlines() 3.72 - )) 3.73 - 3.74 - def alert(self, msg): 3.75 - self._write(map( 3.76 - lambda x: '%3s | %s :: %s' % ('#', self.appname, x), 3.77 - str(msg).splitlines() 3.78 - )) 3.79 - 3.80 - def debug(self, msg): 3.81 - self._write(map( 3.82 - lambda x: '%3s | %s :: %s' % ('`', self.appname, x), 3.83 - str(msg).splitlines() 3.84 - )) 3.85 - 3.86 - @staticmethod 3.87 - def getTiming(name=None): 3.88 - return Timing(name) 3.89 - 3.90 - def sublog(self, name): 3.91 - return self.__class__('%s/%s' % (self.appname, name)) 3.92 - 3.93 - def excpt(self, msg, eClass=None, eObj=None, eTb=None, stack_skip=0): 3.94 - if eClass is None: 3.95 - eClass, eObj, eTb = exc_info() 3.96 - 3.97 - tbData_tb = list(extract_tb(eTb))[::-1] 3.98 - tbData_stack = list(extract_stack())[::-1][(2 + stack_skip):] 3.99 - self.err(msg) 3.100 - self.err('--- EXCEPTION ---') 3.101 - self.err(' %s (%s)' % (eClass.__name__, eObj)) 3.102 - self.err('--- TRACEBACK ---') 3.103 - for _tbFile, _tbLine, _tbFunc, _tbText in tbData_tb: 3.104 - self.err('File: %s, line %s in %s' % (_tbFile, _tbLine, _tbFunc)) 3.105 - self.err(' %s' % _tbText) 3.106 - self.err('>>> Exception Handler <<<') 3.107 - for _tbFile, _tbLine, _tbFunc, _tbText in tbData_stack: 3.108 - self.err('File: %s, line %s in %s' % (_tbFile, _tbLine, _tbFunc)) 3.109 - self.err(' %s' % _tbText) 3.110 - self.err('--- END EXCEPTION ---') 3.111 - 3.112 - 3.113 -class StderrLog(ConsoleLog): 3.114 - @staticmethod 3.115 - def _write(msgItr): 3.116 - for l in msgItr: 3.117 - stderr.write('%s\n' % l) 3.118 - stderr.flush() 3.119 - 3.120 - 3.121 -class StdoutLog(ConsoleLog): 3.122 - @staticmethod 3.123 - def _write(msgItr): 3.124 - for l in msgItr: 3.125 - stdout.write('%s\n' % l) 3.126 - stdout.flush()
4.1 --- a/log/slog_syslogger.py Sat Aug 27 17:56:21 2022 +0300 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,151 +0,0 @@ 4.4 -# coding: utf-8 4.5 - 4.6 -"""\ 4.7 -Логирование в системный журнал Unix 4.8 - 4.9 -Метки в журнале о уровне сообщения: 4.10 - "`": Debug 4.11 - ".": Info 4.12 - "*": Warning 4.13 - "!": Error 4.14 - "#": Alert 4.15 -""" 4.16 - 4.17 -import syslog 4.18 -from sys import exc_info 4.19 -from time import monotonic 4.20 -from traceback import extract_tb, extract_stack 4.21 -from datetime import timedelta 4.22 -from typing import Any 4.23 - 4.24 -LOG_FACILITY = { 4.25 - 'auth': syslog.LOG_AUTH, 4.26 - 'authpriv': syslog.LOG_AUTH, 4.27 - 'cron': syslog.LOG_CRON, 4.28 - 'daemon': syslog.LOG_DAEMON, 4.29 - 'ftp': syslog.LOG_DAEMON, 4.30 - 'kern': syslog.LOG_KERN, 4.31 - 'lpr': syslog.LOG_LPR, 4.32 - 'mail': syslog.LOG_MAIL, 4.33 - 'news': syslog.LOG_NEWS, 4.34 - 'syslog': syslog.LOG_SYSLOG, 4.35 - 'user': syslog.LOG_USER, 4.36 - 'uucp': syslog.LOG_UUCP, 4.37 - 'local0': syslog.LOG_LOCAL0, 4.38 - 'local1': syslog.LOG_LOCAL1, 4.39 - 'local2': syslog.LOG_LOCAL2, 4.40 - 'local3': syslog.LOG_LOCAL3, 4.41 - 'local4': syslog.LOG_LOCAL4, 4.42 - 'local5': syslog.LOG_LOCAL5, 4.43 - 'local6': syslog.LOG_LOCAL6, 4.44 - 'local7': syslog.LOG_LOCAL7 4.45 -} 4.46 - 4.47 - 4.48 -class LoggerError(Exception): pass 4.49 - 4.50 - 4.51 -# --- INTERFACE --- # 4.52 -FACILITY = LOG_FACILITY['user'] 4.53 - 4.54 - 4.55 -def check_facility(facility: str = 'user'): 4.56 - if not facility.lower() in LOG_FACILITY: 4.57 - raise LoggerError(f'Unknown facility: {facility}') 4.58 - 4.59 - 4.60 -def log_prep(ident: str, facility: str = 'user'): 4.61 - global FACILITY 4.62 - check_facility(facility) 4.63 - 4.64 - syslog.openlog(ident, syslog.LOG_PID) 4.65 - 4.66 - FACILITY = LOG_FACILITY[facility] 4.67 - 4.68 - 4.69 -class Timing(object): 4.70 - def __init__(self, name: str = None): 4.71 - if name is None: 4.72 - self.prefix = '' 4.73 - else: 4.74 - self.prefix = f'{name} :: ' 4.75 - self.tsAll = monotonic() 4.76 - self.ts = self.tsAll 4.77 - 4.78 - def get_time(self): 4.79 - return monotonic() - self.ts 4.80 - 4.81 - def reset(self): 4.82 - self.ts = monotonic() 4.83 - self.tsAll = self.ts 4.84 - 4.85 - def __str__(self): 4.86 - ts = monotonic() 4.87 - return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts) 4.88 - 4.89 - def __call__(self, msg: Any) -> str: 4.90 - _buf = f'{self} | {msg}' 4.91 - self.ts = monotonic() 4.92 - return _buf 4.93 - 4.94 - 4.95 -class SysLogger(object): 4.96 - init_log = log_prep 4.97 - 4.98 - @staticmethod 4.99 - def get_timing(name: str = None): 4.100 - return Timing(name) 4.101 - 4.102 - def __init__(self, prefix: str = 'main', facility: int = FACILITY): 4.103 - self.prefix = str(prefix) 4.104 - self.facility = facility 4.105 - 4.106 - def _write(self, flag: int, mark: str, msg: Any): 4.107 - for l in str(msg).splitlines(): 4.108 - syslog.syslog(self.facility | flag, f'{mark} {self.prefix}: {l}') 4.109 - 4.110 - def __call__(self, msg: Any): 4.111 - self._write(syslog.LOG_INFO, '.', msg) 4.112 - 4.113 - def err(self, msg: Any): 4.114 - self._write(syslog.LOG_ERR, '!', msg) 4.115 - 4.116 - def warn(self, msg: Any): 4.117 - self._write(syslog.LOG_WARNING, '*', msg) 4.118 - 4.119 - def debug(self, msg: Any): 4.120 - self._write(syslog.LOG_DEBUG, '`', msg) 4.121 - 4.122 - def alert(self, msg: Any): 4.123 - self._write(syslog.LOG_ALERT, '#', msg) 4.124 - 4.125 - def sublog(self, prefix: str): 4.126 - return self.__class__(f'{self.prefix}/{prefix}', self.facility) 4.127 - 4.128 - def excpt(self, msg: Any, e_class: type = None, e_obj: Exception = None, e_tb=None, stack_skip=0): 4.129 - if e_class is None: 4.130 - e_class, e_obj, e_tb = exc_info() 4.131 - 4.132 - if e_class is None: 4.133 - # Если вдруг вызываем без произошедшего исключения 4.134 - self.err(msg) 4.135 - else: 4.136 - tb_data_tb = list(extract_tb(e_tb))[::-1] 4.137 - tb_data_stack = list(extract_stack())[::-1][(2 + stack_skip):] 4.138 - 4.139 - self.err(msg) 4.140 - 4.141 - self.err('--- EXCEPTION ---') 4.142 - self.err(' %s (%s)' % (e_class.__name__, e_obj)) 4.143 - 4.144 - self.err('--- TRACEBACK ---') 4.145 - for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_tb: 4.146 - self.err('File: %s, line %s in %s' % (_tb_file, _tb_line, _tb_func)) 4.147 - self.err(' %s' % _tb_text) 4.148 - 4.149 - self.err('>>> Exception Handler <<<') 4.150 - for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_stack: 4.151 - self.err('File: %s, line %s in %s' % (_tb_file, _tb_line, _tb_func)) 4.152 - self.err(' %s' % _tb_text) 4.153 - 4.154 - self.err('--- END EXCEPTION ---')
5.1 --- a/log/tiny_slog.py Sat Aug 27 17:56:21 2022 +0300 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,103 +0,0 @@ 5.4 -# coding: utf-8 5.5 -""" 5.6 -Тривиальная реализация сислоггера без блэк-джека и поэтесс 5.7 - 5.8 -Метки в журнале о уровне сообщения: 5.9 - "`": Debug 5.10 - ".": Info 5.11 - "*": Warning 5.12 - "!": Error 5.13 - "#": Alert 5.14 - 5.15 -""" 5.16 -from time import monotonic 5.17 -from datetime import timedelta 5.18 - 5.19 -import syslog 5.20 -from traceback import extract_tb, extract_stack 5.21 -from sys import exc_info 5.22 - 5.23 - 5.24 -class Timing(object): 5.25 - def __init__(self, name=None): 5.26 - if name is None: 5.27 - self.prefix = '' 5.28 - else: 5.29 - self.prefix = '%s :: ' % name 5.30 - self.tsAll = monotonic() 5.31 - self.ts = self.tsAll 5.32 - 5.33 - def getTime(self): 5.34 - return monotonic() - self.ts 5.35 - 5.36 - def reset(self): 5.37 - self.ts = monotonic() 5.38 - self.tsAll = self.ts 5.39 - 5.40 - def __str__(self): 5.41 - ts = monotonic() 5.42 - return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts) 5.43 - 5.44 - def __call__(self, msg): 5.45 - _buf = '%s | %s' % (self, msg) 5.46 - self.ts = monotonic() 5.47 - return _buf 5.48 - 5.49 - 5.50 -class SimpleSysLogger(object): 5.51 - @staticmethod 5.52 - def init_syslog(ident): 5.53 - syslog.openlog(ident, syslog.LOG_PID) 5.54 - 5.55 - @staticmethod 5.56 - def get_timing(name=None): 5.57 - return Timing(name) 5.58 - 5.59 - def __init__(self, prefix='main', facility=syslog.LOG_USER): 5.60 - self.prefix = str(prefix) 5.61 - self.facility = facility 5.62 - 5.63 - def _write(self, flag, mark, msg): 5.64 - for l in str(msg).splitlines(): 5.65 - syslog.syslog(self.facility | flag, f'{self.prefix}: {mark} {l}') 5.66 - 5.67 - def __call__(self, msg): 5.68 - self._write(syslog.LOG_INFO, '.', msg) 5.69 - 5.70 - def err(self, msg): 5.71 - self._write(syslog.LOG_ERR, '!', msg) 5.72 - 5.73 - def warn(self, msg): 5.74 - self._write(syslog.LOG_WARNING, '*', msg) 5.75 - 5.76 - def debug(self, msg): 5.77 - self._write(syslog.LOG_DEBUG, '`', msg) 5.78 - 5.79 - def alert(self, msg): 5.80 - self._write(syslog.LOG_ALERT, '#', msg) 5.81 - 5.82 - def sub_log(self, prefix): 5.83 - return self.__class__('%s/%s' % (self.prefix, prefix), self.facility) 5.84 - 5.85 - def excpt(self, msg, e_class=None, e_obj=None, e_tback=None, stack_skip=0): 5.86 - if e_class is None: 5.87 - e_class, e_obj, e_tback = exc_info() 5.88 - 5.89 - tb_data_tb = list(extract_tb(e_tback))[::-1] 5.90 - tb_data_stack = list(extract_stack())[::-1][(2 + stack_skip):] 5.91 - 5.92 - self.err(msg) 5.93 - self.err('--- EXCEPTION ---') 5.94 - self.err(' %s (%s)' % (e_class.__name__, e_obj)) 5.95 - 5.96 - self.err('--- TRACEBACK ---') 5.97 - for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_tb: 5.98 - self.err('File: %s, line %s in %s' % (_tb_file, _tb_line, _tb_func)) 5.99 - self.err(' %s' % _tb_text) 5.100 - 5.101 - self.err('>>> Exception Handler <<<') 5.102 - for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_stack: 5.103 - self.err('File: %s, line %s in %s' % (_tb_file, _tb_line, _tb_func)) 5.104 - self.err(' %s' % _tb_text) 5.105 - 5.106 - self.err('--- END EXCEPTION ---')