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