1 |
|
---|
2 |
|
---|
3 |
import asynchat |
---|
4 |
import socket |
---|
5 |
import string |
---|
6 |
import time |
---|
7 |
import os |
---|
8 |
import stat |
---|
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 |
class file_logger: |
---|
35 |
|
---|
36 |
|
---|
37 |
def __init__ (self, file, flush=1, mode='a'): |
---|
38 |
if type(file) == type(''): |
---|
39 |
if (file == '-'): |
---|
40 |
import sys |
---|
41 |
self.file = sys.stdout |
---|
42 |
else: |
---|
43 |
self.file = open (file, mode) |
---|
44 |
else: |
---|
45 |
self.file = file |
---|
46 |
self.do_flush = flush |
---|
47 |
|
---|
48 |
def __repr__ (self): |
---|
49 |
return '<file logger: %s>' % self.file |
---|
50 |
|
---|
51 |
def write (self, data): |
---|
52 |
self.file.write (data) |
---|
53 |
self.maybe_flush() |
---|
54 |
|
---|
55 |
def writeline (self, line): |
---|
56 |
self.file.writeline (line) |
---|
57 |
self.maybe_flush() |
---|
58 |
|
---|
59 |
def writelines (self, lines): |
---|
60 |
self.file.writelines (lines) |
---|
61 |
self.maybe_flush() |
---|
62 |
|
---|
63 |
def maybe_flush (self): |
---|
64 |
if self.do_flush: |
---|
65 |
self.file.flush() |
---|
66 |
|
---|
67 |
def flush (self): |
---|
68 |
self.file.flush() |
---|
69 |
|
---|
70 |
def softspace (self, *args): |
---|
71 |
pass |
---|
72 |
|
---|
73 |
def log (self, message): |
---|
74 |
if message[-1] not in ('\r', '\n'): |
---|
75 |
self.write (message + '\n') |
---|
76 |
else: |
---|
77 |
self.write (message) |
---|
78 |
|
---|
79 |
|
---|
80 |
|
---|
81 |
|
---|
82 |
|
---|
83 |
|
---|
84 |
|
---|
85 |
class rotating_file_logger (file_logger): |
---|
86 |
|
---|
87 |
|
---|
88 |
|
---|
89 |
|
---|
90 |
def __init__ (self, file, freq=None, maxsize=None, flush=1, mode='a'): |
---|
91 |
self.filename = file |
---|
92 |
self.mode = mode |
---|
93 |
self.file = open (file, mode) |
---|
94 |
self.freq = freq |
---|
95 |
self.maxsize = maxsize |
---|
96 |
self.rotate_when = self.next_backup(self.freq) |
---|
97 |
self.do_flush = flush |
---|
98 |
|
---|
99 |
def __repr__ (self): |
---|
100 |
return '<rotating-file logger: %s>' % self.file |
---|
101 |
|
---|
102 |
|
---|
103 |
def next_backup (self, freq): |
---|
104 |
(yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) |
---|
105 |
if freq == 'daily': |
---|
106 |
return time.mktime(yr,mo,day+1, 0,0,0, 0,0,-1) |
---|
107 |
elif freq == 'weekly': |
---|
108 |
return time.mktime(yr,mo,day-wd+7, 0,0,0, 0,0,-1) |
---|
109 |
elif freq == 'monthly': |
---|
110 |
return time.mktime(yr,mo+1,1, 0,0,0, 0,0,-1) |
---|
111 |
else: |
---|
112 |
return None |
---|
113 |
|
---|
114 |
def maybe_flush (self): |
---|
115 |
self.maybe_rotate() |
---|
116 |
if self.do_flush: |
---|
117 |
self.file.flush() |
---|
118 |
|
---|
119 |
def maybe_rotate (self): |
---|
120 |
if self.freq and time.time() > self.rotate_when: |
---|
121 |
self.rotate() |
---|
122 |
self.rotate_when = self.next_backup(self.freq) |
---|
123 |
elif self.maxsize: |
---|
124 |
try: |
---|
125 |
if os.stat(self.filename)[stat.ST_SIZE] > self.maxsize: |
---|
126 |
self.rotate() |
---|
127 |
except os.error: |
---|
128 |
self.rotate() |
---|
129 |
|
---|
130 |
def rotate (self): |
---|
131 |
(yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) |
---|
132 |
try: |
---|
133 |
self.file.close() |
---|
134 |
newname = '%s.ends%04d%02d%02d' % (self.filename, yr, mo, day) |
---|
135 |
try: |
---|
136 |
open(newname, "r").close() |
---|
137 |
newname = newname + "-%02d%02d%02d" % (hr, min, sec) |
---|
138 |
except: |
---|
139 |
pass |
---|
140 |
os.rename(self.filename, newname) |
---|
141 |
self.file = open(self.filename, self.mode) |
---|
142 |
except: |
---|
143 |
pass |
---|
144 |
|
---|
145 |
|
---|
146 |
|
---|
147 |
|
---|
148 |
|
---|
149 |
|
---|
150 |
|
---|
151 |
|
---|
152 |
|
---|
153 |
|
---|
154 |
import m_syslog |
---|
155 |
syslog_logger = m_syslog.syslog_client |
---|
156 |
|
---|
157 |
class syslog_logger (m_syslog.syslog_client): |
---|
158 |
def __init__ (self, address, facility='user'): |
---|
159 |
m_syslog.syslog_client.__init__ (self, address) |
---|
160 |
self.facility = m_syslog.facility_names[facility] |
---|
161 |
self.address=address |
---|
162 |
|
---|
163 |
def __repr__ (self): |
---|
164 |
return '<syslog logger address=%s>' % (repr(self.address)) |
---|
165 |
|
---|
166 |
def log (self, message): |
---|
167 |
m_syslog.syslog_client.log ( |
---|
168 |
self, |
---|
169 |
message, |
---|
170 |
facility=self.facility, |
---|
171 |
priority=m_syslog.LOG_INFO |
---|
172 |
) |
---|
173 |
|
---|
174 |
|
---|
175 |
|
---|
176 |
class socket_logger (asynchat.async_chat): |
---|
177 |
|
---|
178 |
def __init__ (self, address): |
---|
179 |
|
---|
180 |
if type(address) == type(''): |
---|
181 |
self.create_socket (socket.AF_UNIX, socket.SOCK_STREAM) |
---|
182 |
else: |
---|
183 |
self.create_socket (socket.AF_INET, socket.SOCK_STREAM) |
---|
184 |
|
---|
185 |
self.connect (address) |
---|
186 |
self.address = address |
---|
187 |
|
---|
188 |
def __repr__ (self): |
---|
189 |
return '<socket logger: address=%s>' % (self.address) |
---|
190 |
|
---|
191 |
def log (self, message): |
---|
192 |
if message[-2:] != '\r\n': |
---|
193 |
self.socket.push (message + '\r\n') |
---|
194 |
else: |
---|
195 |
self.socket.push (message) |
---|
196 |
|
---|
197 |
|
---|
198 |
class multi_logger: |
---|
199 |
def __init__ (self, loggers): |
---|
200 |
self.loggers = loggers |
---|
201 |
|
---|
202 |
def __repr__ (self): |
---|
203 |
return '<multi logger: %s>' % (repr(self.loggers)) |
---|
204 |
|
---|
205 |
def log (self, message): |
---|
206 |
for logger in self.loggers: |
---|
207 |
logger.log (message) |
---|
208 |
|
---|
209 |
class resolving_logger: |
---|
210 |
"""Feed (ip, message) combinations into this logger to get a |
---|
211 |
resolved hostname in front of the message. The message will not |
---|
212 |
be logged until the PTR request finishes (or fails).""" |
---|
213 |
|
---|
214 |
def __init__ (self, resolver, logger): |
---|
215 |
self.resolver = resolver |
---|
216 |
self.logger = logger |
---|
217 |
|
---|
218 |
class logger_thunk: |
---|
219 |
def __init__ (self, message, logger): |
---|
220 |
self.message = message |
---|
221 |
self.logger = logger |
---|
222 |
|
---|
223 |
def __call__ (self, host, ttl, answer): |
---|
224 |
if not answer: |
---|
225 |
answer = host |
---|
226 |
self.logger.log ('%s:%s' % (answer, self.message)) |
---|
227 |
|
---|
228 |
def log (self, ip, message): |
---|
229 |
self.resolver.resolve_ptr ( |
---|
230 |
ip, |
---|
231 |
self.logger_thunk ( |
---|
232 |
message, |
---|
233 |
self.logger |
---|
234 |
) |
---|
235 |
) |
---|
236 |
|
---|
237 |
class unresolving_logger: |
---|
238 |
"Just in case you don't want to resolve" |
---|
239 |
def __init__ (self, logger): |
---|
240 |
self.logger = logger |
---|
241 |
|
---|
242 |
def log (self, ip, message): |
---|
243 |
self.logger.log ('%s:%s' % (ip, message)) |
---|
244 |
|
---|
245 |
|
---|
246 |
def strip_eol (line): |
---|
247 |
while line and line[-1] in '\r\n': |
---|
248 |
line = line[:-1] |
---|
249 |
return line |
---|
250 |
|
---|
251 |
class tail_logger: |
---|
252 |
"Keep track of the last <size> log messages" |
---|
253 |
def __init__ (self, logger, size=500): |
---|
254 |
self.size = size |
---|
255 |
self.logger = logger |
---|
256 |
self.messages = [] |
---|
257 |
|
---|
258 |
def log (self, message): |
---|
259 |
self.messages.append (strip_eol (message)) |
---|
260 |
if len (self.messages) > self.size: |
---|
261 |
del self.messages[0] |
---|
262 |
self.logger.log (message) |
---|