* @link https://www.oxidmodule.com */ declare(strict_types=1); namespace D3\LoggerFactory; use Exception; use Monolog\Handler\AbstractHandler; use Monolog\Handler\AbstractProcessingHandler; use Monolog\Handler\BufferHandler; use Monolog\Handler\DeduplicationHandler; use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Handler\FingersCrossedHandler; use Monolog\Handler\RotatingFileHandler; use Monolog\Handler\StreamHandler; use Monolog\Logger; use OxidEsales\Eshop\Core\Registry; use RuntimeException; class LoggerFactory { public const SPECIAL_HANDLERS_BUFFERING = 'buffering'; public const SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY = 'logOnErrorOnly'; public const SPECIAL_HANDLERS_MAKE_UNIQUE = 'makeUnique'; public const BUFFERING_OPTION_LIMIT = 'bufferLimit'; public const BUFFERING_OPTION_LEVEL = 'loglevel'; public const LOGONERRORONLY_LEVEL = 'activationLevel'; public const MAKEUNIQUE_OPTION_LEVEL = 'loglevel'; public const MAKEUNIQUE_OPTION_TIME = 'time'; public static function create(): LoggerFactory { return new LoggerFactory(); } /** * @throws Exception */ public function getFileLogger( string $loggerName, string $filePath, int $logLevel = Logger::INFO, ?int $maxFiles = null, array $specialHandlers = [] ): Logger { $logger = new Logger($loggerName); $handler = $this->applySpecialHandlers( $this->getFileLoggerStreamHandler($filePath, $logLevel, $maxFiles), $specialHandlers ); $logger->pushHandler($handler); return $logger; } /** * @throws Exception */ public function getFileLoggerStreamHandler( string $filePath, int $logLevel = Logger::INFO, ?int $maxFiles = null ): AbstractProcessingHandler { return is_null($maxFiles) ? new StreamHandler($filePath, $logLevel) : new RotatingFileHandler($filePath, $maxFiles, $logLevel); } /** * @throws Exception */ public function getCombinedOxidAndFileLogger( string $loggerName, string $filePath, int $logLevel = Logger::INFO, ?int $maxFiles = null, array $specialHandlers = [] ): Logger { if (!class_exists(Registry::class)) { throw new RuntimeException(__METHOD__.' can executed in OXID eShop installations only'); } $logger = new Logger($loggerName); $handler = $this->applySpecialHandlers( $this->getFileLoggerStreamHandler($filePath, $logLevel, $maxFiles), $specialHandlers ); $logger->pushHandler($handler); $oxidLogFilePath = $this->getOxidLogPath('oxideshop.log'); $oxidHandler = $this->applySpecialHandlers( new StreamHandler($oxidLogFilePath, Logger::ERROR), $specialHandlers ); $logger->pushHandler($oxidHandler); return $logger; } protected function getOxidLogPath(string $fileName): string { if (!class_exists(Registry::class)) { throw new RuntimeException(__METHOD__.' can executed in OXID eShop installations only'); } return OX_BASE_PATH . '/log' . DIRECTORY_SEPARATOR . $fileName; } public function applySpecialHandlers( AbstractProcessingHandler $handler, array $specialHandlers = [] ): AbstractHandler { if (in_array(self::SPECIAL_HANDLERS_BUFFERING, $specialHandlers, true)) { $handler = $this->setBuffering($handler); } elseif (in_array(self::SPECIAL_HANDLERS_BUFFERING, array_keys($specialHandlers), true)) { $options = $specialHandlers[self::SPECIAL_HANDLERS_BUFFERING]; $handler = $this->setBuffering( $handler, $options[self::BUFFERING_OPTION_LIMIT] ?? 0, $options[self::BUFFERING_OPTION_LEVEL] ?? Logger::DEBUG ); } if (in_array(self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY, $specialHandlers, true)) { $handler = $this->setLogItemsOnErrorOnly($handler); } elseif (in_array(self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY, array_keys($specialHandlers), true)) { $options = $specialHandlers[self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY]; $handler = $this->setLogItemsOnErrorOnly( $handler, $options[self::LOGONERRORONLY_LEVEL] ?? Logger::ERROR ); } if (in_array(self::SPECIAL_HANDLERS_MAKE_UNIQUE, $specialHandlers, true)) { $handler = $this->makeUnique($handler); } elseif (in_array(self::SPECIAL_HANDLERS_MAKE_UNIQUE, array_keys($specialHandlers), true)) { $options = $specialHandlers[self::SPECIAL_HANDLERS_MAKE_UNIQUE]; $handler = $this->makeUnique( $handler, $options[self::MAKEUNIQUE_OPTION_LEVEL] ?? Logger::ERROR, $options[self::MAKEUNIQUE_OPTION_TIME] ?? 60 ); } return $handler; } public function setBuffering( AbstractHandler $handler, int $bufferLimit = 0, int $loglevel = Logger::DEBUG ): BufferHandler { return new BufferHandler($handler, $bufferLimit, $loglevel); } public function setLogItemsOnErrorOnly( AbstractHandler $handler, int $activationLevel = Logger::ERROR ): FingersCrossedHandler { return new FingersCrossedHandler( $handler, new ErrorLevelActivationStrategy($activationLevel) ); } public function makeUnique( AbstractHandler $handler, int $deduplicationLevel = Logger::ERROR, int $time = 60 ): DeduplicationHandler { return new DeduplicationHandler($handler, null, $deduplicationLevel, $time); } }