Merge pull request #14882 from Art4/refractor-logger-factories

Rework logger factories
This commit is contained in:
Philipp 2025-04-27 02:15:48 +02:00 committed by GitHub
commit ffb621f0e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 513 additions and 108 deletions

View file

@ -12,6 +12,8 @@ use Psr\Log\LogLevel;
/**
* Abstract class for creating logger types, which includes common necessary logic/content
*
* @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead
*/
abstract class AbstractLoggerTypeFactory
{
@ -25,6 +27,8 @@ abstract class AbstractLoggerTypeFactory
*/
public function __construct(IHaveCallIntrospections $introspection, string $channel)
{
@trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED);
$this->channel = $channel;
$this->introspection = $introspection;
}
@ -44,21 +48,21 @@ abstract class AbstractLoggerTypeFactory
// legacy WARNING
case "0":
return LogLevel::ERROR;
// legacy INFO
// legacy INFO
case "1":
return LogLevel::WARNING;
// legacy TRACE
// legacy TRACE
case "2":
return LogLevel::NOTICE;
// legacy DEBUG
// legacy DEBUG
case "3":
return LogLevel::INFO;
// legacy DATA
// legacy DATA
case "4":
// legacy ALL
// legacy ALL
case "5":
return LogLevel::DEBUG;
// default if nothing set
// default if nothing set
default:
return $level;
}

View file

@ -0,0 +1,73 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
/**
* Delegates the creation of a logger based on config to other factories
*
* @internal
*/
final class DelegatingLoggerFactory implements LoggerFactory
{
private IManageConfigValues $config;
/** @var array<string,LoggerFactory> */
private array $factories = [];
public function __construct(IManageConfigValues $config)
{
$this->config = $config;
}
public function registerFactory(string $name, LoggerFactory $factory): void
{
$this->factories[$name] = $factory;
}
/**
* Creates and returns a PSR-3 Logger instance.
*
* Calling this method multiple times with the same parameters SHOULD return the same object.
*
* @param \Psr\Log\LogLevel::* $logLevel The log level
* @param \Friendica\Core\Logger\Capability\LogChannel::* $logChannel The log channel
*/
public function createLogger(string $logLevel, string $logChannel): LoggerInterface
{
$factoryName = $this->config->get('system', 'logger_config') ?? '';
/**
* @deprecated 2025.02 The value `monolog` for `system.logger_config` inside the `config/local.config.php` file is deprecated, please use `stream` or `syslog` instead.
*/
if ($factoryName === 'monolog') {
@trigger_error('The config `system.logger_config` with value `monolog` is deprecated since 2025.02 and will stop working in 5 months, please change the value to `stream` or `syslog` in the `config/local.config.php` file.', \E_USER_DEPRECATED);
$factoryName = 'stream';
}
if (!array_key_exists($factoryName, $this->factories)) {
return new NullLogger();
}
$factory = $this->factories[$factoryName];
try {
$logger = $factory->createLogger($logLevel, $logChannel);
} catch (\Throwable $th) {
return new NullLogger();
}
return $logger;
}
}

View file

@ -1,61 +0,0 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
/**
* Bridge for the legacy Logger factory.
*
* This class can be removed after the following classes are replaced or
* refactored implementing the `\Friendica\Core\Logger\Factory\LoggerFactory`:
*
* - Friendica\Core\Logger\Factory\StreamLogger
* - Friendica\Core\Logger\Factory\SyslogLogger
* - monolog addon: Friendica\Addon\monolog\src\Factory\Monolog
*
* @see \Friendica\Core\Logger\Factory\StreamLogger
* @see \Friendica\Core\Logger\Factory\SyslogLogger
*
* @internal
*/
final class LegacyLoggerFactory implements LoggerFactory
{
private ICanCreateInstances $instanceCreator;
private IManageConfigValues $config;
private Profiler $profiler;
public function __construct(ICanCreateInstances $instanceCreator, IManageConfigValues $config, Profiler $profiler)
{
$this->instanceCreator = $instanceCreator;
$this->config = $config;
$this->profiler = $profiler;
}
/**
* Creates and returns a PSR-3 Logger instance.
*
* Calling this method multiple times with the same parameters SHOULD return the same object.
*
* @param \Psr\Log\LogLevel::* $logLevel The log level
* @param \Friendica\Core\Logger\Capability\LogChannel::* $logChannel The log channel
*/
public function createLogger(string $logLevel, string $logChannel): LoggerInterface
{
$factory = new Logger($logChannel);
return $factory->create($this->instanceCreator, $this->config, $this->profiler);
}
}

View file

@ -18,6 +18,8 @@ use Throwable;
/**
* The logger factory for the core logging instances
*
* @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead
*/
class Logger
{
@ -26,6 +28,8 @@ class Logger
public function __construct(string $channel = LogChannel::DEFAULT)
{
@trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED);
$this->channel = $channel;
}

View file

@ -20,6 +20,8 @@ use Psr\Log\NullLogger;
/**
* The logger factory for the StreamLogger instance
*
* @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead
* @see StreamLoggerFactory
* @see StreamLoggerClass
*/
class StreamLogger extends AbstractLoggerTypeFactory
@ -38,6 +40,8 @@ class StreamLogger extends AbstractLoggerTypeFactory
*/
public function create(IManageConfigValues $config, string $logfile = null, string $channel = null): LoggerInterface
{
@trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED);
$fileSystem = new FileSystem();
$logfile = $logfile ?? $config->get('system', 'logfile');

View file

@ -0,0 +1,76 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LoggerArgumentException;
use Friendica\Core\Logger\Exception\LogLevelException;
use Friendica\Core\Logger\Type\StreamLogger;
use Friendica\Core\Logger\Util\FileSystemUtil;
use Psr\Log\LoggerInterface;
/**
* The logger factory for the StreamLogger instance
*
* @see StreamLogger
*
* @internal
*/
final class StreamLoggerFactory implements LoggerFactory
{
private IManageConfigValues $config;
private IHaveCallIntrospections $introspection;
private FileSystemUtil $fileSystem;
public function __construct(
IManageConfigValues $config,
IHaveCallIntrospections $introspection,
FileSystemUtil $fileSystem
) {
$this->config = $config;
$this->introspection = $introspection;
$this->fileSystem = $fileSystem;
}
/**
* Creates and returns a PSR-3 Logger instance.
*
* Calling this method multiple times with the same parameters SHOULD return the same object.
*
* @param \Psr\Log\LogLevel::* $logLevel The log level
* @param \Friendica\Core\Logger\Capability\LogChannel::* $logChannel The log channel
*
* @throws LoggerArgumentException
* @throws LogLevelException
*/
public function createLogger(string $logLevel, string $logChannel): LoggerInterface
{
$logfile = $this->config->get('system', 'logfile');
if (!file_exists($logfile) || !is_writable($logfile)) {
throw new LoggerArgumentException(sprintf('"%s" is not a valid logfile.', $logfile));
}
if (! array_key_exists($logLevel, StreamLogger::levelToInt)) {
throw new LogLevelException(sprintf('The log level "%s" is not supported by "%s".', $logLevel, StreamLogger::class));
}
return new StreamLogger(
$logChannel,
$this->introspection,
$this->fileSystem->createStream($logfile),
StreamLogger::levelToInt[$logLevel],
getmypid()
);
}
}

View file

@ -16,6 +16,8 @@ use Psr\Log\LoggerInterface;
/**
* The logger factory for the SyslogLogger instance
*
* @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead
* @see SyslogLoggerFactory
* @see SyslogLoggerClass
*/
class SyslogLogger extends AbstractLoggerTypeFactory
@ -31,6 +33,8 @@ class SyslogLogger extends AbstractLoggerTypeFactory
*/
public function create(IManageConfigValues $config): LoggerInterface
{
@trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED);
$logOpts = $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS;
$logFacility = $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY;
$loglevel = SyslogLogger::mapLegacyConfigDebugLevel($config->get('system', 'loglevel'));

View file

@ -0,0 +1,66 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LogLevelException;
use Friendica\Core\Logger\Type\SyslogLogger;
use Psr\Log\LoggerInterface;
/**
* The logger factory for the SyslogLogger instance
*
* @see SyslogLogger
*
* @internal
*/
final class SyslogLoggerFactory implements LoggerFactory
{
private IManageConfigValues $config;
private IHaveCallIntrospections $introspection;
public function __construct(
IManageConfigValues $config,
IHaveCallIntrospections $introspection
) {
$this->config = $config;
$this->introspection = $introspection;
}
/**
* Creates and returns a PSR-3 Logger instance.
*
* Calling this method multiple times with the same parameters SHOULD return the same object.
*
* @param \Psr\Log\LogLevel::* $logLevel The log level
* @param \Friendica\Core\Logger\Capability\LogChannel::* $logChannel The log channel
*
* @throws LogLevelException
*/
public function createLogger(string $logLevel, string $logChannel): LoggerInterface
{
$logOpts = (string) $this->config->get('system', 'syslog_flags') ?? SyslogLogger::DEFAULT_FLAGS;
$logFacility = (string) $this->config->get('system', 'syslog_facility') ?? SyslogLogger::DEFAULT_FACILITY;
if (!array_key_exists($logLevel, SyslogLogger::logLevels)) {
throw new LogLevelException(sprintf('The log level "%s" is not supported by "%s".', $logLevel, SyslogLogger::class));
}
return new SyslogLogger(
$logChannel,
$this->introspection,
(string) SyslogLogger::logLevels[$logLevel],
$logOpts,
$logFacility
);
}
}

View file

@ -12,7 +12,7 @@ use Friendica\Core\Logger\Exception\LoggerUnusableException;
/**
* Util class for filesystem manipulation for Logger classes
*/
class FileSystem
class FileSystem implements FileSystemUtil
{
/**
* @var string a error message
@ -31,7 +31,7 @@ class FileSystem
public function createDir(string $file): string
{
$dirname = null;
$pos = strpos($file, '://');
$pos = strpos($file, '://');
if (!$pos) {
$dirname = realpath(dirname($file));

View file

@ -0,0 +1,40 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
namespace Friendica\Core\Logger\Util;
use Friendica\Core\Logger\Exception\LoggerUnusableException;
/**
* interface for Util class for filesystem manipulation for Logger classes
*
* @internal
*/
interface FileSystemUtil
{
/**
* Creates a directory based on a file, which gets accessed
*
* @param string $file The file
*
* @return string The directory name (empty if no directory is found, like urls)
*
* @throws LoggerUnusableException
*/
public function createDir(string $file): string;
/**
* Creates a stream based on a URL (could be a local file or a real URL)
*
* @param string $url The file/url
*
* @return resource the open stream resource
*
* @throws LoggerUnusableException
*/
public function createStream(string $url);
}