Python 的logging 模块的Socket 和 Logging4cplus 的 socket 的格式是不一样的, 现实中需要将日志发送到logging4cplus 的服务器, 不得已, 写了个 Python logging 模块到 logging4cplus的Adapter
1 #!/usr/bin/env python
2 #-*- coding: gbk -*-
3 from struct import pack, unpack
4
5 class BufferPack(object):
6 def __init__(self):
7 self.buffer = ''
8
9 def addChar(self, s, unsigned=False):
10 self.buffer += pack(unsigned and '>b' or '>c', s )
11
12 def addShort(self, s, unsigned=False):
13 self.buffer += pack(unsigned and '>H' or '>h', s )
14
15 def addInt(self, s, unsigned=False):
16 self.buffer += pack(unsigned and '>I' or '>i', s )
17
18 def addLong(self, s, unsigned=False):
19 self.buffer += pack(unsigned and '>L' or '>l', s )
20
21 def addString(self, s):
22 self.addInt( len(s) )
23 self.buffer += s
24
25 def addBuffer(self, s):
26 self.buffer += s.buffer
27
28 class BufferUnpack(object):
29
30 char_bits = len( pack('>b', 0) )
31 short_bits = len( pack('>H', 0) )
32 int_bits = len( pack('>I', 0) )
33 long_bits = len( pack('>L', 0) )
34
35 def __init__(self, buffer):
36 self.buffer = buffer
37 self.pos = 0
38
39 def _read_item(self, unpackstr, len):
40 v = unpack(unpackstr, self.buffer[self.pos:self.pos+len] )
41 self.pos += len
42 return v
43
44 def readChar(self, unsigned=False):
45 return self._read_item(unsigned and '<b' or '<c', self.char_bits)
46
47 def readShort(self, unsigned=False):
48 return self._read_item(unsigned and '<H' or '<h', self.short_bits )
49
50 def readInt(self, unsigned=False):
51 return self._read_item(unsigned and '<I' or '<i', self.int_bits )
52
53 def readLong(self, unsigned=False):
54 return self._read_item(unsigned and '<L' or '<l', self.long_bits )
55
56 def readString(self):
57 len = self.readInt()
58 v = self.buffer[self.pos:self.pos+len]
59 self.pos += len
60 return v
61
62 def PackMessage( record ):
63 bp = BufferPack()
64 bp.addChar(2, True)
65 bp.addChar(1, True)
66
67 bp.addString("{log.servername}")
68 bp.addString(record.name)
69 bp.addInt(record.levelno*1000)
70 bp.addString("")
71 bp.addString(record.msg)
72 bp.addString(str(record.threadName))
73 bp.addString(str(record.process))
74 bp.addInt( record.created )
75 bp.addInt( record.msecs )
76 bp.addString(record.filename)
77 bp.addInt( 1 )
78
79 pkg = BufferPack()
80 pkg.addInt(len(bp.buffer), True)
81 pkg.addBuffer( bp )
82
83 return pkg.buffer
84
85 if __name__=="__main__":
86 import logging, logging.handlers
87
88 logger = logging.getLogger()
89 logging.handlers.SocketHandler.makePickle = lambda self,rc : PackMessage(rc)
90
91 hdlr = logging.handlers.SocketHandler('{logserver.ip}', 8888)
92 formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
93 hdlr.setFormatter(formatter)
94 logger.addHandler(hdlr)
95 logger.setLevel(logging.NOTSET)
96
97 logger.info("hello")
使用的时候.
1. 在logging 创建SocketHandler 的时候, 需要修改logging.handlers.SocketHandler.makePickle 为方法 PackMessage
logging.handlers.SocketHandler.makePickle = lambda self,rc : PackMessage(rc)
2. 需要修改代码中的两部分内容 {log.servername} 和 {logserver.ip}