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\Handler\ErrorLogHandler;
11 use Monolog\Level;
12 use Monolog\Processor\MemoryPeakUsageProcessor;
13 use Monolog\Processor\MemoryUsageProcessor;
14 use Monolog\Processor\ProcessIdProcessor;
15 use Monolog\Processor\PsrLogMessageProcessor;
16 use Monolog\Processor\WebProcessor;
17 use Psr\Log\LogLevel;
18 use Symfony\Component\Console\Input\InputInterface;
19 use Symfony\Component\Console\Output\OutputInterface;
20 
26 class Logger extends \Monolog\Logger {
27 
28  const CHANNEL = 'ELGG';
29 
30  const OFF = 600; // use highest log level for OFF
31 
36  protected static $elgg_levels = [
37  0 => false,
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 
52  protected static $legacy_levels = [
53  'OFF' => false,
54  'INFO' => LogLevel::INFO,
55  'NOTICE' => LogLevel::NOTICE,
56  'WARNING' => LogLevel::WARNING,
57  'ERROR' => LogLevel::ERROR,
58  ];
59 
63  protected $level;
64 
68  protected $disabled_stack = [];
69 
78  public static function factory(?InputInterface $input = null, ?OutputInterface $output = null) {
79  $logger = new static(self::CHANNEL);
80 
81  if (\Elgg\Application::isCli()) {
82  if (is_null($input) || is_null($output)) {
85 
86  $app = new CliApplication();
87  $app->setup($input, $output);
88  }
89 
90  $handler = new ErrorHandler(
91  $output,
92  \Elgg\Application::getStdErr(),
93  true
94  );
95 
96  $formatter = new ErrorFormatter();
97  $formatter->allowInlineLineBreaks();
98  $formatter->ignoreEmptyContextAndExtra();
99 
100  $handler->setFormatter($formatter);
101 
102  $handler->pushProcessor(new BacktraceProcessor(Level::Error));
103  } else {
104  $handler = new ErrorLogHandler();
105 
106  $handler->pushProcessor(new WebProcessor());
107 
108  $formatter = new ElggLogFormatter();
109  $formatter->allowInlineLineBreaks();
110  $formatter->ignoreEmptyContextAndExtra();
111 
112  $handler->setFormatter($formatter);
113 
114  $handler->pushProcessor(new MemoryUsageProcessor());
115  $handler->pushProcessor(new MemoryPeakUsageProcessor());
116  $handler->pushProcessor(new ProcessIdProcessor());
117  $handler->pushProcessor(new BacktraceProcessor(Level::Warning));
118  }
119 
120  $handler->pushProcessor(new PsrLogMessageProcessor());
121 
122  $logger->pushHandler($handler);
123 
124  $logger->setLevel();
125 
126  return $logger;
127  }
128 
136  protected function normalizeLevel($level = null) {
137  if (!is_string($level) || !in_array($level, self::$elgg_levels)) {
138  $level_value = $level;
139  if ($level === false) {
140  $level_value = 'false';
141  }
142 
143  $this->warning("Deprecated in 6.1: Using the log level '{$level_value}' has been deprecated. Use the \Psr\Log\LogLevel constants.");
144  }
145 
146  if (!$level) {
147  return false;
148  }
149 
150  if (array_key_exists($level, self::$legacy_levels)) {
151  $level = self::$legacy_levels[$level];
152  if ($level === false) {
153  // can't array_key_exists for false
154  return 0;
155  }
156  }
157 
158  if (array_key_exists($level, self::$elgg_levels)) {
159  $level = self::$elgg_levels[$level];
160  }
161 
162  if (!in_array($level, self::$elgg_levels)) {
163  $level = false;
164  }
165 
166  return $level;
167  }
168 
177  public function setLevel($level = null) {
178  // TODO: In Elgg 7 we should throw exceptions if level is not a Psr/Log/LogLevel
179 
180  if (!isset($level)) {
181  $php_error_level = error_reporting();
182 
183  $level = LogLevel::CRITICAL;
184 
185  if (($php_error_level & E_NOTICE) == E_NOTICE) {
186  $level = LogLevel::NOTICE;
187  } else if (($php_error_level & E_WARNING) == E_WARNING) {
188  $level = LogLevel::WARNING;
189  } else if (($php_error_level & E_ERROR) == E_ERROR) {
190  $level = LogLevel::ERROR;
191  }
192  }
193 
194  $this->level = $this->normalizeLevel($level);
195  }
196 
205  public function getLevel($severity = true) {
206  if ($severity) {
207  return array_search($this->level, self::$elgg_levels);
208  }
209 
210  return $this->level;
211  }
212 
220  public function isLoggable($level) {
221  $level = $this->normalizeLevel($level);
222 
223  $severity = array_search($level, self::$elgg_levels);
224  if (!$this->getLevel() || $severity < $this->getLevel()) {
225  return false;
226  }
227 
228  return true;
229  }
230 
234  public function log($level, $message, array $context = []): void {
235 
236  $level = $this->normalizeLevel($level);
237 
238  if (!empty($this->disabled_stack)) {
239  // capture to top of stack
240  end($this->disabled_stack);
241  $key = key($this->disabled_stack);
242  $this->disabled_stack[$key][] = [
243  'message' => $message,
244  'level' => $level,
245  ];
246 
247  return;
248  }
249 
250  if (!$this->isLoggable($level)) {
251  return;
252  }
253 
254  parent::log($level, $message, $context);
255  }
256 
260  public function emergency($message, array $context = []): void {
261  $this->log(LogLevel::EMERGENCY, $message, $context);
262  }
263 
267  public function alert($message, array $context = []): void {
268  $this->log(LogLevel::ALERT, $message, $context);
269  }
270 
274  public function critical($message, array $context = []): void {
275  $this->log(LogLevel::CRITICAL, $message, $context);
276  }
277 
281  public function error($message, array $context = []): void {
282  $this->log(LogLevel::ERROR, $message, $context);
283  }
284 
288  public function warning($message, array $context = []): void {
289  $this->log(LogLevel::WARNING, $message, $context);
290  }
291 
295  public function notice($message, array $context = []): void {
296  $this->log(LogLevel::NOTICE, $message, $context);
297  }
298 
302  public function info($message, array $context = []): void {
303  $this->log(LogLevel::INFO, $message, $context);
304  }
305 
309  public function debug($message, array $context = []): void {
310  $this->log(LogLevel::DEBUG, $message, $context);
311  }
312 
320  public function dump($data) {
321  $this->log(LogLevel::ERROR, $data);
322  }
323 
336  public function disable() {
337  $this->disabled_stack[] = [];
338  }
339 
347  public function enable() {
348  return array_pop($this->disabled_stack);
349  }
350 }
$handler
Definition: add.php:7
$context
Definition: add.php:8
if(! $entity instanceof \ElggUser) $data
Definition: attributes.php:13
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.
Inject backtrace stack into the record.
Logger.
Definition: Logger.php:26
dump($data)
Dump data to log.
Definition: Logger.php:320
log($level, $message, array $context=[])
{}
Definition: Logger.php:234
notice($message, array $context=[])
{}
Definition: Logger.php:295
normalizeLevel($level=null)
Normalizes legacy string or numeric representation of the level to LogLevel strings.
Definition: Logger.php:136
getLevel($severity=true)
Get the current logging level severity.
Definition: Logger.php:205
emergency($message, array $context=[])
{}
Definition: Logger.php:260
alert($message, array $context=[])
{}
Definition: Logger.php:267
isLoggable($level)
Check if a level is loggable under current logging level.
Definition: Logger.php:220
enable()
Restore logging and get record of log calls (after tests)
Definition: Logger.php:347
debug($message, array $context=[])
{}
Definition: Logger.php:309
error($message, array $context=[])
{}
Definition: Logger.php:281
static factory(?InputInterface $input=null, ?OutputInterface $output=null)
Build a new logger.
Definition: Logger.php:78
critical($message, array $context=[])
{}
Definition: Logger.php:274
info($message, array $context=[])
{}
Definition: Logger.php:302
setLevel($level=null)
Set the logging level.
Definition: Logger.php:177
warning($message, array $context=[])
{}
Definition: Logger.php:288
disable()
Temporarily disable logging and capture logs (before tests)
Definition: Logger.php:336
$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