-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLogFile.py
130 lines (115 loc) · 4.77 KB
/
LogFile.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
124
125
126
127
128
129
130
import time
import os
import datetime
from threading import RLock, Thread, Event
def synchronized(method):
def smethod(self, *params, **args):
self._Lock.acquire()
try:
return method(self, *params, **args)
finally:
self._Lock.release()
return smethod
def make_timestamp(t=None):
if t is None:
t = datetime.datetime.now()
elif isinstance(t, (int, float)):
t = datetime.datetime.fromtimestamp(t)
return t.strftime("%m/%d/%Y %H:%M:%S") + ".%03d" % (t.microsecond//1000)
class LogStream:
def __init__(self, stream, add_timestamp=True):
self._Lock = RLock()
self.Stream = stream # sys.stdout, sys.stderr
self.AddTimestamps = add_timestamp
@synchronized
def log(self, msg, add_timestamp=True):
if add_timestamp:
msg = "%s: %s" % (make_timestamp(), msg)
self.Stream.write(msg + '\n');
self.Stream.flush()
class LogFile(Thread):
def __init__(self, path, interval = '1d', keep = 10, add_timestamp=True, append=True, flush_interval=5.0):
# interval = 'midnight' means roll over at midnight
Thread.__init__(self)
assert isinstance(path, str)
self._Lock = RLock()
self.Path = path
self.File = None
self.CurLogBegin = 0
if type(interval) == type(''):
mult = 1
if interval[-1] == 'd' or interval[-1] == 'D':
interval = interval[:-1]
mult = 24 * 3600
interval = int(interval) * mult
elif interval[-1] == 'h' or interval[-1] == 'H':
interval = interval[:-1]
mult = 3600
interval = int(interval) * mult
elif interval[-1] == 'm' or interval[-1] == 'M':
interval = interval[:-1]
mult = 60
interval = int(interval) * mult
self.Interval = interval
self.Keep = keep
self.AddTimestamps = add_timestamp
self.LineBuf = ''
self.LastLog = None
self.LastFlush = time.time()
self.FlushInterval = flush_interval
if append:
self.File = open(self.Path, 'a')
self.File.write("%s: [appending to old log]\n" % (make_timestamp(),))
self.CurLogBegin = time.time()
#print("LogFile: created with file:", self.File)
def run(self):
while True:
time.sleep(self.FlushInterval)
self.flush()
def newLog(self):
if self.File != None:
self.File.close()
try: os.remove('%s.%d' % (self.Path, self.Keep))
except: pass
for i in range(self.Keep - 1):
inx = self.Keep - i
old = '%s.%d' % (self.Path, inx - 1)
new = '%s.%d' % (self.Path, inx)
try: os.rename(old, new)
except: pass
try: os.rename(self.Path, self.Path + '.1')
except: pass
self.File = open(self.Path, 'w')
self.CurLogBegin = time.time()
@synchronized
def log(self, msg, raw=False, add_timestamp=True):
t = time.time()
if self.Interval == 'midnight':
if datetime.date.today() != self.LastLog:
self.newLog()
elif isinstance(self.Interval, (int, float)):
if t > self.CurLogBegin + self.Interval:
self.newLog()
if add_timestamp and not raw:
msg = "%s: %s" % (make_timestamp(t), msg)
self._write(msg if raw else msg + "\n")
@synchronized
def write(self, msg):
self.log(msg, raw=True)
@synchronized
def _write(self, msg):
if msg:
#print("LogFile.write: writing to:", self.File)
self.File.write(msg)
self.flush()
self.LastLog = datetime.date.today()
@synchronized
def flush(self):
if time.time() > self.LastFlush + self.FlushInterval:
self.File.flush()
self.LastFlush = time.time()
def __del__(self):
#self.flush()
if self.File is not None:
self.File.close()
self.File = None