From 00b36364e1be608d3db64b0abb1daf507b651d8c Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Tue, 2 Aug 2022 12:07:26 +0200 Subject: [PATCH] add separate logger to set the non restricted debug bar handler --- Application/Component/DebugBarComponent.php | 18 +- Application/Core/LoggerCascade.php | 242 ++++++++++++++++++++ Application/Core/LoggerNotSetException.php | 23 ++ Modules/functions.php | 29 ++- 4 files changed, 308 insertions(+), 4 deletions(-) create mode 100644 Application/Core/LoggerCascade.php create mode 100644 Application/Core/LoggerNotSetException.php diff --git a/Application/Component/DebugBarComponent.php b/Application/Component/DebugBarComponent.php index 8e24095..d97f231 100644 --- a/Application/Component/DebugBarComponent.php +++ b/Application/Component/DebugBarComponent.php @@ -15,6 +15,8 @@ declare(strict_types=1); namespace D3\DebugBar\Application\Component; +use D3\DebugBar\Application\Core\LoggerCascade; +use D3\DebugBar\Application\Core\LoggerNotSetException; use D3\DebugBar\Application\Models\Collectors\SmartyCollector; use D3\DebugBar\Application\Models\TimeDataCollectorHandler; use DebugBar\Bridge\DoctrineCollector; @@ -23,6 +25,7 @@ use DebugBar\DebugBarException; use DebugBar\JavascriptRenderer; use DebugBar\StandardDebugBar; use Doctrine\DBAL\Logging\DebugStack; +use Monolog\Logger; use OxidEsales\Eshop\Core\Controller\BaseController; use OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; @@ -70,8 +73,19 @@ class DebugBarComponent extends BaseController */ public function getMonologCollector(): MonologCollector { - $loggerWrapper = Registry::getLogger(); - $monolog = $this->getNonPublicProperty($loggerWrapper, 'logger'); + $logger = Registry::getLogger(); + + try { + if ( $logger instanceof LoggerCascade ) { + $monolog = $logger->getLogger( LoggerCascade::DEBUGBAR_LOGGER ); + } else { + /** @var Logger $monolog */ + $monolog = $this->getNonPublicProperty( $logger, 'logger' ); + } + } catch ( LoggerNotSetException $e ) { + $monolog = new Logger( 'nullLogger' ); + } + return new MonologCollector($monolog); } diff --git a/Application/Core/LoggerCascade.php b/Application/Core/LoggerCascade.php new file mode 100644 index 0000000..ec3aacc --- /dev/null +++ b/Application/Core/LoggerCascade.php @@ -0,0 +1,242 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DebugBar\Application\Core; + +use InvalidArgumentException; +use Monolog\Logger; +use Psr\Log\LoggerInterface; +use Stringable; + +class LoggerCascade implements LoggerInterface +{ + public const OXID_LOGGER = 'oxidLogger'; + public const DEBUGBAR_LOGGER = 'debugBarLogger'; + + /** + * List of all loggers in the registry (by named indexes) + * + * @var Logger[] + */ + private $loggers = array(); + + /** + * Adds new logging channel to the registry + * + * @param LoggerInterface $logger Instance of the logging channel + * @param string $name Name of the logging channel ($logger->getName() by default) + * @param bool $overwrite Overwrite instance in the registry if the given name already exists? + * @throws InvalidArgumentException If $overwrite set to false and named Logger instance already exists + * @return void + */ + public function addLogger(LoggerInterface $logger, $name, $overwrite = false): void + { + if (isset($this->loggers[$name]) && !$overwrite) { + throw new InvalidArgumentException('Logger with the given name already exists'); + } + + $this->loggers[$name] = $logger; + } + + /** + * Checks if such logging channel exists by name or instance + * + * @param string|Logger $logger Name or logger instance + * @return bool + */ + public function hasLogger($logger): bool + { + if ($logger instanceof LoggerInterface) { + $index = array_search($logger, $this->loggers, true); + + return false !== $index; + } else { + return isset($this->loggers[$logger]); + } + } + + /** + * Removes instance from registry by name or instance + * + * @param string|Logger $logger Name or logger instance + * @return void + */ + public function removeLogger($logger): void + { + if ($logger instanceof LoggerInterface) { + if (false !== ($idx = array_search($logger, $this->loggers, true))) { + unset($this->loggers[$idx]); + } + } else { + unset($this->loggers[$logger]); + } + } + + /** + * Clears the registry + * @return void + */ + public function clear(): void + { + $this->loggers = array(); + } + + /** + * + * @return Logger[] + */ + public function getLoggers(): array + { + return $this->loggers; + } + + /** + * @param $logger + * + * @return LoggerInterface + * @throws LoggerNotSetException + */ + public function getLogger($logger): LoggerInterface + { + if ($this->hasLogger($logger)) { + if ($logger instanceof LoggerInterface) { + $index = array_search($logger, $this->loggers, true); + + return $this->getLoggers()[$index]; + } else { + return $this->getLoggers()[$logger]; + } + } + + throw oxNew(LoggerNotSetException::class); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function emergency($message, array $context = [] ): bool + { + return $this->call('emergency', $message, $context); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function alert($message, array $context = [] ): bool + { + return $this->call('alert', $message, $context); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function critical($message, array $context = [] ): bool + { + return $this->call('critical', $message, $context); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function error($message, array $context = [] ): bool + { + return $this->call('error', $message, $context); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function warning($message, array $context = [] ): bool + { + return $this->call('warning', $message, $context); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function notice($message, array $context = [] ): bool + { + return $this->call('notice', $message, $context); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function info($message, array $context = [] ): bool + { + return $this->call('info', $message, $context); + } + + /** + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function debug($message, array $context = [] ): bool + { + return $this->call('debug', $message, $context); + } + + /** + * @param mixed $level + * @param string|Stringable $message + * @param array $context + * + * @return bool + */ + public function log( $level, $message, array $context = [] ): bool + { + return $this->call('log', $level, $message, $context); + } + + /** + * @param $method + * @param ...$arguments + * + * @return bool + */ + protected function call($method, ...$arguments): bool + { + $return = []; + + foreach ($this->getLoggers() as $logger) { + $return[] = call_user_func_array([$logger, $method], $arguments); + } + + return false === in_array(false, $return); + } +} \ No newline at end of file diff --git a/Application/Core/LoggerNotSetException.php b/Application/Core/LoggerNotSetException.php new file mode 100644 index 0000000..a68f1f0 --- /dev/null +++ b/Application/Core/LoggerNotSetException.php @@ -0,0 +1,23 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DebugBar\Application\Core; + +use OxidEsales\Eshop\Core\Exception\StandardException; + +class LoggerNotSetException extends StandardException +{ + +} \ No newline at end of file diff --git a/Modules/functions.php b/Modules/functions.php index d6df5d8..aa1a086 100644 --- a/Modules/functions.php +++ b/Modules/functions.php @@ -13,13 +13,21 @@ declare(strict_types=1); +use D3\DebugBar\Application\Core\LoggerCascade; +use D3\DebugBar\Application\Models\TimeDataCollectorHandler; +use Monolog\Logger; +use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Log\LoggerInterface; + function startProfile($sProfileName) { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); $trace[0] = $sProfileName; $hash = md5(serialize($trace)).'-'.$sProfileName; - $timeDataCollector = \D3\DebugBar\Application\Models\TimeDataCollectorHandler::getInstance(); + $timeDataCollector = TimeDataCollectorHandler::getInstance(); $timeDataCollector->startMeasure($hash, $sProfileName); global $aStartTimes; @@ -40,7 +48,7 @@ function stopProfile($sProfileName) $trace[0] = $sProfileName; $hash = md5(serialize($trace)).'-'.$sProfileName; - $timeDataCollector = \D3\DebugBar\Application\Models\TimeDataCollectorHandler::getInstance(); + $timeDataCollector = TimeDataCollectorHandler::getInstance(); $timeDataCollector->stopMeasure($hash); @@ -54,4 +62,21 @@ function stopProfile($sProfileName) } $executionCounts[$sProfileName]++; $aStartTimes[$sProfileName] = microtime(true); +} + +/** + * @return LoggerCascade + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ +function getLogger(): LoggerCascade +{ + $container = ContainerFactory::getInstance()->getContainer(); + $logger = $container->get( LoggerInterface::class); + + $cascade = new LoggerCascade(); + $cascade->addLogger($logger, LoggerCascade::OXID_LOGGER); + $cascade->addLogger(new Logger(LoggerCascade::DEBUGBAR_LOGGER), LoggerCascade::DEBUGBAR_LOGGER); + + return $cascade; } \ No newline at end of file