Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
PsrLoggerErrorReporter
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
2 / 2
3
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 report
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/**
6 * This file is part of fast-forward/defer.
7 *
8 * This source file is subject to the license bundled
9 * with this source code in the file LICENSE.
10 *
11 * @copyright Copyright (c) 2026 Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
12 * @license   https://opensource.org/licenses/MIT MIT License
13 *
14 * @see       https://github.com/php-fast-forward/defer
15 * @see       https://github.com/php-fast-forward
16 * @see       https://datatracker.ietf.org/doc/html/rfc2119
17 */
18
19namespace FastForward\Defer\ErrorReporter;
20
21use Throwable;
22use FastForward\Defer\ErrorReporterInterface;
23use FastForward\Defer\Support\CallbackDescriber;
24use Psr\Log\LoggerInterface;
25
26/**
27 * This error reporter implementation MUST log all reported exceptions using a PSR-3 compatible logger.
28 * It SHALL provide a detailed log message including the exception class, message, file, line, callback description, and arguments.
29 * This class MUST NOT throw exceptions during reporting.
30 */
31final readonly class PsrLoggerErrorReporter implements ErrorReporterInterface
32{
33    /**
34     * Constructs a new PsrLoggerErrorReporter instance.
35     *
36     * @param LoggerInterface $logger the PSR-3 logger to use for error reporting
37     */
38    public function __construct(
39        private LoggerInterface $logger
40    ) {}
41
42    /**
43     * Reports a throwable using the PSR-3 logger.
44     *
45     * This method MUST log the exception details and callback description. It MUST NOT throw exceptions.
46     *
47     * @param Throwable $throwable the exception or error to report
48     * @param callable|null $callback the related callback, if available
49     * @param array $args arguments passed to the callback, if any
50     *
51     * @return void
52     */
53    public function report(Throwable $throwable, ?callable $callback = null, array $args = []): void
54    {
55        $this->logger->error(
56            'Deferred callback failed: {exception_class}: {message}',
57            [
58                'exception_class' => $throwable::class,
59                'message' => $throwable->getMessage(),
60                'file' => $throwable->getFile(),
61                'line' => $throwable->getLine(),
62                'callback' => null !== $callback ? CallbackDescriber::describe($callback) : null,
63                'callback_arguments' => $args,
64                'exception' => $throwable,
65            ]
66        );
67    }
68}