Megaphone is a bottle.py based service that is intended to proxy and collate JSON based status data in a centralized service.
The idea is to provide a per system consistent API for checking the status of all services on that system. This means:
A) Any service that is registered or discovered on a box will instantly be monitored
B) Operations will always know how to monitor a new system
The intended targets of this data are things like monitoring systems and load-balancers.
By using object based data, application developers can add or remove fields they care about without effecting the operations of megaphone.
By running this locally you get access to process lists and local commands for things like auto-discovery. This also allows you access to local services data and commands without running through additional proxies or worrying about remote execution.
Since anything can be used to poll data from zookeeper, it can be stored anywhere. If I ever have time I'd like to include some framework for adding reporting, but it's not on the current roadmap.
Install the requirements with pip file pip install -r requirements.txt
Configure megaphone.conf
Start the service with: python megaphone.py
If you'd like to run it in a more production-ready manner you can use supervisor to manage it as a service.
Once megaphone is running, you register a check by posting JSON data consisting of {"id": "some global id", "url": "http://some.status.url"}. Megaphone currently only pays attention to 'status' (in order of least to most critical: OK, Unknown, Warning, Critical) and 'message'. It will then process each check and present the most critical result returned from any one check as the result in the main status page. It will present all messages returned higher than OK in the message result on the main status page.
The status presented to megaphone should conform to the standard followed by most monitoring systems: http://nagios.sourceforge.net/docs/3_0/pluginapi.html
You can get a list of all the registered services by GETting /checks. The entire JSON payload of a check can be retrieved by GETting /checks/'id'
Below is an example session.
METHOD GET: http://localhost:18001/
RESULT: {"status": "Unknown", "date": "2013-06-06T14:49:26CDT", "message": "No services are registered!"}
METHOD GET: http://localhost:18001/checks
RESULT: {}
initiate this by using: ./sample_service.py OK
METHOD POST: http://localhost:18001/checks
DATA: {"id": "bar", "url": "http://localhost:18081/status"}
If 'status' isn't in the root of your JSON output, you can pass two objects, 'addr' and 'jsonpath', inside 'url':
addr - the full URL for your check, exactly what you'd pass inside url if status was in the root of your JSON output
jsonpath - a slash delimited 'path' to you status.
for instance if your check output looks like this:
{"megaphone": {"status": "OK", "date": "2014-02-01T23:36:38CST", "message": "Everything is OK!", "id": "ok"}}
You would use this to register your check:
DATA: {"id": "bar", "url": {"addr": "http://localhost:18081/status", "jsonpath": "megaphone/status"}}
METHOD GET: http://localhost:18001/checks
RESULT: {"bar": "http://localhost:18081/status"}
METHOD GET: http://localhost:18001/
RESULT: {"status": "OK", "date": "2013-06-06T14:49:26CDT", "message": "Everything is OK!"}
initiate this by using: ./sample_service2.py Warning
METHOD POST: http://localhost:18001/checks
DATA: {"id": "foo", "url": "http://localhost:18082/status"}
METHOD GET: http://localhost:18001/checks
RESULT: {"foo": "http://localhost:18082/status", "bar": "http://localhost:18081/status"
METHOD GET: http://localhost:18001/
RESULT: {"status": "Warning", "date": "2013-06-06T14:49:26CDT", "message": "foo:Warning:Houston, I think we have a problem."}
METHOD GET: http://localhost:18001/checks/foo:
RESULT: {"status": "Warning", "date": "2013-06-06T14:54:21CDT", "message": "Houston, I think we have a problem.", "version": "2.0.0", "id": "foo"}
METHOD GET: http://localhost:18001/checks/bar:
RESULT: {"status": "OK", "date": "2013-06-06T14:51:56CDT", "message": "Everything is groovy man.", "version": "1.0.0", "id": "bar"}
METHOD DELETE: http://localhost:18001/checks/bar
You can create a global Critical override on a megaphone (reflected at the http://localhost:18001/ level) by creating a check with the id "--global". This can be used to block a server at a global level, though this won't be reflected at the individual check status level.
If you're using the extended url object, you can also use 'statusoverride' to override the status of a check:
DATA: {"id": "bar", "url": {"addr": "http://localhost:18081/status", "statusoverride": "Critical"}}
Now there are tests for the development of megaphone. Run them with nosetest.