tools.win_pg_dump_controller
2022-01-30
Child:7c93b0305522
tools.win_pg_dump_controller/win_pg_dump_controller/log_controller.py
..init
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/win_pg_dump_controller/log_controller.py Sun Jan 30 22:17:39 2022 +0300 1.3 @@ -0,0 +1,167 @@ 1.4 +# coding: utf-8 1.5 +"""\ 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 +from time import time, ctime 1.17 +from datetime import timedelta, datetime 1.18 +from sys import exc_info 1.19 +from os.path import join as p_join 1.20 +from os import listdir, remove as file_remove, stat 1.21 +from traceback import extract_tb, extract_stack 1.22 +from typing import Optional 1.23 + 1.24 +from .config import Config 1.25 + 1.26 + 1.27 +class Timing(object): 1.28 + def __init__(self, name: Optional[str] = None): 1.29 + if name is None: 1.30 + self.prefix = '' 1.31 + else: 1.32 + self.prefix = f'{name} :: ' 1.33 + self.tsAll = time() 1.34 + self.ts = self.tsAll 1.35 + 1.36 + def get_time(self): 1.37 + return time() - self.ts 1.38 + 1.39 + def reset(self): 1.40 + self.ts = time() 1.41 + self.tsAll = self.ts 1.42 + 1.43 + def __str__(self): 1.44 + ts = time() 1.45 + return self.prefix + '%s(%.4f)' % (timedelta(seconds=(ts - self.tsAll)), ts - self.ts) 1.46 + 1.47 + def __call__(self, msg): 1.48 + _buf = f'{self} | {msg}' 1.49 + self.ts = time() 1.50 + return _buf 1.51 + 1.52 + 1.53 +class BaseLogger(object): 1.54 + def __init__(self, appname='main'): 1.55 + self.appname = appname 1.56 + 1.57 + @staticmethod 1.58 + def _write(itr_content): 1.59 + raise NotImplemented() 1.60 + 1.61 + def __call__(self, msg): 1.62 + self._write(map( 1.63 + lambda x: '%3s | %s :: %s' % ('.', self.appname, x), 1.64 + str(msg).splitlines() 1.65 + )) 1.66 + 1.67 + def err(self, msg): 1.68 + self._write(map( 1.69 + lambda x: '%3s | %s :: %s' % ('!', self.appname, x), 1.70 + str(msg).splitlines() 1.71 + )) 1.72 + 1.73 + def warn(self, msg): 1.74 + self._write(map( 1.75 + lambda x: '%3s | %s :: %s' % ('*', self.appname, x), 1.76 + str(msg).splitlines() 1.77 + )) 1.78 + 1.79 + def alert(self, msg): 1.80 + self._write(map( 1.81 + lambda x: '%3s | %s :: %s' % ('#', self.appname, x), 1.82 + str(msg).splitlines() 1.83 + )) 1.84 + 1.85 + def debug(self, msg): 1.86 + self._write(map( 1.87 + lambda x: '%3s | %s :: %s' % ('`', self.appname, x), 1.88 + str(msg).splitlines() 1.89 + )) 1.90 + 1.91 + @staticmethod 1.92 + def get_timing(name: Optional[str] = None): 1.93 + return Timing(name) 1.94 + 1.95 + def sublog(self, name): 1.96 + return self.__class__(f'{self.appname}/{name}') 1.97 + 1.98 + def excpt(self, msg, e_class=None, e_obj=None, e_tb=None, stack_skip=0): 1.99 + if e_class is None: 1.100 + e_class, e_obj, e_tb = exc_info() 1.101 + 1.102 + tb_data_tb = list(extract_tb(e_tb))[::-1] 1.103 + tb_data_stack = list(extract_stack())[::-1][(2 + stack_skip):] 1.104 + self.err(msg) 1.105 + self.err('--- EXCEPTION ---') 1.106 + self.err(' %s (%s)' % (e_class.__name__, e_obj)) 1.107 + self.err('--- TRACEBACK ---') 1.108 + for _tbFile, _tbLine, _tbFunc, _tbText in tb_data_tb: 1.109 + self.err('File: %s, line %s in %s' % (_tbFile, _tbLine, _tbFunc)) 1.110 + self.err(' %s' % _tbText) 1.111 + self.err('>>> Exception Handler <<<') 1.112 + for _tbFile, _tbLine, _tbFunc, _tbText in tb_data_stack: 1.113 + self.err('File: %s, line %s in %s' % (_tbFile, _tbLine, _tbFunc)) 1.114 + self.err(' %s' % _tbText) 1.115 + self.err('--- END EXCEPTION ---') 1.116 + 1.117 + 1.118 +class NullLogger(BaseLogger): 1.119 + @staticmethod 1.120 + def _write(itr_content): 1.121 + pass 1.122 + 1.123 + 1.124 +class FileLogger(BaseLogger): 1.125 + def __init__(self, filename: str, appname: str = 'main'): 1.126 + super().__init__(appname) 1.127 + self.fd = open(filename, 'a') 1.128 + 1.129 + def _write(self, itr_content): 1.130 + cur_time = ctime() 1.131 + for i in itr_content: 1.132 + self.fd.write(f'{cur_time}{i}\n') 1.133 + 1.134 + self.fd.flush() 1.135 + 1.136 + def __del__(self): 1.137 + try: 1.138 + self.fd.close() 1.139 + except: 1.140 + pass 1.141 + 1.142 + 1.143 +class LogController(object): 1.144 + def __init__(self, config: Config): 1.145 + self.log_dir = config.log_dir 1.146 + self.keep_logs_days = config.keep_logs_days 1.147 + 1.148 + @staticmethod 1.149 + def _get_timeprefix() -> str: 1.150 + return datetime.now().strftime('%Y-%m-%d_%H-%M-%S') 1.151 + 1.152 + def get_logger(self, name: str) -> BaseLogger: 1.153 + if self.log_dir is not None: 1.154 + return FileLogger(p_join(self.log_dir, f'{self._get_timeprefix()} - {name}.log'), appname=name) 1.155 + else: 1.156 + return NullLogger(appname=name) 1.157 + 1.158 + def get_filename(self, name: str) -> Optional[str]: 1.159 + if self.log_dir is not None: 1.160 + return str(p_join(self.log_dir, f'{self._get_timeprefix()} - {name}.log')) 1.161 + 1.162 + def clean(self): 1.163 + if self.log_dir is not None: 1.164 + now = time() 1.165 + for f in listdir(self.log_dir): 1.166 + f_path = p_join(self.log_dir, f) 1.167 + f_stat = stat(f_path) 1.168 + 1.169 + if divmod(now - f_stat.st_ctime, 86400)[0] > self.keep_logs_days: 1.170 + file_remove(f_path)