فهرست منبع

Add FallbackGroupHandler

Malachi Soord 6 سال پیش
والد
کامیت
ab236865a7

+ 5 - 0
doc/02-handlers-formatters-processors.md

@@ -108,6 +108,11 @@
    exceptions raised by each child handler. This allows you to ignore issues
    where a remote tcp connection may have died but you do not want your entire
    application to crash and may wish to continue to log to other handlers.
+- [_FallbackGroupHandler_](../src/Monolog/Handler/FallbackGroupHandler.php): This handler extends the _GroupHandler_ ignoring
+   exceptions raised by each child handler, until one has handled without throwing.
+   This allows you to ignore issues where a remote tcp connection may have died 
+   but you do not want your entire application to crash and may wish to continue 
+   to attempt log to other handlers, until one does not throw.
 - [_BufferHandler_](../src/Monolog/Handler/BufferHandler.php): This handler will buffer all the log records it receives
   until `close()` is called at which point it will call `handleBatch()` on the
   handler it wraps with all the log messages at once. This is very useful to

+ 63 - 0
src/Monolog/Handler/FallbackGroupHandler.php

@@ -0,0 +1,63 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Throwable;
+
+class FallbackGroupHandler extends GroupHandler
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function handle(array $record): bool
+    {
+        if ($this->processors) {
+            foreach ($this->processors as $processor) {
+                $record = call_user_func($processor, $record);
+            }
+        }
+        foreach ($this->handlers as $handler) {
+            try {
+                $handler->handle($record);
+                break;
+            } catch (Throwable $e) {
+                // What throwable?
+            }
+        }
+        return false === $this->bubble;
+    }
+    /**
+     * {@inheritdoc}
+     */
+    public function handleBatch(array $records): void
+    {
+        if ($this->processors) {
+            $processed = [];
+            foreach ($records as $record) {
+                foreach ($this->processors as $processor) {
+                    $record = call_user_func($processor, $record);
+                }
+                $processed[] = $record;
+            }
+            $records = $processed;
+        }
+
+        foreach ($this->handlers as $handler) {
+            try {
+                $handler->handleBatch($records);
+                break;
+            } catch (Throwable $e) {
+                // What throwable?
+            }
+        }
+    }
+}

+ 27 - 0
tests/Monolog/Handler/ExceptionTestHandler.php

@@ -0,0 +1,27 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Exception;
+
+class ExceptionTestHandler extends TestHandler
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function handle(array $record): bool
+    {
+        throw new Exception("ExceptionTestHandler::handle");
+
+        parent::handle($record);
+    }
+}

+ 141 - 0
tests/Monolog/Handler/FallbackGroupHandlerTest.php

@@ -0,0 +1,141 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+use Monolog\Test\TestCase;
+
+class FallbackGroupHandlerTest extends TestCase
+{
+    /**
+     * @covers Monolog\Handler\FallbackGroupHandler::__construct
+     * @covers Monolog\Handler\FallbackGroupHandler::handle
+     */
+    public function testHandle()
+    {
+        $testHandlerOne = new TestHandler();
+        $testHandlerTwo = new TestHandler();
+        $testHandlers = [$testHandlerOne, $testHandlerTwo];
+        $handler = new FallbackGroupHandler($testHandlers);
+        $handler->handle($this->getRecord(Logger::DEBUG));
+        $handler->handle($this->getRecord(Logger::INFO));
+
+        $this->assertCount(2, $testHandlerOne->getRecords());
+        $this->assertCount(0, $testHandlerTwo->getRecords());
+    }
+
+    /**
+     * @covers Monolog\Handler\FallbackGroupHandler::__construct
+     * @covers Monolog\Handler\FallbackGroupHandler::handle
+     */
+    public function testHandleExceptionThrown()
+    {
+        $testHandlerOne = new ExceptionTestHandler();
+        $testHandlerTwo = new TestHandler();
+        $testHandlers = [$testHandlerOne, $testHandlerTwo];
+        $handler = new FallbackGroupHandler($testHandlers);
+        $handler->handle($this->getRecord(Logger::DEBUG));
+        $handler->handle($this->getRecord(Logger::INFO));
+
+        $this->assertCount(0, $testHandlerOne->getRecords());
+        $this->assertCount(2, $testHandlerTwo->getRecords());
+    }
+
+    /**
+     * @covers Monolog\Handler\FallbackGroupHandler::handleBatch
+     */
+    public function testHandleBatch()
+    {
+        $testHandlerOne = new TestHandler();
+        $testHandlerTwo = new TestHandler();
+        $testHandlers = [$testHandlerOne, $testHandlerTwo];
+        $handler = new FallbackGroupHandler($testHandlers);
+        $handler->handleBatch([$this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)]);
+        $this->assertCount(2, $testHandlerOne->getRecords());
+        $this->assertCount(0, $testHandlerTwo->getRecords());
+    }
+
+    /**
+     * @covers Monolog\Handler\FallbackGroupHandler::handleBatch
+     */
+    public function testHandleBatchExceptionThrown()
+    {
+        $testHandlerOne = new ExceptionTestHandler();
+        $testHandlerTwo = new TestHandler();
+        $testHandlers = [$testHandlerOne, $testHandlerTwo];
+        $handler = new FallbackGroupHandler($testHandlers);
+        $handler->handleBatch([$this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)]);
+        $this->assertCount(0, $testHandlerOne->getRecords());
+        $this->assertCount(2, $testHandlerTwo->getRecords());
+    }
+
+    /**
+     * @covers Monolog\Handler\FallbackGroupHandler::isHandling
+     */
+    public function testIsHandling()
+    {
+        $testHandlers = [new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING)];
+        $handler = new FallbackGroupHandler($testHandlers);
+        $this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR)));
+        $this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING)));
+        $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
+    }
+
+    /**
+     * @covers Monolog\Handler\FallbackGroupHandler::handle
+     */
+    public function testHandleUsesProcessors()
+    {
+        $test = new TestHandler();
+        $handler = new FallbackGroupHandler([$test]);
+        $handler->pushProcessor(function ($record) {
+            $record['extra']['foo'] = true;
+
+            return $record;
+        });
+        $handler->handle($this->getRecord(Logger::WARNING));
+        $this->assertTrue($test->hasWarningRecords());
+        $records = $test->getRecords();
+        $this->assertTrue($records[0]['extra']['foo']);
+    }
+
+    /**
+     * @covers Monolog\Handler\FallbackGroupHandler::handleBatch
+     */
+    public function testHandleBatchUsesProcessors()
+    {
+        $testHandlerOne = new ExceptionTestHandler();
+        $testHandlerTwo = new TestHandler();
+        $testHandlers = [$testHandlerOne, $testHandlerTwo];
+        $handler = new FallbackGroupHandler($testHandlers);
+        $handler->pushProcessor(function ($record) {
+            $record['extra']['foo'] = true;
+
+            return $record;
+        });
+        $handler->pushProcessor(function ($record) {
+            $record['extra']['foo2'] = true;
+
+            return $record;
+        });
+        $handler->handleBatch([$this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)]);
+        $this->assertEmpty($testHandlerOne->getRecords());
+        $this->assertTrue($testHandlerTwo->hasDebugRecords());
+        $this->assertTrue($testHandlerTwo->hasInfoRecords());
+        $this->assertCount(2, $testHandlerTwo->getRecords());
+        $records = $testHandlerTwo->getRecords();
+        $this->assertTrue($records[0]['extra']['foo']);
+        $this->assertTrue($records[1]['extra']['foo']);
+        $this->assertTrue($records[0]['extra']['foo2']);
+        $this->assertTrue($records[1]['extra']['foo2']);
+    }
+}

+ 0 - 13
tests/Monolog/Handler/WhatFailureGroupHandlerTest.php

@@ -136,16 +136,3 @@ class WhatFailureGroupHandlerTest extends TestCase
         $this->assertTrue($records[0]['extra']['foo']);
     }
 }
-
-class ExceptionTestHandler extends TestHandler
-{
-    /**
-     * {@inheritdoc}
-     */
-    public function handle(array $record): bool
-    {
-        parent::handle($record);
-
-        throw new \Exception("ExceptionTestHandler::handle");
-    }
-}