Logger::notice()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Platine Logger
5
 *
6
 * Platine Logger is the implementation of PSR 3
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine Logger
11
 *
12
 * Permission is hereby granted, free of charge, to any person obtaining a copy
13
 * of this software and associated documentation files (the "Software"), to deal
14
 * in the Software without restriction, including without limitation the rights
15
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
 * copies of the Software, and to permit persons to whom the Software is
17
 * furnished to do so, subject to the following conditions:
18
 *
19
 * The above copyright notice and this permission notice shall be included in all
20
 * copies or substantial portions of the Software.
21
 *
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
 * SOFTWARE.
29
 */
30
31
/**
32
 *  @file Logger.php
33
 *
34
 *  The Logger class is the main class to use to handle application log.
35
 *
36
 *  @package    Platine\Logger
37
 *  @author Platine Developers Team
38
 *  @copyright  Copyright (c) 2020
39
 *  @license    http://opensource.org/licenses/MIT  MIT License
40
 *  @link   https://www.platine-php.com
41
 *  @version 1.0.0
42
 *  @filesource
43
 */
44
45
declare(strict_types=1);
46
47
namespace Platine\Logger;
48
49
use Exception;
50
use Platine\Logger\Formatter\DefaultFormatter;
51
52
/**
53
 * @class Logger
54
 * @package Platine\Logger
55
 */
56
class Logger implements LoggerInterface
57
{
58
    /**
59
     * Special minimum log level which will not log any log levels.
60
     */
61
    public const LOG_LEVEL_NONE = 'none';
62
63
    /**
64
     * The list of logger handler
65
     * @var array<string, LoggerHandlerInterface>
66
     */
67
    protected array $handlers = [];
68
69
    /**
70
     * Log level hierarchy
71
     * @var array<string, int>
72
     */
73
    protected array $levels = [
74
        self::LOG_LEVEL_NONE => 999,
75
        LogLevel::DEBUG => 0,
76
        LogLevel::INFO => 1,
77
        LogLevel::NOTICE => 2,
78
        LogLevel::WARNING => 3,
79
        LogLevel::ERROR => 4,
80
        LogLevel::CRITICAL => 5,
81
        LogLevel::ALERT => 6,
82
        LogLevel::EMERGENCY => 7,
83
    ];
84
85
    /**
86
     * Lowest log level to log.
87
     * @var int
88
     */
89
    protected int $logLevel;
90
91
    /**
92
     * Channel used to identify each log message
93
     * @var string
94
     */
95
    protected string $channel = 'MAIN';
96
97
    /**
98
     * The configuration to use
99
     * @var Configuration
100
     */
101
    protected Configuration $config;
102
103
    /**
104
     * Logger formatter to be used
105
     * @var LoggerFormatterInterface
106
     */
107
    protected LoggerFormatterInterface $formatter;
108
109
    /**
110
     * Create new logger instance
111
     *
112
     * @param Configuration|null $config the configuration to use
113
     * @param LoggerFormatterInterface|null $formatter the formatter to use
114
     */
115
    public function __construct(
116
        ?Configuration $config = null,
117
        ?LoggerFormatterInterface $formatter = null
118
    ) {
119
        $this->config = $config ?? new Configuration([]);
120
        $this->formatter = $formatter ?? new DefaultFormatter($this->config);
121
122
        $level = $this->config->has('level')
123
                ? $this->config->get('level')
124
                : LogLevel::DEBUG;
125
126
        $this->setLevel($level);
127
    }
128
129
    /**
130
     * Return the logger formatter
131
     * @return LoggerFormatterInterface
132
     */
133
    public function getFormatter(): LoggerFormatterInterface
134
    {
135
        return $this->formatter;
136
    }
137
138
    /**
139
     * Set logger formatter for future use
140
     * @param LoggerFormatterInterface $formatter
141
     * @return $this
142
     */
143
    public function setFormatter(LoggerFormatterInterface $formatter): self
144
    {
145
        $this->formatter = $formatter;
146
147
        return $this;
148
    }
149
150
151
    /**
152
     * Add logger handler
153
     * @param string $name
154
     * @param LoggerHandlerInterface $handler
155
     * @return $this
156
     */
157
    public function addHandler(string $name, LoggerHandlerInterface $handler): self
158
    {
159
        $this->handlers[$name] = $handler;
160
161
        return $this;
162
    }
163
164
    /**
165
     * Return the list of handlers instance
166
     * @return array<string, LoggerHandlerInterface>
167
     */
168
    public function getHandlers(): array
169
    {
170
        return $this->handlers;
171
    }
172
173
    /**
174
     * Set the minimum log level
175
     *
176
     * @param string $logLevel
177
     *
178
     * @throws Exception
179
     *
180
     * @return $this
181
     */
182
    public function setLevel(string $logLevel): self
183
    {
184
        if (!array_key_exists($logLevel, $this->levels)) {
185
            throw new Exception(sprintf(
186
                'Log level [%s] is not a valid log level. '
187
                . 'Must be one of (%s)',
188
                $logLevel,
189
                implode(', ', array_keys($this->levels))
190
            ));
191
        }
192
        $this->logLevel = $this->levels[$logLevel];
193
194
        return $this;
195
    }
196
197
    /**
198
     * Set log channel
199
     *
200
     * @param string $channel
201
     *
202
     * @return self
203
     */
204
    public function setChannel(string $channel): self
205
    {
206
        $this->channel = $channel;
207
208
        return $this;
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     */
214
    public function emergency(string $message, array $context = []): void
215
    {
216
        $this->log(LogLevel::EMERGENCY, $message, $context);
217
    }
218
219
    /**
220
     * {@inheritdoc}
221
     */
222
    public function alert(string $message, array $context = []): void
223
    {
224
        $this->log(LogLevel::ALERT, $message, $context);
225
    }
226
227
    /**
228
     * {@inheritdoc}
229
     */
230
    public function critical(string $message, array $context = []): void
231
    {
232
        $this->log(LogLevel::CRITICAL, $message, $context);
233
    }
234
235
    /**
236
     * {@inheritdoc}
237
     */
238
    public function error(string $message, array $context = []): void
239
    {
240
        $this->log(LogLevel::ERROR, $message, $context);
241
    }
242
243
    /**
244
     * {@inheritdoc}
245
     */
246
    public function warning(string $message, array $context = []): void
247
    {
248
        $this->log(LogLevel::WARNING, $message, $context);
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254
    public function notice(string $message, array $context = []): void
255
    {
256
        $this->log(LogLevel::NOTICE, $message, $context);
257
    }
258
259
    /**
260
     * {@inheritdoc}
261
     */
262
    public function info(string $message, array $context = []): void
263
    {
264
        $this->log(LogLevel::INFO, $message, $context);
265
    }
266
267
    /**
268
     * {@inheritdoc}
269
     */
270
    public function debug(string $message, array $context = []): void
271
    {
272
        $this->log(LogLevel::DEBUG, $message, $context);
273
    }
274
275
    /**
276
     * {@inheritdoc}
277
     */
278
    public function log(string $level, string $message, array $context = []): void
279
    {
280
        $msg = $this->formatter->format(
281
            $level,
282
            $message,
283
            $context,
284
            $this->channel
285
        );
286
287
        foreach ($this->handlers as $name => $handler) {
288
            if ($this->handlerCanLog($name, $level)) {
289
                $handler->log($msg);
290
            }
291
        }
292
    }
293
294
    /**
295
     * Whether the given handler can log
296
     * @param string $name
297
     * @param string $level
298
     * @return bool
299
     */
300
    protected function handlerCanLog(string $name, string $level): bool
301
    {
302
        $key = 'handlers.' . $name;
303
        $currentLevel = $this->logLevel;
304
        $logLevel = $this->levels[$level];
305
306
        if ($this->config->has($key)) {
307
            $handler = $this->config->get($key);
308
            $handlerLevel = $handler['level'] ?? $this->config->get('level');
309
310
            $currentLevel = $this->levels[$handlerLevel];
311
        }
312
313
        return $logLevel >= $currentLevel;
314
    }
315
}
316