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