Skip to content

Commit

Permalink
ENHANCEMENT Ensure 'trace' is captured for non-exceptions
Browse files Browse the repository at this point in the history
Fixes #693
  • Loading branch information
Damian Mooyman committed Nov 15, 2017
1 parent fd8c787 commit d787aed
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
15 changes: 13 additions & 2 deletions src/Monolog/ErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ErrorHandler
private $hasFatalErrorHandler;
private $fatalLevel;
private $reservedMemory;
private $lastFatalTrace;
private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);

public function __construct(LoggerInterface $logger)
Expand Down Expand Up @@ -152,10 +153,20 @@ public function handleError($code, $message, $file = '', $line = 0, $context = a
return;
}

/*
* http://php.net/manual/en/function.debug-backtrace.php
* As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added.
* Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'.
*/
$trace = debug_backtrace((PHP_VERSION_ID < 50306) ? 2 : DEBUG_BACKTRACE_IGNORE_ARGS);
array_shift($trace); // Exclude handleError from trace

// fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
$level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL;
$this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
$this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => $trace));
} else {
$this->lastFatalTrace = $trace;
}

if ($this->previousErrorHandler === true) {
Expand All @@ -177,7 +188,7 @@ public function handleFatalError()
$this->logger->log(
$this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel,
'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'])
array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace)
);

if ($this->logger instanceof Logger) {
Expand Down
8 changes: 6 additions & 2 deletions tests/Monolog/ErrorHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ public function testHandleError()
{
$logger = new Logger('test', array($handler = new TestHandler));
$errHandler = new ErrorHandler($logger);

$errHandler->registerErrorHandler(array(E_USER_NOTICE => Logger::EMERGENCY), false);

trigger_error('Foo', E_USER_ERROR);
$this->assertCount(1, $handler->getRecords());
$errorRecords = $handler->getRecords();
$this->assertCount(1, $errorRecords);
$this->assertNotEmpty($errorRecords[0]['context']['trace']);
$this->assertEquals(__FUNCTION__, $errorRecords[0]['context']['trace'][1]['function']);
$this->assertTrue($handler->hasErrorRecords());

trigger_error('Foo', E_USER_NOTICE);
$this->assertCount(2, $handler->getRecords());
$this->assertTrue($handler->hasEmergencyRecords());
Expand Down

0 comments on commit d787aed

Please sign in to comment.