02.04.2012 by alvaro.videla

For one of our projects we wanted to be able to check the system health once we go live. Our idea was to have a system that let us see the status of the services like MySQL or Memcached from the point of view of the application itself. Since our project was developed in PHP using the Symfony framework we decided to create a new Symfony bundle where we could implement this functionality. The bundle is called LiipMonitorBundle and can be obtained here.

So one goal of our bundle was to do something more advanced than a simple “Ping” to a server –for that we can just use Nagios. We wanted that the bundle could do something like: “Let’s write a session object to Redis, updating the user membership status, read it back and see that the data stored in the server is correct”. So we can know more than just a simple “ping redis”. Also when we get a report that the system is misbehaving we want to be able to run the health checks from the point of view of the app itself. For example we can ping Redis and see that is up and running but that doesn’t mean our application is using it properly.

A second goal was that the health checks themselves should be easy to write and easy to run. Also they should be totally independent from the bundle itself. So the bundle should provide functionality for auto discovering health checks, for running them and for giving reports, but it should not provide any health checks. That means that the health checks should be implemented by the applications themselves.

In regard to how to run the checks we added two possibilities: via web using a REST API and by using the command line. Also since each health check has an id that identifies it, we can run the checks all together or individually. If the checks succeed you get an “OK” message for each of them. If they fail you get a “KO” plus the message from the Exception that made the test fail.

Now, what are health checks, how do you implement them? Health checks are simply a PHP class that implements the CheckInterface from the MonitorBundle. This interface has two methods: CheckInterface::check and CheckInterface::getName. The method getName just returns the Health Check name while the method check implements the actual logic for the health check. The bundle documentation explains these in detail.

Once we implement a health check we have to add it as a service to our Service Container and tag it as monitor.check. By doing just that our health check is ready and available to be picked up by the bundle’s Health Check Runner.

Running health checks from the command line is quite easy, just execute the following command and you will see the results right away:

1

2

3

4

5

$./app/console monitor:health

Jackrabbit Health Check:OK

Redis Health Check:OK

Memcache Health Check:KO-No configuration set forsession.save_path

PHP Extensions Health Check:OK

As you can see there the bundle ran four Health Checks of which only the Memcache one failed.

Health Checks are not only for your applications, you could also ship them inside your bundles and let the bundle auto-discover them. This means that for example if you create your own bundle that say connects to a RabbitMQ, your bundle could provide the health checks required to see that your connection with RabbitMQ is working as expected.

As for the technology the bundle has a couple of peculiarities. Since the bundle provides also a REST API that allows us to run health checks and get the replies as JSON objects we built a web app for it that’s implemented using Ember.js. Ember.js is an MVC javascript framework that deserves a post on it’s own. You can learn more about it here. The views for the Ember.js app are rendered by Symfony with a template engine agnostic solution. By doing that the bundle doesn’t require for you to use Twig or the PHP templating engine from Symfony. We had to provide that feature since we have apps that use Twig for frontend views and PHP for backen views.

All in all we’ve got an easy to use bundle that was quite well received by the Symfony community, counting 49 followers on Github and 2 forks. From one of those forks we already merged pull request. Apart from that it spawned a new bundle called LiipMonitorExtraBundle that serves as a repository of reusable Health Checks for and by the community. Is time that you fork it and contribute your own health checks.

P. S.: As a side note a week after the bundle was released a new Java web framework came to life with exactly the same concept. That framework was created by @coda an engineer that works at Yammer.