implement UnixDatagramSocket and LogSource.handleMessage
authorTero Marttila <terom@fixme.fi>
Fri, 05 Feb 2010 20:38:21 +0200
changeset 51 342850300d6a
parent 50 edbc337b7c29
child 52 13fc80450862
implement UnixDatagramSocket and LogSource.handleMessage
etc/fixbot-logwatch.py
fixbot/logwatch/sources.py
--- a/etc/fixbot-logwatch.py	Fri Feb 05 20:37:51 2010 +0200
+++ b/etc/fixbot-logwatch.py	Fri Feb 05 20:38:21 2010 +0200
@@ -18,4 +18,7 @@
         filters.su_nobody_killer,
         filters.all,
     )),
+    UnixDatagramSocket("test", os.path.join(logwatch_dir, "test.sock"), (
+        filters.all,
+    )),
 )
--- a/fixbot/logwatch/sources.py	Fri Feb 05 20:37:51 2010 +0200
+++ b/fixbot/logwatch/sources.py	Fri Feb 05 20:38:21 2010 +0200
@@ -2,10 +2,11 @@
     Implementations of the various sources of log data
 """
 
-from twisted.internet import protocol
+from twisted.internet import protocol, reactor
 from twisted.python import log
 
 from fixbot import fifo
+from fixbot.logwatch import message
 
 class LogSource (object) :
     """
@@ -39,20 +40,44 @@
 
     def handleData (self, data) :
         """
-            Buffer the given chunk of data, passing any full lines to handleLine
+            Feed binary data into the buffer, processing all lines via handleLine()
         """
 
         data = self.buf + data
         
         while "\n" in data :
             line, data = data.split("\n", 1)
-
+            
+            # full line
             self.handleLine(line)
 
         self.buf = data
 
     def handleLine (self, line) :
-        log.msg("Matching line `%s'..." % line)
+        """
+            Parse given line into a SyslogMessage, and pass it to handleMessage
+        """
+
+        # parse
+        try :
+            msg = message.SyslogMessage(line)
+    
+        except Exception, e :
+            # log and ignore
+            log.err(e, "Invalid syslog message from source %s: %s" % (self.name, line))
+    
+        else :
+            # handle the structured message
+            self.handleMessage(msg)
+
+    def handleMessage (self, msg) :
+        """
+            Process the given SyslogMessage
+        """
+
+        # XXX: filters should accept messages...
+        line = str(msg)
+        log.msg(repr(msg))
 
         for filter in self.filters :
             # let the filter process the line
@@ -129,4 +154,28 @@
         super(Fifo, self).connectionLost(reason)
         self.handleError("lost fifo for %s: %s" % (self.name, reason.getErrorMessage()))
 
+class UnixDatagramSocket (LogSource, protocol.DatagramProtocol) :
+    """
+        Stream messages from a UNIX datagram socket
+    """
+    
+    # maximum size of the recieved messages
+    # native syslog is 1024, but syslog-ng does better... so 4k
+    MAX_PACKET_SIZE = 4096
 
+    def __init__ (self, name, path, filters) :
+        LogSource.__init__(self, name, filters)
+
+        log.msg("opening unix socket for %s at: %s" % (name, path))
+        
+        # open UNIX socket
+        reactor.listenUNIXDatagram(path, self, self.MAX_PACKET_SIZE)
+
+    def datagramReceived (self, data, addr) :
+        """
+            Got message from syslog-ng
+        """
+        
+        # handle it as a line of data
+        self.handleLine(data)
+