]> git.mxchange.org Git - friendica.git/blob - src/Factory/LoggerFactory.php
f940d9d84c9b189db6e6a96311a1c04453e38e53
[friendica.git] / src / Factory / LoggerFactory.php
1 <?php
2
3 namespace Friendica\Factory;
4
5 use Friendica\Core\Config\Configuration;
6 use Friendica\Core\Logger;
7 use Friendica\Network\HTTPException\InternalServerErrorException;
8 use Friendica\Util\Introspection;
9 use Friendica\Util\Logger\Monolog\FriendicaDevelopHandler;
10 use Friendica\Util\Logger\Monolog\FriendicaIntrospectionProcessor;
11 use Friendica\Util\Logger\SyslogLogger;
12 use Friendica\Util\Logger\VoidLogger;
13 use Friendica\Util\Logger\WorkerLogger;
14 use Friendica\Util\Profiler;
15 use Monolog;
16 use Psr\Log\LoggerInterface;
17 use Psr\Log\LogLevel;
18
19 /**
20  * A logger factory
21  *
22  * Currently only Monolog is supported
23  */
24 class LoggerFactory
25 {
26         /**
27          * A list of classes, which shouldn't get logged
28          * @var array
29          */
30         private static $ignoreClassList = [
31                 Logger::class,
32                 Profiler::class,
33                 WorkerLogger::class
34         ];
35
36         /**
37          * Creates a new PSR-3 compliant logger instances
38          *
39          * @param string        $channel The channel of the logger instance
40          * @param Configuration $config  The config
41          *
42          * @return LoggerInterface The PSR-3 compliant logger instance
43          *
44          * @throws \Exception
45          * @throws InternalServerErrorException
46          */
47         public static function create($channel, Configuration $config)
48         {
49                 if (empty($config->get('system', 'debugging', false))) {
50                         $logger = new VoidLogger();
51                         Logger::init($logger);
52                         return $logger;
53                 }
54
55                 $introspection = new Introspection(self::$ignoreClassList);
56
57                 switch ($config->get('system', 'logger_adapter', 'monolog')) {
58                         case 'syslog':
59                                 $level = $config->get('system', 'loglevel');
60
61                                 $logger = new SyslogLogger($channel, $introspection, $level);
62                                 break;
63                         case 'monolog':
64                         default:
65                                 $loggerTimeZone = new \DateTimeZone('UTC');
66                                 Monolog\Logger::setTimezone($loggerTimeZone);
67
68                                 $logger = new Monolog\Logger($channel);
69                                 $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
70                                 $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
71                                 $logger->pushProcessor(new Monolog\Processor\UidProcessor());
72                                 $logger->pushProcessor(new FriendicaIntrospectionProcessor($introspection, LogLevel::DEBUG));
73
74                                 $stream = $config->get('system', 'logfile');
75                                 $level  = $config->get('system', 'loglevel');
76
77                                 $loglevel = self::mapLegacyConfigDebugLevel((string)$level);
78                                 static::addStreamHandler($logger, $stream, $loglevel);
79                                 break;
80                 }
81
82                 Logger::init($logger);
83
84                 return $logger;
85         }
86
87         /**
88          * Creates a new PSR-3 compliant develop logger
89          *
90          * If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
91          * you'll use this logger instance for the duration of your work.
92          *
93          * It should never get filled during normal usage of Friendica
94          *
95          * @param string        $channel The channel of the logger instance
96          * @param Configuration $config  The config
97          *
98          * @return LoggerInterface The PSR-3 compliant logger instance
99          * @throws InternalServerErrorException
100          */
101         public static function createDev($channel, Configuration $config)
102         {
103                 $debugging   = $config->get('system', 'debugging');
104                 $stream      = $config->get('system', 'dlogfile');
105                 $developerIp = $config->get('system', 'dlogip');
106
107                 if (!isset($developerIp) || !$debugging) {
108                         return null;
109                 }
110
111                 $loggerTimeZone = new \DateTimeZone('UTC');
112                 Monolog\Logger::setTimezone($loggerTimeZone);
113
114                 $introspection = new Introspection(self::$ignoreClassList);
115
116                 $logger = new Monolog\Logger($channel);
117                 $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
118                 $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
119                 $logger->pushProcessor(new Monolog\Processor\UidProcessor());
120                 $logger->pushProcessor(new FriendicaIntrospectionProcessor($introspection, LogLevel::DEBUG));
121
122                 $logger->pushHandler(new FriendicaDevelopHandler($developerIp));
123
124                 static::addStreamHandler($logger, $stream, LogLevel::DEBUG);
125
126                 Logger::setDevLogger($logger);
127
128                 return $logger;
129         }
130
131         /**
132          * Mapping a legacy level to the PSR-3 compliant levels
133          * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel
134          *
135          * @param string $level the level to be mapped
136          *
137          * @return string the PSR-3 compliant level
138          */
139         private static function mapLegacyConfigDebugLevel($level)
140         {
141                 switch ($level) {
142                         // legacy WARNING
143                         case "0":
144                                 return LogLevel::ERROR;
145                         // legacy INFO
146                         case "1":
147                                 return LogLevel::WARNING;
148                         // legacy TRACE
149                         case "2":
150                                 return LogLevel::NOTICE;
151                         // legacy DEBUG
152                         case "3":
153                                 return LogLevel::INFO;
154                         // legacy DATA
155                         case "4":
156                                 return LogLevel::DEBUG;
157                         // legacy ALL
158                         case "5":
159                                 return LogLevel::DEBUG;
160                         // default if nothing set
161                         default:
162                                 return $level;
163                 }
164         }
165
166         /**
167          * Adding a handler to a given logger instance
168          *
169          * @param LoggerInterface $logger  The logger instance
170          * @param mixed           $stream  The stream which handles the logger output
171          * @param string          $level   The level, for which this handler at least should handle logging
172          *
173          * @return void
174          *
175          * @throws InternalServerErrorException if the logger is incompatible to the logger factory
176          * @throws \Exception in case of general failures
177          */
178         public static function addStreamHandler($logger, $stream, $level = LogLevel::NOTICE)
179         {
180                 if ($logger instanceof Monolog\Logger) {
181                         $loglevel = Monolog\Logger::toMonologLevel($level);
182
183                         // fallback to notice if an invalid loglevel is set
184                         if (!is_int($loglevel)) {
185                                 $loglevel = LogLevel::NOTICE;
186                         }
187
188                         $fileHandler = new Monolog\Handler\StreamHandler($stream, $loglevel);
189
190                         $formatter = new Monolog\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n");
191                         $fileHandler->setFormatter($formatter);
192
193                         $logger->pushHandler($fileHandler);
194                 } else {
195                         throw new InternalServerErrorException('Logger instance incompatible for MonologFactory');
196                 }
197         }
198
199         public static function addVoidHandler($logger)
200         {
201                 if ($logger instanceof Monolog\Logger) {
202                         $logger->pushHandler(new Monolog\Handler\NullHandler());
203                 }
204         }
205 }