-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathlogServer.py
105 lines (82 loc) · 2.82 KB
/
logServer.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
import asyncore
import datetime
import logging, logging.handlers
import os
import pickle
import socket
import struct
import sys
class MyFormatter(logging.Formatter):
"Custom logging formatter to return usecs as part of time"
def __init__(self, *args, **kwargs):
logging.Formatter.__init__(self, *args, **kwargs)
def formatTime(self, record, datefmt=None):
return datetime.datetime.fromtimestamp(record.created).strftime('%Y%m%d %H%M%S.%f')
def getLogger(fname=None):
format='%(asctime)s:%(process)d:%(threadName)s:%(levelname)s:%(name)s:%(pathname)s %(lineno)d:%(message)s'
formatter = MyFormatter(format)
logger = logging.getLogger('sdx')
if fname:
fh = logging.FileHandler(fname)
fh.setFormatter(formatter)
logger.addHandler(fh)
ch = logging.StreamHandler(stream=sys.stdout)
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
fname = None
if len(sys.argv) > 1:
fname = sys.argv[1]
globalLogger = getLogger(fname)
class LogRecordHandler(asyncore.dispatcher):
def __init__(self, sock):
asyncore.dispatcher.__init__(self, sock)
self.data = ''
self.rlen = 0
self.dlen = 4
def handle_read(self):
try:
data = self.recv(self.dlen)
if len(data) == 0:
return
except socket.error as e:
if e[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
return
self.data += data
self.dlen -= len(data)
if self.dlen > 0:
# don't have complete record yet. wait for more data to read
return
if self.rlen == 0:
self.dlen = self.rlen = struct.unpack('>L', self.data)[0]
self.data = ''
# got record length. now read record
return
# got complete record
obj = pickle.loads(self.data)
record = logging.makeLogRecord(obj)
# Note: EVERY record gets logged. This is because Logger.handle
# is normally called AFTER logger-level filtering.
# Filter (e.g., only WARNING or higher)
# at the sender to save network bandwidth.
globalLogger.handle(record)
# reset for next record
self.data = ''
self.rlen = 0
self.dlen = 4
def writable(self):
return False
class LogRecordServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(5)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
LogRecordHandler(sock)
LogRecordServer('', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
asyncore.loop(timeout=None, use_poll=True)