From 2d9c905b76eb6103eb089c2fcde15538593106c7 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 15 Nov 2017 18:05:17 +1300 Subject: [PATCH 1/2] ENHANCEMENT Ensure 'trace' is captured for non-exceptions Fixes #693 --- src/Monolog/ErrorHandler.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Monolog/ErrorHandler.php b/src/Monolog/ErrorHandler.php index 7bfcd833..b3025738 100644 --- a/src/Monolog/ErrorHandler.php +++ b/src/Monolog/ErrorHandler.php @@ -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) @@ -156,6 +157,13 @@ class ErrorHandler 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)); + } else { + // 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 + $this->lastFatalTrace = $trace; } if ($this->previousErrorHandler === true) { @@ -177,7 +185,7 @@ class ErrorHandler $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) { From e8db808dd3e079c194f6f4dbdb06cf5758b0d0f6 Mon Sep 17 00:00:00 2001 From: Klemen Bratec Date: Mon, 18 Jun 2018 11:31:46 +0200 Subject: [PATCH 2/2] Allow setting stream chunk size in SocketHandler (#1129) --- src/Monolog/Handler/SocketHandler.php | 39 +++++++++++++++++++++ tests/Monolog/Handler/SocketHandlerTest.php | 26 ++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php index 79d49ece..db50d97f 100644 --- a/src/Monolog/Handler/SocketHandler.php +++ b/src/Monolog/Handler/SocketHandler.php @@ -27,6 +27,7 @@ class SocketHandler extends AbstractProcessingHandler private $timeout = 0; private $writingTimeout = 10; private $lastSentBytes = null; + private $chunkSize = null; private $persistent = false; private $errno; private $errstr; @@ -127,6 +128,16 @@ class SocketHandler extends AbstractProcessingHandler $this->writingTimeout = (float) $seconds; } + /** + * Set chunk size. Only has effect during connection in the writing cycle. + * + * @param float $bytes + */ + public function setChunkSize($bytes) + { + $this->chunkSize = $bytes; + } + /** * Get current connection string * @@ -177,6 +188,16 @@ class SocketHandler extends AbstractProcessingHandler return $this->writingTimeout; } + /** + * Get current chunk size + * + * @return float + */ + public function getChunkSize() + { + return $this->chunkSize; + } + /** * Check to see if the socket is currently available. * @@ -219,6 +240,16 @@ class SocketHandler extends AbstractProcessingHandler return stream_set_timeout($this->resource, $seconds, $microseconds); } + /** + * Wrapper to allow mocking + * + * @see http://php.net/manual/en/function.stream-set-chunk-size.php + */ + protected function streamSetChunkSize() + { + return stream_set_chunk_size($this->resource, $this->chunkSize); + } + /** * Wrapper to allow mocking */ @@ -268,6 +299,7 @@ class SocketHandler extends AbstractProcessingHandler { $this->createSocketResource(); $this->setSocketTimeout(); + $this->setStreamChunkSize(); } private function createSocketResource() @@ -290,6 +322,13 @@ class SocketHandler extends AbstractProcessingHandler } } + private function setStreamChunkSize() + { + if ($this->chunkSize && !$this->streamSetChunkSize()) { + throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()"); + } + } + private function writeToSocket($data) { $length = strlen($data); diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index 1f9c1f28..1da987c9 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -77,6 +77,13 @@ class SocketHandlerTest extends TestCase $this->assertEquals(10.25, $this->handler->getWritingTimeout()); } + public function testSetChunkSize() + { + $this->createHandler('localhost:1234'); + $this->handler->setChunkSize(1025); + $this->assertEquals(1025, $this->handler->getChunkSize()); + } + public function testSetConnectionString() { $this->createHandler('tcp://localhost:9090'); @@ -120,6 +127,19 @@ class SocketHandlerTest extends TestCase $this->writeRecord('Hello world'); } + /** + * @expectedException UnexpectedValueException + */ + public function testExceptionIsThrownIfCannotSetChunkSize() + { + $this->setMockHandler(array('streamSetChunkSize')); + $this->handler->setChunkSize(8192); + $this->handler->expects($this->once()) + ->method('streamSetChunkSize') + ->will($this->returnValue(false)); + $this->writeRecord('Hello world'); + } + /** * @expectedException RuntimeException */ @@ -304,6 +324,12 @@ class SocketHandlerTest extends TestCase ->will($this->returnValue(true)); } + if (!in_array('streamSetChunkSize', $methods)) { + $this->handler->expects($this->any()) + ->method('streamSetChunkSize') + ->will($this->returnValue(8192)); + } + $this->handler->setFormatter($this->getIdentityFormatter()); } }