1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 __doc__='''zensyslog
16
17 Turn syslog messages into events.
18
19 $Id$
20 '''
21
22 import time
23 import socket
24 import os
25
26 from twisted.internet.protocol import DatagramProtocol
27 from twisted.internet import reactor
28 from twisted.names.client import lookupPointer
29 from twisted.python import failure
30
31 from EventServer import EventServer
32 from SyslogProcessing import SyslogProcessor
33
34 import Globals
35 from Products.ZenUtils.Utils import zenPath
36
37 SYSLOG_PORT = 514
38 try:
39 SYSLOG_PORT = socket.getservbyname('syslog', 'udp')
40 except socket.error:
41 pass
42
43 -class ZenSyslog(DatagramProtocol, EventServer):
44
45 name = 'zensyslog'
46 SYSLOG_DATE_FORMAT = '%b %d %H:%M:%S'
47 SAMPLE_DATE = 'Apr 10 15:19:22'
48
49
51 EventServer.__init__(self)
52 self.changeUser()
53 self.minpriority = self.options.minpriority
54 self.processor = SyslogProcessor(self.dmd.ZenEventManager,
55 self.options.minpriority,
56 self.options.parsehost)
57
58 if self.options.logorig:
59 import logging
60 self.olog = logging.getLogger("origsyslog")
61 self.olog.setLevel(20)
62 self.olog.propagate = False
63 lname = zenPath("log/origsyslog.log")
64 hdlr = logging.FileHandler(lname)
65 hdlr.setFormatter(logging.Formatter("%(message)s"))
66 self.olog.addHandler(hdlr)
67 if self.options.useFileDescriptor is not None:
68 self.useUdpFileDescriptor(int(self.options.useFileDescriptor))
69 else:
70 reactor.listenUDP(self.options.syslogport, self)
71
72
73 - def expand(self, msg, client_address):
110
111
113 """Use a separate thread to process the request."""
114 ipaddr, port = client_address
115 if self.options.logorig:
116 if self.options.logformat == 'human':
117 message = self.expand(msg, client_address)
118 else:
119 message = msg
120
121 self.olog.info(message)
122
123 ptr = '.'.join(ipaddr.split('.')[::-1]) + '.in-addr.arpa'
124 lookupPointer(ptr, timeout=(1,)).addBoth(self.gotHostname, (msg,ipaddr,time.time()))
125
126
128 "send the resolved address, if possible, and the event via the thread"
129 if isinstance(response, failure.Failure) or len(response[0]) == 0:
130 self.q.put( (data[1],) + data )
131 else:
132 self.q.put( (str(response[0][0].payload.name),) + data )
133
134
136 "process a single syslog message, called from the inherited thread"
137 self.processor.process(msg, ipaddr, host, rtime)
138
139
141 EventServer.buildOptions(self)
142 self.parser.add_option('--dmdpath',
143 dest='dmdpath', default="/zport/dmd",
144 help="zope path to our dmd /zport/dmd")
145 self.parser.add_option('--parsehost',
146 dest='parsehost', action="store_true", default=False,
147 help="try to parse the hostname part of a syslog HEADER")
148 self.parser.add_option('--stats',
149 dest='stats', action="store_true", default=False,
150 help="print stats to log every 2 secs")
151 self.parser.add_option('--logorig',
152 dest='logorig', action="store_true", default=False,
153 help="log the original message")
154 self.parser.add_option('--logformat',
155 dest='logformat', default="human",
156 help="human (/var/log/messages) or raw (wire)")
157 self.parser.add_option('--debug',
158 dest='debug', action="store_true", default=False,
159 help="debug mode no threads")
160 self.parser.add_option('--minpriority',
161 dest='minpriority', default=6, type="int",
162 help="Minimum priority that syslog will accecpt")
163 self.parser.add_option('--heartbeat',
164 dest='heartbeat', default=60,
165 help="Number of seconds between heartbeats")
166 self.parser.add_option('--syslogport',
167 dest='syslogport', default=SYSLOG_PORT, type='int',
168 help="Port number to use for syslog events")
169 self.parser.add_option('--useFileDescriptor',
170 dest='useFileDescriptor',
171 type='int',
172 help="Read from an existing connection rather opening a new port.",
173 default=None)
174
175
176 if __name__ == '__main__':
177 ZenSyslog().main()
178