WEB Advent 2010 / Color for the Holidays

If part of your job involves debugging or monitoring PHP apps, you’ll most likely have used tail to check for errors in a log file. While practical, it can become tedious to identify certain types of errors or warnings. If, on average, you spend 15 minutes per day searching for problems, those minutes add up to about 91 hours per year — time you could have spent doing more interesting work!

This article will look at implementing ptail, a PHP version of tail -f. We’ll introduce the libevent PECL extension to detect file changes and ANSI escape codes to add some color.

PECL libevent

If you’re unfamiliar with libevent, it is an event notification library used by many open source projects such as Memcached. The library is cross-platform, written in C, and allows developers to provide callback functions that are executed when a specific event happens on a file descriptor (the event notification part). You can learn more about how to work with this library at developerWorks.

Why are we not doing a while loop in PHP to check whether the file has been modified? Because it costs a lot of CPU cycles and wastes precious disk IO.

Libevent executes a PHP callback function every time specific events occur on a file.

Here’s an example:

function onRead($buf)
{
    $logMessage = event_buffer_read($buf, 4096);
    // You can modify the log message here.
	echo $logMessage;
}

$fp = @fopen('/var/log/messages', 'r');
$base = event_base_new();

// Use a special "buffered event" for read/write callbacks.
$eb = event_buffer_new($fp, 'onRead', NULL, 'onError', $base);
event_buffer_base_set($eb, $base);

// Listen for read event.
event_buffer_enable($eb, EV_READ);

// Loop and execute callbacks when events in $base occur.
event_base_loop($base);

The PECL extension is currently in beta, but as interest grows in libevent, I wouldn’t be surprised to see a stable version in 2011.

ANSI escape codes

Thanks to our event notification library, we can focus on the fun part, transforming our log messages to add some color.

The trick to do this in a Bash shell is to add an escape character (\033) followed by a CSI code. A what? A special, cryptic syntax to say “all text after this control code will be red.” For example, you would use echo "\033[1;31m" . "text is red"; where m is a CSI command to switch rendering colors and 1;31 are CSI parameters. (1 means bright; 31 means red.)

echo  "\033[1;31m". "text is red" . "\033[0m". "text normal" . "\033[1;33m" . "text yellow";

Note here that \033[0m restores the text color to the default. To learn more, have a look at Wikipedia’s article on ANSI escape codes.

The result? An improvement over tail.

For fun, I’ve added a bell character (\007), which should play a sound each time it sees the string Ho!. So, get creative with your error logging and save time using PHP to handle log messages.

The full source code is available under the public domain.

Windows support?

Unfortunately, Windows NT no longer supports ANSI escape codes, but you can use Microsoft’s console API. Search the Web for “PHP DynamicWrapper” for some information on how to add color to a Windows console using PHP.

Happy Holidays — and hacking PHP — in 2011!

Other posts