py.lib.aw_log
2024-02-11
Child:894923fbd0d0
py.lib.aw_log/src/aw_log/__init__.py
..init
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/aw_log/__init__.py Sun Feb 11 13:53:23 2024 +0300 1.3 @@ -0,0 +1,101 @@ 1.4 +# coding: utf-8 1.5 +# devel.a0fs.ru -- aw_log -- v0.r202402.1 1.6 +""" Реализация классов логирования 1.7 + 1.8 +Метки в журнале о уровне сообщения: 1.9 + "`": Debug 1.10 + ".": Info 1.11 + "*": Warning 1.12 + "!": Error 1.13 + "#": Alert 1.14 + 1.15 +""" 1.16 + 1.17 +from time import monotonic 1.18 +from datetime import timedelta 1.19 +from traceback import extract_tb, extract_stack 1.20 +from typing import Optional, Any, Iterable 1.21 +from sys import exc_info 1.22 + 1.23 + 1.24 +class Timing(object): 1.25 + def __init__(self, name: Optional[str] = None): 1.26 + if name is None: 1.27 + self.prefix = '' 1.28 + 1.29 + else: 1.30 + self.prefix = f'{name} :: ' 1.31 + 1.32 + self.tsAll = monotonic() 1.33 + self.ts = self.tsAll 1.34 + 1.35 + def get_time(self): 1.36 + return monotonic() - self.ts 1.37 + 1.38 + def reset(self): 1.39 + self.ts = monotonic() 1.40 + self.tsAll = self.ts 1.41 + 1.42 + def __str__(self): 1.43 + ts = monotonic() 1.44 + return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts) 1.45 + 1.46 + def __call__(self, msg): 1.47 + _buf = f'{self} | {msg}' 1.48 + self.ts = monotonic() 1.49 + return _buf 1.50 + 1.51 + 1.52 +class AbstractLogBase(object): 1.53 + def __init__(self, prefix: str = 'main'): 1.54 + self.prefix = prefix 1.55 + 1.56 + def _write_helper(self, mark: str, msg: Any) -> Iterable[str]: 1.57 + for l in str(msg).splitlines(): 1.58 + yield f'{mark} {self.prefix} | {l}' 1.59 + 1.60 + def _write(self, mark: str, msg: Any): 1.61 + raise NotImplemented(f'Метод write не определён для класса "{type(self).__name__}"') 1.62 + 1.63 + def __call__(self, msg): 1.64 + self._write('.', msg) 1.65 + 1.66 + def err(self, msg): 1.67 + self._write('!', msg) 1.68 + 1.69 + def warn(self, msg): 1.70 + self._write('*', msg) 1.71 + 1.72 + def alert(self, msg): 1.73 + self._write('#', msg) 1.74 + 1.75 + def debug(self, msg): 1.76 + self._write('`', msg) 1.77 + 1.78 + @staticmethod 1.79 + def get_timing(name: Optional[str] = None): 1.80 + return Timing(name) 1.81 + 1.82 + def sub_log(self, name: str): 1.83 + return self.__class__(f'{self.prefix}/{name}') 1.84 + 1.85 + def excpt(self, msg, e_class=None, e_obj=None, e_tb=None, stack_skip=0): 1.86 + if e_class is None: 1.87 + e_class, e_obj, e_tb = exc_info() 1.88 + 1.89 + tb_data_tb = list(extract_tb(e_tb))[::-1] 1.90 + tb_data_stack = list(extract_stack())[::-1][(2 + stack_skip):] 1.91 + self.err(msg) 1.92 + self.err('--- EXCEPTION ---') 1.93 + self.err(f' {e_class.__name__} ({e_obj})') 1.94 + self.err('--- TRACEBACK ---') 1.95 + for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_tb: 1.96 + self.err(f'File: {_tb_file}, line {_tb_line} in {_tb_func}') 1.97 + self.err(f' {_tb_text}') 1.98 + 1.99 + self.err('>>> Exception Handler <<<') 1.100 + for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_stack: 1.101 + self.err(f'File: {_tb_file}, line {_tb_line} in {_tb_func}') 1.102 + self.err(f' {_tb_text}') 1.103 + 1.104 + self.err('--- END EXCEPTION ---')