|
a |
|
b/aggmap/utils/logtools.py |
|
|
1 |
#!/usr/bin/env python3 |
|
|
2 |
# -*- coding: utf-8 -*- |
|
|
3 |
""" |
|
|
4 |
Created on Sat Aug 17 16:54:12 2019 |
|
|
5 |
|
|
|
6 |
@author: wanxiang.shen@u.nus.edu |
|
|
7 |
|
|
|
8 |
@logtools |
|
|
9 |
""" |
|
|
10 |
|
|
|
11 |
|
|
|
12 |
import os, sys, logging, time, traceback, inspect |
|
|
13 |
from colorlog import ColoredFormatter |
|
|
14 |
from colored import fg, bg, attr |
|
|
15 |
|
|
|
16 |
formatter = ColoredFormatter( |
|
|
17 |
"%(asctime)s - %(log_color)s%(levelname).4s%(reset)s - %(message_log_color)s[%(name)s]%(reset)s - %(message_log_color)s%(message)s", |
|
|
18 |
datefmt=None, |
|
|
19 |
reset=True, |
|
|
20 |
log_colors={ |
|
|
21 |
'DEBUG': 'cyan', |
|
|
22 |
'INFO': 'green', |
|
|
23 |
'WARNING': 'yellow', |
|
|
24 |
'ERROR': 'red', |
|
|
25 |
'CRITICAL': 'red,bg_white', |
|
|
26 |
}, |
|
|
27 |
secondary_log_colors={ |
|
|
28 |
'message':{ |
|
|
29 |
'ERROR': 'red', |
|
|
30 |
'CRITICAL': 'red,bg_white', |
|
|
31 |
}, |
|
|
32 |
}, |
|
|
33 |
style='%', |
|
|
34 |
) |
|
|
35 |
|
|
|
36 |
|
|
|
37 |
logger = logging.getLogger('bidd-aggmap') |
|
|
38 |
logger.propagate = False |
|
|
39 |
|
|
|
40 |
|
|
|
41 |
all_loggers = [ logger] |
|
|
42 |
|
|
|
43 |
def set_level(level): |
|
|
44 |
for _logger in all_loggers: |
|
|
45 |
_logger.setLevel(getattr(logging, level.upper())) |
|
|
46 |
|
|
|
47 |
set_level('INFO') |
|
|
48 |
|
|
|
49 |
file_handler = None |
|
|
50 |
def log_to_file(path): |
|
|
51 |
global file_handler |
|
|
52 |
if file_handler is not None: |
|
|
53 |
for _logger in all_loggers: |
|
|
54 |
_logger.removeHandler(file_handler) |
|
|
55 |
|
|
|
56 |
logpath = os.path.join(os.getcwd(), path + '.' + get_datetime() + '.log') |
|
|
57 |
print_info('log to file:', logpath) |
|
|
58 |
file_handler = logging.FileHandler(logpath) |
|
|
59 |
file_handler.setFormatter(formatter) |
|
|
60 |
for _logger in all_loggers: |
|
|
61 |
_logger.addHandler(file_handler) |
|
|
62 |
|
|
|
63 |
def reset_handler(handler): |
|
|
64 |
for _logger in all_loggers: |
|
|
65 |
del _logger.handlers[:] |
|
|
66 |
_logger.addHandler(handler) |
|
|
67 |
if file_handler is not None: |
|
|
68 |
_logger.addHandler(file_handler) |
|
|
69 |
|
|
|
70 |
handler = logging.StreamHandler(sys.stdout) |
|
|
71 |
handler.setFormatter(formatter) |
|
|
72 |
reset_handler(handler) |
|
|
73 |
|
|
|
74 |
DEFAULT_TEXT_LENGTH = 5000 |
|
|
75 |
DEFAULT_TEXT_LENGTH_PREFIX = 4000 |
|
|
76 |
DEFAULT_TEXT_LENGTH_SUFFIX = DEFAULT_TEXT_LENGTH - DEFAULT_TEXT_LENGTH_PREFIX |
|
|
77 |
def set_text_length(prefix, suffix): |
|
|
78 |
global DEFAULT_TEXT_LENGTH, DEFAULT_TEXT_LENGTH_PREFIX, DEFAULT_TEXT_LENGTH_SUFFIX |
|
|
79 |
DEFAULT_TEXT_LENGTH = prefix + suffix |
|
|
80 |
DEFAULT_TEXT_LENGTH_PREFIX = prefix |
|
|
81 |
DEFAULT_TEXT_LENGTH_SUFFIX = suffix |
|
|
82 |
|
|
|
83 |
def clip_text(text): |
|
|
84 |
if len(text) > DEFAULT_TEXT_LENGTH: |
|
|
85 |
text = '%s %s%s... [%d chars truncated] ...%s %s' % (text[:DEFAULT_TEXT_LENGTH_PREFIX], fg('red'), attr('bold'), len(text) - DEFAULT_TEXT_LENGTH, attr('reset'), text[-DEFAULT_TEXT_LENGTH_SUFFIX:]) |
|
|
86 |
return text |
|
|
87 |
|
|
|
88 |
def create_print_method(level): |
|
|
89 |
print_method = getattr(logger, level) |
|
|
90 |
def func(*args, sep=' ', verbose=True): |
|
|
91 |
if verbose: print_method(clip_text(sep.join(map(str, args)))) |
|
|
92 |
return func |
|
|
93 |
|
|
|
94 |
print_error = create_print_method('error') |
|
|
95 |
print_warn = create_print_method('warn') |
|
|
96 |
print_info = create_print_method('info') |
|
|
97 |
print_debug = create_print_method('debug') |
|
|
98 |
|
|
|
99 |
def format_exc(error): |
|
|
100 |
return traceback.format_exception(error.__class__, error, error.__traceback__) |
|
|
101 |
|
|
|
102 |
def print_exc(error, verbose=True): |
|
|
103 |
lines = format_exc(error) |
|
|
104 |
logger.error(lines[-1].rstrip()) |
|
|
105 |
if verbose: |
|
|
106 |
logger.info(''.join(lines[:-1])) |
|
|
107 |
|
|
|
108 |
def print_exc_s(error): |
|
|
109 |
logger.error('%s: %s', type(error).__name__, error) |
|
|
110 |
|
|
|
111 |
def print_traceback(): |
|
|
112 |
logger.info('Traceback (most recent call last):') |
|
|
113 |
for frame in reversed(inspect.getouterframes(inspect.currentframe())[1:]): |
|
|
114 |
logger.info(' File "%s", line %s, in %s', frame.filename, frame.lineno, frame.function) |
|
|
115 |
logger.info(' %s', frame.code_context[0].strip()) |
|
|
116 |
|
|
|
117 |
last_time = time.time() |
|
|
118 |
def print_timedelta(*args, sep=' '): |
|
|
119 |
global last_time |
|
|
120 |
this_time = time.time() |
|
|
121 |
logger.info('[%7.2f] %s', (this_time - last_time) * 1000, sep.join(map(str, args))) |
|
|
122 |
last_time = this_time |
|
|
123 |
|
|
|
124 |
def get_date(): |
|
|
125 |
return time.strftime('%Y%m%d') |
|
|
126 |
|
|
|
127 |
def get_datetime(): |
|
|
128 |
return time.strftime('%Y%m%d%H%M%S') |
|
|
129 |
|
|
|
130 |
from tqdm import tqdm |
|
|
131 |
|
|
|
132 |
class PBarHandler(logging.Handler): |
|
|
133 |
|
|
|
134 |
def __init__(self, pbar): |
|
|
135 |
logging.Handler.__init__(self) |
|
|
136 |
self.pbar = pbar |
|
|
137 |
|
|
|
138 |
def emit(self, record): |
|
|
139 |
self.pbar.write(self.format(record)) |
|
|
140 |
|
|
|
141 |
def pbar(*args, **kwargs): |
|
|
142 |
kwargs['ascii'] = kwargs.get('ascii', True) |
|
|
143 |
kwargs['smoothing'] = kwargs.get('smoothing', 0.7) |
|
|
144 |
|
|
|
145 |
pb = tqdm(*args, **kwargs) |
|
|
146 |
handler = PBarHandler(pb) |
|
|
147 |
handler.setFormatter(formatter) |
|
|
148 |
|
|
|
149 |
pb.handler = handler |
|
|
150 |
reset_handler(handler) |
|
|
151 |
|
|
|
152 |
return pb |
|
|
153 |
|
|
|
154 |
if __name__ == '__main__': |
|
|
155 |
pb = pbar(range(100)) |
|
|
156 |
for i in pb: |
|
|
157 |
time.sleep(0.05) |
|
|
158 |
print_info(str(i)) |