1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Spiral\Monolog\Bootloader; |
6
|
|
|
|
7
|
|
|
use Monolog\Formatter\LineFormatter; |
8
|
|
|
use Monolog\Handler\HandlerInterface; |
9
|
|
|
use Monolog\Handler\RotatingFileHandler; |
10
|
|
|
use Monolog\Level; |
11
|
|
|
use Monolog\Logger; |
12
|
|
|
use Monolog\ResettableInterface; |
13
|
|
|
use Psr\Log\LoggerInterface; |
14
|
|
|
use Spiral\Boot\Bootloader\Bootloader; |
15
|
|
|
use Spiral\Boot\EnvironmentInterface; |
16
|
|
|
use Spiral\Boot\FinalizerInterface; |
17
|
|
|
use Spiral\Config\ConfiguratorInterface; |
18
|
|
|
use Spiral\Config\Patch\Append; |
19
|
|
|
use Spiral\Core\Attribute\Singleton; |
20
|
|
|
use Spiral\Core\Container; |
21
|
|
|
use Spiral\Logger\Bootloader\LoggerBootloader; |
22
|
|
|
use Spiral\Logger\LogsInterface; |
23
|
|
|
use Spiral\Monolog\Config\MonologConfig; |
24
|
|
|
use Spiral\Monolog\LogFactory; |
25
|
|
|
|
26
|
|
|
#[Singleton] |
27
|
|
|
final class MonologBootloader extends Bootloader |
28
|
|
|
{ |
29
|
|
|
protected const SINGLETONS = [ |
30
|
|
|
LogsInterface::class => LogFactory::class, |
31
|
|
|
Logger::class => Logger::class, |
32
|
|
|
]; |
33
|
|
|
|
34
|
|
|
protected const BINDINGS = [ |
35
|
|
|
'log.rotate' => [self::class, 'logRotate'], |
36
|
|
|
]; |
37
|
|
|
|
38
|
|
|
protected const DEPENDENCIES = [ |
39
|
|
|
LoggerBootloader::class, |
40
|
|
|
]; |
41
|
|
|
|
42
|
|
|
private const DEFAULT_FORMAT = "[%datetime%] %level_name%: %message% %context%\n"; |
43
|
|
|
|
44
|
21 |
|
public function __construct( |
45
|
|
|
private readonly ConfiguratorInterface $config, |
46
|
|
|
private readonly EnvironmentInterface $env, |
47
|
|
|
) { |
48
|
21 |
|
} |
49
|
|
|
|
50
|
21 |
|
public function init(Container $container, FinalizerInterface $finalizer): void |
51
|
|
|
{ |
52
|
21 |
|
$finalizer->addFinalizer(static function (bool $terminate) use ($container): void { |
53
|
3 |
|
if ($terminate) { |
54
|
1 |
|
return; |
55
|
|
|
} |
56
|
|
|
|
57
|
2 |
|
if ($container->hasInstance(LoggerInterface::class)) { |
58
|
2 |
|
$logger = $container->get(LoggerInterface::class); |
59
|
|
|
|
60
|
2 |
|
if ($logger instanceof ResettableInterface) { |
61
|
2 |
|
$logger->reset(); |
62
|
|
|
} |
63
|
|
|
} |
64
|
|
|
|
65
|
2 |
|
if ($container->hasInstance(LogsInterface::class)) { |
66
|
2 |
|
$factory = $container->get(LogsInterface::class); |
67
|
|
|
|
68
|
2 |
|
if ($factory instanceof ResettableInterface) { |
69
|
1 |
|
$factory->reset(); |
70
|
|
|
} |
71
|
|
|
} |
72
|
21 |
|
}); |
73
|
|
|
|
74
|
21 |
|
$this->config->setDefaults(MonologConfig::CONFIG, [ |
75
|
21 |
|
'default' => $this->env->get('MONOLOG_DEFAULT_CHANNEL', MonologConfig::DEFAULT_CHANNEL), |
76
|
21 |
|
'globalLevel' => Logger::DEBUG, |
|
|
|
|
77
|
21 |
|
'handlers' => [], |
78
|
21 |
|
]); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
public function addHandler(string $channel, HandlerInterface $handler): void |
82
|
|
|
{ |
83
|
|
|
if (!isset($this->config->getConfig(MonologConfig::CONFIG)['handlers'][$channel])) { |
84
|
|
|
$this->config->modify(MonologConfig::CONFIG, new Append('handlers', $channel, [])); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
$this->config->modify( |
88
|
|
|
MonologConfig::CONFIG, |
89
|
|
|
new Append( |
90
|
|
|
'handlers.' . $channel, |
91
|
|
|
null, |
92
|
|
|
$handler |
93
|
|
|
) |
94
|
|
|
); |
95
|
|
|
} |
96
|
|
|
|
97
|
2 |
|
public function logRotate( |
98
|
|
|
string $filename, |
99
|
|
|
int|Level $level = Logger::DEBUG, |
|
|
|
|
100
|
|
|
int $maxFiles = 0, |
101
|
|
|
bool $bubble = true |
102
|
|
|
): HandlerInterface { |
103
|
2 |
|
$handler = new RotatingFileHandler( |
104
|
2 |
|
$filename, |
105
|
2 |
|
$maxFiles, |
106
|
2 |
|
$level, |
107
|
2 |
|
$bubble, |
108
|
2 |
|
null, |
109
|
2 |
|
true |
110
|
2 |
|
); |
111
|
|
|
|
112
|
2 |
|
return $handler->setFormatter( |
113
|
2 |
|
new LineFormatter($this->env->get('MONOLOG_FORMAT', self::DEFAULT_FORMAT)) |
114
|
2 |
|
); |
115
|
|
|
} |
116
|
|
|
} |
117
|
|
|
|
This class constant has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.