|
1 |
| -import logging.handlers as handlers, socket, os, time |
2 |
| - |
3 |
| - |
4 |
| -class WebsockifySysLogHandler(handlers.SysLogHandler): |
5 |
| - """ |
6 |
| - A handler class that sends proper Syslog-formatted messages, |
7 |
| - as defined by RFC 5424. |
8 |
| - """ |
9 |
| - |
10 |
| - _legacy_head_fmt = '<{pri}>{ident}[{pid}]: ' |
11 |
| - _rfc5424_head_fmt = '<{pri}>1 {timestamp} {hostname} {ident} {pid} - - ' |
12 |
| - _head_fmt = _rfc5424_head_fmt |
13 |
| - _legacy = False |
14 |
| - _timestamp_fmt = '%Y-%m-%dT%H:%M:%SZ' |
15 |
| - _max_hostname = 255 |
16 |
| - _max_ident = 24 #safer for old daemons |
17 |
| - _send_length = False |
18 |
| - _tail = '\n' |
19 |
| - |
20 |
| - |
21 |
| - ident = None |
22 |
| - |
23 |
| - |
24 |
| - def __init__(self, address=('localhost', handlers.SYSLOG_UDP_PORT), |
25 |
| - facility=handlers.SysLogHandler.LOG_USER, |
26 |
| - socktype=None, ident=None, legacy=False): |
27 |
| - """ |
28 |
| - Initialize a handler. |
29 |
| -
|
30 |
| - If address is specified as a string, a UNIX socket is used. To log to a |
31 |
| - local syslogd, "WebsockifySysLogHandler(address="/dev/log")" can be |
32 |
| - used. If facility is not specified, LOG_USER is used. If socktype is |
33 |
| - specified as socket.SOCK_DGRAM or socket.SOCK_STREAM, that specific |
34 |
| - socket type will be used. For Unix sockets, you can also specify a |
35 |
| - socktype of None, in which case socket.SOCK_DGRAM will be used, falling |
36 |
| - back to socket.SOCK_STREAM. If ident is specified, this string will be |
37 |
| - used as the application name in all messages sent. Set legacy to True |
38 |
| - to use the old version of the protocol. |
39 |
| - """ |
40 |
| - |
41 |
| - self.ident = ident |
42 |
| - |
43 |
| - if legacy: |
44 |
| - self._legacy = True |
45 |
| - self._head_fmt = self._legacy_head_fmt |
46 |
| - |
47 |
| - super().__init__(address, facility, socktype) |
48 |
| - |
49 |
| - |
50 |
| - def emit(self, record): |
51 |
| - """ |
52 |
| - Emit a record. |
53 |
| -
|
54 |
| - The record is formatted, and then sent to the syslog server. If |
55 |
| - exception information is present, it is NOT sent to the server. |
56 |
| - """ |
57 |
| - |
58 |
| - try: |
59 |
| - # Gather info. |
60 |
| - text = self.format(record).replace(self._tail, ' ') |
61 |
| - if not text: # nothing to log |
62 |
| - return |
63 |
| - |
64 |
| - pri = self.encodePriority(self.facility, |
65 |
| - self.mapPriority(record.levelname)) |
66 |
| - |
67 |
| - timestamp = time.strftime(self._timestamp_fmt, time.gmtime()); |
68 |
| - |
69 |
| - hostname = socket.gethostname()[:self._max_hostname] |
70 |
| - |
71 |
| - if self.ident: |
72 |
| - ident = self.ident[:self._max_ident] |
73 |
| - else: |
74 |
| - ident = '' |
75 |
| - |
76 |
| - pid = os.getpid() # shouldn't need truncation |
77 |
| - |
78 |
| - # Format the header. |
79 |
| - head = { |
80 |
| - 'pri': pri, |
81 |
| - 'timestamp': timestamp, |
82 |
| - 'hostname': hostname, |
83 |
| - 'ident': ident, |
84 |
| - 'pid': pid, |
85 |
| - } |
86 |
| - msg = self._head_fmt.format(**head).encode('ascii', 'ignore') |
87 |
| - |
88 |
| - # Encode text as plain ASCII if possible, else use UTF-8 with BOM. |
89 |
| - try: |
90 |
| - msg += text.encode('ascii') |
91 |
| - except UnicodeEncodeError: |
92 |
| - msg += text.encode('utf-8-sig') |
93 |
| - |
94 |
| - # Add length or tail character, if necessary. |
95 |
| - if self.socktype != socket.SOCK_DGRAM: |
96 |
| - if self._send_length: |
97 |
| - msg = ('%d ' % len(msg)).encode('ascii') + msg |
98 |
| - else: |
99 |
| - msg += self._tail.encode('ascii') |
100 |
| - |
101 |
| - # Send the message. |
102 |
| - if self.unixsocket: |
103 |
| - try: |
104 |
| - self.socket.send(msg) |
105 |
| - except OSError: |
106 |
| - self._connect_unixsocket(self.address) |
107 |
| - self.socket.send(msg) |
108 |
| - |
109 |
| - else: |
110 |
| - if self.socktype == socket.SOCK_DGRAM: |
111 |
| - self.socket.sendto(msg, self.address) |
112 |
| - else: |
113 |
| - self.socket.sendall(msg) |
114 |
| - |
115 |
| - except (KeyboardInterrupt, SystemExit): |
116 |
| - raise |
117 |
| - except: |
118 |
| - self.handleError(record) |
| 1 | +import logging.handlers as handlers, socket, os, time |
| 2 | + |
| 3 | + |
| 4 | +class WebsockifySysLogHandler(handlers.SysLogHandler): |
| 5 | + """ |
| 6 | + A handler class that sends proper Syslog-formatted messages, |
| 7 | + as defined by RFC 5424. |
| 8 | + """ |
| 9 | + |
| 10 | + _legacy_head_fmt = '<{pri}>{ident}[{pid}]: ' |
| 11 | + _rfc5424_head_fmt = '<{pri}>1 {timestamp} {hostname} {ident} {pid} - - ' |
| 12 | + _head_fmt = _rfc5424_head_fmt |
| 13 | + _legacy = False |
| 14 | + _timestamp_fmt = '%Y-%m-%dT%H:%M:%SZ' |
| 15 | + _max_hostname = 255 |
| 16 | + _max_ident = 24 #safer for old daemons |
| 17 | + _send_length = False |
| 18 | + _tail = '\n' |
| 19 | + |
| 20 | + |
| 21 | + ident = None |
| 22 | + |
| 23 | + |
| 24 | + def __init__(self, address=('localhost', handlers.SYSLOG_UDP_PORT), |
| 25 | + facility=handlers.SysLogHandler.LOG_USER, |
| 26 | + socktype=None, ident=None, legacy=False): |
| 27 | + """ |
| 28 | + Initialize a handler. |
| 29 | +
|
| 30 | + If address is specified as a string, a UNIX socket is used. To log to a |
| 31 | + local syslogd, "WebsockifySysLogHandler(address="/dev/log")" can be |
| 32 | + used. If facility is not specified, LOG_USER is used. If socktype is |
| 33 | + specified as socket.SOCK_DGRAM or socket.SOCK_STREAM, that specific |
| 34 | + socket type will be used. For Unix sockets, you can also specify a |
| 35 | + socktype of None, in which case socket.SOCK_DGRAM will be used, falling |
| 36 | + back to socket.SOCK_STREAM. If ident is specified, this string will be |
| 37 | + used as the application name in all messages sent. Set legacy to True |
| 38 | + to use the old version of the protocol. |
| 39 | + """ |
| 40 | + |
| 41 | + self.ident = ident |
| 42 | + |
| 43 | + if legacy: |
| 44 | + self._legacy = True |
| 45 | + self._head_fmt = self._legacy_head_fmt |
| 46 | + |
| 47 | + super().__init__(address, facility, socktype) |
| 48 | + |
| 49 | + |
| 50 | + def emit(self, record): |
| 51 | + """ |
| 52 | + Emit a record. |
| 53 | +
|
| 54 | + The record is formatted, and then sent to the syslog server. If |
| 55 | + exception information is present, it is NOT sent to the server. |
| 56 | + """ |
| 57 | + |
| 58 | + try: |
| 59 | + # Gather info. |
| 60 | + text = self.format(record).replace(self._tail, ' ') |
| 61 | + if not text: # nothing to log |
| 62 | + return |
| 63 | + |
| 64 | + pri = self.encodePriority(self.facility, |
| 65 | + self.mapPriority(record.levelname)) |
| 66 | + |
| 67 | + timestamp = time.strftime(self._timestamp_fmt, time.gmtime()); |
| 68 | + |
| 69 | + hostname = socket.gethostname()[:self._max_hostname] |
| 70 | + |
| 71 | + if self.ident: |
| 72 | + ident = self.ident[:self._max_ident] |
| 73 | + else: |
| 74 | + ident = '' |
| 75 | + |
| 76 | + pid = os.getpid() # shouldn't need truncation |
| 77 | + |
| 78 | + # Format the header. |
| 79 | + head = { |
| 80 | + 'pri': pri, |
| 81 | + 'timestamp': timestamp, |
| 82 | + 'hostname': hostname, |
| 83 | + 'ident': ident, |
| 84 | + 'pid': pid, |
| 85 | + } |
| 86 | + msg = self._head_fmt.format(**head).encode('ascii', 'ignore') |
| 87 | + |
| 88 | + # Encode text as plain ASCII if possible, else use UTF-8 with BOM. |
| 89 | + try: |
| 90 | + msg += text.encode('ascii') |
| 91 | + except UnicodeEncodeError: |
| 92 | + msg += text.encode('utf-8-sig') |
| 93 | + |
| 94 | + # Add length or tail character, if necessary. |
| 95 | + if self.socktype != socket.SOCK_DGRAM: |
| 96 | + if self._send_length: |
| 97 | + msg = ('%d ' % len(msg)).encode('ascii') + msg |
| 98 | + else: |
| 99 | + msg += self._tail.encode('ascii') |
| 100 | + |
| 101 | + # Send the message. |
| 102 | + if self.unixsocket: |
| 103 | + try: |
| 104 | + self.socket.send(msg) |
| 105 | + except OSError: |
| 106 | + self._connect_unixsocket(self.address) |
| 107 | + self.socket.send(msg) |
| 108 | + |
| 109 | + else: |
| 110 | + if self.socktype == socket.SOCK_DGRAM: |
| 111 | + self.socket.sendto(msg, self.address) |
| 112 | + else: |
| 113 | + self.socket.sendall(msg) |
| 114 | + |
| 115 | + except (KeyboardInterrupt, SystemExit): |
| 116 | + raise |
| 117 | + except: |
| 118 | + self.handleError(record) |
0 commit comments