From 69a95de38d64c62aa4c3db0b433d6e4f8cbf695f Mon Sep 17 00:00:00 2001 From: Joby Harding Date: Tue, 19 Oct 2021 18:31:08 +0100 Subject: [PATCH] [8.x] Add method for on-demand log creation --- src/Illuminate/Log/LogManager.php | 29 ++++++++++++---- tests/Log/LogManagerTest.php | 55 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Log/LogManager.php b/src/Illuminate/Log/LogManager.php index 03c53e3f4e33..7e1aae8a66c3 100644 --- a/src/Illuminate/Log/LogManager.php +++ b/src/Illuminate/Log/LogManager.php @@ -110,12 +110,13 @@ public function getChannels() * Attempt to get the log from the local cache. * * @param string $name + * @param array|null $config * @return \Psr\Log\LoggerInterface */ - protected function get($name) + protected function get($name, ?array $config = null) { try { - return $this->channels[$name] ?? with($this->resolve($name), function ($logger) use ($name) { + return $this->channels[$name] ?? with($this->resolve($name, $config), function ($logger) use ($name) { return $this->channels[$name] = $this->tap($name, new Logger($logger, $this->app['events'])); }); } catch (Throwable $e) { @@ -180,13 +181,14 @@ protected function createEmergencyLogger() * Resolve the given log instance by name. * * @param string $name + * @param array|null $config * @return \Psr\Log\LoggerInterface * * @throws \InvalidArgumentException */ - protected function resolve($name) + protected function resolve($name, ?array $config = null) { - $config = $this->configurationFor($name); + $config = $config ?? $this->configurationFor($name); if (is_null($config)) { throw new InvalidArgumentException("Log [{$name}] is not defined."); @@ -242,11 +244,15 @@ protected function createStackDriver(array $config) } $handlers = collect($config['channels'])->flatMap(function ($channel) { - return $this->channel($channel)->getHandlers(); + return $channel instanceof LoggerInterface + ? $channel->getHandlers() + : $this->channel($channel)->getHandlers(); })->all(); $processors = collect($config['channels'])->flatMap(function ($channel) { - return $this->channel($channel)->getProcessors(); + return $channel instanceof LoggerInterface + ? $channel->getProcessors() + : $this->channel($channel)->getProcessors(); })->all(); if ($config['ignore_exceptions'] ?? false) { @@ -630,6 +636,17 @@ public function log($level, $message, array $context = []) $this->driver()->log($level, $message, $context); } + /** + * Build an on-demand channel. + * + * @param array $config + * @return \Psr\Log\LoggerInterface + */ + public function build(array $config) + { + return $this->get('ondemand', $config); + } + /** * Dynamically call the default driver instance. * diff --git a/tests/Log/LogManagerTest.php b/tests/Log/LogManagerTest.php index 4dfd9fb51e32..b460d6ec514f 100755 --- a/tests/Log/LogManagerTest.php +++ b/tests/Log/LogManagerTest.php @@ -13,6 +13,7 @@ use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogHandler; use Monolog\Logger as Monolog; +use Monolog\Processor\UidProcessor; use Orchestra\Testbench\TestCase; use ReflectionProperty; use RuntimeException; @@ -377,4 +378,58 @@ public function testLogManagerPurgeResolvedChannels() $this->assertEmpty($manager->getChannels()); } + + public function testLogManagerCanBuildOnDemandChannel() + { + $manager = new LogManager($this->app); + + $logger = $manager->build([ + 'driver' => 'single', + 'path' => storage_path('logs/on-demand.log'), + ]); + $handler = $logger->getLogger()->getHandlers()[0]; + + $this->assertInstanceOf(StreamHandler::class, $handler); + + $url = new ReflectionProperty(get_class($handler), 'url'); + $url->setAccessible(true); + + $this->assertSame(storage_path('logs/on-demand.log'), $url->getValue($handler)); + } + + public function testLogManagerCanUseOnDemandChannelInOnDemandStack() + { + $manager = new LogManager($this->app); + $this->app['config']->set('logging.channels.test', [ + 'driver' => 'single', + ]); + + $factory = new class() + { + public function __invoke() + { + return new Monolog( + 'uuid', + [new StreamHandler(storage_path('logs/custom.log'))], + [new UidProcessor()] + ); + } + }; + $channel = $manager->build([ + 'driver' => 'custom', + 'via' => get_class($factory), + ]); + $logger = $manager->stack(['test', $channel]); + + $handler = $logger->getLogger()->getHandlers()[1]; + $processor = $logger->getLogger()->getProcessors()[0]; + + $this->assertInstanceOf(StreamHandler::class, $handler); + $this->assertInstanceOf(UidProcessor::class, $processor); + + $url = new ReflectionProperty(get_class($handler), 'url'); + $url->setAccessible(true); + + $this->assertSame(storage_path('logs/custom.log'), $url->getValue($handler)); + } }