3 namespace Friendica\Factory;
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;
17 use Psr\Log\LoggerInterface;
23 * Currently only Monolog is supported
28 * A list of classes, which shouldn't get logged
31 private static $ignoreClassList = [
38 * Creates a new PSR-3 compliant logger instances
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
44 * @return LoggerInterface The PSR-3 compliant logger instance
47 * @throws InternalServerErrorException
49 public static function create($channel, Configuration $config, Profiler $profiler)
51 if (empty($config->get('system', 'debugging', false))) {
52 $logger = new VoidLogger();
53 Logger::init($logger);
57 $introspection = new Introspection(self::$ignoreClassList);
58 $level = $config->get('system', 'loglevel');
60 switch ($config->get('system', 'logger_adapter', 'monolog')) {
63 $logger = new SyslogLogger($channel, $introspection, $profiler, $level);
67 $logger = new StreamLogger($channel, $introspection, $profiler, $level);
72 $loggerTimeZone = new \DateTimeZone('UTC');
73 Monolog\Logger::setTimezone($loggerTimeZone);
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));
81 $stream = $config->get('system', 'logfile');
83 $loglevel = self::mapLegacyConfigDebugLevel((string)$level);
84 static::addStreamHandler($logger, $stream, $loglevel);
88 Logger::init($logger);
94 * Creates a new PSR-3 compliant develop logger
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.
99 * It should never get filled during normal usage of Friendica
101 * @param string $channel The channel of the logger instance
102 * @param Configuration $config The config
104 * @return LoggerInterface The PSR-3 compliant logger instance
105 * @throws InternalServerErrorException
107 public static function createDev($channel, Configuration $config)
109 $debugging = $config->get('system', 'debugging');
110 $stream = $config->get('system', 'dlogfile');
111 $developerIp = $config->get('system', 'dlogip');
113 if (!isset($developerIp) || !$debugging) {
117 $loggerTimeZone = new \DateTimeZone('UTC');
118 Monolog\Logger::setTimezone($loggerTimeZone);
120 $introspection = new Introspection(self::$ignoreClassList);
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));
128 $logger->pushHandler(new FriendicaDevelopHandler($developerIp));
130 static::addStreamHandler($logger, $stream, LogLevel::DEBUG);
132 Logger::setDevLogger($logger);
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
141 * @param string $level the level to be mapped
143 * @return string the PSR-3 compliant level
145 private static function mapLegacyConfigDebugLevel($level)
150 return LogLevel::ERROR;
153 return LogLevel::WARNING;
156 return LogLevel::NOTICE;
159 return LogLevel::INFO;
162 return LogLevel::DEBUG;
165 return LogLevel::DEBUG;
166 // default if nothing set
173 * Adding a handler to a given logger instance
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
181 * @throws InternalServerErrorException if the logger is incompatible to the logger factory
182 * @throws \Exception in case of general failures
184 public static function addStreamHandler($logger, $stream, $level = LogLevel::NOTICE)
186 if ($logger instanceof Monolog\Logger) {
187 $loglevel = Monolog\Logger::toMonologLevel($level);
189 // fallback to notice if an invalid loglevel is set
190 if (!is_int($loglevel)) {
191 $loglevel = LogLevel::NOTICE;
194 $fileHandler = new Monolog\Handler\StreamHandler($stream, $loglevel);
196 $formatter = new Monolog\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n");
197 $fileHandler->setFormatter($formatter);
199 $logger->pushHandler($fileHandler);
201 throw new InternalServerErrorException('Logger instance incompatible for MonologFactory');
205 public static function addVoidHandler($logger)
207 if ($logger instanceof Monolog\Logger) {
208 $logger->pushHandler(new Monolog\Handler\NullHandler());