Package ZenEvents :: Module zensyslog
[hide private]
[frames] | no frames]

Source Code for Module ZenEvents.zensyslog

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13  #! /usr/bin/env python  
 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
50 - def __init__(self):
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):
74 """expands a syslog message into a string format suitable for writing 75 to the filesystem such that it appears the same as it would 76 had the message been logged by the syslog daemon.""" 77 78 # pri := facility * severity 79 stop = msg.find('>') 80 pri = msg[1:stop] 81 82 # check for a datestamp. default to right now if date not present 83 start = stop + 1 84 stop = start + len(ZenSyslog.SAMPLE_DATE) 85 dateField = msg[start:stop] 86 try: 87 date = time.strptime(dateField, ZenSyslog.SYSLOG_DATE_FORMAT) 88 year = time.localtime()[0] 89 date = (year,) + date[1:] 90 start = stop + 1 91 except ValueError: 92 # date not present, so use today's date 93 date = time.localtime() 94 95 # check for a hostname. default to localhost if not present 96 stop = msg.find(' ', start) 97 if msg[stop - 1] == ':': 98 hostname = client_address[0] 99 else: 100 hostname = msg[start:stop] 101 start = stop + 1 102 103 # the message content 104 body = msg[start:] 105 106 # assemble the message 107 prettyTime = time.strftime(ZenSyslog.SYSLOG_DATE_FORMAT, date) 108 message = '%s %s %s' % (prettyTime, hostname, body) 109 return message
110 111
112 - def datagramReceived(self, msg, client_address):
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
127 - def gotHostname(self, response, data):
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
135 - def doHandleRequest(self, host, msg, ipaddr, rtime):
136 "process a single syslog message, called from the inherited thread" 137 self.processor.process(msg, ipaddr, host, rtime)
138 139
140 - def buildOptions(self):
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