diff --git a/.gitignore b/.gitignore index 85e33e3..fa545f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ vendor/ .phpunit.result.cache -composer.lock \ No newline at end of file +composer.lock +.vscode/ diff --git a/Middleware/ContextProcessor.php b/Middleware/ContextProcessor.php index 03ee40f..d6f5818 100644 --- a/Middleware/ContextProcessor.php +++ b/Middleware/ContextProcessor.php @@ -20,10 +20,19 @@ class ContextProcessor implements MiddlewareInterface */ public function process($level, $message, $context): array { + if ($context instanceof ContextualInterface) { + $context = $context->getContext(); + } + + if ($message instanceof \Throwable && $message->getPrevious() && $message->getPrevious() instanceof \Throwable) { + [$previousMessage, $context] = $this->process($level, $message->getPrevious(), $context); + } + if ($message instanceof ContextualInterface) { $context = array_merge($context, $message->getContext()); } + return [$message, $context]; } } diff --git a/Middleware/ExceptionCodeProcessor.php b/Middleware/ExceptionCodeProcessor.php index 69613e0..739c7c3 100644 --- a/Middleware/ExceptionCodeProcessor.php +++ b/Middleware/ExceptionCodeProcessor.php @@ -12,18 +12,27 @@ class ExceptionCodeProcessor implements MiddlewareInterface { /** - * @param string $level - * @param mixed $message - * @param array $context + * @param string $level + * @param mixed $message + * @param array $context + * @param bool|false $nesting * * @return array */ - public function process($level, $message, $context): array + public function process($level, $message, $context, $nesting=false): array { + if ($message instanceof \Throwable && $message->getPrevious() && $message->getPrevious() instanceof \Throwable) { + $nesting = true; + [$previousMessage, $context] = $this->process($level, $message->getPrevious(), $context, true); + } + if ($message instanceof \Throwable) { $context = array_merge($context, [ 'code' => $message->getCode(), ]); + if ($nesting) { + $context['codes'] = array_merge([$message->getCode()], $context['codes'] ?? []); + } } return [$message, $context]; diff --git a/Tests/Middleware/ContextProcessorTest.php b/Tests/Middleware/ContextProcessorTest.php new file mode 100644 index 0000000..8d9b505 --- /dev/null +++ b/Tests/Middleware/ContextProcessorTest.php @@ -0,0 +1,155 @@ + + * + * @covers \KoderHut\OnelogBundle\Middleware\ContextProcessor + */ +class ContextProcessorTest extends TestCase +{ + /** + * @test + */ + public function testProcessWithException() + { + $processor = new ContextProcessor(); + + $exception = new class extends \Exception implements ContextualInterface { + use ContextualTrait; + }; + $exception->setContext(['this is' => 'the context']); + + $processed = $processor->process('debug', $exception, []); + + $this->assertEquals([ + $exception, + [ + 'this is' => 'the context' + ]], + $processed + ); + } + + /** + * @test + */ + public function testProcessWithExceptionAndContext() + { + $processor = new ContextProcessor(); + + $exception = new class extends \Exception implements ContextualInterface { + use ContextualTrait; + }; + $exception->setContext(['this is' => 'the context']); + + $processed = $processor->process('debug', $exception, ['and this is' => 'another context']); + + $this->assertEquals([ + $exception, + [ + 'this is' => 'the context', + 'and this is' => 'another context', + ]], + $processed + ); + } + + /** + * @test + */ + public function testProcessWithNestedException() + { + $processor = new ContextProcessor(); + + $grandChildException = new class('grand child exception') extends \Exception implements ContextualInterface { + use ContextualTrait; + }; + $childException = new class('child exception', 0, $grandChildException) extends \Exception implements ContextualInterface { + use ContextualTrait; + }; + $parentException = new class('parent exception', 0, $childException) extends \Exception implements ContextualInterface { + use ContextualTrait; + }; + + $parentException->setContext(['this is1' => '1the context']); + $childException->setContext(['this is2' => '2the context']); + $grandChildException->setContext(['this is3' => '3the context']); + + $processed = $processor->process('debug', $parentException, ['and this is' => 'another context']); + + $this->assertEquals([ + $parentException, + [ + 'and this is' => 'another context', + 'this is1' => '1the context', + 'this is2' => '2the context', + 'this is3' => '3the context', + ]], + $processed + ); + } + + /** + * @test + */ + public function testProcessWithClassContext() + { + $processor = new ContextProcessor(); + + $classWithContext = new class() implements ContextualInterface { + use ContextualTrait; + }; + + $classWithContext->setContext(['this is1' => '1the context']); + + $processed = $processor->process('debug', $classWithContext, []); + + $this->assertEquals([ + $classWithContext, + [ + 'this is1' => '1the context', + ]], + $processed + ); + } + + /** + * @test + */ + public function testProcessWithNestedClassContext() + { + $processor = new ContextProcessor(); + + $classWithContext = new class() implements ContextualInterface { + use ContextualTrait; + }; + + $classWithContext->setContext(['this is1' => '1the context']); + + $secondClassWithContext = new class() implements ContextualInterface { + use ContextualTrait; + }; + + $secondClassWithContext->setContext($classWithContext); + + + $processed = $processor->process('debug', $secondClassWithContext, []); + + $this->assertEquals([ + $secondClassWithContext, + [ + 'this is1' => '1the context', + ]], + $processed + ); + } +} diff --git a/Tests/Middleware/ExceptionCodeProcessorTest.php b/Tests/Middleware/ExceptionCodeProcessorTest.php new file mode 100644 index 0000000..d58bec6 --- /dev/null +++ b/Tests/Middleware/ExceptionCodeProcessorTest.php @@ -0,0 +1,59 @@ + + * + * @covers \KoderHut\OnelogBundle\Middleware\ExceptionCodeProcessor + */ +class ExceptionCodeProcessorTest extends TestCase +{ + /** + * @test + */ + public function testProcessWithException() + { + $processor = new ExceptionCodeProcessor(); + + $parentException = new \Exception('parent exception', 204); + + $processed = $processor->process('debug', $parentException, []); + + $this->assertEquals([ + $parentException, + [ + 'code' => 204 + ]], + $processed + ); + } + + /** + * @test + */ + public function testProcessWithNestedExceptions() + { + $processor = new ExceptionCodeProcessor(); + + $grandChildException = new \Exception('grand child exception', 202); + $childException = new \Exception('child exception', 203, $grandChildException); + $parentException = new \Exception('parent exception', 204, $childException); + + $processed = $processor->process('debug', $parentException, []); + + $this->assertEquals([ + $parentException, + [ + 'codes' => [204, 203, 202], + 'code' => 204 + ]], + $processed + ); + } +} diff --git a/Tests/Middleware/SimpleMessageProcessorTest.php b/Tests/Middleware/SimpleMessageProcessorTest.php new file mode 100644 index 0000000..01ede21 --- /dev/null +++ b/Tests/Middleware/SimpleMessageProcessorTest.php @@ -0,0 +1,30 @@ + + * + * @covers \KoderHut\OnelogBundle\Middleware\SimpleMessageProcessor + */ +class SimpleMessageProcessorTest extends TestCase +{ + /** + * @test + */ + public function testProcess() + { + $processor = new SimpleMessageProcessor(); + + $simpleException = new \Exception('simple exception'); + + $processed = $processor->process('debug', $simpleException, []); + + $this->assertEquals($processed[0], 'simple exception'); + } +} diff --git a/Tests/Middleware/StackTraceProcessorTest.php b/Tests/Middleware/StackTraceProcessorTest.php new file mode 100644 index 0000000..9a74d3b --- /dev/null +++ b/Tests/Middleware/StackTraceProcessorTest.php @@ -0,0 +1,36 @@ + + * + * @covers \KoderHut\OnelogBundle\Middleware\StackTraceProcessor + */ +class StackTraceProcessorTest extends TestCase +{ + /** + * @test + */ + public function testProcess() + { + $processor = new StackTraceProcessor(); + + $parentException = new \Exception('parent exception', 204); + + try { + throw $parentException; + } catch (\Exception $exc) { + } + + $processed = $processor->process('debug', $parentException, []); + + $this->assertNotEmpty($parentException); + $this->assertTrue(count($processed[1]) > 0); + } +}