Slim 4 use monolog to wtire all error logs

I configured monolog in my slim 4 application and set logErrors and logErrorDetails to true in ErrorMIddleware but when I got an error it does not write logs. To emulate error I turn on the cache on my app and I’m getting an error like this Call to undefined function apcu_fetch() b-z doctrine using apcu by default to cache all metadata and apcu is not installed on my dev env.

Here is the PHP-DI config for logger:

           LoggerInterface::class => static function (Container $container) {
                $config = $container->get(Config::class);
                $logger = new Logger((string)$config->get('logger.name'));

                $fileNameSuffix = PHP_SAPI === 'cli' ? 'php-cli-' : 'php-fpm';
                $logger->pushHandler(
                    new StreamHandler(
                        $config->get('logger.log_dir') . '/' . $fileNameSuffix . '-' .    $config->get('logger.name') . '.log',
                        $config->get('logger.log_level'))
                );

                if ((bool)$config->get('main.debug')) {
                    $logger->pushHandler(new FirePHPHandler());
                }

                return $logger;
            }

and here is the the ErrorMiddleware config:

     $definitions[ErrorMiddleware::class] = static function(ContainerInterface $container): ErrorMiddleware {

        $middleware = new ErrorMiddleware(
            $container->get(CallableResolverInterface::class),
            $container->get(ResponseFactoryInterface::class),
            (bool)$container->get(Config::class)->get('main.debug'), //false or true
            $container->has(LoggerInterface::class) ? true : false,
            $container->has(LoggerInterface::class) ? true : false
        );
        $middleware->setErrorHandler(HttpNotFoundException::class, $container->get(NotFoundHandler::class));


        return $middleware;
    };

And yes, I’m adding that middleware to the App like this $app->add($container->get(ErrorMiddleware::class));

I check different slim 4 skeleton Github repositories and I did not find any extra configurations, so I do not know why it’s not writing the logs to the files. Maybe I need to set a custom default error handler? As slim 4 default one using php error_log function to write the logs?

  1. Make sure that you don’t call $app->addErrorMiddleware(...);
  2. Try to comment out all “exotic” logging handler: // $logger->pushHandler(new FirePHPHandler());
  3. Make sure that the log directory exists and has the correct write permissions.
  4. This will always evalutate to true, because the logger defintion exists.
    $container->has(LoggerInterface::class) ? true : false,

1 I set it with $app->add not $app->addErrorMiddleware
2 and 3. Handlers and logger works, as when I inject logger for example to controller and manually adding some logs it working (writing logs to the file) , it’s only not working for errors cathed by slim
4 thanks, I’ll fix that

as far as I can see the issue is because slim using default Slim\Handlers\ErrorHandler which is using error_log($error); and probably I need to override default handler to some custom one when defining middleware? But honestly, I do not like such approach, as for me it too much to write own handler for monolog :slight_smile:

I think if you define a custom error logger, then the responsibility for logging is also delegated to your custom (NotFoundHandler) class. The parameters $displayErrorDetails, $logErrors, $logErrorDetails will be passed to your custom handler. Your error handler should declare the LoggerInterface or a LoggerFactory as dependency.

@odan So you agreed that Slim is not working with monolog or any other LoggerInterface implementation out of the box and I need to write custom handler(s) to add the ability of log every application error? And yeah in such a case if I want my NotFoundHandler to log not found info I need to inject logger to it (but it’s optionally). I was hope that slim log all errors by default no matter what handler I’m using, as slim trying to follow PSR and LoggerInterface is also PSR :frowning:

The current implementation of the default ErrorHandler class uses error_log($error); which doesn’t work out of the box with the PSR-3 LoggerInterface. But you can add a custom default handler to it, which uses it’s own logger. This is a very flexible concept, but yeah… I know what you mean.

I was hope that slim log all errors by default no matter what handler I’m using

That’s the case. There are people who doesn’t even use a PSR-11 container. But Slim has to create an log entry even in such situations. By default it works for everyone, but if you have a specific requirement, you can create a custom handler (and logger) for your use case.

1 Like

well, it’s probably possible to check if LoggerInterface is implemented and if yes use it, otherwise use error_log. Anyway thank you @odan for your help, I’m using Slim by the first time and was not sure if it’s I’m doing something wrong or not, documentation is really limited (maybe slim 3 has more detailed documentation). I understand it’s a micro framework but still is nice to have some more detailed documentation :slight_smile: . Btw @odan I saw you have sleketon app on GitHub, it’s also using error_log for errors, or you made some custom handler?

I saw you have sleketon app on GitHub, it’s also using error_log for errors, or you made some custom handler?

The skeleton registers a custom error handler (renderer) per request type, like HTML and JSON:

$errorMiddleware = $app->addErrorMiddleware($displayErrorDetails, $logErrors, $logErrorDetails);

$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->registerErrorRenderer('text/html', HtmlErrorRenderer::class);
$errorHandler->registerErrorRenderer('application/json', JsonErrorRenderer::class);

Each error renderer has a LoggerFactory as dependency, because I need different logfiles per class.

public function __construct(LoggerFactory $loggerFactory)
{
    $this->logger = $loggerFactory
        ->addFileHandler('html_error.log')
        ->createInstance('html_error_renderer');
}

I see, thank you @odan!

1 Like