#!/usr/bin/env python # # Copyright 2014 Infoxchange Australia # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Send received events to a syslog instance. """ from __future__ import print_function import logging import os import re import socket import sys import time from logging.handlers import SysLogHandler class PalletFormatter(logging.Formatter): """ A formatter for the Pallet environment. """ HOSTNAME = re.sub( r':\d+$', '', os.environ.get('SITE_DOMAIN', socket.gethostname())) FORMAT = '%(asctime)s {hostname} %(name)s[%(process)d]: %(message)s'.\ format(hostname=HOSTNAME) DATE_FORMAT = '%Y-%m-%dT%H:%M:%S' converter = time.gmtime def __init__(self): super(PalletFormatter, self).__init__(fmt=self.FORMAT, datefmt=self.DATE_FORMAT) def formatTime(self, record, datefmt=None): """ Format time, including milliseconds. """ formatted = super(PalletFormatter, self).formatTime( record, datefmt=datefmt) return formatted + '.%03dZ' % record.msecs def format(self, record): # strip newlines message = super(PalletFormatter, self).format(record) message = message.replace('\n', ' ') message += '\n' return message def get_headers(line): """ Parse Supervisor message headers. """ return dict([x.split(':') for x in line.split()]) def eventdata(payload): """ Parse a Supervisor event. """ headerinfo, data = payload.split('\n', 1) headers = get_headers(headerinfo) return headers, data def supervisor_events(stdin, stdout): """ An event stream from Supervisor. """ while True: stdout.write('READY\n') stdout.flush() line = stdin.readline() headers = get_headers(line) payload = stdin.read(int(headers['len'])) event_headers, event_data = eventdata(payload) yield event_headers, event_data stdout.write('RESULT 2\nOK') stdout.flush() def main(): """ Main application loop. """ env = os.environ try: host = env['SYSLOG_SERVER'] port = int(env['SYSLOG_PORT']) socktype = socket.SOCK_DGRAM if env['SYSLOG_PROTO'] == 'udp' \ else socket.SOCK_STREAM except KeyError: sys.exit("SYSLOG_SERVER, SYSLOG_PORT and SYSLOG_PROTO are required.") handler = SysLogHandler( address=(host, port), socktype=socktype, ) handler.setFormatter(PalletFormatter()) for event_headers, event_data in supervisor_events(sys.stdin, sys.stdout): event = logging.LogRecord( name=event_headers['processname'], level=logging.INFO, pathname=None, lineno=0, msg=event_data, args=(), exc_info=None, ) event.process = int(event_headers['pid']) handler.handle(event) if __name__ == '__main__': main()