skylog: stop using standard SysLogHandler, it's broken
authorMarko Kreen <markokr@gmail.com>
Thu, 5 Apr 2012 11:04:26 +0000 (14:04 +0300)
committerMarko Kreen <markokr@gmail.com>
Thu, 5 Apr 2012 11:04:26 +0000 (14:04 +0300)
It fails to handle unicode strings - it puts BOM in
wrong place.  Wrap logging.handlers implementation
in class that simply drops the BOM addition.

python/conf/skylog.ini
python/skytools/skylog.py

index 5e3531b489fd1dc5bc620a24a799168418ffb229..af8853772f900a08f2133139a6224d3e94cb0905 100644 (file)
@@ -78,7 +78,7 @@ args=('~/log/%(job_name)s.log', 100*1024*1024, 3)
 formatter=long
 
 [handler_syslog]
-class=handlers.SysLogHandler
+class=skylog.SysLogHandler
 args=(('localhost', 514),)
 formatter=syslog
 
index 330de053ac97c53fd346a5b61a7e27f051a8a01e..354ef9163ec7b4558d3acbdc89bae9df73eb0889 100644 (file)
@@ -232,7 +232,48 @@ class LogDBHandler(logging.handlers.SocketHandler):
             query = "select * from log.add(%s, %s, %s)"
             logcur.execute(query, [type, service, msg])
 
-# send messages to syslog
+# fix unicode bug in SysLogHandler
+class SysLogHandler(logging.handlers.SysLogHandler):
+    """Fixes unicode bug in logging.handlers.SysLogHandler."""
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        The record is formatted, and then sent to the syslog server. If
+        exception information is present, it is NOT sent to the server.
+        """
+        msg = self.format(record) + '\000'
+        """
+        We need to convert record level to lowercase, maybe this will
+        change in the future.
+        """
+        prio = '<%d>' % self.encodePriority(self.facility,
+                                            self.mapPriority(record.levelname))
+        # Message is a string. Convert to bytes as required by RFC 5424
+        if type(msg) is unicode:
+            msg = msg.encode('utf-8')
+            ## this puts BOM in wrong place
+            #if codecs:
+            #    msg = codecs.BOM_UTF8 + msg
+        msg = prio + msg
+        try:
+            if self.unixsocket:
+                try:
+                    self.socket.send(msg)
+                except socket.error:
+                    self._connect_unixsocket(self.address)
+                    self.socket.send(msg)
+            elif self.socktype == socket.SOCK_DGRAM:
+                self.socket.sendto(msg, self.address)
+            else:
+                self.socket.sendall(msg)
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+
 class SysLogHostnameHandler(logging.handlers.SysLogHandler):
     """Slightly modified standard SysLogHandler - sends also hostname and service type"""
 
@@ -243,6 +284,8 @@ class SysLogHostnameHandler(logging.handlers.SysLogHandler):
                                _hostname,
                                _service_name,
                                msg)
+        if type(msg) is unicode:
+            msg = msg.encode('utf-8')
         try:
             if self.unixsocket:
                 try: