Просмотр исходного кода

Simplify addRecord further by doing a single foreach over all handlers, refs #1489

Jordi Boggiano 5 лет назад
Родитель
Сommit
df4d93f148
1 измененных файлов с 40 добавлено и 34 удалено
  1. 40 34
      src/Monolog/Logger.php

+ 40 - 34
src/Monolog/Logger.php

@@ -286,47 +286,53 @@ class Logger implements LoggerInterface, ResettableInterface
     public function addRecord(int $level, string $message, array $context = []): bool
     {
         $offset = 0;
-        foreach ($this->handlers as $handler) {
-            if ($handler->isHandling(['level' => $level])) {
-                break;
-            }
-
-            $offset++;
-        }
-        // cut off checked not handleable handlers
-        $remainedHandlers = array_slice($this->handlers, $offset);
+        $record = null;
 
-        if (!$remainedHandlers) {
-            return false;
-        }
-
-        $levelName = static::getLevelName($level);
-
-        $record = [
-            'message' => $message,
-            'context' => $context,
-            'level' => $level,
-            'level_name' => $levelName,
-            'channel' => $this->name,
-            'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
-            'extra' => [],
-        ];
+        foreach ($this->handlers as $handler) {
+            if (null === $record) {
+                // skip creating the record as long as no handler is going to handle it
+                if (!$handler->isHandling(['level' => $level])) {
+                    continue;
+                }
 
-        try {
-            foreach ($this->processors as $processor) {
-                $record = $processor($record);
+                $levelName = static::getLevelName($level);
+
+                $record = [
+                    'message' => $message,
+                    'context' => $context,
+                    'level' => $level,
+                    'level_name' => $levelName,
+                    'channel' => $this->name,
+                    'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
+                    'extra' => [],
+                ];
+
+                try {
+                    foreach ($this->processors as $processor) {
+                        $record = $processor($record);
+                    }
+                } catch (Throwable $e) {
+                    $this->handleException($e, $record);
+
+                    return true;
+                }
             }
 
-            foreach ($remainedHandlers as $handler) {
-                if (true === $handler->handle($record)) {
-                    break;
+            // once the record exist, send it to all handlers as long as the bubbling chain is not interrupted
+            if (null !== $record) {
+                try {
+                    if (true === $handler->handle($record)) {
+                        break;
+                    }
+                } catch (Throwable $e) {
+                    $this->handleException($e, $record);
+
+                    return true;
                 }
             }
-        } catch (Throwable $e) {
-            $this->handleException($e, $record);
         }
 
-        return true;
+        return null !== $record;
     }
 
     /**
@@ -407,7 +413,7 @@ class Logger implements LoggerInterface, ResettableInterface
             if (is_numeric($level)) {
                 return intval($level);
             }
-            
+
             // Contains chars of all log levels and avoids using strtoupper() which may have
             // strange results depending on locale (for example, "i" will become "İ" in Turkish locale)
             $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY');