diff --git a/src/Commands/DrushCommands.php b/src/Commands/DrushCommands.php index 92f1dc74d6..f901645fcc 100644 --- a/src/Commands/DrushCommands.php +++ b/src/Commands/DrushCommands.php @@ -2,6 +2,7 @@ namespace Drush\Commands; +use Drush\Log\DrushLoggerManager; use Drush\Log\Logger; use Symfony\Component\Console\Style\SymfonyStyle; use Consolidation\AnnotatedCommand\CommandData; @@ -63,7 +64,7 @@ protected function io(): SymfonyStyle /** * Returns a logger object. */ - protected function logger(): ?Logger + protected function logger(): ?DrushLoggerManager { return $this->logger; } diff --git a/src/Log/DrushLoggerManager.php b/src/Log/DrushLoggerManager.php new file mode 100644 index 0000000000..bb7a8422de --- /dev/null +++ b/src/Log/DrushLoggerManager.php @@ -0,0 +1,14 @@ +log(ConsoleLogLevel::SUCCESS, $message, $context); + } +} diff --git a/src/Log/Logger.php b/src/Log/Logger.php index 3c09938895..9078c7598b 100644 --- a/src/Log/Logger.php +++ b/src/Log/Logger.php @@ -20,12 +20,11 @@ namespace Drush\Log; -use Consolidation\Log\ConsoleLogLevel; use Drush\Drush; use Robo\Log\RoboLogger; use Symfony\Component\Console\Output\OutputInterface; -class Logger extends RoboLogger implements SuccessInterface +class Logger extends RoboLogger { public function __construct(OutputInterface $output) { @@ -73,9 +72,4 @@ public static function formatSize($size) return str_replace('@size', round($size, 2), $unit); } } - - public function success($message, array $context = array()) - { - $this->log(ConsoleLogLevel::SUCCESS, $message, $context); - } } diff --git a/src/Runtime/DependencyInjection.php b/src/Runtime/DependencyInjection.php index 298a25d300..7d77239f1e 100644 --- a/src/Runtime/DependencyInjection.php +++ b/src/Runtime/DependencyInjection.php @@ -2,6 +2,7 @@ namespace Drush\Runtime; +use Drush\Log\Logger; use League\Container\Container; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\ConsoleOutput; @@ -63,7 +64,7 @@ public function initContainer( $container = new Container(); // With league/container 3.x, first call wins, so add Drush services first. - $this->addDrushServices($container, $loader, $drupalFinder, $aliasManager, $config); + $this->addDrushServices($container, $loader, $drupalFinder, $aliasManager, $config, $output); // Robo has the same signature for configureContainer in 1.x, 2.x and 3.x. Robo::configureContainer($container, $application, $config, $input, $output); @@ -93,12 +94,12 @@ public function installHandlers($container): void } // Add Drush Services to league/container 3.x - protected function addDrushServices($container, ClassLoader $loader, DrupalFinder $drupalFinder, SiteAliasManager $aliasManager, DrushConfig $config): void + protected function addDrushServices($container, ClassLoader $loader, DrupalFinder $drupalFinder, SiteAliasManager $aliasManager, DrushConfig $config, OutputInterface $output): void { - // Override Robo's logger with our own - $container->share('logger', 'Drush\Log\Logger') - ->addArgument('output') - ->addMethodCall('setLogOutputStyler', ['logStyler']); + // Override Robo's logger with a LoggerManager that delegates to the Drush logger. + $container->share('logger', '\Drush\Log\DrushLoggerManager') + ->addMethodCall('setLogOutputStyler', ['logStyler']) + ->addMethodCall('add', ['drush', new Logger($output)]); $container->share('loader', $loader); $container->share('site.alias.manager', $aliasManager); diff --git a/sut/drush/Commands/SimpleSutCommands.php b/sut/drush/Commands/SimpleSutCommands.php index 06b6087236..ffccfcbc4a 100644 --- a/sut/drush/Commands/SimpleSutCommands.php +++ b/sut/drush/Commands/SimpleSutCommands.php @@ -5,8 +5,12 @@ use Consolidation\AnnotatedCommand\CommandData; use Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface; use Consolidation\AnnotatedCommand\Events\CustomEventAwareTrait; +use Consolidation\Log\ConsoleLogLevel; use Consolidation\OutputFormatters\StructuredData\RowsOfFields; +use Drush\Drush; +use Drush\Symfony\DrushArgvInput; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Logger\ConsoleLogger; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Drush\Commands\DrushCommands; @@ -21,7 +25,7 @@ class SimpleSutCommands extends DrushCommands { /** - * Show a fabulous picture. + * Show a message. * * @command sut:simple * @hidden @@ -30,4 +34,23 @@ public function example() { $this->logger()->notice(dt("This is an example site-wide command committed to the repository in the SUT inside of the 'drush/Commands' directory.")); } + + /** + * Replace Drush logger with a custom one. + * + * In a real-world implementation, you would likely use `@hook *` instead of `@hook sut:simple`. + * + * @hook init sut:simple + */ + public function customLogger(DrushArgvInput $argv, AnnotationData $annotationData): void + { + $verbosityLevelMap = [ConsoleLogLevel::SUCCESS => OutputInterface::VERBOSITY_NORMAL]; + $formatLevelMap = [ConsoleLogLevel::SUCCESS => \Psr\Log\LogLevel::INFO]; + // One could use Monolog if desired. + // Drush expects custom loggers to always write to stderr, so dont use ConsoleLogger directly, + $newLogger = new ConsoleLogger(Drush::output(), $verbosityLevelMap, $formatLevelMap); + $drushLoggerManager = $this->logger(); + $drushLoggerManager->reset()->add('foo', $newLogger); + } } + diff --git a/tests/integration/CustomLoggerTest.php b/tests/integration/CustomLoggerTest.php new file mode 100644 index 0000000000..98ca6fd0a6 --- /dev/null +++ b/tests/integration/CustomLoggerTest.php @@ -0,0 +1,17 @@ +drush('version', [], ['debug' => true]); + $this->assertStringContainsString('sec', $this->getErrorOutputRaw()); + + // sut:simple has been hooked so that a custom logger is use. It doesn't show timing information during --debug. + $this->drush('sut:simple', [], ['debug' => true, 'simulate' => true]); + $this->assertStringNotContainsString('sec', $this->getOutput()); + } +}