import logging.handlers as handlers, socket, os, time class WebsockifySysLogHandler(handlers.SysLogHandler): """ A handler class that sends proper Syslog-formatted messages, as defined by RFC 5424. """ _legacy_head_fmt = '<{pri}>{ident}[{pid}]: ' _rfc5424_head_fmt = '<{pri}>1 {timestamp} {hostname} {ident} {pid} - - ' _head_fmt = _rfc5424_head_fmt _legacy = False _timestamp_fmt = '%Y-%m-%dT%H:%M:%SZ' _max_hostname = 255 _max_ident = 24 #safer for old daemons _send_length = False _tail = '\n' ident = None def __init__(self, address=('localhost', handlers.SYSLOG_UDP_PORT), facility=handlers.SysLogHandler.LOG_USER, socktype=None, ident=None, legacy=False): """ Initialize a handler. If address is specified as a string, a UNIX socket is used. To log to a local syslogd, "WebsockifySysLogHandler(address="/dev/log")" can be used. If facility is not specified, LOG_USER is used. If socktype is specified as socket.SOCK_DGRAM or socket.SOCK_STREAM, that specific socket type will be used. For Unix sockets, you can also specify a socktype of None, in which case socket.SOCK_DGRAM will be used, falling back to socket.SOCK_STREAM. If ident is specified, this string will be used as the application name in all messages sent. Set legacy to True to use the old version of the protocol. """ self.ident = ident if legacy: self._legacy = True self._head_fmt = self._legacy_head_fmt super().__init__(address, facility, socktype) 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. """ try: # Gather info. text = self.format(record).replace(self._tail, ' ') if not text: # nothing to log return pri = self.encodePriority(self.facility, self.mapPriority(record.levelname)) timestamp = time.strftime(self._timestamp_fmt, time.gmtime()); hostname = socket.gethostname()[:self._max_hostname] if self.ident: ident = self.ident[:self._max_ident] else: ident = '' pid = os.getpid() # shouldn't need truncation # Format the header. head = { 'pri': pri, 'timestamp': timestamp, 'hostname': hostname, 'ident': ident, 'pid': pid, } msg = self._head_fmt.format(**head).encode('ascii', 'ignore') # Encode text as plain ASCII if possible, else use UTF-8 with BOM. try: msg += text.encode('ascii') except UnicodeEncodeError: msg += text.encode('utf-8-sig') # Add length or tail character, if necessary. if self.socktype != socket.SOCK_DGRAM: if self._send_length: msg = ('%d ' % len(msg)).encode('ascii') + msg else: msg += self._tail.encode('ascii') # Send the message. if self.unixsocket: try: self.socket.send(msg) except socket.error: self._connect_unixsocket(self.address) self.socket.send(msg) else: if self.socktype == socket.SOCK_DGRAM: self.socket.sendto(msg, self.address) else: self.socket.sendall(msg) except (KeyboardInterrupt, SystemExit): raise except: self.handleError(record)