-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog.py
123 lines (100 loc) · 3.14 KB
/
log.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import threading
import time
import datetime
import queue
import json
import config
class LogLevel:
debug = 0
info = 1
error = 2
_vdic = None
_ndic = None
@classmethod
def names(cls):
if cls._ndic is None:
cls._ndic = {
k: v for k, v in cls.__dict__.items()
if isinstance(v, int)
}
return cls._ndic
@classmethod
def name(cls, val):
if cls._vdic is None:
cls._vdic = {v: k for k, v in cls.names().items()}
return cls._vdic[val]
class Loggable:
def __init__(self, content, level, show):
self.timestamp = time.time()
self.content = content
self.type = content.pop('type', '')
self.show = show
self.level = getattr(LogLevel, level)
@property
def level_name(self):
return LogLevel.name(self.level)
def __repr__(self):
timestamp = datetime.datetime.fromtimestamp(self.timestamp)
try:
data = json.dumps(self.content)
except Exception:
data = repr(self.content)
return ','.join([
str(timestamp),
self.level_name,
self.type,
self.content.get('action', ''),
json.dumps(data)
])
def __str__(self):
content = self.content.copy()
return '[{}] '.format(self.level_name) + \
self.type.capitalize() + ': ' + \
', '.join(x.capitalize().replace('_', ' ')
if isinstance(x, str) else str(x)
for x in content.values())
class MetaLogger(type):
def __init__(cls, *args):
super().__init__(*args)
def maker(name):
def loglevel(self, *args, **kw):
return self.log(name, *args, **kw)
return loglevel
for name in LogLevel.names():
setattr(cls, name, maker(name))
class Logger(threading.Thread, metaclass=MetaLogger):
def __init__(self, file, open_mode):
super().__init__(daemon=False)
self._run = True
self.file_name = file
self.file = None
self.open_mode = open_mode
self.queue = queue.Queue()
self.level = LogLevel.debug
def print_level(self, level=None):
if level is not None:
if isinstance(level, int):
self.level = level
else:
self.level = getattr(LogLevel, level)
else:
return level
def log(self, level='info', show=True, **kw):
self.queue.put(Loggable(kw, level, show))
def run(self):
with open(self.file_name, self.open_mode) as self.file:
self.write_log()
def write_log(self):
while True:
obj = self.queue.get()
if obj is None or not self._run:
break
self.file.write(repr(obj) + '\n')
if obj.show and obj.level > self.level:
print(obj)
def stop(self):
self._run = False
self.queue.put(None)
logger = Logger(config.local_file(config.g('log', 'file')),
config.g('log', 'open_mode'))
logger.start()