Hook into exceptions catched by kirby

Hi,

I want to log exceptions in production (no matter if throwed by kirby, a plugin, a template…) with monolog.

The (in my opinion) cleanest solution would be that Kirby also offers a hook (e.g. like Symfony => events.kernel-exception) that I can directly listen and react to exceptions in Kirby. This way Kirby can output the error page and I can log the exception without polluting the index.php.

Current solution (public/index.php):

<?php
include __DIR__ . '/../vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$kirby = new Kirby([
    'roots' => [
        'index'    => __DIR__,
        'base'     => $base    = dirname(__DIR__),
        'content'  => $base . '/content',
        ...
    ]
]);

// if NOT in debug mode!
if (!$kirby->option('debug')) {
    function global_exception_handler(\Throwable $exception) {
        $log = new Logger('ErrorLogger');
        $log->pushHandler(new StreamHandler('../logs/error.log', Logger::ERROR));
        $log->error(sprintf('Global exception handler! Message: %s | Trace: %s', $exception->getMessage(), $exception->getTraceAsString()));

        if (file_exists('../kirby/views/fatal.php')) {
            include '../kirby/views/fatal.php';
        } else {
            echo 'No valid error template found.';
            $log->error('No valid error template found.');
        }
    }

    set_exception_handler('global_exception_handler');
}

echo $kirby->render();

It would be cleaner to have an e.g. a custom plugin for this task, listening for e.g. ‘global.exception’

Would be nice solution:
/site/plugin/helllicht-custom-logger/index.php

<?php

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

Kirby::plugin('helllicht/custom-logger', [
    'hooks' => [
        'global.exception' => function (\Throwable $e) {
            // if NOT in debug mode!
            if (!$this->option('debug')) {
                $log = new Logger('ErrorLogger');
                $log->pushHandler(new StreamHandler('../logs/error.log', Logger::ERROR));
                $log->error(sprintf('Global exception handler! Message: %s | Trace: %s', $e->getMessage(), $e->getTraceAsString()));
                // probably also send a notification via slack/e-mail whatever
            }
        },
    ]
]);

If I can solve it via a plugin, I don’t have to handle the the rendering of the fatal.php

Greetings

1 Like