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