Skip to content

Instantly share code, notes, and snippets.

@chrigl
Created May 6, 2015 08:09
Show Gist options
  • Save chrigl/5a30d5fca48bb533653e to your computer and use it in GitHub Desktop.
Save chrigl/5a30d5fca48bb533653e to your computer and use it in GitHub Desktop.
upstartwatch... not sure if this is a good idea.
#!/usr/bin/env python3
import sys
import dbus
import time
import json
import argparse
import threading
import functools
import http.server
from gi.repository import GObject
from dbus.mainloop.glib import DBusGMainLoop
EMPTY_INSTANCE = 'instance='
RESPAWN_TIME = 10 # if respawn happens in RESPAWN_TIME seconds, log it
LISTEN_IP = '127.0.0.1'
LISTEN_PORT = 18000
STORAGE = {}
lock = threading.Lock()
class ReqHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path != '/':
self.send_response(404)
self.end_headers()
self.wfile.write(b'Not found')
return
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(STORAGE).encode('utf-8', errors='ignore'))
return
def run_httpd(server_addr):
httpd = http.server.HTTPServer(server_addr, ReqHandler)
httpd.serve_forever()
def detect_respawn_loops(respawn_time, event_name, event):
if event_name == 'started':
job = event[0].lower().split('=')[1]
instance = event[1].lower()
if instance == EMPTY_INSTANCE:
# not interrested in e.g.
# string "JOB=startpar-bridge"
# string "INSTANCE=chris-test--started"
with lock:
if job not in STORAGE:
STORAGE[job] = {'respawn_count': 0,
'last_respawn': 0}
if STORAGE[job]['last_respawn'] + respawn_time > time.time():
if STORAGE[job]['respawn_count'] < sys.maxsize:
STORAGE[job]['respawn_count'] += 1
else:
STORAGE[job]['respawn_count'] = 0
STORAGE[job]['last_respawn'] = time.time()
def params():
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--port', type=int, default=LISTEN_PORT,
help='Listen port of httpd (default: 18000)')
parser.add_argument('-l', '--listen', type=str, default=LISTEN_IP,
help='Listen address (default: 127.0.0.1)')
parser.add_argument('-r', '--respawn', type=int, default=RESPAWN_TIME,
help='Allowed respawn seconds. If service respawns '
'within this period, internal counter will be '
'increased. (default: 10)')
return parser
def main():
args = params().parse_args()
thread_fn = functools.partial(run_httpd, (args.listen, args.port))
httpd_thread = threading.Thread(target=thread_fn, daemon=True)
httpd_thread.start()
# no need to join.
# prepare detect_respawn_loops with argument
_detect_respawn_loops = functools.partial(detect_respawn_loops,
args.respawn)
DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus(mainloop=DBusGMainLoop())
bus.add_signal_receiver(_detect_respawn_loops,
dbus_interface="com.ubuntu.Upstart0_6",
path="/com/ubuntu/Upstart")
loop = GObject.MainLoop()
try:
loop.run()
except KeyboardInterrupt:
print("Bye")
exit(0)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment