Elgg  Version master
Logger.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg;
4 
5 use Elgg\Cli\Application as CliApplication;
10 use Monolog\Formatter\LineFormatter;
11 use Monolog\Handler\ErrorLogHandler;
12 use Monolog\Level;
13 use Monolog\Processor\MemoryPeakUsageProcessor;
14 use Monolog\Processor\MemoryUsageProcessor;
15 use Monolog\Processor\ProcessIdProcessor;
16 use Monolog\Processor\PsrLogMessageProcessor;
17 use Monolog\Processor\WebProcessor;
18 use Psr\Log\LogLevel;
19 use Symfony\Component\Console\Input\InputInterface;
20 use Symfony\Component\Console\Output\OutputInterface;
21 
27 class Logger extends \Monolog\Logger {
28 
29  const CHANNEL = 'ELGG';
30 
31  const OFF = 600; // use highest log level for OFF
32 
37  protected static array $elgg_levels = [
38  100 => LogLevel::DEBUG,
39  200 => LogLevel::INFO,
40  250 => LogLevel::NOTICE,
41  300 => LogLevel::WARNING,
42  400 => LogLevel::ERROR,
43  500 => LogLevel::CRITICAL,
44  550 => LogLevel::ALERT,
45  600 => LogLevel::EMERGENCY,
46  ];
47 
48  protected string $level = LogLevel::EMERGENCY;
49 
50  protected array $disabled_stack = [];
51 
60  public static function factory(?InputInterface $input = null, ?OutputInterface $output = null) {
61  $logger = new static(self::CHANNEL);
62 
63  if (\Elgg\Application::isCli()) {
64  if (is_null($input) || is_null($output)) {
67 
68  $app = new CliApplication();
69  $app->setup($input, $output);
70  }
71 
72  $handler = new ErrorHandler(
73  $output,
74  \Elgg\Application::getStdErr(),
75  true
76  );
77 
78  $formatter = new ErrorFormatter();
79  $formatter->allowInlineLineBreaks();
80  $formatter->ignoreEmptyContextAndExtra();
81 
82  $handler->setFormatter($formatter);
83 
84  if ($output->isVeryVerbose()) {
85  $handler->pushProcessor(new BacktraceProcessor(Level::Error));
86  }
87  } else {
88  $handler = new ErrorLogHandler();
89 
90  $handler->pushProcessor(new WebProcessor());
91 
92  $formatter = new LineFormatter();
93  $formatter->allowInlineLineBreaks();
94  $formatter->ignoreEmptyContextAndExtra();
95 
96  $handler->setFormatter($formatter);
97 
98  $handler->pushProcessor(new MemoryUsageProcessor());
99  $handler->pushProcessor(new MemoryPeakUsageProcessor());
100  $handler->pushProcessor(new ProcessIdProcessor());
101  $handler->pushProcessor(new BacktraceProcessor(Level::Warning));
102  }
103 
104  $handler->pushProcessor(new PsrLogMessageProcessor());
105 
106  $logger->pushHandler($handler);
107 
108  // determine default log level
109  $php_error_level = error_reporting();
110 
111  $level = LogLevel::CRITICAL;
112 
113  if (($php_error_level & E_NOTICE) == E_NOTICE) {
114  $level = LogLevel::NOTICE;
115  } else if (($php_error_level & E_WARNING) == E_WARNING) {
116  $level = LogLevel::WARNING;
117  } else if (($php_error_level & E_ERROR) == E_ERROR) {
118  $level = LogLevel::ERROR;
119  }
120 
121  $logger->setLevel($level);
122 
123  return $logger;
124  }
125 
134  protected function assertLevel(string $level): void {
135  if (!in_array($level, self::$elgg_levels)) {
136  throw new InvalidArgumentException("Using the log level '{$level}' is not allowed. Use one of the \Psr\Log\LogLevel constants.");
137  }
138  }
139 
149  public function setLevel(string $level = LogLevel::EMERGENCY): void {
150  $this->assertLevel($level);
151 
152  $this->level = $level;
153  }
154 
163  public function getLevel(bool $severity = true): int|string {
164  return $severity ? array_search($this->level, self::$elgg_levels) : $this->level;
165  }
166 
175  public function isLoggable(string $level): bool {
176  $this->assertLevel($level);
177 
178  $severity = (int) array_search($level, self::$elgg_levels);
179  return $severity >= $this->getLevel();
180  }
181 
186  public function log($level, $message, array $context = []): void {
187  $level = (string) $level;
188  $this->assertLevel($level);
189 
190  if ($message instanceof \Throwable) {
191  if (!isset($context['throwable']) && $this->isLoggable(LogLevel::NOTICE)) {
192  $context['throwable'] = $message;
193  }
194 
195  $message = $message->getMessage();
196  }
197 
198  if (!empty($this->disabled_stack)) {
199  // capture to top of stack
200  end($this->disabled_stack);
201  $key = key($this->disabled_stack);
202  $this->disabled_stack[$key][] = [
203  'message' => $message,
204  'level' => $level,
205  ];
206 
207  return;
208  }
209 
210  if (!$this->isLoggable($level)) {
211  return;
212  }
213 
214  parent::log($level, $message, $context);
215  }
216 
220  public function emergency($message, array $context = []): void {
221  $this->log(LogLevel::EMERGENCY, $message, $context);
222  }
223 
227  public function alert($message, array $context = []): void {
228  $this->log(LogLevel::ALERT, $message, $context);
229  }
230 
234  public function critical($message, array $context = []): void {
235  $this->log(LogLevel::CRITICAL, $message, $context);
236  }
237 
241  public function error($message, array $context = []): void {
242  $this->log(LogLevel::ERROR, $message, $context);
243  }
244 
248  public function warning($message, array $context = []): void {
249  $this->log(LogLevel::WARNING, $message, $context);
250  }
251 
255  public function notice($message, array $context = []): void {
256  $this->log(LogLevel::NOTICE, $message, $context);
257  }
258 
262  public function info($message, array $context = []): void {
263  $this->log(LogLevel::INFO, $message, $context);
264  }
265 
269  public function debug($message, array $context = []): void {
270  $this->log(LogLevel::DEBUG, $message, $context);
271  }
272 
285  public function disable() {
286  $this->disabled_stack[] = [];
287  }
288 
296  public function enable() {
297  return array_pop($this->disabled_stack);
298  }
299 }
$handler
Definition: add.php:7
$context
Definition: add.php:8
return[ 'admin/delete_admin_notices'=>['access'=> 'admin'], 'admin/menu/save'=>['access'=> 'admin'], 'admin/plugins/activate'=>['access'=> 'admin'], 'admin/plugins/activate_all'=>['access'=> 'admin'], 'admin/plugins/deactivate'=>['access'=> 'admin'], 'admin/plugins/deactivate_all'=>['access'=> 'admin'], 'admin/plugins/set_priority'=>['access'=> 'admin'], 'admin/security/security_txt'=>['access'=> 'admin'], 'admin/security/settings'=>['access'=> 'admin'], 'admin/security/regenerate_site_secret'=>['access'=> 'admin'], 'admin/site/cache/invalidate'=>['access'=> 'admin'], 'admin/site/flush_cache'=>['access'=> 'admin'], 'admin/site/icons'=>['access'=> 'admin'], 'admin/site/set_maintenance_mode'=>['access'=> 'admin'], 'admin/site/set_robots'=>['access'=> 'admin'], 'admin/site/theme'=>['access'=> 'admin'], 'admin/site/unlock_upgrade'=>['access'=> 'admin'], 'admin/site/settings'=>['access'=> 'admin'], 'admin/upgrade'=>['access'=> 'admin'], 'admin/upgrade/reset'=>['access'=> 'admin'], 'admin/user/ban'=>['access'=> 'admin'], 'admin/user/bulk/ban'=>['access'=> 'admin'], 'admin/user/bulk/delete'=>['access'=> 'admin'], 'admin/user/bulk/unban'=>['access'=> 'admin'], 'admin/user/bulk/validate'=>['access'=> 'admin'], 'admin/user/change_email'=>['access'=> 'admin'], 'admin/user/delete'=>['access'=> 'admin'], 'admin/user/login_as'=>['access'=> 'admin'], 'admin/user/logout_as'=>[], 'admin/user/makeadmin'=>['access'=> 'admin'], 'admin/user/resetpassword'=>['access'=> 'admin'], 'admin/user/removeadmin'=>['access'=> 'admin'], 'admin/user/unban'=>['access'=> 'admin'], 'admin/user/validate'=>['access'=> 'admin'], 'annotation/delete'=>[], 'avatar/upload'=>[], 'comment/save'=>[], 'diagnostics/download'=>['access'=> 'admin'], 'entity/chooserestoredestination'=>[], 'entity/delete'=>[], 'entity/mute'=>[], 'entity/restore'=>[], 'entity/subscribe'=>[], 'entity/trash'=>[], 'entity/unmute'=>[], 'entity/unsubscribe'=>[], 'login'=>['access'=> 'logged_out'], 'logout'=>[], 'notifications/mute'=>['access'=> 'public'], 'plugins/settings/remove'=>['access'=> 'admin'], 'plugins/settings/save'=>['access'=> 'admin'], 'plugins/usersettings/save'=>[], 'register'=>['access'=> 'logged_out', 'middleware'=>[\Elgg\Router\Middleware\RegistrationAllowedGatekeeper::class,],], 'river/delete'=>[], 'settings/notifications'=>[], 'settings/notifications/subscriptions'=>[], 'user/changepassword'=>['access'=> 'public'], 'user/requestnewpassword'=>['access'=> 'public'], 'useradd'=>['access'=> 'admin'], 'usersettings/save'=>[], 'widgets/add'=>[], 'widgets/delete'=>[], 'widgets/move'=>[], 'widgets/save'=>[],]
Definition: actions.php:73
Handle system and PHP errors.
static getStdOut()
Load console output interface.
static getStdIn()
Load console input interface.
Wrapper for console application.
Definition: Application.php:11
Format errors for console output.
Console handler.
Exception thrown if an argument is not of the expected type.
Inject backtrace stack into the record.
Logger.
Definition: Logger.php:27
log($level, $message, array $context=[])
{}
Definition: Logger.php:186
setLevel(string $level=LogLevel::EMERGENCY)
Set the logging level.
Definition: Logger.php:149
notice($message, array $context=[])
{}
Definition: Logger.php:255
isLoggable(string $level)
Check if a level is loggable under current logging level.
Definition: Logger.php:175
getLevel(bool $severity=true)
Get the current logging level severity.
Definition: Logger.php:163
emergency($message, array $context=[])
{}
Definition: Logger.php:220
alert($message, array $context=[])
{}
Definition: Logger.php:227
enable()
Restore logging and get record of log calls (after tests)
Definition: Logger.php:296
assertLevel(string $level)
Assert the given level.
Definition: Logger.php:134
debug($message, array $context=[])
{}
Definition: Logger.php:269
error($message, array $context=[])
{}
Definition: Logger.php:241
static factory(?InputInterface $input=null, ?OutputInterface $output=null)
Build a new logger.
Definition: Logger.php:60
critical($message, array $context=[])
{}
Definition: Logger.php:234
info($message, array $context=[])
{}
Definition: Logger.php:262
warning($message, array $context=[])
{}
Definition: Logger.php:248
disable()
Temporarily disable logging and capture logs (before tests)
Definition: Logger.php:285
$output
Definition: download.php:9
$input
Form field view.
Definition: field.php:13
if($container instanceof ElggGroup && $container->guid !=elgg_get_page_owner_guid()) $key
Definition: summary.php:44
if(parse_url(elgg_get_site_url(), PHP_URL_PATH) !=='/') if(file_exists(elgg_get_root_path() . 'robots.txt'))
Set robots.txt.
Definition: robots.php:10