LogLevel Strategy
Monolog uses only the eight RFC 5424 levels (debug, info, notice, warning, error, critical, alert, emergency) for basic filtering purposes.
If it’s enough to limit log records received by each handler, we need more flexibility with GrowlHandler to avoid to be spammed with ton of log records.
We have a start of solution with the FilterHandler
available in Monolog since version 1.8.0,
that filter log records on one or more levels.
But this is not without counted the new CallbackFilterHandler
that raised this limitation,
and allow advanced filtering behaviours (you can filter on each log record property).
Advanced filtering Strategy
Suppose you want to be notified at end of a long process with a specific message or contextual data,
CallbackFilterHandler
is what you’re waiting for.
It can be combined as a wrapper with any other monolog handlers, and not just the GrowlHandler.
Here we will only demonstrate its capabilities in one example. We simulate a file queue processing that log all filenames and a message when it’s over.
<?php
require_once 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Processor\PsrLogMessageProcessor;
$processors = array(
new PsrLogMessageProcessor(),
);
// Create the logger
$logger = new Logger('long_process', array(), $processors);
// Create some handlers
$stream = new RotatingFileHandler(__DIR__ . DIRECTORY_SEPARATOR . 'long_process.log');
$stream->setFilenameFormat('{filename}-{date}', 'Ymd');
$logger->pushHandler($stream);
// Processing each file in a queue
$queue = new \SplQueue();
for ($i = 1; $i < 10; $i++) {
$queue->enqueue( sprintf('File_%02d.txt', $i) );
}
$fileCount = count($queue);
while (!$queue->isEmpty()) {
$file = $queue->dequeue();
$logger->addInfo('Processing file "{filename}"', array('filename' => $file));
echo '.';
// simulate the long process
sleep(1);
}
$logger->addInfo(
'Long Process with {count} files, is over !',
array('count' => $fileCount)
);
At this step, if we just push an instance of GrowlHandler to the logger stack, as following
<?php
use Bartlett\Monolog\Handler\GrowlHandler;
try {
$growl = new GrowlHandler(
array(), // with all default options
Logger::INFO
);
$logger->pushHandler($growl);
} catch (\Exception $e) {
// Growl server is probably not started
echo $e->getMessage(), PHP_EOL;
}
We will receive all log INFO record notifications to our Growl client.
The solution is to use the CallbackFilterHandler
to send only one notification (the end message only).
Suppose we want to be notified only if at least 5 files were proceeded.
<?php
$filters = array(
function ($record) {
if (!array_key_exists('count', $record['context'])) {
return false;
}
return ($record['context']['count'] > 5);
}
);
And in script, we will replaced the previous $growl
instance with this one :
<?php
use Bartlett\Monolog\Handler\CallbackFilterHandler;
$growl = new CallbackFilterHandler(
new GrowlHandler(
array(), // with all default options
Logger::INFO
),
$filters
);