Passed
Push — main ( bec60e...3fc145 )
by Sammy
03:12 queued 01:40
created

LogLaddy.php (1 issue)

Severity
1
<?php
2
3
/*
4
 * LogLaddy
5
 *
6
 * I carry a log – yes. Is it funny to you? It is not to me.
7
 * Behind all things are reasons. Reasons can even explain the absurd.
8
 *
9
 * LogLaddy manages error reporting
10
 * PSR-3 Compliant, with a NICE bonus
11
 */
12
13
namespace HexMakina\LogLaddy;
14
15
// Debugger
16
use Psr\Log\LogLevel;
17
use HexMakina\Debugger\Debugger;
18
use HexMakina\BlackBox\StateAgentInterface;
19
20
class LogLaddy extends \Psr\Log\AbstractLogger
21
{
22
    private $state_agent = null;
23
    private static $level_mapping = null;
24
25
26
    public function __construct(StateAgentInterface $agent = null)
27
    {
28
        $this->state_agent = $agent;
29
        $this->setHandlers();
30
    }
31
32
    public function setHandlers()
33
    {
34
        set_error_handler([$this, 'errorHandler']);
35
        set_exception_handler([$this, 'exceptionHandler']);
36
    }
37
38
    public function restoreHandlers()
39
    {
40
        restore_error_handler();
41
        restore_exception_handler();
42
    }
43
44
    /*
45
    * handler for errors
46
    * use set_error_handler('\HexMakina\kadro\Logger\LogLaddy::error_handler')
47
    */
48
    public function errorHandler($level, $message, $file = '', $line = 0)
49
    {
50
        $loglevel = self::mapErrorLevelToLogLevel($level);
51
        $this->$loglevel($message, ['file' => $file, 'line' => $line, 'trace' => debug_backtrace()]);
52
    }
53
54
    /*
55
    * static handlers for throwables,
56
    * use set_exception_handler('\HexMakina\kadro\Logger\LogLaddy::exception_handler');
57
    */
58
    public function exceptionHandler(\Throwable $throwable)
59
    {
60
        $this->critical(Debugger::formatThrowable($throwable), $throwable->getTrace());
61
    }
62
63
    public function log($level, $message, array $context = [])
64
    {
65
        switch ($level) {
66
            case LogLevel::DEBUG:
67
                Debugger::visualDump($context, $message, true);
68
                break;
69
70
            case LogLevel::INFO:
71
            case LogLevel::NOTICE:
72
            case LogLevel::WARNING:
73
                if (is_null($this->state_agent)) {
74
                    Debugger::visualDump($context, $message, true);
75
                } else {
76
                    $this->state_agent->addMessage($level, $message, $context);
77
                }
78
                break;
79
80
            case LogLevel::CRITICAL:
81
            case LogLevel::ALERT:
82
            case LogLevel::EMERGENCY:
83
              // if dev, show, else logto file
84
                echo Debugger::toHTML($message, $level, $context, true);
85
                http_response_code(500);
86
                die;
1 ignored issue
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
87
            break;
88
        }
89
    }
90
91
92
    // -- Error level mapping from \Psr\Log\LogLevel.php & http://php.net/manual/en/errorfunc.constants.php
93
    /** Error level meaning , from \Psr\Log\LogLevel.php
94
     * const EMERGENCY = 'emergency';
95
     *                 // System is unusable.
96
     * const ALERT     = 'alert';
97
     *                 // Action must be taken immediately, Example: Entire website down, database unavailable, etc.
98
     * const CRITICAL  = 'critical';
99
     *                 // Application component unavailable, unexpected exception.
100
     * const ERROR     = 'error';
101
     *                 // Run time errors that do not require immediate action
102
     * const WARNING   = 'warning';
103
     *                 // Exceptional occurrences that are not errors, undesirable things that are not necessarily wrong
104
     * const NOTICE    = 'notice';
105
     *                 // Normal but significant events.
106
     * const INFO      = 'info';
107
     *                 // Interesting events. User logs in, SQL logs.
108
     * const DEBUG     = 'debug';
109
     *                 // Detailed debug information.
110
     */
111
    private static function mapErrorLevelToLogLevel($level): string
112
    {
113
      // http://php.net/manual/en/errorfunc.constants.php
114
        if (is_null(self::$level_mapping)) {
115
            self::$level_mapping =
116
              array_fill_keys([E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR], LogLevel::ALERT)
117
              + array_fill_keys([E_WARNING, E_CORE_WARNING, E_COMPILE_WARNING, E_USER_WARNING], LogLevel::CRITICAL)
118
              + array_fill_keys([E_NOTICE, E_USER_NOTICE], LogLevel::ERROR)
119
              + array_fill_keys([E_STRICT,E_DEPRECATED,E_USER_DEPRECATED,E_ALL], LogLevel::DEBUG);
120
121
        }
122
123
        if (!isset(self::$level_mapping[$level])) {
124
            throw new \Exception(__FUNCTION__ . "($level): $level is unknown");
125
        }
126
127
        return self::$level_mapping[$level];
128
    }
129
}
130