py.lib

Yohn Y. 2022-06-05 Parent:7e0e6ee3031b Child:fe4a96d06243

25:72069a2200d3 Go to Latest

py.lib/log/slog_syslogger.py

+ Заготовка корневого класса ошибок

History
awgur@13 1 # coding: utf-8
awgur@13 2
awgur@13 3 """\
awgur@13 4 Логирование в системный журнал Unix
awgur@9 5
awgur@9 6 Метки в журнале о уровне сообщения:
awgur@9 7 "`": Debug
awgur@9 8 ".": Info
awgur@9 9 "*": Warning
awgur@9 10 "!": Error
awgur@9 11 "#": Alert
awgur@9 12 """
awgur@13 13
awgur@9 14 import syslog
awgur@13 15 from sys import exc_info
awgur@9 16 from time import time
awgur@13 17 from traceback import extract_tb, extract_stack
awgur@13 18 from datetime import timedelta
awgur@22 19 from typing import Any
awgur@9 20
awgur@9 21 LOG_FACILITY = {
awgur@9 22 'auth': syslog.LOG_AUTH,
awgur@9 23 'authpriv': syslog.LOG_AUTH,
awgur@9 24 'cron': syslog.LOG_CRON,
awgur@9 25 'daemon': syslog.LOG_DAEMON,
awgur@9 26 'ftp': syslog.LOG_DAEMON,
awgur@9 27 'kern': syslog.LOG_KERN,
awgur@9 28 'lpr': syslog.LOG_LPR,
awgur@9 29 'mail': syslog.LOG_MAIL,
awgur@9 30 'news': syslog.LOG_NEWS,
awgur@9 31 'syslog': syslog.LOG_SYSLOG,
awgur@9 32 'user': syslog.LOG_USER,
awgur@9 33 'uucp': syslog.LOG_UUCP,
awgur@9 34 'local0': syslog.LOG_LOCAL0,
awgur@9 35 'local1': syslog.LOG_LOCAL1,
awgur@9 36 'local2': syslog.LOG_LOCAL2,
awgur@9 37 'local3': syslog.LOG_LOCAL3,
awgur@9 38 'local4': syslog.LOG_LOCAL4,
awgur@9 39 'local5': syslog.LOG_LOCAL5,
awgur@9 40 'local6': syslog.LOG_LOCAL6,
awgur@9 41 'local7': syslog.LOG_LOCAL7
awgur@9 42 }
awgur@9 43
awgur@22 44
awgur@13 45 class LoggerError(Exception): pass
awgur@13 46
awgur@13 47
awgur@9 48 # --- INTERFACE --- #
awgur@9 49 FACILITY = LOG_FACILITY['user']
awgur@13 50
awgur@13 51
awgur@22 52 def check_facility(facility: str = 'user'):
awgur@22 53 if not facility.lower() in LOG_FACILITY:
awgur@22 54 raise LoggerError(f'Unknown facility: {facility}')
awgur@22 55
awgur@22 56
awgur@22 57 def log_prep(ident: str, facility: str = 'user'):
awgur@9 58 global FACILITY
awgur@22 59 check_facility(facility)
awgur@13 60
awgur@9 61 syslog.openlog(ident, syslog.LOG_PID)
awgur@9 62
awgur@9 63 FACILITY = LOG_FACILITY[facility]
awgur@9 64
awgur@9 65
awgur@13 66 class Timing(object):
awgur@22 67 def __init__(self, name: str = None):
awgur@13 68 if name is None:
awgur@13 69 self.prefix = ''
awgur@9 70 else:
awgur@22 71 self.prefix = f'{name} :: '
awgur@13 72 self.tsAll = time()
awgur@13 73 self.ts = self.tsAll
awgur@9 74
awgur@22 75 def get_time(self):
awgur@13 76 return time() - self.ts
awgur@9 77
awgur@13 78 def reset(self):
awgur@13 79 self.ts = time()
awgur@13 80 self.tsAll = self.ts
awgur@9 81
awgur@9 82 def __str__(self):
awgur@13 83 ts = time()
awgur@13 84 return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts)
awgur@9 85
awgur@22 86 def __call__(self, msg: Any) -> str:
awgur@22 87 _buf = f'{self} | {msg}'
awgur@13 88 self.ts = time()
awgur@13 89 return _buf
awgur@9 90
awgur@9 91
awgur@13 92 class SysLogger(object):
awgur@13 93 init_log = log_prep
awgur@9 94
awgur@13 95 @staticmethod
awgur@22 96 def get_timing(name: str = None):
awgur@13 97 return Timing(name)
awgur@9 98
awgur@22 99 def __init__(self, prefix: str = 'main', facility: int = FACILITY):
awgur@13 100 self.prefix = str(prefix)
awgur@13 101 self.facility = facility
awgur@9 102
awgur@22 103 def _write(self, flag: int, mark: str, msg: Any):
awgur@13 104 for l in str(msg).splitlines():
awgur@22 105 syslog.syslog(self.facility | flag, f'{mark} {self.prefix}: {l}')
awgur@9 106
awgur@22 107 def __call__(self, msg: Any):
awgur@13 108 self._write(syslog.LOG_INFO, '.', msg)
awgur@9 109
awgur@22 110 def err(self, msg: Any):
awgur@13 111 self._write(syslog.LOG_ERR, '!', msg)
awgur@9 112
awgur@22 113 def warn(self, msg: Any):
awgur@13 114 self._write(syslog.LOG_WARNING, '*', msg)
awgur@9 115
awgur@22 116 def debug(self, msg: Any):
awgur@13 117 self._write(syslog.LOG_DEBUG, '`', msg)
awgur@9 118
awgur@22 119 def alert(self, msg: Any):
awgur@13 120 self._write(syslog.LOG_ALERT, '#', msg)
awgur@9 121
awgur@22 122 def sublog(self, prefix: str):
awgur@22 123 return self.__class__(f'{self.prefix}/{prefix}', self.facility)
awgur@9 124
awgur@22 125 def excpt(self, msg: Any, e_class: type = None, e_obj: Exception = None, e_tb=None, stack_skip=0):
awgur@22 126 if e_class is None:
awgur@22 127 e_class, e_obj, e_tb = exc_info()
awgur@9 128
awgur@22 129 if e_class is None:
awgur@13 130 # Если вдруг вызываем без произошедшего исключения
awgur@13 131 self.err(msg)
awgur@13 132 else:
awgur@22 133 tb_data_tb = list(extract_tb(e_tb))[::-1]
awgur@22 134 tb_data_stack = list(extract_stack())[::-1][(2 + stack_skip):]
awgur@9 135
awgur@13 136 self.err(msg)
awgur@9 137
awgur@13 138 self.err('--- EXCEPTION ---')
awgur@22 139 self.err(' %s (%s)' % (e_class.__name__, e_obj))
awgur@9 140
awgur@13 141 self.err('--- TRACEBACK ---')
awgur@22 142 for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_tb:
awgur@22 143 self.err('File: %s, line %s in %s' % (_tb_file, _tb_line, _tb_func))
awgur@22 144 self.err(' %s' % _tb_text)
awgur@9 145
awgur@13 146 self.err('>>> Exception Handler <<<')
awgur@22 147 for _tb_file, _tb_line, _tb_func, _tb_text in tb_data_stack:
awgur@22 148 self.err('File: %s, line %s in %s' % (_tb_file, _tb_line, _tb_func))
awgur@22 149 self.err(' %s' % _tb_text)
awgur@9 150
awgur@13 151 self.err('--- END EXCEPTION ---')