Browse Source

Make console logging allow application override

By providing a `Console` logger application developers can override
the framework defaults. This should help improve logging for console
commands in containerized environments.
Mark Story 2 years ago
parent
commit
39713efb17
2 changed files with 40 additions and 0 deletions
  1. 13 0
      src/Console/ConsoleIo.php
  2. 27 0
      tests/TestCase/Console/ConsoleIoTest.php

+ 13 - 0
src/Console/ConsoleIo.php

@@ -540,6 +540,10 @@ class ConsoleIo
      * If you don't wish all log output in stdout or stderr
      * through Cake's Log class, call this function with `$enable=false`.
      *
+     * If you would like to take full control of how console application logging
+     * to stdout works add a logger that uses `'className' => 'Console'`. By
+     * providing a console logger you replace the framework default behavior.
+     *
      * @param int|bool $enable Use a boolean to enable/toggle all logging. Use
      *   one of the verbosity constants (self::VERBOSE, self::QUIET, self::NORMAL)
      *   to control logging levels. VERBOSE enables debug logs, NORMAL does not include debug logs,
@@ -553,6 +557,15 @@ class ConsoleIo
         if ($enable === false) {
             return;
         }
+        // If the application has configured a console logger
+        // we don't add a redundant one.
+        foreach (Log::configured() as $loggerName) {
+            $log = Log::engine($loggerName);
+            if ($log instanceof ConsoleLog) {
+                return;
+            }
+        }
+
         $outLevels = ['notice', 'info'];
         if ($enable === static::VERBOSE || $enable === true) {
             $outLevels[] = 'debug';

+ 27 - 0
tests/TestCase/Console/ConsoleIoTest.php

@@ -77,6 +77,7 @@ class ConsoleIoTest extends TestCase
             $fs = new Filesystem();
             $fs->deleteDir(TMP . 'shell_test');
         }
+        Log::drop('console-logger');
     }
 
     /**
@@ -465,6 +466,32 @@ class ConsoleIoTest extends TestCase
     }
 
     /**
+     * Tests that setLoggers does not add loggers if the
+     * application already has a console logger. This
+     * lets developers opt-out of the default behavior
+     * by configuring something equivalent.
+     */
+    public function testSetLoggersWithCustom(): void
+    {
+        Log::drop('stdout');
+        Log::drop('stderr');
+        Log::setConfig('console-logger', [
+            'className' => 'Console',
+            'stream' => $this->out,
+            'types' => ['error', 'warning'],
+        ]);
+        $this->io->setLoggers(true);
+        $this->assertEmpty(Log::engine('stdout'));
+        $this->assertEmpty(Log::engine('stderr'));
+        $this->assertNotEmpty(Log::engine('console-logger'));
+
+        $this->io->setLoggers(false);
+        $this->assertNull(Log::engine('stdout'));
+        $this->assertNull(Log::engine('stderr'));
+        $this->assertNotEmpty(Log::engine('console-logger'));
+    }
+
+    /**
      * Tests that setLoggers works properly with quiet
      */
     public function testSetLoggersQuiet(): void