-
-
Save kitos9112/f77439d2aa421e0c76226d27de7ff132 to your computer and use it in GitHub Desktop.
A Python log handler for Papertrail.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import socket | |
class PapertrailHandler(logging.Handler): | |
"""An RFC 5425 log handler that has been tested to interact | |
with Papertrail. | |
""" | |
# RFC 5424 Severities | |
LOG_EMERG = 0 | |
LOG_ALERT = 1 | |
LOG_CRIT = 2 | |
LOG_ERR = 3 | |
LOG_WARNING = 4 | |
LOG_NOTICE = 5 | |
LOG_INFO = 6 | |
LOG_DEBUG = 7 | |
# RFC 5424 Facilities | |
LOG_KERN = 0 | |
LOG_USER = 1 | |
LOG_MAIL = 2 | |
LOG_DAEMON = 3 | |
LOG_AUTH = 4 | |
LOG_SYSLOG = 5 | |
LOG_LPR = 6 | |
LOG_NEWS = 7 | |
LOG_UUCP = 8 | |
LOG_CRON = 9 | |
LOG_AUTHPRIV = 10 | |
LOG_FTP = 11 | |
LOG_NTP = 12 | |
LOG_AUDIT = 13 | |
LOG_ALERT = 14 | |
LOG_AT = 15 | |
LOG_LOCAL0 = 16 | |
LOG_LOCAL1 = 17 | |
LOG_LOCAL2 = 18 | |
LOG_LOCAL3 = 19 | |
LOG_LOCAL4 = 20 | |
LOG_LOCAL5 = 21 | |
LOG_LOCAL6 = 22 | |
LOG_LOCAL7 = 23 | |
priority_names = { | |
'emerg': LOG_EMERG, | |
'alert': LOG_ALERT, | |
'crit': LOG_CRIT, | |
'err': LOG_ERR, | |
'warn': LOG_WARNING, | |
'notice': LOG_NOTICE, | |
'info': LOG_INFO, | |
'debug': LOG_DEBUG, | |
} | |
facility_names = { | |
'kern': LOG_KERN, | |
'user': LOG_USER, | |
'mail': LOG_MAIL, | |
'daemon': LOG_DAEMON, | |
'auth': LOG_AUTH, | |
'syslog': LOG_SYSLOG, | |
'lpr': LOG_LPR, | |
'news': LOG_NEWS, | |
'uucp': LOG_UUCP, | |
'cron': LOG_CRON, | |
'authpriv': LOG_AUTHPRIV, | |
'ftp': LOG_FTP, | |
'ntp': LOG_NTP, | |
'audit': LOG_AUDIT, | |
'alert': LOG_ALERT, | |
'at': LOG_AT, | |
'local0': LOG_LOCAL0, | |
'local1': LOG_LOCAL1, | |
'local2': LOG_LOCAL2, | |
'local3': LOG_LOCAL3, | |
'local4': LOG_LOCAL4, | |
'local5': LOG_LOCAL5, | |
'local6': LOG_LOCAL6, | |
'local7': LOG_LOCAL7, | |
} | |
def __init__(self, address=('localhost', 514), facility=LOG_USER, | |
socktype=socket.SOCK_STREAM): | |
"""Initialize the PapertrailHandler | |
Args: | |
address (tuple): First element is the host, second is the port | |
facility (int): Integer representation of the syslog facility | |
socktype (int): Integer representation of the socket type | |
""" | |
logging.Handler.__init__(self) | |
self.address = address | |
self.facility = facility | |
self.socktype = socktype | |
self.socket = socket.socket(socket.AF_INET, socktype) | |
if socktype == socket.SOCK_STREAM: | |
self.socket.connect(address) | |
def encode_priority(self, facility, priority): | |
"""Encode the syslog facility and priority. Strings or integers are | |
accepted. If strings are passed, the facility and priority mappings | |
are used to convert them to integers. | |
Args: | |
facility (str, int): A string or integer syslog facility | |
priority (str, int): A string or integer syslog priority | |
""" | |
if isinstance(facility, str): | |
facility = self.facility_names[facility] | |
if isinstance(priority, str): | |
priority = self.priority_names[priority] | |
return (facility << 3) | priority | |
def close(self): | |
"""Closes the socket.""" | |
self.acquire() | |
try: | |
self.socket.close() | |
logging.Handler.close(self) | |
finally: | |
self.release() | |
def clean_record(self, record): | |
"""Clean log entry by removing newlines and NUL bytes. | |
Args: | |
record (LogRecord): A log record | |
""" | |
return self.format( | |
record).replace('\n', ' ').replace('\r', ' ').replace('\x00', ' ') | |
def emit(self, record): | |
"""Emit a formatted record, which is then sent to the syslog server. | |
If exception information is present, the message is NOT sent to the | |
server. | |
Args: | |
record (str): A log entry | |
""" | |
try: | |
priority = self.encode_priority(self.facility, | |
self.priority_names.get( | |
record.levelname.lower(), | |
'warning')) | |
message = '<{}>{}\n'.format(priority, | |
self.clean_record(record)) | |
if self.socktype == socket.SOCK_DGRAM: | |
self.socket.sendto(message[:1024].encode('utf-8'), | |
self.address) | |
else: | |
self.socket.sendall('{}\n'.format(message).encode('utf-8')) | |
except Exception: | |
self.handleError(record) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment