From: Philipp <admin@philipp.info>
Date: Sat, 23 Oct 2021 10:22:27 +0000 (+0200)
Subject: Restructure Logger to new paradigm
X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=184f6cc255ff40e4db428bc256127403b03bd087;p=friendica.git

Restructure Logger to new paradigm
---

diff --git a/src/Core/Logger.php b/src/Core/Logger.php
index 6dde142cc9..4e2575d1b9 100644
--- a/src/Core/Logger.php
+++ b/src/Core/Logger.php
@@ -22,7 +22,7 @@
 namespace Friendica\Core;
 
 use Friendica\DI;
-use Friendica\Util\Logger\WorkerLogger;
+use Friendica\Core\Logger\Type\WorkerLogger;
 use Psr\Log\LoggerInterface;
 use Psr\Log\LogLevel;
 
diff --git a/src/Core/Logger/Exception/LoggerArgumentException.php b/src/Core/Logger/Exception/LoggerArgumentException.php
new file mode 100644
index 0000000000..1b5f653f43
--- /dev/null
+++ b/src/Core/Logger/Exception/LoggerArgumentException.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Friendica\Core\Logger\Exception;
+
+use Throwable;
+
+class LoggerArgumentException extends \InvalidArgumentException
+{
+	public function __construct($message = "", Throwable $previous = null)
+	{
+		parent::__construct($message, 500, $previous);
+	}
+}
diff --git a/src/Core/Logger/Exception/LoggerException.php b/src/Core/Logger/Exception/LoggerException.php
new file mode 100644
index 0000000000..665dc21efd
--- /dev/null
+++ b/src/Core/Logger/Exception/LoggerException.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Friendica\Core\Logger\Exception;
+
+use Throwable;
+
+class LoggerException extends \Exception
+{
+	public function __construct($message = "", Throwable $previous = null)
+	{
+		parent::__construct($message, 500, $previous);
+	}
+}
diff --git a/src/Core/Logger/Factory/Logger.php b/src/Core/Logger/Factory/Logger.php
new file mode 100644
index 0000000000..4ca4f050a9
--- /dev/null
+++ b/src/Core/Logger/Factory/Logger.php
@@ -0,0 +1,291 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Factory;
+
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Core;
+use Friendica\Database\Database;
+use Friendica\Util\FileSystem;
+use Friendica\Util\Introspection;
+use Friendica\Core\Logger\Type\Monolog\DevelopHandler;
+use Friendica\Core\Logger\Type\Monolog\IntrospectionProcessor;
+use Friendica\Core\Logger\Type\ProfilerLogger;
+use Friendica\Core\Logger\Type\StreamLogger;
+use Friendica\Core\Logger\Type\SyslogLogger;
+use Friendica\Core\Logger\Type\VoidLogger;
+use Friendica\Util\Profiler;
+use Monolog;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * A logger factory
+ */
+class Logger
+{
+	const DEV_CHANNEL = 'dev';
+
+	/**
+	 * A list of classes, which shouldn't get logged
+	 *
+	 * @var string[]
+	 */
+	private static $ignoreClassList = [
+		Core\Logger::class,
+		Profiler::class,
+		'Friendica\\Core\\Logger\\Type',
+		'Friendica\\Core\\Logger\\Type\\Monolog',
+	];
+
+	/** @var string The log-channel (app, worker, ...) */
+	private $channel;
+
+	public function __construct(string $channel)
+	{
+		$this->channel = $channel;
+	}
+
+	/**
+	 * Creates a new PSR-3 compliant logger instances
+	 *
+	 * @param Database            $database   The Friendica Database instance
+	 * @param IManageConfigValues $config     The config
+	 * @param Profiler            $profiler   The profiler of the app
+	 * @param FileSystem          $fileSystem FileSystem utils
+	 *
+	 * @return LoggerInterface The PSR-3 compliant logger instance
+	 */
+	public function create(Database $database, IManageConfigValues $config, Profiler $profiler, FileSystem $fileSystem): LoggerInterface
+	{
+		if (empty($config->get('system', 'debugging', false))) {
+			$logger = new VoidLogger();
+			$database->setLogger($logger);
+			return $logger;
+		}
+
+		$introspection = new Introspection(self::$ignoreClassList);
+		$level         = $config->get('system', 'loglevel');
+		$loglevel      = self::mapLegacyConfigDebugLevel((string)$level);
+
+		switch ($config->get('system', 'logger_config', 'stream')) {
+			case 'monolog':
+				$loggerTimeZone = new \DateTimeZone('UTC');
+				Monolog\Logger::setTimezone($loggerTimeZone);
+
+				$logger = new Monolog\Logger($this->channel);
+				$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
+				$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
+				$logger->pushProcessor(new Monolog\Processor\UidProcessor());
+				$logger->pushProcessor(new IntrospectionProcessor($introspection, LogLevel::DEBUG));
+
+				$stream = $config->get('system', 'logfile');
+
+				// just add a stream in case it's either writable or not file
+				if (!is_file($stream) || is_writable($stream)) {
+					try {
+						static::addStreamHandler($logger, $stream, $loglevel);
+					} catch (\Throwable $e) {
+						// No Logger ..
+						/// @todo isn't it possible to give the admin any hint about this wrong configuration?
+						$logger = new VoidLogger();
+					}
+				}
+				break;
+
+			case 'syslog':
+				try {
+					$logger = new SyslogLogger($this->channel, $introspection, $loglevel);
+				} catch (\Throwable $e) {
+					// No logger ...
+					/// @todo isn't it possible to give the admin any hint about this wrong configuration?
+					$logger = new VoidLogger();
+				}
+				break;
+
+			case 'stream':
+			default:
+				$stream = $config->get('system', 'logfile');
+				// just add a stream in case it's either writable or not file
+				if (!is_file($stream) || is_writable($stream)) {
+					try {
+						$logger = new StreamLogger($this->channel, $stream, $introspection, $fileSystem, $loglevel);
+					} catch (\Throwable $t) {
+						// No logger ...
+						/// @todo isn't it possible to give the admin any hint about this wrong configuration?
+						$logger = new VoidLogger();
+					}
+				} else {
+					/// @todo isn't it possible to give the admin any hint about this wrong configuration?
+					$logger = new VoidLogger();
+				}
+				break;
+		}
+
+		$profiling = $config->get('system', 'profiling', false);
+
+		// In case profiling is enabled, wrap the ProfilerLogger around the current logger
+		if (isset($profiling) && $profiling !== false) {
+			$logger = new ProfilerLogger($logger, $profiler);
+		}
+
+		$database->setLogger($logger);
+		return $logger;
+	}
+
+	/**
+	 * Creates a new PSR-3 compliant develop logger
+	 *
+	 * If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
+	 * you'll use this logger instance for the duration of your work.
+	 *
+	 * It should never get filled during normal usage of Friendica
+	 *
+	 * @param IManageConfigValues $config     The config
+	 * @param Profiler            $profiler   The profiler of the app
+	 * @param FileSystem          $fileSystem FileSystem utils
+	 *
+	 * @return LoggerInterface The PSR-3 compliant logger instance
+	 * @throws \Exception
+	 */
+	public static function createDev(IManageConfigValues $config, Profiler $profiler, FileSystem $fileSystem)
+	{
+		$debugging   = $config->get('system', 'debugging');
+		$stream      = $config->get('system', 'dlogfile');
+		$developerIp = $config->get('system', 'dlogip');
+
+		if ((!isset($developerIp) || !$debugging) &&
+			(!is_file($stream) || is_writable($stream))) {
+			return new VoidLogger();
+		}
+
+		$loggerTimeZone = new \DateTimeZone('UTC');
+		Monolog\Logger::setTimezone($loggerTimeZone);
+
+		$introspection = new Introspection(self::$ignoreClassList);
+
+		switch ($config->get('system', 'logger_config', 'stream')) {
+
+			case 'monolog':
+				$loggerTimeZone = new \DateTimeZone('UTC');
+				Monolog\Logger::setTimezone($loggerTimeZone);
+
+				$logger = new Monolog\Logger(self::DEV_CHANNEL);
+				$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
+				$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
+				$logger->pushProcessor(new Monolog\Processor\UidProcessor());
+				$logger->pushProcessor(new IntrospectionProcessor($introspection, LogLevel::DEBUG));
+
+				$logger->pushHandler(new DevelopHandler($developerIp));
+
+				static::addStreamHandler($logger, $stream, LogLevel::DEBUG);
+				break;
+
+			case 'syslog':
+				$logger = new SyslogLogger(self::DEV_CHANNEL, $introspection, LogLevel::DEBUG);
+				break;
+
+			case 'stream':
+			default:
+				$logger = new StreamLogger(self::DEV_CHANNEL, $stream, $introspection, $fileSystem, LogLevel::DEBUG);
+				break;
+		}
+
+		$profiling = $config->get('system', 'profiling', false);
+
+		// In case profiling is enabled, wrap the ProfilerLogger around the current logger
+		if (isset($profiling) && $profiling !== false) {
+			$logger = new ProfilerLogger($logger, $profiler);
+		}
+
+		return $logger;
+	}
+
+	/**
+	 * Mapping a legacy level to the PSR-3 compliant levels
+	 *
+	 * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel
+	 *
+	 * @param string $level the level to be mapped
+	 *
+	 * @return string the PSR-3 compliant level
+	 */
+	private static function mapLegacyConfigDebugLevel(string $level): string
+	{
+		switch ($level) {
+			// legacy WARNING
+			case "0":
+				return LogLevel::ERROR;
+			// legacy INFO
+			case "1":
+				return LogLevel::WARNING;
+			// legacy TRACE
+			case "2":
+				return LogLevel::NOTICE;
+			// legacy DEBUG
+			case "3":
+				return LogLevel::INFO;
+			// legacy DATA
+			case "4":
+			// legacy ALL
+			case "5":
+				return LogLevel::DEBUG;
+			// default if nothing set
+			default:
+				return $level;
+		}
+	}
+
+	/**
+	 * Adding a handler to a given logger instance
+	 *
+	 * @param LoggerInterface $logger The logger instance
+	 * @param mixed           $stream The stream which handles the logger output
+	 * @param string          $level  The level, for which this handler at least should handle logging
+	 *
+	 * @return void
+	 *
+	 * @throws LoggerException
+	 */
+	public static function addStreamHandler(LoggerInterface $logger, $stream, string $level = LogLevel::NOTICE)
+	{
+		if ($logger instanceof Monolog\Logger) {
+			$loglevel = Monolog\Logger::toMonologLevel($level);
+
+			// fallback to notice if an invalid loglevel is set
+			if (!is_int($loglevel)) {
+				$loglevel = LogLevel::NOTICE;
+			}
+
+			try {
+				$fileHandler = new Monolog\Handler\StreamHandler($stream, $loglevel);
+
+				$formatter = new Monolog\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n");
+				$fileHandler->setFormatter($formatter);
+
+				$logger->pushHandler($fileHandler);
+			} catch (\Exception $exception) {
+				throw new LoggerException('Cannot create Monolog Logger.', $exception);
+			}
+		}
+	}
+}
diff --git a/src/Core/Logger/Type/AbstractLogger.php b/src/Core/Logger/Type/AbstractLogger.php
new file mode 100644
index 0000000000..0b6d9f38fd
--- /dev/null
+++ b/src/Core/Logger/Type/AbstractLogger.php
@@ -0,0 +1,206 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type;
+
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Util\Introspection;
+use Friendica\Util\Strings;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * This class contains all necessary dependencies and calls for Friendica
+ * Every new Logger should extend this class and define, how addEntry() works
+ *
+ * Additional information for each Logger, who extends this class:
+ * - Introspection
+ * - UID for each call
+ * - Channel of the current call (i.e. index, worker, daemon, ...)
+ */
+abstract class AbstractLogger implements LoggerInterface
+{
+	/**
+	 * The output channel of this logger
+	 * @var string
+	 */
+	protected $channel;
+
+	/**
+	 * The Introspection for the current call
+	 * @var Introspection
+	 */
+	protected $introspection;
+
+	/**
+	 * The UID of the current call
+	 * @var string
+	 */
+	protected $logUid;
+
+	/**
+	 * Adds a new entry to the log
+	 *
+	 * @param mixed  $level
+	 * @param string $message
+	 * @param array  $context
+	 *
+	 * @return void
+	 */
+	abstract protected function addEntry($level, string $message, array $context = []);
+
+	/**
+	 * @param string        $channel       The output channel
+	 * @param Introspection $introspection The introspection of the current call
+	 *
+	 * @throws LoggerException
+	 */
+	public function __construct(string $channel, Introspection $introspection)
+	{
+		$this->channel       = $channel;
+		$this->introspection = $introspection;
+
+		try {
+			$this->logUid = Strings::getRandomHex(6);
+		} catch (\Exception $exception) {
+			throw new LoggerException('Cannot generate log Id', $exception);
+		}
+	}
+
+	/**
+	 * Simple interpolation of PSR-3 compliant replacements ( variables between '{' and '}' )
+	 *
+	 * @see https://www.php-fig.org/psr/psr-3/#12-message
+	 *
+	 * @param string $message
+	 * @param array  $context
+	 *
+	 * @return string the interpolated message
+	 */
+	protected function psrInterpolate(string $message, array $context = []): string
+	{
+		$replace = [];
+		foreach ($context as $key => $value) {
+			// check that the value can be casted to string
+			if (!is_array($value) && (!is_object($value) || method_exists($value, '__toString'))) {
+				$replace['{' . $key . '}'] = $value;
+			} elseif (is_array($value)) {
+				$replace['{' . $key . '}'] = @json_encode($value);
+			}
+		}
+
+		return strtr($message, $replace);
+	}
+
+	/**
+	 * JSON Encodes a complete array including objects with "__toString()" methods
+	 *
+	 * @param array $input an Input Array to encode
+	 *
+	 * @return false|string The json encoded output of the array
+	 */
+	protected function jsonEncodeArray(array $input)
+	{
+		$output = [];
+
+		foreach ($input as $key => $value) {
+			if (is_object($value) && method_exists($value, '__toString')) {
+				$output[$key] = $value->__toString();
+			} else {
+				$output[$key] = $value;
+			}
+		}
+
+		return @json_encode($output);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function emergency($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::EMERGENCY, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function alert($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::ALERT, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function critical($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::CRITICAL, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function error($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::ERROR, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function warning($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::WARNING, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function notice($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::NOTICE, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function info($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::INFO, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function debug($message, array $context = [])
+	{
+		$this->addEntry(LogLevel::DEBUG, (string) $message, $context);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function log($level, $message, array $context = [])
+	{
+		$this->addEntry($level, (string) $message, $context);
+	}
+}
diff --git a/src/Core/Logger/Type/Monolog/DevelopHandler.php b/src/Core/Logger/Type/Monolog/DevelopHandler.php
new file mode 100644
index 0000000000..5d2a84401c
--- /dev/null
+++ b/src/Core/Logger/Type/Monolog/DevelopHandler.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type\Monolog;
+
+use Monolog\Handler;
+use Monolog\Logger;
+
+/**
+ * Simple handler for Friendica developers to use for deeper logging
+ *
+ * If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
+ * you'll use Logger::develop() for the duration of your work, and you clean it up when you're done before submitting your PR.
+ */
+class DevelopHandler extends Handler\AbstractHandler
+{
+	/**
+	 * @var string The IP of the developer who wants to debug
+	 */
+	private $developerIp;
+
+	/**
+	 * @param string $developerIp  The IP of the developer who wants to debug
+	 * @param int    $level        The minimum logging level at which this handler will be triggered
+	 * @param bool   $bubble       Whether the messages that are handled can bubble up the stack or not
+	 */
+	public function __construct($developerIp, $level = Logger::DEBUG, bool $bubble = true)
+	{
+		parent::__construct($level, $bubble);
+
+		$this->developerIp = $developerIp;
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function handle(array $record): bool
+	{
+		if (!$this->isHandling($record)) {
+			return false;
+		}
+
+		/// Just in case the remote IP is the same as the developer IP log the output
+		if (!is_null($this->developerIp) && $_SERVER['REMOTE_ADDR'] != $this->developerIp) {
+			return false;
+		}
+
+		return false === $this->bubble;
+	}
+}
diff --git a/src/Core/Logger/Type/Monolog/IntrospectionProcessor.php b/src/Core/Logger/Type/Monolog/IntrospectionProcessor.php
new file mode 100644
index 0000000000..756331b22f
--- /dev/null
+++ b/src/Core/Logger/Type/Monolog/IntrospectionProcessor.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type\Monolog;
+
+use Friendica\Util\Introspection;
+use Monolog\Logger;
+use Monolog\Processor\ProcessorInterface;
+
+/**
+ * Injects line/file//function where the log message came from
+ */
+class IntrospectionProcessor implements ProcessorInterface
+{
+	private $level;
+
+	private $introspection;
+
+	/**
+	 * @param Introspection $introspection Holds the Introspection of the current call
+	 * @param string|int    $level         The minimum logging level at which this Processor will be triggered
+	 */
+	public function __construct(Introspection $introspection, $level = Logger::DEBUG)
+	{
+		$this->level = Logger::toMonologLevel($level);
+		$introspection->addClasses(['Monolog\\']);
+		$this->introspection = $introspection;
+	}
+
+	public function __invoke(array $record): array
+	{
+		// return if the level is not high enough
+		if ($record['level'] < $this->level) {
+			return $record;
+		}
+		// we should have the call source now
+		$record['extra'] = array_merge(
+			$record['extra'],
+			$this->introspection->getRecord()
+		);
+
+		return $record;
+	}
+}
diff --git a/src/Core/Logger/Type/ProfilerLogger.php b/src/Core/Logger/Type/ProfilerLogger.php
new file mode 100644
index 0000000000..2333dd5403
--- /dev/null
+++ b/src/Core/Logger/Type/ProfilerLogger.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type;
+
+use Friendica\Util\Profiler;
+use Psr\Log\LoggerInterface;
+
+/**
+ * This Logger adds additional profiling data in case profiling is enabled.
+ * It uses a predefined logger.
+ */
+class ProfilerLogger implements LoggerInterface
+{
+	/**
+	 * The Logger of the current call
+	 * @var LoggerInterface
+	 */
+	private $logger;
+
+	/**
+	 * The Profiler for the current call
+	 * @var Profiler
+	 */
+	protected $profiler;
+
+	/**
+	 * ProfilerLogger constructor.
+	 * @param LoggerInterface $logger   The Logger of the current call
+	 * @param Profiler        $profiler The profiler of the current call
+	 */
+	public function __construct(LoggerInterface $logger, Profiler $profiler)
+	{
+		$this->logger   = $logger;
+		$this->profiler = $profiler;
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function emergency($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->emergency($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function alert($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->alert($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function critical($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->critical($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function error($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->error($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function warning($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->warning($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function notice($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->notice($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function info($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->info($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function debug($message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->debug($message, $context);
+		$this->profiler->stopRecording();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function log($level, $message, array $context = [])
+	{
+		$this->profiler->startRecording('file');
+		$this->logger->log($level, $message, $context);
+		$this->profiler->stopRecording();
+	}
+}
diff --git a/src/Core/Logger/Type/README.md b/src/Core/Logger/Type/README.md
new file mode 100644
index 0000000000..449403194d
--- /dev/null
+++ b/src/Core/Logger/Type/README.md
@@ -0,0 +1,27 @@
+## Friendica\Util\Logger
+
+This namespace contains the different implementations of a Logger.
+
+### Configuration guideline
+
+The following settings are possible for `logger_config`:
+-	`monolog`: A Logging framework with lots of additions (see [Monolog](https://github.com/Seldaek/monolog/)). There are just Friendica additions inside the Monolog directory
+-	[`stream`](StreamLogger.php): A small logger for files or streams
+-	[`syslog`](SyslogLogger.php): Prints the logging output into the syslog
+
+[`VoidLogger`](VoidLogger.php) is a fallback logger without any function if no debugging is enabled.
+
+[`ProfilerLogger`](ProfilerLogger.php) is a wrapper around an existing logger in case profiling is enabled for Friendica.
+Every log call will be saved to the `Profiler` with a timestamp.
+
+### Implementation guideline
+
+Each logging implementation should pe capable of printing at least the following information:
+-	An unique ID for each Request/Call
+-	The process ID (PID)
+-	A timestamp of the logging entry
+-	The critically of the log entry
+-	A log message
+-	A context of the log message (f.e which user)
+
+If possible, a Logger should extend [`AbstractLogger`](AbstractLogger.php), because it contains additional, Friendica specific business logic for each logging call.
diff --git a/src/Core/Logger/Type/StreamLogger.php b/src/Core/Logger/Type/StreamLogger.php
new file mode 100644
index 0000000000..be0283d0ec
--- /dev/null
+++ b/src/Core/Logger/Type/StreamLogger.php
@@ -0,0 +1,203 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type;
+
+use Friendica\Core\Logger\Exception\LoggerArgumentException;
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\FileSystem;
+use Friendica\Util\Introspection;
+use Psr\Log\LogLevel;
+
+/**
+ * A Logger instance for logging into a stream (file, stdout, stderr)
+ */
+class StreamLogger extends AbstractLogger
+{
+	/**
+	 * The minimum loglevel at which this logger will be triggered
+	 * @var string
+	 */
+	private $logLevel;
+
+	/**
+	 * The file URL of the stream (if needed)
+	 * @var string
+	 */
+	private $url;
+
+	/**
+	 * The stream, where the current logger is writing into
+	 * @var resource
+	 */
+	private $stream;
+
+	/**
+	 * The current process ID
+	 * @var int
+	 */
+	private $pid;
+
+	/**
+	 * @var FileSystem
+	 */
+	private $fileSystem;
+
+	/**
+	 * Translates LogLevel log levels to integer values
+	 * @var array
+	 */
+	private $levelToInt = [
+		LogLevel::EMERGENCY => 0,
+		LogLevel::ALERT     => 1,
+		LogLevel::CRITICAL  => 2,
+		LogLevel::ERROR     => 3,
+		LogLevel::WARNING   => 4,
+		LogLevel::NOTICE    => 5,
+		LogLevel::INFO      => 6,
+		LogLevel::DEBUG     => 7,
+	];
+
+	/**
+	 * {@inheritdoc}
+	 * @param string|resource $stream The stream to write with this logger (either a file or a stream, i.e. stdout)
+	 * @param string          $level  The minimum loglevel at which this logger will be triggered
+	 *
+	 * @throws LoggerArgumentException
+	 */
+	public function __construct($channel, $stream, Introspection $introspection, FileSystem $fileSystem, string $level = LogLevel::DEBUG)
+	{
+		$this->fileSystem = $fileSystem;
+
+		parent::__construct($channel, $introspection);
+
+		if (is_resource($stream)) {
+			$this->stream = $stream;
+		} elseif (is_string($stream)) {
+			$this->url = $stream;
+		} else {
+			throw new LoggerArgumentException('A stream must either be a resource or a string.');
+		}
+
+		$this->pid = getmypid();
+		if (array_key_exists($level, $this->levelToInt)) {
+			$this->logLevel = $this->levelToInt[$level];
+		} else {
+			throw new LoggerArgumentException(sprintf('The level "%s" is not valid.', $level));
+		}
+
+		$this->checkStream();
+	}
+
+	public function close()
+	{
+		if ($this->url && is_resource($this->stream)) {
+			fclose($this->stream);
+		}
+
+		$this->stream = null;
+	}
+
+	/**
+	 * Adds a new entry to the log
+	 *
+	 * @param mixed  $level
+	 * @param string $message
+	 * @param array  $context
+	 *
+	 * @return void
+	 *
+	 * @throws LoggerException
+	 * @throws LoggerArgumentException
+	 */
+	protected function addEntry($level, string $message, array $context = [])
+	{
+		if (!array_key_exists($level, $this->levelToInt)) {
+			throw new LoggerArgumentException(sprintf('The level "%s" is not valid.', $level));
+		}
+
+		$logLevel = $this->levelToInt[$level];
+
+		if ($logLevel > $this->logLevel) {
+			return;
+		}
+
+		$this->checkStream();
+
+		$formattedLog = $this->formatLog($level, $message, $context);
+		fwrite($this->stream, $formattedLog);
+	}
+
+	/**
+	 * Formats a log record for the syslog output
+	 *
+	 * @param mixed  $level   The loglevel/priority
+	 * @param string $message The message
+	 * @param array  $context The context of this call
+	 *
+	 * @return string the formatted syslog output
+	 *
+	 * @throws LoggerException
+	 */
+	private function formatLog($level, string $message, array $context = []): string
+	{
+		$record = $this->introspection->getRecord();
+		$record = array_merge($record, ['uid' => $this->logUid, 'process_id' => $this->pid]);
+
+		try {
+			$logMessage = DateTimeFormat::utcNow(DateTimeFormat::ATOM) . ' ';
+		} catch (\Exception $exception) {
+			throw new LoggerException('Cannot get current datetime.', $exception);
+		}
+		$logMessage .= $this->channel . ' ';
+		$logMessage .= '[' . strtoupper($level) . ']: ';
+		$logMessage .= $this->psrInterpolate($message, $context) . ' ';
+		$logMessage .= $this->jsonEncodeArray($context) . ' - ';
+		$logMessage .= $this->jsonEncodeArray($record);
+		$logMessage .= PHP_EOL;
+
+		return $logMessage;
+	}
+
+	/**
+	 * Checks the current stream
+	 *
+	 * @throws LoggerException
+	 * @throws LoggerArgumentException
+	 */
+	private function checkStream()
+	{
+		if (is_resource($this->stream)) {
+			return;
+		}
+
+		if (empty($this->url)) {
+			throw new LoggerArgumentException('Missing stream URL.');
+		}
+
+		try {
+			$this->stream = $this->fileSystem->createStream($this->url);
+		} catch (\UnexpectedValueException $exception) {
+			throw new LoggerException('Cannot create stream.', $exception);
+		}
+	}
+}
diff --git a/src/Core/Logger/Type/SyslogLogger.php b/src/Core/Logger/Type/SyslogLogger.php
new file mode 100644
index 0000000000..667b44ccc7
--- /dev/null
+++ b/src/Core/Logger/Type/SyslogLogger.php
@@ -0,0 +1,230 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type;
+
+use Friendica\Core\Logger\Exception\LoggerArgumentException;
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Util\Introspection;
+use Psr\Log\InvalidArgumentException;
+use Psr\Log\LogLevel;
+
+/**
+ * A Logger instance for syslogging (fast, but simple)
+ * @see http://php.net/manual/en/function.syslog.php
+ */
+class SyslogLogger extends AbstractLogger
+{
+	const IDENT = 'Friendica';
+
+	/**
+	 * Translates LogLevel log levels to syslog log priorities.
+	 * @var array
+	 */
+	private $logLevels = [
+		LogLevel::DEBUG     => LOG_DEBUG,
+		LogLevel::INFO      => LOG_INFO,
+		LogLevel::NOTICE    => LOG_NOTICE,
+		LogLevel::WARNING   => LOG_WARNING,
+		LogLevel::ERROR     => LOG_ERR,
+		LogLevel::CRITICAL  => LOG_CRIT,
+		LogLevel::ALERT     => LOG_ALERT,
+		LogLevel::EMERGENCY => LOG_EMERG,
+	];
+
+	/**
+	 * Translates log priorities to string outputs
+	 * @var array
+	 */
+	private $logToString = [
+		LOG_DEBUG   => 'DEBUG',
+		LOG_INFO    => 'INFO',
+		LOG_NOTICE  => 'NOTICE',
+		LOG_WARNING => 'WARNING',
+		LOG_ERR     => 'ERROR',
+		LOG_CRIT    => 'CRITICAL',
+		LOG_ALERT   => 'ALERT',
+		LOG_EMERG   => 'EMERGENCY'
+	];
+
+	/**
+	 * Indicates what logging options will be used when generating a log message
+	 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
+	 *
+	 * @var int
+	 */
+	private $logOpts;
+
+	/**
+	 * Used to specify what type of program is logging the message
+	 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
+	 *
+	 * @var int
+	 */
+	private $logFacility;
+
+	/**
+	 * The minimum loglevel at which this logger will be triggered
+	 * @var int
+	 */
+	private $logLevel;
+
+	/**
+	 * A error message of the current operation
+	 * @var string
+	 */
+	private $errorMessage;
+
+	/**
+	 * {@inheritdoc}
+	 * @param string $level       The minimum loglevel at which this logger will be triggered
+	 * @param int    $logOpts     Indicates what logging options will be used when generating a log message
+	 * @param int    $logFacility Used to specify what type of program is logging the message
+	 *
+	 * @throws LoggerArgumentException
+	 */
+	public function __construct($channel, Introspection $introspection, string $level = LogLevel::NOTICE, int $logOpts = LOG_PID, int $logFacility = LOG_USER)
+	{
+		parent::__construct($channel, $introspection);
+		$this->logOpts     = $logOpts;
+		$this->logFacility = $logFacility;
+		$this->logLevel    = $this->mapLevelToPriority($level);
+		$this->introspection->addClasses([self::class]);
+	}
+
+	/**
+	 * Adds a new entry to the syslog
+	 *
+	 * @param mixed  $level
+	 * @param string $message
+	 * @param array  $context
+	 *
+	 * @throws LoggerArgumentException in case the level isn't valid
+	 * @throws LoggerException In case the syslog cannot be opened for writing
+	 */
+	protected function addEntry($level, string $message, array $context = [])
+	{
+		$logLevel = $this->mapLevelToPriority($level);
+
+		if ($logLevel > $this->logLevel) {
+			return;
+		}
+
+		$formattedLog = $this->formatLog($logLevel, $message, $context);
+		$this->write($logLevel, $formattedLog);
+	}
+
+	/**
+	 * Maps the LogLevel (@see LogLevel) to a SysLog priority (@see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters)
+	 *
+	 * @param string $level A LogLevel
+	 *
+	 * @return int The SysLog priority
+	 *
+	 * @throws LoggerArgumentException If the loglevel isn't valid
+	 */
+	public function mapLevelToPriority(string $level): int
+	{
+		if (!array_key_exists($level, $this->logLevels)) {
+			throw new LoggerArgumentException(sprintf('The level "%s" is not valid.', $level));
+		}
+
+		return $this->logLevels[$level];
+	}
+
+	/**
+	 * Closes the Syslog
+	 */
+	public function close()
+	{
+		closelog();
+	}
+
+	/**
+	 * Writes a message to the syslog
+	 *
+	 * @see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters
+	 *
+	 * @param int    $priority The Priority
+	 * @param string $message  The message of the log
+	 *
+	 * @throws LoggerException In case the syslog cannot be opened/written
+	 */
+	private function write(int $priority, string $message)
+	{
+		set_error_handler([$this, 'customErrorHandler']);
+		$opened = openlog(self::IDENT, $this->logOpts, $this->logFacility);
+		restore_error_handler();
+
+		if (!$opened) {
+			throw new LoggerException(sprintf('Can\'t open syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, $this->logFacility));
+		}
+
+		$this->syslogWrapper($priority, $message);
+	}
+
+	/**
+	 * Formats a log record for the syslog output
+	 *
+	 * @param int    $level   The loglevel/priority
+	 * @param string $message The message
+	 * @param array  $context The context of this call
+	 *
+	 * @return string the formatted syslog output
+	 */
+	private function formatLog(int $level, string $message, array $context = []): string
+	{
+		$record = $this->introspection->getRecord();
+		$record = array_merge($record, ['uid' => $this->logUid]);
+
+		$logMessage = $this->channel . ' ';
+		$logMessage .= '[' . $this->logToString[$level] . ']: ';
+		$logMessage .= $this->psrInterpolate($message, $context) . ' ';
+		$logMessage .= $this->jsonEncodeArray($context) . ' - ';
+		$logMessage .= $this->jsonEncodeArray($record);
+
+		return $logMessage;
+	}
+
+	private function customErrorHandler($code, $msg)
+	{
+		$this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
+	}
+
+	/**
+	 * A syslog wrapper to make syslog functionality testable
+	 *
+	 * @param int    $level The syslog priority
+	 * @param string $entry The message to send to the syslog function
+	 *
+	 * @throws LoggerException
+	 */
+	protected function syslogWrapper(int $level, string $entry)
+	{
+		set_error_handler([$this, 'customErrorHandler']);
+		$written = syslog($level, $entry);
+		restore_error_handler();
+
+		if (!$written) {
+			throw new LoggerException(sprintf('Can\'t write into syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, $this->logFacility));
+		}
+	}
+}
diff --git a/src/Core/Logger/Type/VoidLogger.php b/src/Core/Logger/Type/VoidLogger.php
new file mode 100644
index 0000000000..5cd2cac868
--- /dev/null
+++ b/src/Core/Logger/Type/VoidLogger.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type;
+
+use Psr\Log\LoggerInterface;
+
+/**
+ * A Logger instance to not log
+ */
+class VoidLogger implements LoggerInterface
+{
+	/**
+	 * System is unusable.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function emergency($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Action must be taken immediately.
+	 *
+	 * Example: Entire website down, database unavailable, etc. This should
+	 * trigger the SMS alerts and wake you up.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function alert($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Critical conditions.
+	 *
+	 * Example: Application component unavailable, unexpected exception.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function critical($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Runtime errors that do not require immediate action but should typically
+	 * be logged and monitored.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function error($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Exceptional occurrences that are not errors.
+	 *
+	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
+	 * that are not necessarily wrong.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function warning($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Normal but significant events.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function notice($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Interesting events.
+	 *
+	 * Example: User logs in, SQL logs.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function info($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Detailed debug information.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function debug($message, array $context = array())
+	{
+		return;
+	}
+
+	/**
+	 * Logs with an arbitrary level.
+	 *
+	 * @param mixed $level
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function log($level, $message, array $context = array())
+	{
+		return;
+	}
+}
diff --git a/src/Core/Logger/Type/WorkerLogger.php b/src/Core/Logger/Type/WorkerLogger.php
new file mode 100644
index 0000000000..fcbe128013
--- /dev/null
+++ b/src/Core/Logger/Type/WorkerLogger.php
@@ -0,0 +1,235 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Logger\Type;
+
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Util\Strings;
+use Psr\Log\LoggerInterface;
+
+/**
+ * A Logger for specific worker tasks, which adds a worker id to it.
+ * Uses the decorator pattern (https://en.wikipedia.org/wiki/Decorator_pattern)
+ */
+class WorkerLogger implements LoggerInterface
+{
+	/**
+	 * @var LoggerInterface The original Logger instance
+	 */
+	private $logger;
+
+	/**
+	 * @var string the current worker ID
+	 */
+	private $workerId;
+
+	/**
+	 * @var string The called function name
+	 */
+	private $functionName;
+
+	/**
+	 * @param LoggerInterface $logger       The logger for worker entries
+	 * @param string          $functionName The current function name of the worker
+	 * @param int             $idLength     The length of the generated worker ID
+	 *
+	 * @throws LoggerException
+	 */
+	public function __construct(LoggerInterface $logger, string $functionName = '', int $idLength = 7)
+	{
+		$this->logger       = $logger;
+		$this->functionName = $functionName;
+		try {
+			$this->workerId = Strings::getRandomHex($idLength);
+		} catch (\Exception $exception) {
+			throw new LoggerException('Cannot generate random Hex.', $exception);
+		}
+	}
+
+	/**
+	 * Sets the function name for additional logging
+	 *
+	 * @param string $functionName
+	 */
+	public function setFunctionName(string $functionName)
+	{
+		$this->functionName = $functionName;
+	}
+
+	/**
+	 * Adds the worker context for each log entry
+	 *
+	 * @param array $context
+	 */
+	private function addContext(array &$context)
+	{
+		$context['worker_id']  = $this->workerId;
+		$context['worker_cmd'] = $this->functionName;
+	}
+
+	/**
+	 * Returns the worker ID
+	 *
+	 * @return string
+	 */
+	public function getWorkerId(): string
+	{
+		return $this->workerId;
+	}
+
+	/**
+	 * System is unusable.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function emergency($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->emergency($message, $context);
+	}
+
+	/**
+	 * Action must be taken immediately.
+	 *
+	 * Example: Entire website down, database unavailable, etc. This should
+	 * trigger the SMS alerts and wake you up.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function alert($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->alert($message, $context);
+	}
+
+	/**
+	 * Critical conditions.
+	 *
+	 * Example: Application component unavailable, unexpected exception.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function critical($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->critical($message, $context);
+	}
+
+	/**
+	 * Runtime errors that do not require immediate action but should typically
+	 * be logged and monitored.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function error($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->error($message, $context);
+	}
+
+	/**
+	 * Exceptional occurrences that are not errors.
+	 *
+	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
+	 * that are not necessarily wrong.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function warning($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->warning($message, $context);
+	}
+
+	/**
+	 * Normal but significant events.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function notice($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->notice($message, $context);
+	}
+
+	/**
+	 * Interesting events.
+	 *
+	 * Example: User logs in, SQL logs.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function info($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->info($message, $context);
+	}
+
+	/**
+	 * Detailed debug information.
+	 *
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function debug($message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->debug($message, $context);
+	}
+
+	/**
+	 * Logs with an arbitrary level.
+	 *
+	 * @param mixed $level
+	 * @param string $message
+	 * @param array $context
+	 *
+	 * @return void
+	 */
+	public function log($level, $message, array $context = [])
+	{
+		$this->addContext($context);
+		$this->logger->log($level, $message, $context);
+	}
+}
diff --git a/src/DI.php b/src/DI.php
index 5ba7e88db1..8ee7004408 100644
--- a/src/DI.php
+++ b/src/DI.php
@@ -243,7 +243,7 @@ abstract class DI
 	 */
 	public static function workerLogger()
 	{
-		return self::$dice->create(Util\Logger\WorkerLogger::class);
+		return self::$dice->create(Core\Logger\Type\WorkerLogger::class);
 	}
 
 	//
diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php
deleted file mode 100644
index d01b477e1e..0000000000
--- a/src/Factory/LoggerFactory.php
+++ /dev/null
@@ -1,293 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Factory;
-
-use Friendica\Core\Config\Capability\IManageConfigValues;
-use Friendica\Core\Logger;
-use Friendica\Database\Database;
-use Friendica\Network\HTTPException\InternalServerErrorException;
-use Friendica\Util\FileSystem;
-use Friendica\Util\Introspection;
-use Friendica\Util\Logger\Monolog\DevelopHandler;
-use Friendica\Util\Logger\Monolog\IntrospectionProcessor;
-use Friendica\Util\Logger\ProfilerLogger;
-use Friendica\Util\Logger\StreamLogger;
-use Friendica\Util\Logger\SyslogLogger;
-use Friendica\Util\Logger\VoidLogger;
-use Friendica\Util\Profiler;
-use Monolog;
-use Psr\Log\LoggerInterface;
-use Psr\Log\LogLevel;
-
-/**
- * A logger factory
- *
- * Currently only Monolog is supported
- */
-class LoggerFactory
-{
-	const DEV_CHANNEL = 'dev';
-
-	/**
-	 * A list of classes, which shouldn't get logged
-	 *
-	 * @var array
-	 */
-	private static $ignoreClassList = [
-		Logger::class,
-		Profiler::class,
-		'Friendica\\Util\\Logger',
-	];
-
-	private $channel;
-
-	public function __construct(string $channel)
-	{
-		$this->channel = $channel;
-	}
-
-	/**
-	 * Creates a new PSR-3 compliant logger instances
-	 *
-	 * @param Database            $database   The Friendica Database instance
-	 * @param IManageConfigValues $config     The config
-	 * @param Profiler            $profiler   The profiler of the app
-	 * @param FileSystem          $fileSystem FileSystem utils
-	 *
-	 * @return LoggerInterface The PSR-3 compliant logger instance
-	 */
-	public function create(Database $database, IManageConfigValues $config, Profiler $profiler, FileSystem $fileSystem)
-	{
-		if (empty($config->get('system', 'debugging', false))) {
-			$logger = new VoidLogger();
-			$database->setLogger($logger);
-			return $logger;
-		}
-
-		$introspection = new Introspection(self::$ignoreClassList);
-		$level         = $config->get('system', 'loglevel');
-		$loglevel      = self::mapLegacyConfigDebugLevel((string)$level);
-
-		switch ($config->get('system', 'logger_config', 'stream')) {
-			case 'monolog':
-				$loggerTimeZone = new \DateTimeZone('UTC');
-				Monolog\Logger::setTimezone($loggerTimeZone);
-
-				$logger = new Monolog\Logger($this->channel);
-				$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
-				$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
-				$logger->pushProcessor(new Monolog\Processor\UidProcessor());
-				$logger->pushProcessor(new IntrospectionProcessor($introspection, LogLevel::DEBUG));
-
-				$stream = $config->get('system', 'logfile');
-
-				// just add a stream in case it's either writable or not file
-				if (!is_file($stream) || is_writable($stream)) {
-					try {
-						static::addStreamHandler($logger, $stream, $loglevel);
-					} catch (\Throwable $e) {
-						// No Logger ..
-						$logger = new VoidLogger();
-					}
-				}
-				break;
-
-			case 'syslog':
-				try {
-					$logger = new SyslogLogger($this->channel, $introspection, $loglevel);
-				} catch (\Throwable $e) {
-					// No logger ...
-					$logger = new VoidLogger();
-				}
-				break;
-
-			case 'stream':
-			default:
-				$stream = $config->get('system', 'logfile');
-				// just add a stream in case it's either writable or not file
-				if (!is_file($stream) || is_writable($stream)) {
-					try {
-						$logger = new StreamLogger($this->channel, $stream, $introspection, $fileSystem, $loglevel);
-					} catch (\Throwable $t) {
-						// No logger ...
-						$logger = new VoidLogger();
-					}
-				} else {
-					$logger = new VoidLogger();
-				}
-				break;
-		}
-
-		$profiling = $config->get('system', 'profiling', false);
-
-		// In case profiling is enabled, wrap the ProfilerLogger around the current logger
-		if (isset($profiling) && $profiling !== false) {
-			$logger = new ProfilerLogger($logger, $profiler);
-		}
-
-		$database->setLogger($logger);
-		return $logger;
-	}
-
-	/**
-	 * Creates a new PSR-3 compliant develop logger
-	 *
-	 * If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
-	 * you'll use this logger instance for the duration of your work.
-	 *
-	 * It should never get filled during normal usage of Friendica
-	 *
-	 * @param IManageConfigValues $config     The config
-	 * @param Profiler            $profiler   The profiler of the app
-	 * @param FileSystem          $fileSystem FileSystem utils
-	 *
-	 * @return LoggerInterface The PSR-3 compliant logger instance
-	 *
-	 * @throws InternalServerErrorException
-	 * @throws \Exception
-	 */
-	public static function createDev(IManageConfigValues $config, Profiler $profiler, FileSystem $fileSystem)
-	{
-		$debugging   = $config->get('system', 'debugging');
-		$stream      = $config->get('system', 'dlogfile');
-		$developerIp = $config->get('system', 'dlogip');
-
-		if ((!isset($developerIp) || !$debugging) &&
-		    (!is_file($stream) || is_writable($stream))) {
-			$logger = new VoidLogger();
-			return $logger;
-		}
-
-		$loggerTimeZone = new \DateTimeZone('UTC');
-		Monolog\Logger::setTimezone($loggerTimeZone);
-
-		$introspection = new Introspection(self::$ignoreClassList);
-
-		switch ($config->get('system', 'logger_config', 'stream')) {
-
-			case 'monolog':
-				$loggerTimeZone = new \DateTimeZone('UTC');
-				Monolog\Logger::setTimezone($loggerTimeZone);
-
-				$logger = new Monolog\Logger(self::DEV_CHANNEL);
-				$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
-				$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
-				$logger->pushProcessor(new Monolog\Processor\UidProcessor());
-				$logger->pushProcessor(new IntrospectionProcessor($introspection, LogLevel::DEBUG));
-
-				$logger->pushHandler(new DevelopHandler($developerIp));
-
-				static::addStreamHandler($logger, $stream, LogLevel::DEBUG);
-				break;
-
-			case 'syslog':
-				$logger = new SyslogLogger(self::DEV_CHANNEL, $introspection, LogLevel::DEBUG);
-				break;
-
-			case 'stream':
-			default:
-				$logger = new StreamLogger(self::DEV_CHANNEL, $stream, $introspection, $fileSystem, LogLevel::DEBUG);
-				break;
-		}
-
-		$profiling = $config->get('system', 'profiling', false);
-
-		// In case profiling is enabled, wrap the ProfilerLogger around the current logger
-		if (isset($profiling) && $profiling !== false) {
-			$logger = new ProfilerLogger($logger, $profiler);
-		}
-
-		return $logger;
-	}
-
-	/**
-	 * Mapping a legacy level to the PSR-3 compliant levels
-	 *
-	 * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel
-	 *
-	 * @param string $level the level to be mapped
-	 *
-	 * @return string the PSR-3 compliant level
-	 */
-	private static function mapLegacyConfigDebugLevel($level)
-	{
-		switch ($level) {
-			// legacy WARNING
-			case "0":
-				return LogLevel::ERROR;
-			// legacy INFO
-			case "1":
-				return LogLevel::WARNING;
-			// legacy TRACE
-			case "2":
-				return LogLevel::NOTICE;
-			// legacy DEBUG
-			case "3":
-				return LogLevel::INFO;
-			// legacy DATA
-			case "4":
-			// legacy ALL
-			case "5":
-				return LogLevel::DEBUG;
-			// default if nothing set
-			default:
-				return $level;
-		}
-	}
-
-	/**
-	 * Adding a handler to a given logger instance
-	 *
-	 * @param LoggerInterface $logger The logger instance
-	 * @param mixed           $stream The stream which handles the logger output
-	 * @param string          $level  The level, for which this handler at least should handle logging
-	 *
-	 * @return void
-	 *
-	 * @throws \Exception in case of general failures
-	 */
-	public static function addStreamHandler($logger, $stream, $level = LogLevel::NOTICE)
-	{
-		if ($logger instanceof Monolog\Logger) {
-			$loglevel = Monolog\Logger::toMonologLevel($level);
-
-			// fallback to notice if an invalid loglevel is set
-			if (!is_int($loglevel)) {
-				$loglevel = LogLevel::NOTICE;
-			}
-
-			$fileHandler = new Monolog\Handler\StreamHandler($stream, $loglevel);
-
-			$formatter = new Monolog\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n");
-			$fileHandler->setFormatter($formatter);
-
-			$logger->pushHandler($fileHandler);
-		}
-	}
-
-	public static function addVoidHandler($logger)
-	{
-		if ($logger instanceof Monolog\Logger) {
-			$logger->pushHandler(new Monolog\Handler\NullHandler());
-		}
-	}
-}
diff --git a/src/Util/FileSystem.php b/src/Util/FileSystem.php
index 4fa5c31c8a..1a86f43be7 100644
--- a/src/Util/FileSystem.php
+++ b/src/Util/FileSystem.php
@@ -73,7 +73,9 @@ class FileSystem
 	 *
 	 * @param string $url The file/url
 	 *
-	 * @return false|resource the open stream ressource
+	 * @return resource the open stream rssource
+	 *
+	 * @throws \UnexpectedValueException
 	 */
 	public function createStream(string $url)
 	{
diff --git a/src/Util/Logger/AbstractLogger.php b/src/Util/Logger/AbstractLogger.php
deleted file mode 100644
index a8aba34d34..0000000000
--- a/src/Util/Logger/AbstractLogger.php
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger;
-
-use Friendica\Util\Introspection;
-use Friendica\Util\Strings;
-use Psr\Log\LoggerInterface;
-use Psr\Log\LogLevel;
-
-/**
- * This class contains all necessary dependencies and calls for Friendica
- * Every new Logger should extend this class and define, how addEntry() works
- *
- * Additional information for each Logger, who extends this class:
- * - Introspection
- * - UID for each call
- * - Channel of the current call (i.e. index, worker, daemon, ...)
- */
-abstract class AbstractLogger implements LoggerInterface
-{
-	/**
-	 * The output channel of this logger
-	 * @var string
-	 */
-	protected $channel;
-
-	/**
-	 * The Introspection for the current call
-	 * @var Introspection
-	 */
-	protected $introspection;
-
-	/**
-	 * The UID of the current call
-	 * @var string
-	 */
-	protected $logUid;
-
-	/**
-	 * Adds a new entry to the log
-	 *
-	 * @param int    $level
-	 * @param string $message
-	 * @param array  $context
-	 *
-	 * @return void
-	 */
-	abstract protected function addEntry($level, $message, $context = []);
-
-	/**
-	 * @param string        $channel       The output channel
-	 * @param Introspection $introspection The introspection of the current call
-	 *
-	 * @throws \Exception
-	 */
-	public function __construct($channel, Introspection $introspection)
-	{
-		$this->channel       = $channel;
-		$this->introspection = $introspection;
-		$this->logUid        = Strings::getRandomHex(6);
-	}
-
-	/**
-	 * Simple interpolation of PSR-3 compliant replacements ( variables between '{' and '}' )
-	 * @see https://www.php-fig.org/psr/psr-3/#12-message
-	 *
-	 * @param string $message
-	 * @param array  $context
-	 *
-	 * @return string the interpolated message
-	 */
-	protected function psrInterpolate($message, array $context = array())
-	{
-		$replace = [];
-		foreach ($context as $key => $value) {
-			// check that the value can be casted to string
-			if (!is_array($value) && (!is_object($value) || method_exists($value, '__toString'))) {
-				$replace['{' . $key . '}'] = $value;
-			} elseif (is_array($value)) {
-				$replace['{' . $key . '}'] = @json_encode($value);
-			}
-		}
-
-		return strtr($message, $replace);
-	}
-
-	/**
-	 * JSON Encodes an complete array including objects with "__toString()" methods
-	 *
-	 * @param array $input an Input Array to encode
-	 *
-	 * @return false|string The json encoded output of the array
-	 */
-	protected function jsonEncodeArray(array $input)
-	{
-		$output = [];
-
-		foreach ($input as $key => $value) {
-			if (is_object($value) && method_exists($value, '__toString')) {
-				$output[$key] = $value->__toString();
-			} else {
-				$output[$key] = $value;
-			}
-		}
-
-		return @json_encode($output);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function emergency($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::EMERGENCY, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function alert($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::ALERT, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function critical($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::CRITICAL, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function error($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::ERROR, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function warning($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::WARNING, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function notice($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::NOTICE, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function info($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::INFO, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function debug($message, array $context = array())
-	{
-		$this->addEntry(LogLevel::DEBUG, (string) $message, $context);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function log($level, $message, array $context = array())
-	{
-		$this->addEntry($level, (string) $message, $context);
-	}
-}
diff --git a/src/Util/Logger/Monolog/DevelopHandler.php b/src/Util/Logger/Monolog/DevelopHandler.php
deleted file mode 100644
index a55ac373ac..0000000000
--- a/src/Util/Logger/Monolog/DevelopHandler.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger\Monolog;
-
-use Monolog\Handler;
-use Monolog\Logger;
-
-/**
- * Simple handler for Friendica developers to use for deeper logging
- *
- * If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
- * you'll use Logger::develop() for the duration of your work, and you clean it up when you're done before submitting your PR.
- */
-class DevelopHandler extends Handler\AbstractHandler
-{
-	/**
-	 * @var string The IP of the developer who wants to debug
-	 */
-	private $developerIp;
-
-	/**
-	 * @param string $developerIp  The IP of the developer who wants to debug
-	 * @param int    $level        The minimum logging level at which this handler will be triggered
-	 * @param bool   $bubble       Whether the messages that are handled can bubble up the stack or not
-	 */
-	public function __construct($developerIp, $level = Logger::DEBUG, $bubble = true)
-	{
-		parent::__construct($level, $bubble);
-
-		$this->developerIp = $developerIp;
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function handle(array $record)
-	{
-		if (!$this->isHandling($record)) {
-			return false;
-		}
-
-		/// Just in case the remote IP is the same as the developer IP log the output
-		if (!is_null($this->developerIp) && $_SERVER['REMOTE_ADDR'] != $this->developerIp)
-		{
-			return false;
-		}
-
-		return false === $this->bubble;
-	}
-}
diff --git a/src/Util/Logger/Monolog/IntrospectionProcessor.php b/src/Util/Logger/Monolog/IntrospectionProcessor.php
deleted file mode 100644
index ceb0e3123e..0000000000
--- a/src/Util/Logger/Monolog/IntrospectionProcessor.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger\Monolog;
-
-use Friendica\Util\Introspection;
-use Monolog\Logger;
-use Monolog\Processor\ProcessorInterface;
-
-/**
- * Injects line/file//function where the log message came from
- */
-class IntrospectionProcessor implements ProcessorInterface
-{
-	private $level;
-
-	private $introspection;
-
-	/**
-	 * @param Introspection $introspection Holds the Introspection of the current call
-	 * @param string|int    $level         The minimum logging level at which this Processor will be triggered
-	 */
-	public function __construct(Introspection $introspection, $level = Logger::DEBUG)
-	{
-		$this->level = Logger::toMonologLevel($level);
-		$introspection->addClasses(array('Monolog\\'));
-		$this->introspection = $introspection;
-	}
-
-	public function __invoke(array $record)
-	{
-		// return if the level is not high enough
-		if ($record['level'] < $this->level) {
-			return $record;
-		}
-		// we should have the call source now
-		$record['extra'] = array_merge(
-			$record['extra'],
-			$this->introspection->getRecord()
-		);
-
-		return $record;
-	}
-}
diff --git a/src/Util/Logger/ProfilerLogger.php b/src/Util/Logger/ProfilerLogger.php
deleted file mode 100644
index 1c190d4f55..0000000000
--- a/src/Util/Logger/ProfilerLogger.php
+++ /dev/null
@@ -1,146 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger;
-
-use Friendica\Core\System;
-use Friendica\Util\Profiler;
-use Psr\Log\LoggerInterface;
-
-/**
- * This Logger adds additional profiling data in case profiling is enabled.
- * It uses a predefined logger.
- */
-class ProfilerLogger implements LoggerInterface
-{
-	/**
-	 * The Logger of the current call
-	 * @var LoggerInterface
-	 */
-	private $logger;
-
-	/**
-	 * The Profiler for the current call
-	 * @var Profiler
-	 */
-	protected $profiler;
-
-	/**
-	 * ProfilerLogger constructor.
-	 * @param LoggerInterface $logger   The Logger of the current call
-	 * @param Profiler        $profiler The profiler of the current call
-	 */
-	public function __construct(LoggerInterface $logger, Profiler $profiler)
-	{
-		$this->logger = $logger;
-		$this->profiler = $profiler;
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function emergency($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->emergency($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function alert($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->alert($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function critical($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->critical($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function error($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->error($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function warning($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->warning($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function notice($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->notice($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function info($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->info($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function debug($message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->debug($message, $context);
-		$this->profiler->stopRecording();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	public function log($level, $message, array $context = array())
-	{
-		$this->profiler->startRecording('file');
-		$this->logger->log($level, $message, $context);
-		$this->profiler->stopRecording();
-	}
-}
diff --git a/src/Util/Logger/README.md b/src/Util/Logger/README.md
deleted file mode 100644
index 449403194d..0000000000
--- a/src/Util/Logger/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-## Friendica\Util\Logger
-
-This namespace contains the different implementations of a Logger.
-
-### Configuration guideline
-
-The following settings are possible for `logger_config`:
--	`monolog`: A Logging framework with lots of additions (see [Monolog](https://github.com/Seldaek/monolog/)). There are just Friendica additions inside the Monolog directory
--	[`stream`](StreamLogger.php): A small logger for files or streams
--	[`syslog`](SyslogLogger.php): Prints the logging output into the syslog
-
-[`VoidLogger`](VoidLogger.php) is a fallback logger without any function if no debugging is enabled.
-
-[`ProfilerLogger`](ProfilerLogger.php) is a wrapper around an existing logger in case profiling is enabled for Friendica.
-Every log call will be saved to the `Profiler` with a timestamp.
-
-### Implementation guideline
-
-Each logging implementation should pe capable of printing at least the following information:
--	An unique ID for each Request/Call
--	The process ID (PID)
--	A timestamp of the logging entry
--	The critically of the log entry
--	A log message
--	A context of the log message (f.e which user)
-
-If possible, a Logger should extend [`AbstractLogger`](AbstractLogger.php), because it contains additional, Friendica specific business logic for each logging call.
diff --git a/src/Util/Logger/StreamLogger.php b/src/Util/Logger/StreamLogger.php
deleted file mode 100644
index 752f486583..0000000000
--- a/src/Util/Logger/StreamLogger.php
+++ /dev/null
@@ -1,183 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger;
-
-use Friendica\Util\DateTimeFormat;
-use Friendica\Util\FileSystem;
-use Friendica\Util\Introspection;
-use Psr\Log\LogLevel;
-
-/**
- * A Logger instance for logging into a stream (file, stdout, stderr)
- */
-class StreamLogger extends AbstractLogger
-{
-	/**
-	 * The minimum loglevel at which this logger will be triggered
-	 * @var string
-	 */
-	private $logLevel;
-
-	/**
-	 * The file URL of the stream (if needed)
-	 * @var string
-	 */
-	private $url;
-
-	/**
-	 * The stream, where the current logger is writing into
-	 * @var resource
-	 */
-	private $stream;
-
-	/**
-	 * The current process ID
-	 * @var int
-	 */
-	private $pid;
-
-	/**
-	 * @var FileSystem
-	 */
-	private $fileSystem;
-
-	/**
-	 * Translates LogLevel log levels to integer values
-	 * @var array
-	 */
-	private $levelToInt = [
-		LogLevel::EMERGENCY => 0,
-		LogLevel::ALERT     => 1,
-		LogLevel::CRITICAL  => 2,
-		LogLevel::ERROR     => 3,
-		LogLevel::WARNING   => 4,
-		LogLevel::NOTICE    => 5,
-		LogLevel::INFO      => 6,
-		LogLevel::DEBUG     => 7,
-	];
-
-	/**
-	 * {@inheritdoc}
-	 * @param string|resource $stream The stream to write with this logger (either a file or a stream, i.e. stdout)
-	 * @param string          $level  The minimum loglevel at which this logger will be triggered
-	 *
-	 * @throws \Exception
-	 */
-	public function __construct($channel, $stream, Introspection $introspection, FileSystem $fileSystem, $level = LogLevel::DEBUG)
-	{
-		$this->fileSystem = $fileSystem;
-
-		parent::__construct($channel, $introspection);
-
-		if (is_resource($stream)) {
-			$this->stream = $stream;
-		} elseif (is_string($stream)) {
-			$this->url = $stream;
-		} else {
-			throw new \InvalidArgumentException('A stream must either be a resource or a string.');
-		}
-
-		$this->pid = getmypid();
-		if (array_key_exists($level, $this->levelToInt)) {
-			$this->logLevel = $this->levelToInt[$level];
-		} else {
-			throw new \InvalidArgumentException(sprintf('The level "%s" is not valid.', $level));
-		}
-
-		$this->checkStream();
-	}
-
-	public function close()
-	{
-		if ($this->url && is_resource($this->stream)) {
-			fclose($this->stream);
-		}
-
-		$this->stream = null;
-	}
-
-	/**
-	 * Adds a new entry to the log
-	 *
-	 * @param int $level
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	protected function addEntry($level, $message, $context = [])
-	{
-		if (!array_key_exists($level, $this->levelToInt)) {
-			throw new \InvalidArgumentException(sprintf('The level "%s" is not valid.', $level));
-		}
-
-		$logLevel = $this->levelToInt[$level];
-
-		if ($logLevel > $this->logLevel) {
-			return;
-		}
-
-		$this->checkStream();
-
-		$formattedLog = $this->formatLog($level, $message, $context);
-		fwrite($this->stream, $formattedLog);
-	}
-
-	/**
-	 * Formats a log record for the syslog output
-	 *
-	 * @param int    $level   The loglevel/priority
-	 * @param string $message The message
-	 * @param array  $context The context of this call
-	 *
-	 * @return string the formatted syslog output
-	 */
-	private function formatLog($level, $message, $context = [])
-	{
-		$record = $this->introspection->getRecord();
-		$record = array_merge($record, ['uid' => $this->logUid, 'process_id' => $this->pid]);
-		$logMessage = '';
-
-		$logMessage .= DateTimeFormat::utcNow(DateTimeFormat::ATOM) . ' ';
-		$logMessage .= $this->channel . ' ';
-		$logMessage .= '[' . strtoupper($level) . ']: ';
-		$logMessage .= $this->psrInterpolate($message, $context) . ' ';
-		$logMessage .= $this->jsonEncodeArray($context) . ' - ';
-		$logMessage .= $this->jsonEncodeArray($record);
-		$logMessage .= PHP_EOL;
-
-		return $logMessage;
-	}
-
-	private function checkStream()
-	{
-		if (is_resource($this->stream)) {
-			return;
-		}
-
-		if (empty($this->url)) {
-			throw new \LogicException('Missing stream URL.');
-		}
-
-		$this->stream = $this->fileSystem->createStream($this->url);
-	}
-}
diff --git a/src/Util/Logger/SyslogLogger.php b/src/Util/Logger/SyslogLogger.php
deleted file mode 100644
index f33e2d624a..0000000000
--- a/src/Util/Logger/SyslogLogger.php
+++ /dev/null
@@ -1,225 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger;
-
-use Friendica\Network\HTTPException\InternalServerErrorException;
-use Friendica\Util\Introspection;
-use Psr\Log\LogLevel;
-
-/**
- * A Logger instance for syslogging (fast, but simple)
- * @see http://php.net/manual/en/function.syslog.php
- */
-class SyslogLogger extends AbstractLogger
-{
-	const IDENT = 'Friendica';
-
-	/**
-	 * Translates LogLevel log levels to syslog log priorities.
-	 * @var array
-	 */
-	private $logLevels = [
-		LogLevel::DEBUG     => LOG_DEBUG,
-		LogLevel::INFO      => LOG_INFO,
-		LogLevel::NOTICE    => LOG_NOTICE,
-		LogLevel::WARNING   => LOG_WARNING,
-		LogLevel::ERROR     => LOG_ERR,
-		LogLevel::CRITICAL  => LOG_CRIT,
-		LogLevel::ALERT     => LOG_ALERT,
-		LogLevel::EMERGENCY => LOG_EMERG,
-	];
-
-	/**
-	 * Translates log priorities to string outputs
-	 * @var array
-	 */
-	private $logToString = [
-		LOG_DEBUG   => 'DEBUG',
-		LOG_INFO    => 'INFO',
-		LOG_NOTICE  => 'NOTICE',
-		LOG_WARNING => 'WARNING',
-		LOG_ERR     => 'ERROR',
-		LOG_CRIT    => 'CRITICAL',
-		LOG_ALERT   => 'ALERT',
-		LOG_EMERG   => 'EMERGENCY'
-	];
-
-	/**
-	 * Indicates what logging options will be used when generating a log message
-	 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
-	 *
-	 * @var int
-	 */
-	private $logOpts;
-
-	/**
-	 * Used to specify what type of program is logging the message
-	 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
-	 *
-	 * @var int
-	 */
-	private $logFacility;
-
-	/**
-	 * The minimum loglevel at which this logger will be triggered
-	 * @var int
-	 */
-	private $logLevel;
-
-	/**
-	 * A error message of the current operation
-	 * @var string
-	 */
-	private $errorMessage;
-
-	/**
-	 * {@inheritdoc}
-	 * @param string $level       The minimum loglevel at which this logger will be triggered
-	 * @param int    $logOpts     Indicates what logging options will be used when generating a log message
-	 * @param int    $logFacility Used to specify what type of program is logging the message
-	 *
-	 * @throws \Exception
-	 */
-	public function __construct($channel, Introspection $introspection, $level = LogLevel::NOTICE, $logOpts = LOG_PID, $logFacility = LOG_USER)
-	{
-		parent::__construct($channel, $introspection);
-		$this->logOpts = $logOpts;
-		$this->logFacility = $logFacility;
-		$this->logLevel = $this->mapLevelToPriority($level);
-		$this->introspection->addClasses(array(self::class));
-	}
-
-	/**
-	 * Adds a new entry to the syslog
-	 *
-	 * @param int    $level
-	 * @param string $message
-	 * @param array  $context
-	 *
-	 * @throws InternalServerErrorException if the syslog isn't available
-	 */
-	protected function addEntry($level, $message, $context = [])
-	{
-		$logLevel = $this->mapLevelToPriority($level);
-
-		if ($logLevel > $this->logLevel) {
-			return;
-		}
-
-		$formattedLog = $this->formatLog($logLevel, $message, $context);
-		$this->write($logLevel, $formattedLog);
-	}
-
-	/**
-	 * Maps the LogLevel (@see LogLevel) to a SysLog priority (@see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters)
-	 *
-	 * @param string $level A LogLevel
-	 *
-	 * @return int The SysLog priority
-	 *
-	 * @throws \Psr\Log\InvalidArgumentException If the loglevel isn't valid
-	 */
-	public function mapLevelToPriority($level)
-	{
-		if (!array_key_exists($level, $this->logLevels)) {
-			throw new \InvalidArgumentException(sprintf('The level "%s" is not valid.', $level));
-		}
-
-		return $this->logLevels[$level];
-	}
-
-	/**
-	 * Closes the Syslog
-	 */
-	public function close()
-	{
-		closelog();
-	}
-
-	/**
-	 * Writes a message to the syslog
-	 * @see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters
-	 *
-	 * @param int    $priority The Priority
-	 * @param string $message  The message of the log
-	 *
-	 * @throws InternalServerErrorException if syslog cannot be used
-	 */
-	private function write($priority, $message)
-	{
-		set_error_handler([$this, 'customErrorHandler']);
-		$opened = openlog(self::IDENT, $this->logOpts, $this->logFacility);
-		restore_error_handler();
-
-		if (!$opened) {
-			throw new \UnexpectedValueException(sprintf('Can\'t open syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, $this->logFacility));
-		}
-
-		$this->syslogWrapper($priority, $message);
-	}
-
-	/**
-	 * Formats a log record for the syslog output
-	 *
-	 * @param int    $level   The loglevel/priority
-	 * @param string $message The message
-	 * @param array  $context The context of this call
-	 *
-	 * @return string the formatted syslog output
-	 */
-	private function formatLog($level, $message, $context = [])
-	{
-		$record = $this->introspection->getRecord();
-		$record = array_merge($record, ['uid' => $this->logUid]);
-		$logMessage = '';
-
-		$logMessage .= $this->channel . ' ';
-		$logMessage .= '[' . $this->logToString[$level] . ']: ';
-		$logMessage .= $this->psrInterpolate($message, $context) . ' ';
-		$logMessage .= $this->jsonEncodeArray($context) . ' - ';
-		$logMessage .= $this->jsonEncodeArray($record);
-
-		return $logMessage;
-	}
-
-	private function customErrorHandler($code, $msg)
-	{
-		$this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
-	}
-
-	/**
-	 * A syslog wrapper to make syslog functionality testable
-	 *
-	 * @param int    $level The syslog priority
-	 * @param string $entry The message to send to the syslog function
-	 */
-	protected function syslogWrapper($level, $entry)
-	{
-		set_error_handler([$this, 'customErrorHandler']);
-		$written = syslog($level, $entry);
-		restore_error_handler();
-
-		if (!$written) {
-			throw new \UnexpectedValueException(sprintf('Can\'t write into syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, $this->logFacility));
-		}
-	}
-}
diff --git a/src/Util/Logger/VoidLogger.php b/src/Util/Logger/VoidLogger.php
deleted file mode 100644
index 6c47601a0a..0000000000
--- a/src/Util/Logger/VoidLogger.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger;
-
-use Psr\Log\LoggerInterface;
-
-/**
- * A Logger instance to not log
- */
-class VoidLogger implements LoggerInterface
-{
-	/**
-	 * System is unusable.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function emergency($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Action must be taken immediately.
-	 *
-	 * Example: Entire website down, database unavailable, etc. This should
-	 * trigger the SMS alerts and wake you up.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function alert($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Critical conditions.
-	 *
-	 * Example: Application component unavailable, unexpected exception.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function critical($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Runtime errors that do not require immediate action but should typically
-	 * be logged and monitored.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function error($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Exceptional occurrences that are not errors.
-	 *
-	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
-	 * that are not necessarily wrong.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function warning($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Normal but significant events.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function notice($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Interesting events.
-	 *
-	 * Example: User logs in, SQL logs.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function info($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Detailed debug information.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function debug($message, array $context = array())
-	{
-		return;
-	}
-
-	/**
-	 * Logs with an arbitrary level.
-	 *
-	 * @param mixed $level
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function log($level, $message, array $context = array())
-	{
-		return;
-	}
-}
diff --git a/src/Util/Logger/WorkerLogger.php b/src/Util/Logger/WorkerLogger.php
deleted file mode 100644
index fdda6c9b53..0000000000
--- a/src/Util/Logger/WorkerLogger.php
+++ /dev/null
@@ -1,228 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Util\Logger;
-
-use Friendica\Util\Strings;
-use Psr\Log\LoggerInterface;
-
-/**
- * A Logger for specific worker tasks, which adds an additional woker-id to it.
- * Uses the decorator pattern (https://en.wikipedia.org/wiki/Decorator_pattern)
- */
-class WorkerLogger implements LoggerInterface
-{
-	/**
-	 * @var LoggerInterface The original Logger instance
-	 */
-	private $logger;
-
-	/**
-	 * @var string the current worker ID
-	 */
-	private $workerId;
-
-	/**
-	 * @var string The called function name
-	 */
-	private $functionName;
-
-	/**
-	 * @param LoggerInterface $logger The logger for worker entries
-	 * @param string $functionName The current function name of the worker
-	 * @param int $idLength The length of the generated worker ID
-	 */
-	public function __construct(LoggerInterface $logger, $functionName = '', $idLength = 7)
-	{
-		$this->logger = $logger;
-		$this->functionName = $functionName;
-		$this->workerId = Strings::getRandomHex($idLength);
-	}
-
-	/**
-	 * Sets the function name for additional logging
-	 *
-	 * @param string $functionName
-	 */
-	public function setFunctionName(string $functionName)
-	{
-		$this->functionName = $functionName;
-	}
-
-	/**
-	 * Adds the worker context for each log entry
-	 *
-	 * @param array $context
-	 */
-	private function addContext(array &$context)
-	{
-		$context['worker_id'] = $this->workerId;
-		$context['worker_cmd'] = $this->functionName;
-	}
-
-	/**
-	 * Returns the worker ID
-	 *
-	 * @return string
-	 */
-	public function getWorkerId()
-	{
-		return $this->workerId;
-	}
-
-	/**
-	 * System is unusable.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function emergency($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->emergency($message, $context);
-	}
-
-	/**
-	 * Action must be taken immediately.
-	 *
-	 * Example: Entire website down, database unavailable, etc. This should
-	 * trigger the SMS alerts and wake you up.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function alert($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->alert($message, $context);
-	}
-
-	/**
-	 * Critical conditions.
-	 *
-	 * Example: Application component unavailable, unexpected exception.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function critical($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->critical($message, $context);
-	}
-
-	/**
-	 * Runtime errors that do not require immediate action but should typically
-	 * be logged and monitored.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function error($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->error($message, $context);
-	}
-
-	/**
-	 * Exceptional occurrences that are not errors.
-	 *
-	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
-	 * that are not necessarily wrong.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function warning($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->warning($message, $context);
-	}
-
-	/**
-	 * Normal but significant events.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function notice($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->notice($message, $context);
-	}
-
-	/**
-	 * Interesting events.
-	 *
-	 * Example: User logs in, SQL logs.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function info($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->info($message, $context);
-	}
-
-	/**
-	 * Detailed debug information.
-	 *
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function debug($message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->debug($message, $context);
-	}
-
-	/**
-	 * Logs with an arbitrary level.
-	 *
-	 * @param mixed $level
-	 * @param string $message
-	 * @param array $context
-	 *
-	 * @return void
-	 */
-	public function log($level, $message, array $context = [])
-	{
-		$this->addContext($context);
-		$this->logger->log($level, $message, $context);
-	}
-}
diff --git a/static/dependencies.config.php b/static/dependencies.config.php
index bbf8c5599c..042949e60e 100644
--- a/static/dependencies.config.php
+++ b/static/dependencies.config.php
@@ -141,7 +141,7 @@ return [
 	 *    and is automatically passed as an argument with the same name
 	 */
 	LoggerInterface::class          => [
-		'instanceOf' => Factory\LoggerFactory::class,
+		'instanceOf' => \Friendica\Core\Logger\Factory\Logger::class,
 		'constructParams' => [
 			'index',
 		],
@@ -150,7 +150,7 @@ return [
 		],
 	],
 	'$devLogger'                    => [
-		'instanceOf' => Factory\LoggerFactory::class,
+		'instanceOf' => \Friendica\Core\Logger\Factory\Logger::class,
 		'constructParams' => [
 			'dev',
 		],
diff --git a/tests/src/Console/AutomaticInstallationConsoleTest.php b/tests/src/Console/AutomaticInstallationConsoleTest.php
index 760a732d67..3f4f8c03c9 100644
--- a/tests/src/Console/AutomaticInstallationConsoleTest.php
+++ b/tests/src/Console/AutomaticInstallationConsoleTest.php
@@ -32,7 +32,7 @@ use Friendica\Database\Database;
 use Friendica\DI;
 use Friendica\Test\Util\RendererMockTrait;
 use Friendica\Test\Util\VFSTrait;
-use Friendica\Util\Logger\VoidLogger;
+use Friendica\Core\Logger\Type\VoidLogger;
 use Mockery;
 use Mockery\MockInterface;
 use org\bovigo\vfs\vfsStream;
diff --git a/tests/src/Contact/FriendSuggest/Factory/FriendSuggestTest.php b/tests/src/Contact/FriendSuggest/Factory/FriendSuggestTest.php
index afa0711ae0..9691073168 100644
--- a/tests/src/Contact/FriendSuggest/Factory/FriendSuggestTest.php
+++ b/tests/src/Contact/FriendSuggest/Factory/FriendSuggestTest.php
@@ -5,7 +5,7 @@ namespace Friendica\Test\src\Contact\FriendSuggest\Factory;
 use Friendica\Contact\FriendSuggest\Factory\FriendSuggest;
 use Friendica\Contact\FriendSuggest\Entity;
 use Friendica\Test\MockedTest;
-use Friendica\Util\Logger\VoidLogger;
+use Friendica\Core\Logger\Type\VoidLogger;
 
 class FriendSuggestTest extends MockedTest
 {
diff --git a/tests/src/Core/Logger/AbstractLoggerTest.php b/tests/src/Core/Logger/AbstractLoggerTest.php
new file mode 100644
index 0000000000..f1a0553102
--- /dev/null
+++ b/tests/src/Core/Logger/AbstractLoggerTest.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+use Friendica\Test\MockedTest;
+use Friendica\Util\Introspection;
+use Mockery\MockInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+abstract class AbstractLoggerTest extends MockedTest
+{
+	use LoggerDataTrait;
+
+	const LOGLINE = '/.* \[.*\]: .* \{.*\"file\":\".*\".*,.*\"line\":\d*,.*\"function\":\".*\".*,.*\"uid\":\".*\".*}/';
+
+	const FILE = 'test';
+	const LINE = 666;
+	const FUNC = 'myfunction';
+
+	/**
+	 * @var Introspection|MockInterface
+	 */
+	protected $introspection;
+
+	/**
+	 * Returns the content of the current logger instance
+	 *
+	 * @return string
+	 */
+	abstract protected function getContent();
+
+	/**
+	 * Returns the current logger instance
+	 *
+	 * @param string $level the default loglevel
+	 *
+	 * @return LoggerInterface
+	 */
+	abstract protected function getInstance($level = LogLevel::DEBUG);
+
+	protected function setUp(): void
+	{
+		parent::setUp();
+
+		$this->introspection = \Mockery::mock(Introspection::class);
+		$this->introspection->shouldReceive('getRecord')->andReturn([
+			'file'     => self::FILE,
+			'line'     => self::LINE,
+			'function' => self::FUNC
+		]);
+	}
+
+	public function assertLogline($string)
+	{
+		self::assertRegExp(self::LOGLINE, $string);
+	}
+
+	public function assertLoglineNums($assertNum, $string)
+	{
+		self::assertEquals($assertNum, preg_match_all(self::LOGLINE, $string));
+	}
+
+	/**
+	 * Test if the logger works correctly
+	 */
+	public function testNormal()
+	{
+		$logger = $this->getInstance();
+		$logger->emergency('working!');
+		$logger->alert('working too!');
+		$logger->debug('and now?');
+		$logger->notice('message', ['an' => 'context']);
+
+		$text = $this->getContent();
+		self::assertLogline($text);
+		self::assertLoglineNums(4, $text);
+	}
+
+	/**
+	 * Test if a log entry is correctly interpolated
+	 */
+	public function testPsrInterpolate()
+	{
+		$logger = $this->getInstance();
+
+		$logger->emergency('A {psr} test', ['psr' => 'working']);
+		$logger->alert('An {array} test', ['array' => ['it', 'is', 'working']]);
+		$text = $this->getContent();
+		self::assertStringContainsString('A working test', $text);
+		self::assertStringContainsString('An ["it","is","working"] test', $text);
+	}
+
+	/**
+	 * Test if a log entry contains all necessary information
+	 */
+	public function testContainsInformation()
+	{
+		$logger = $this->getInstance();
+		$logger->emergency('A test');
+
+		$text = $this->getContent();
+		self::assertStringContainsString('"file":"' . self::FILE . '"', $text);
+		self::assertStringContainsString('"line":' . self::LINE, $text);
+		self::assertStringContainsString('"function":"' . self::FUNC . '"', $text);
+	}
+
+	/**
+	 * Test if the minimum level is working
+	 */
+	public function testMinimumLevel()
+	{
+		$logger = $this->getInstance(LogLevel::NOTICE);
+
+		$logger->emergency('working');
+		$logger->alert('working');
+		$logger->error('working');
+		$logger->warning('working');
+		$logger->notice('working');
+		$logger->info('not working');
+		$logger->debug('not working');
+
+		$text = $this->getContent();
+
+		self::assertLoglineNums(5, $text);
+	}
+
+	/**
+	 * Test with different logging data
+	 * @dataProvider dataTests
+	 */
+	public function testDifferentTypes($function, $message, array $context)
+	{
+		$logger = $this->getInstance();
+		$logger->$function($message, $context);
+
+		$text = $this->getContent();
+
+		self::assertLogline($text);
+
+		self::assertStringContainsString(@json_encode($context), $text);
+	}
+
+	/**
+	 * Test a message with an exception
+	 */
+	public function testExceptionHandling()
+	{
+		$e = new \Exception("Test String", 123);
+		$eFollowUp = new \Exception("FollowUp", 456, $e);
+
+		$assertion = $eFollowUp->__toString();
+
+		$logger = $this->getInstance();
+		$logger->alert('test', ['e' => $eFollowUp]);
+		$text = $this->getContent();
+
+		self::assertLogline($text);
+
+		self::assertStringContainsString(@json_encode($assertion), $this->getContent());
+	}
+
+	public function testNoObjectHandling()
+	{
+		$logger = $this->getInstance();
+		$logger->alert('test', ['e' => ['test' => 'test']]);
+		$text = $this->getContent();
+
+		self::assertLogline($text);
+
+		self::assertStringContainsString('test', $this->getContent());
+	}
+}
diff --git a/tests/src/Core/Logger/LoggerDataTrait.php b/tests/src/Core/Logger/LoggerDataTrait.php
new file mode 100644
index 0000000000..0d6b004cfe
--- /dev/null
+++ b/tests/src/Core/Logger/LoggerDataTrait.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+trait LoggerDataTrait
+{
+	public function dataTests()
+	{
+		return [
+			'emergency' => [
+				'function' => 'emergency',
+				'message' => 'test',
+				'context' => ['a' => 'context'],
+			],
+			'alert' => [
+				'function' => 'alert',
+				'message' => 'test {test}',
+				'context' => ['a' => 'context', 2 => 'so', 'test' => 'works'],
+			],
+			'critical' => [
+				'function' => 'critical',
+				'message' => 'test crit 2345',
+				'context' => ['a' => 'context', 'wit' => ['more', 'array']],
+			],
+			'error' => [
+				'function' => 'error',
+				'message' => 2.554,
+				'context' => [],
+			],
+			'warning' => [
+				'function' => 'warning',
+				'message' => 'test warn',
+				'context' => ['a' => 'context'],
+			],
+			'notice' => [
+				'function' => 'notice',
+				'message' => 2346,
+				'context' => ['a' => 'context'],
+			],
+			'info' => [
+				'function' => 'info',
+				'message' => null,
+				'context' => ['a' => 'context'],
+			],
+			'debug' => [
+				'function' => 'debug',
+				'message' => true,
+				'context' => ['a' => false],
+			],
+		];
+	}
+}
diff --git a/tests/src/Core/Logger/ProfilerLoggerTest.php b/tests/src/Core/Logger/ProfilerLoggerTest.php
new file mode 100644
index 0000000000..3b8e7711f8
--- /dev/null
+++ b/tests/src/Core/Logger/ProfilerLoggerTest.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+use Friendica\Test\MockedTest;
+use Friendica\Core\Logger\Type\ProfilerLogger;
+use Friendica\Util\Profiler;
+use Mockery\MockInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+class ProfilerLoggerTest extends MockedTest
+{
+	use LoggerDataTrait;
+
+	/**
+	 * @var LoggerInterface|MockInterface
+	 */
+	private $logger;
+	/**
+	 * @var Profiler|MockInterface
+	 */
+	private $profiler;
+
+	protected function setUp(): void
+	{
+		parent::setUp();
+
+		$this->logger = \Mockery::mock(LoggerInterface::class);
+		$this->profiler = \Mockery::mock(Profiler::class);
+	}
+
+	/**
+	 * Test if the profiler is profiling data
+	 * @dataProvider dataTests
+	 * @doesNotPerformAssertions
+	 */
+	public function testProfiling($function, $message, array $context)
+	{
+		$logger = new ProfilerLogger($this->logger, $this->profiler);
+
+		$this->logger->shouldReceive($function)->with($message, $context)->once();
+		$this->profiler->shouldReceive('startRecording')->with('file')->once();
+		$this->profiler->shouldReceive('stopRecording');
+		$this->profiler->shouldReceive('saveTimestamp');
+		$logger->$function($message, $context);
+	}
+
+	/**
+	 * Test the log() function
+	 * @doesNotPerformAssertions
+	 */
+	public function testProfilingLog()
+	{
+		$logger = new ProfilerLogger($this->logger, $this->profiler);
+
+		$this->logger->shouldReceive('log')->with(LogLevel::WARNING, 'test', ['a' => 'context'])->once();
+		$this->profiler->shouldReceive('startRecording')->with('file')->once();
+		$this->profiler->shouldReceive('stopRecording');
+		$this->profiler->shouldReceive('saveTimestamp');
+
+		$logger->log(LogLevel::WARNING, 'test', ['a' => 'context']);
+	}
+}
diff --git a/tests/src/Core/Logger/StreamLoggerTest.php b/tests/src/Core/Logger/StreamLoggerTest.php
new file mode 100644
index 0000000000..65ef76ea3d
--- /dev/null
+++ b/tests/src/Core/Logger/StreamLoggerTest.php
@@ -0,0 +1,213 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+use Friendica\Core\Logger\Exception\LoggerArgumentException;
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Util\FileSystem;
+use Friendica\Test\Util\VFSTrait;
+use Friendica\Core\Logger\Type\StreamLogger;
+use org\bovigo\vfs\vfsStream;
+use org\bovigo\vfs\vfsStreamFile;
+use Psr\Log\LogLevel;
+
+class StreamLoggerTest extends AbstractLoggerTest
+{
+	use VFSTrait;
+
+	/**
+	 * @var vfsStreamFile
+	 */
+	private $logfile;
+
+	/**
+	 * @var Filesystem
+	 */
+	private $fileSystem;
+
+	protected function setUp(): void
+	{
+		parent::setUp();
+
+		$this->setUpVfsDir();
+
+		$this->fileSystem = new FileSystem();
+	}
+
+	/**
+	 * {@@inheritdoc}
+	 */
+	protected function getInstance($level = LogLevel::DEBUG)
+	{
+		$this->logfile = vfsStream::newFile('friendica.log')
+			->at($this->root);
+
+		$logger = new StreamLogger('test', $this->logfile->url(), $this->introspection, $this->fileSystem, $level);
+
+		return $logger;
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	protected function getContent()
+	{
+		return $this->logfile->getContent();
+	}
+
+	/**
+	 * Test if a stream is working
+	 */
+	public function testStream()
+	{
+		$logfile = vfsStream::newFile('friendica.log')
+			->at($this->root);
+
+		$filehandler = fopen($logfile->url(), 'ab');
+
+		$logger = new \Friendica\Core\Logger\Type\StreamLogger('test', $filehandler, $this->introspection, $this->fileSystem);
+		$logger->emergency('working');
+
+		$text = $logfile->getContent();
+
+		self::assertLogline($text);
+	}
+
+	/**
+	 * Test if the close statement is working
+	 */
+	public function testClose()
+	{
+		$logfile = vfsStream::newFile('friendica.log')
+			->at($this->root);
+
+		$logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
+		$logger->emergency('working');
+		$logger->close();
+		// close doesn't affect
+		$logger->emergency('working too');
+
+		$text = $logfile->getContent();
+
+		self::assertLoglineNums(2, $text);
+	}
+
+	/**
+	 * Test when a file isn't set
+	 */
+	public function testNoUrl()
+	{
+		$this->expectException(LoggerArgumentException::class);
+		$this->expectExceptionMessage("Missing stream URL.");
+
+		$logger = new StreamLogger('test', '', $this->introspection, $this->fileSystem);
+
+		$logger->emergency('not working');
+	}
+
+	/**
+	 * Test when a file cannot be opened
+	 */
+	public function testWrongUrl()
+	{
+		$this->expectException(LoggerException::class);
+		$this->expectExceptionMessage("Cannot create stream.");
+
+		$logfile = vfsStream::newFile('friendica.log')
+			->at($this->root)->chmod(0);
+
+		$logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
+
+		$logger->emergency('not working');
+	}
+
+	/**
+	 * Test when the directory cannot get created
+	 */
+	public function testWrongDir()
+	{
+		$this->expectException(\UnexpectedValueException::class);
+		$this->expectExceptionMessageMatches("/Directory .* cannot get created: .* /");
+
+		static::markTestIncomplete('We need a platform independent way to set directory to readonly');
+
+		$logger = new StreamLogger('test', '/$%/wrong/directory/file.txt', $this->introspection, $this->fileSystem);
+
+		$logger->emergency('not working');
+	}
+
+	/**
+	 * Test when the minimum level is not valid
+	 */
+	public function testWrongMinimumLevel()
+	{
+		$this->expectException(LoggerArgumentException::class);
+		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
+
+		$logger = new StreamLogger('test', 'file.text', $this->introspection, $this->fileSystem, 'NOPE');
+	}
+
+	/**
+	 * Test when the minimum level is not valid
+	 */
+	public function testWrongLogLevel()
+	{
+		$this->expectException(LoggerArgumentException::class);
+		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
+
+		$logfile = vfsStream::newFile('friendica.log')
+			->at($this->root);
+
+		$logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
+
+		$logger->log('NOPE', 'a test');
+	}
+
+	/**
+	 * Test when the file is null
+	 */
+	public function testWrongFile()
+	{
+		$this->expectException(LoggerArgumentException::class);
+		$this->expectExceptionMessage("A stream must either be a resource or a string.");
+
+		$logger = new StreamLogger('test', null, $this->introspection, $this->fileSystem);
+	}
+
+	/**
+	 * Test a relative path
+	 * @doesNotPerformAssertions
+	 */
+	public function testRealPath()
+	{
+		static::markTestSkipped('vfsStream isn\'t compatible with chdir, so not testable.');
+
+		$logfile = vfsStream::newFile('friendica.log')
+		                    ->at($this->root);
+
+		chdir($this->root->getChild('logs')->url());
+
+		$logger = new StreamLogger('test', '../friendica.log' , $this->introspection, $this->fileSystem);
+
+		$logger->info('Test');
+	}
+}
diff --git a/tests/src/Core/Logger/SyslogLoggerTest.php b/tests/src/Core/Logger/SyslogLoggerTest.php
new file mode 100644
index 0000000000..8ba2ebc084
--- /dev/null
+++ b/tests/src/Core/Logger/SyslogLoggerTest.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+use Friendica\Core\Logger\Exception\LoggerArgumentException;
+use Friendica\Core\Logger\Exception\LoggerException;
+use Friendica\Core\Logger\Type\SyslogLogger;
+use Psr\Log\LogLevel;
+
+class SyslogLoggerTest extends AbstractLoggerTest
+{
+	/**
+	 * @var SyslogLoggerWrapper
+	 */
+	private $logger;
+
+	protected function setUp(): void
+	{
+		parent::setUp();
+
+		$this->introspection->shouldReceive('addClasses')->with([SyslogLogger::class]);
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	protected function getContent()
+	{
+		return $this->logger->getContent();
+	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	protected function getInstance($level = LogLevel::DEBUG)
+	{
+		$this->logger = new SyslogLoggerWrapper('test', $this->introspection, $level);
+
+		return $this->logger;
+	}
+
+
+	/**
+	 * Test when the minimum level is not valid
+	 */
+	public function testWrongMinimumLevel()
+	{
+		$this->expectException(LoggerArgumentException::class);
+		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
+		
+		$logger = new SyslogLoggerWrapper('test', $this->introspection, 'NOPE');
+	}
+
+	/**
+	 * Test when the minimum level is not valid
+	 */
+	public function testWrongLogLevel()
+	{
+		$this->expectException(LoggerArgumentException::class);
+		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
+
+		$logger = new SyslogLoggerWrapper('test', $this->introspection);
+
+		$logger->log('NOPE', 'a test');
+	}
+
+	/**
+	 * Test the close() method
+	 * @doesNotPerformAssertions
+	 */
+	public function testClose()
+	{
+		$logger = new SyslogLoggerWrapper('test', $this->introspection);
+		$logger->emergency('test');
+		$logger->close();
+		// Reopened itself
+		$logger->emergency('test');
+	}
+}
diff --git a/tests/src/Core/Logger/SyslogLoggerWrapper.php b/tests/src/Core/Logger/SyslogLoggerWrapper.php
new file mode 100644
index 0000000000..05dcbd6bc5
--- /dev/null
+++ b/tests/src/Core/Logger/SyslogLoggerWrapper.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+use Friendica\Core\Logger\Type\SyslogLogger;
+use Friendica\Util\Introspection;
+use Psr\Log\LogLevel;
+
+/**
+ * Wraps the SyslogLogger for replacing the syslog call with a string field.
+ */
+class SyslogLoggerWrapper extends SyslogLogger
+{
+	private $content;
+
+	public function __construct($channel, Introspection $introspection, $level = LogLevel::NOTICE, $logOpts = LOG_PID, $logFacility = LOG_USER)
+	{
+		parent::__construct($channel, $introspection, $level, $logOpts, $logFacility);
+
+		$this->content = '';
+	}
+
+	/**
+	 * Gets the content from the wrapped Syslog
+	 *
+	 * @return string
+	 */
+	public function getContent()
+	{
+		return $this->content;
+	}
+
+	/**
+	 * {@inheritdoc}
+	 * @noinspection PhpMissingParentCallCommonInspection
+	 */
+	protected function syslogWrapper(int $level, string $entry)
+	{
+		$this->content .= $entry . PHP_EOL;
+	}
+}
diff --git a/tests/src/Core/Logger/VoidLoggerTest.php b/tests/src/Core/Logger/VoidLoggerTest.php
new file mode 100644
index 0000000000..a2134ce711
--- /dev/null
+++ b/tests/src/Core/Logger/VoidLoggerTest.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+use Friendica\Test\MockedTest;
+use Friendica\Core\Logger\Type\VoidLogger;
+use Psr\Log\LogLevel;
+
+class VoidLoggerTest extends MockedTest
+{
+	use LoggerDataTrait;
+
+	/**
+	 * Test if the profiler is profiling data
+	 * @dataProvider dataTests
+	 * @doesNotPerformAssertions
+	 */
+	public function testNormal($function, $message, array $context)
+	{
+		$logger = new VoidLogger();
+		$logger->$function($message, $context);
+	}
+
+	/**
+	 * Test the log() function
+	 * @doesNotPerformAssertions
+	 */
+	public function testProfilingLog()
+	{
+		$logger = new VoidLogger();
+		$logger->log(LogLevel::WARNING, 'test', ['a' => 'context']);
+	}
+}
diff --git a/tests/src/Core/Logger/WorkerLoggerTest.php b/tests/src/Core/Logger/WorkerLoggerTest.php
new file mode 100644
index 0000000000..0f751f2e4d
--- /dev/null
+++ b/tests/src/Core/Logger/WorkerLoggerTest.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Core\Logger;
+
+use Friendica\Core\Logger\Type\WorkerLogger;
+use Friendica\Test\MockedTest;
+use Psr\Log\LoggerInterface;
+
+class WorkerLoggerTest extends MockedTest
+{
+	private function assertUid($uid, $length = 7)
+	{
+		self::assertRegExp('/^[a-zA-Z0-9]{' . $length . '}+$/', $uid);
+	}
+
+	/**
+	 * Test the a id with length zero
+	 *
+	 */
+	public function testGetWorkerIdZero()
+	{
+		$this->expectException(\Error::class);
+		
+		$logger = \Mockery::mock(LoggerInterface::class);
+		new WorkerLogger($logger, 'test', 0);
+	}
+
+	/**
+	 * Test the generated Uid
+	 */
+	public function testGetWorkerId()
+	{
+		$logger = \Mockery::mock(LoggerInterface::class);
+		for ($i = 1; $i < 14; $i++) {
+			$workLogger = new WorkerLogger($logger, 'test', $i);
+			$uid = $workLogger->getWorkerId();
+			self::assertUid($uid, $i);
+		}
+	}
+
+	public function dataTest()
+	{
+		return [
+			'info' => [
+				'func' => 'info',
+				'msg' => 'the alert',
+				'context' => [],
+			],
+			'alert' => [
+				'func' => 'alert',
+				'msg' => 'another alert',
+				'context' => ['test' => 'it'],
+			],
+			'critical' => [
+				'func' => 'critical',
+				'msg' => 'Critical msg used',
+				'context' => ['test' => 'it', 'more' => 0.24545],
+			],
+			'error' => [
+				'func' => 'error',
+				'msg' => 21345623,
+				'context' => ['test' => 'it', 'yet' => true],
+			],
+			'warning' => [
+				'func' => 'warning',
+				'msg' => 'another alert' . 123523 . 324.54534 . 'test',
+				'context' => ['test' => 'it', 2 => 'nope'],
+			],
+			'notice' => [
+				'func' => 'notice',
+				'msg' => 'Notice' . ' alert' . true . 'with' . '\'strange\'' . 1.24. 'behavior',
+				'context' => ['test' => 'it'],
+			],
+			'debug' => [
+				'func' => 'debug',
+				'msg' => 'at last a debug',
+				'context' => ['test' => 'it'],
+			],
+		];
+	}
+
+	/**
+	 * Test the WorkerLogger with different log calls
+	 * @dataProvider dataTest
+	 */
+	public function testEmergency($func, $msg, $context = [])
+	{
+		$logger = \Mockery::mock(LoggerInterface::class);
+		$workLogger = new WorkerLogger($logger, 'test');
+		$testContext = $context;
+		$testContext['worker_id'] = $workLogger->getWorkerId();
+		$testContext['worker_cmd'] = 'test';
+		self::assertUid($testContext['worker_id']);
+		$logger
+			->shouldReceive($func)
+			->with($msg, $testContext)
+			->once();
+		$workLogger->$func($msg, $context);
+	}
+
+	/**
+	 * Test the WorkerLogger with
+	 */
+	public function testLog()
+	{
+		$logger = \Mockery::mock(LoggerInterface::class);
+		$workLogger = new WorkerLogger($logger, 'test');
+		$context = $testContext = ['test' => 'it'];
+		$testContext['worker_id'] = $workLogger->getWorkerId();
+		$testContext['worker_cmd'] = 'test';
+		self::assertUid($testContext['worker_id']);
+		$logger
+			->shouldReceive('log')
+			->with('debug', 'a test', $testContext)
+			->once();
+		$workLogger->log('debug', 'a test', $context);
+	}
+}
diff --git a/tests/src/Profile/ProfileField/Entity/ProfileFieldTest.php b/tests/src/Profile/ProfileField/Entity/ProfileFieldTest.php
index 275a1d5972..6e054428d8 100644
--- a/tests/src/Profile/ProfileField/Entity/ProfileFieldTest.php
+++ b/tests/src/Profile/ProfileField/Entity/ProfileFieldTest.php
@@ -11,7 +11,7 @@ use Friendica\Security\PermissionSet\Factory\PermissionSet as PermissionSetFacto
 use Friendica\Test\MockedTest;
 use Friendica\Util\ACLFormatter;
 use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Logger\VoidLogger;
+use Friendica\Core\Logger\Type\VoidLogger;
 use Mockery\MockInterface;
 
 class ProfileFieldTest extends MockedTest
diff --git a/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php b/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php
index 0a093db5a1..e27445d32b 100644
--- a/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php
+++ b/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php
@@ -5,7 +5,7 @@ namespace Friendica\Test\src\Security\TwoFactor\Factory;
 use Friendica\Security\TwoFactor\Factory\TrustedBrowser;
 use Friendica\Test\MockedTest;
 use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Logger\VoidLogger;
+use Friendica\Core\Logger\Type\VoidLogger;
 use Friendica\Util\Strings;
 
 class TrustedBrowserTest extends MockedTest
diff --git a/tests/src/Util/Logger/AbstractLoggerTest.php b/tests/src/Util/Logger/AbstractLoggerTest.php
deleted file mode 100644
index d008f4dc42..0000000000
--- a/tests/src/Util/Logger/AbstractLoggerTest.php
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-use Friendica\Test\MockedTest;
-use Friendica\Util\Introspection;
-use Mockery\MockInterface;
-use Psr\Log\LoggerInterface;
-use Psr\Log\LogLevel;
-
-abstract class AbstractLoggerTest extends MockedTest
-{
-	use LoggerDataTrait;
-
-	const LOGLINE = '/.* \[.*\]: .* \{.*\"file\":\".*\".*,.*\"line\":\d*,.*\"function\":\".*\".*,.*\"uid\":\".*\".*}/';
-
-	const FILE = 'test';
-	const LINE = 666;
-	const FUNC = 'myfunction';
-
-	/**
-	 * @var Introspection|MockInterface
-	 */
-	protected $introspection;
-
-	/**
-	 * Returns the content of the current logger instance
-	 *
-	 * @return string
-	 */
-	abstract protected function getContent();
-
-	/**
-	 * Returns the current logger instance
-	 *
-	 * @param string $level the default loglevel
-	 *
-	 * @return LoggerInterface
-	 */
-	abstract protected function getInstance($level = LogLevel::DEBUG);
-
-	protected function setUp(): void
-	{
-		parent::setUp();
-
-		$this->introspection = \Mockery::mock(Introspection::class);
-		$this->introspection->shouldReceive('getRecord')->andReturn([
-			'file'     => self::FILE,
-			'line'     => self::LINE,
-			'function' => self::FUNC
-		]);
-	}
-
-	public function assertLogline($string)
-	{
-		self::assertRegExp(self::LOGLINE, $string);
-	}
-
-	public function assertLoglineNums($assertNum, $string)
-	{
-		self::assertEquals($assertNum, preg_match_all(self::LOGLINE, $string));
-	}
-
-	/**
-	 * Test if the logger works correctly
-	 */
-	public function testNormal()
-	{
-		$logger = $this->getInstance();
-		$logger->emergency('working!');
-		$logger->alert('working too!');
-		$logger->debug('and now?');
-		$logger->notice('message', ['an' => 'context']);
-
-		$text = $this->getContent();
-		self::assertLogline($text);
-		self::assertLoglineNums(4, $text);
-	}
-
-	/**
-	 * Test if a log entry is correctly interpolated
-	 */
-	public function testPsrInterpolate()
-	{
-		$logger = $this->getInstance();
-
-		$logger->emergency('A {psr} test', ['psr' => 'working']);
-		$logger->alert('An {array} test', ['array' => ['it', 'is', 'working']]);
-		$text = $this->getContent();
-		self::assertStringContainsString('A working test', $text);
-		self::assertStringContainsString('An ["it","is","working"] test', $text);
-	}
-
-	/**
-	 * Test if a log entry contains all necessary information
-	 */
-	public function testContainsInformation()
-	{
-		$logger = $this->getInstance();
-		$logger->emergency('A test');
-
-		$text = $this->getContent();
-		self::assertStringContainsString('"file":"' . self::FILE . '"', $text);
-		self::assertStringContainsString('"line":' . self::LINE, $text);
-		self::assertStringContainsString('"function":"' . self::FUNC . '"', $text);
-	}
-
-	/**
-	 * Test if the minimum level is working
-	 */
-	public function testMinimumLevel()
-	{
-		$logger = $this->getInstance(LogLevel::NOTICE);
-
-		$logger->emergency('working');
-		$logger->alert('working');
-		$logger->error('working');
-		$logger->warning('working');
-		$logger->notice('working');
-		$logger->info('not working');
-		$logger->debug('not working');
-
-		$text = $this->getContent();
-
-		self::assertLoglineNums(5, $text);
-	}
-
-	/**
-	 * Test with different logging data
-	 * @dataProvider dataTests
-	 */
-	public function testDifferentTypes($function, $message, array $context)
-	{
-		$logger = $this->getInstance();
-		$logger->$function($message, $context);
-
-		$text = $this->getContent();
-
-		self::assertLogline($text);
-
-		self::assertStringContainsString(@json_encode($context), $text);
-	}
-
-	/**
-	 * Test a message with an exception
-	 */
-	public function testExceptionHandling()
-	{
-		$e = new \Exception("Test String", 123);
-		$eFollowUp = new \Exception("FollowUp", 456, $e);
-
-		$assertion = $eFollowUp->__toString();
-
-		$logger = $this->getInstance();
-		$logger->alert('test', ['e' => $eFollowUp]);
-		$text = $this->getContent();
-
-		self::assertLogline($text);
-
-		self::assertStringContainsString(@json_encode($assertion), $this->getContent());
-	}
-
-	public function testNoObjectHandling()
-	{
-		$logger = $this->getInstance();
-		$logger->alert('test', ['e' => ['test' => 'test']]);
-		$text = $this->getContent();
-
-		self::assertLogline($text);
-
-		self::assertStringContainsString('test', $this->getContent());
-	}
-}
diff --git a/tests/src/Util/Logger/LoggerDataTrait.php b/tests/src/Util/Logger/LoggerDataTrait.php
deleted file mode 100644
index 0bebe7d2cb..0000000000
--- a/tests/src/Util/Logger/LoggerDataTrait.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-trait LoggerDataTrait
-{
-	public function dataTests()
-	{
-		return [
-			'emergency' => [
-				'function' => 'emergency',
-				'message' => 'test',
-				'context' => ['a' => 'context'],
-			],
-			'alert' => [
-				'function' => 'alert',
-				'message' => 'test {test}',
-				'context' => ['a' => 'context', 2 => 'so', 'test' => 'works'],
-			],
-			'critical' => [
-				'function' => 'critical',
-				'message' => 'test crit 2345',
-				'context' => ['a' => 'context', 'wit' => ['more', 'array']],
-			],
-			'error' => [
-				'function' => 'error',
-				'message' => 2.554,
-				'context' => [],
-			],
-			'warning' => [
-				'function' => 'warning',
-				'message' => 'test warn',
-				'context' => ['a' => 'context'],
-			],
-			'notice' => [
-				'function' => 'notice',
-				'message' => 2346,
-				'context' => ['a' => 'context'],
-			],
-			'info' => [
-				'function' => 'info',
-				'message' => null,
-				'context' => ['a' => 'context'],
-			],
-			'debug' => [
-				'function' => 'debug',
-				'message' => true,
-				'context' => ['a' => false],
-			],
-		];
-	}
-}
diff --git a/tests/src/Util/Logger/ProfilerLoggerTest.php b/tests/src/Util/Logger/ProfilerLoggerTest.php
deleted file mode 100644
index 7b62446142..0000000000
--- a/tests/src/Util/Logger/ProfilerLoggerTest.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-use Friendica\Test\MockedTest;
-use Friendica\Util\Logger\ProfilerLogger;
-use Friendica\Util\Profiler;
-use Mockery\MockInterface;
-use Psr\Log\LoggerInterface;
-use Psr\Log\LogLevel;
-
-class ProfilerLoggerTest extends MockedTest
-{
-	use LoggerDataTrait;
-
-	/**
-	 * @var LoggerInterface|MockInterface
-	 */
-	private $logger;
-	/**
-	 * @var Profiler|MockInterface
-	 */
-	private $profiler;
-
-	protected function setUp(): void
-	{
-		parent::setUp();
-
-		$this->logger = \Mockery::mock(LoggerInterface::class);
-		$this->profiler = \Mockery::mock(Profiler::class);
-	}
-
-	/**
-	 * Test if the profiler is profiling data
-	 * @dataProvider dataTests
-	 * @doesNotPerformAssertions
-	 */
-	public function testProfiling($function, $message, array $context)
-	{
-		$logger = new ProfilerLogger($this->logger, $this->profiler);
-
-		$this->logger->shouldReceive($function)->with($message, $context)->once();
-		$this->profiler->shouldReceive('startRecording')->with('file')->once();
-		$this->profiler->shouldReceive('stopRecording');
-		$this->profiler->shouldReceive('saveTimestamp');
-		$logger->$function($message, $context);
-	}
-
-	/**
-	 * Test the log() function
-	 * @doesNotPerformAssertions
-	 */
-	public function testProfilingLog()
-	{
-		$logger = new ProfilerLogger($this->logger, $this->profiler);
-
-		$this->logger->shouldReceive('log')->with(LogLevel::WARNING, 'test', ['a' => 'context'])->once();
-		$this->profiler->shouldReceive('startRecording')->with('file')->once();
-		$this->profiler->shouldReceive('stopRecording');
-		$this->profiler->shouldReceive('saveTimestamp');
-
-		$logger->log(LogLevel::WARNING, 'test', ['a' => 'context']);
-	}
-}
diff --git a/tests/src/Util/Logger/StreamLoggerTest.php b/tests/src/Util/Logger/StreamLoggerTest.php
deleted file mode 100644
index 8599e08f45..0000000000
--- a/tests/src/Util/Logger/StreamLoggerTest.php
+++ /dev/null
@@ -1,211 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-use Friendica\Util\FileSystem;
-use Friendica\Test\Util\VFSTrait;
-use Friendica\Util\Logger\StreamLogger;
-use org\bovigo\vfs\vfsStream;
-use org\bovigo\vfs\vfsStreamFile;
-use Psr\Log\LogLevel;
-
-class StreamLoggerTest extends AbstractLoggerTest
-{
-	use VFSTrait;
-
-	/**
-	 * @var vfsStreamFile
-	 */
-	private $logfile;
-
-	/**
-	 * @var Filesystem
-	 */
-	private $fileSystem;
-
-	protected function setUp(): void
-	{
-		parent::setUp();
-
-		$this->setUpVfsDir();
-
-		$this->fileSystem = new FileSystem();
-	}
-
-	/**
-	 * {@@inheritdoc}
-	 */
-	protected function getInstance($level = LogLevel::DEBUG)
-	{
-		$this->logfile = vfsStream::newFile('friendica.log')
-			->at($this->root);
-
-		$logger = new StreamLogger('test', $this->logfile->url(), $this->introspection, $this->fileSystem, $level);
-
-		return $logger;
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	protected function getContent()
-	{
-		return $this->logfile->getContent();
-	}
-
-	/**
-	 * Test if a stream is working
-	 */
-	public function testStream()
-	{
-		$logfile = vfsStream::newFile('friendica.log')
-			->at($this->root);
-
-		$filehandler = fopen($logfile->url(), 'ab');
-
-		$logger = new StreamLogger('test', $filehandler, $this->introspection, $this->fileSystem);
-		$logger->emergency('working');
-
-		$text = $logfile->getContent();
-
-		self::assertLogline($text);
-	}
-
-	/**
-	 * Test if the close statement is working
-	 */
-	public function testClose()
-	{
-		$logfile = vfsStream::newFile('friendica.log')
-			->at($this->root);
-
-		$logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
-		$logger->emergency('working');
-		$logger->close();
-		// close doesn't affect
-		$logger->emergency('working too');
-
-		$text = $logfile->getContent();
-
-		self::assertLoglineNums(2, $text);
-	}
-
-	/**
-	 * Test when a file isn't set
-	 */
-	public function testNoUrl()
-	{
-		$this->expectException(\LogicException::class);
-		$this->expectExceptionMessage("Missing stream URL.");
-
-		$logger = new StreamLogger('test', '', $this->introspection, $this->fileSystem);
-
-		$logger->emergency('not working');
-	}
-
-	/**
-	 * Test when a file cannot be opened
-	 */
-	public function testWrongUrl()
-	{
-		$this->expectException(\UnexpectedValueException::class);
-		$this->expectExceptionMessageMatches("/The stream or file .* could not be opened: .* /");
-
-		$logfile = vfsStream::newFile('friendica.log')
-			->at($this->root)->chmod(0);
-
-		$logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
-
-		$logger->emergency('not working');
-	}
-
-	/**
-	 * Test when the directory cannot get created
-	 */
-	public function testWrongDir()
-	{
-		$this->expectException(\UnexpectedValueException::class);
-		$this->expectExceptionMessageMatches("/Directory .* cannot get created: .* /");
-
-		static::markTestIncomplete('We need a platform independent way to set directory to readonly');
-
-		$logger = new StreamLogger('test', '/$%/wrong/directory/file.txt', $this->introspection, $this->fileSystem);
-
-		$logger->emergency('not working');
-	}
-
-	/**
-	 * Test when the minimum level is not valid
-	 */
-	public function testWrongMinimumLevel()
-	{
-		$this->expectException(\InvalidArgumentException::class);
-		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
-
-		$logger = new StreamLogger('test', 'file.text', $this->introspection, $this->fileSystem, 'NOPE');
-	}
-
-	/**
-	 * Test when the minimum level is not valid
-	 */
-	public function testWrongLogLevel()
-	{
-		$this->expectException(\InvalidArgumentException::class);
-		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
-
-		$logfile = vfsStream::newFile('friendica.log')
-			->at($this->root);
-
-		$logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
-
-		$logger->log('NOPE', 'a test');
-	}
-
-	/**
-	 * Test when the file is null
-	 */
-	public function testWrongFile()
-	{
-		$this->expectException(\InvalidArgumentException::class);
-		$this->expectExceptionMessage("A stream must either be a resource or a string.");
-
-		$logger = new StreamLogger('test', null, $this->introspection, $this->fileSystem);
-	}
-
-	/**
-	 * Test a relative path
-	 * @doesNotPerformAssertions
-	 */
-	public function testRealPath()
-	{
-		static::markTestSkipped('vfsStream isn\'t compatible with chdir, so not testable.');
-
-		$logfile = vfsStream::newFile('friendica.log')
-		                    ->at($this->root);
-
-		chdir($this->root->getChild('logs')->url());
-
-		$logger = new StreamLogger('test', '../friendica.log' , $this->introspection, $this->fileSystem);
-
-		$logger->info('Test');
-	}
-}
diff --git a/tests/src/Util/Logger/SyslogLoggerTest.php b/tests/src/Util/Logger/SyslogLoggerTest.php
deleted file mode 100644
index e93e43dd5c..0000000000
--- a/tests/src/Util/Logger/SyslogLoggerTest.php
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-use Friendica\Util\Logger\SyslogLogger;
-use Psr\Log\LogLevel;
-
-class SyslogLoggerTest extends AbstractLoggerTest
-{
-	/**
-	 * @var SyslogLoggerWrapper
-	 */
-	private $logger;
-
-	protected function setUp(): void
-	{
-		parent::setUp();
-
-		$this->introspection->shouldReceive('addClasses')->with([SyslogLogger::class]);
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	protected function getContent()
-	{
-		return $this->logger->getContent();
-	}
-
-	/**
-	 * {@inheritdoc}
-	 */
-	protected function getInstance($level = LogLevel::DEBUG)
-	{
-		$this->logger = new SyslogLoggerWrapper('test', $this->introspection, $level);
-
-		return $this->logger;
-	}
-
-
-	/**
-	 * Test when the minimum level is not valid
-	 */
-	public function testWrongMinimumLevel()
-	{
-		$this->expectException(\InvalidArgumentException::class);
-		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
-		
-		$logger = new SyslogLoggerWrapper('test', $this->introspection, 'NOPE');
-	}
-
-	/**
-	 * Test when the minimum level is not valid
-	 */
-	public function testWrongLogLevel()
-	{
-		$this->expectException(\InvalidArgumentException::class);
-		$this->expectExceptionMessageMatches("/The level \".*\" is not valid./");
-
-		$logger = new SyslogLoggerWrapper('test', $this->introspection);
-
-		$logger->log('NOPE', 'a test');
-	}
-
-	/**
-	 * Test when the logfacility is wrong (string)
-	 */
-	public function testServerException()
-	{
-		if (PHP_MAJOR_VERSION < 8) {
-			$this->expectException(\UnexpectedValueException::class);
-			$this->expectExceptionMessageMatches("/Can\'t open syslog for ident \".*\" and facility \".*\": .* /");
-		} else {
-			$this->expectException(\TypeError::class);
-			$this->expectExceptionMessage("openlog(): Argument #3 (\$facility) must be of type int, string given");
-		}
-
-		$logger = new SyslogLoggerWrapper('test', $this->introspection, LogLevel::DEBUG, null, 'a string');
-		$logger->emergency('not working');
-	}
-
-	/**
-	 * Test the close() method
-	 * @doesNotPerformAssertions
-	 */
-	public function testClose()
-	{
-		$logger = new SyslogLoggerWrapper('test', $this->introspection);
-		$logger->emergency('test');
-		$logger->close();
-		// Reopened itself
-		$logger->emergency('test');
-	}
-}
diff --git a/tests/src/Util/Logger/SyslogLoggerWrapper.php b/tests/src/Util/Logger/SyslogLoggerWrapper.php
deleted file mode 100644
index 710899cc2b..0000000000
--- a/tests/src/Util/Logger/SyslogLoggerWrapper.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-use Friendica\Util\Introspection;
-use Friendica\Util\Logger\SyslogLogger;
-use Psr\Log\LogLevel;
-
-/**
- * Wraps the SyslogLogger for replacing the syslog call with a string field.
- */
-class SyslogLoggerWrapper extends SyslogLogger
-{
-	private $content;
-
-	public function __construct($channel, Introspection $introspection, $level = LogLevel::NOTICE, $logOpts = LOG_PID, $logFacility = LOG_USER)
-	{
-		parent::__construct($channel, $introspection, $level, $logOpts, $logFacility);
-
-		$this->content = '';
-	}
-
-	/**
-	 * Gets the content from the wrapped Syslog
-	 *
-	 * @return string
-	 */
-	public function getContent()
-	{
-		return $this->content;
-	}
-
-	/**
-	 * {@inheritdoc}
-	 * @noinspection PhpMissingParentCallCommonInspection
-	 */
-	protected function syslogWrapper($level, $entry)
-	{
-		$this->content .= $entry . PHP_EOL;
-	}
-}
diff --git a/tests/src/Util/Logger/VoidLoggerTest.php b/tests/src/Util/Logger/VoidLoggerTest.php
deleted file mode 100644
index 75b2d1a8b8..0000000000
--- a/tests/src/Util/Logger/VoidLoggerTest.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-use Friendica\Test\MockedTest;
-use Friendica\Util\Logger\VoidLogger;
-use Psr\Log\LogLevel;
-
-class VoidLoggerTest extends MockedTest
-{
-	use LoggerDataTrait;
-
-	/**
-	 * Test if the profiler is profiling data
-	 * @dataProvider dataTests
-	 * @doesNotPerformAssertions
-	 */
-	public function testNormal($function, $message, array $context)
-	{
-		$logger = new VoidLogger();
-		$logger->$function($message, $context);
-	}
-
-	/**
-	 * Test the log() function
-	 * @doesNotPerformAssertions
-	 */
-	public function testProfilingLog()
-	{
-		$logger = new VoidLogger();
-		$logger->log(LogLevel::WARNING, 'test', ['a' => 'context']);
-	}
-}
diff --git a/tests/src/Util/Logger/WorkerLoggerTest.php b/tests/src/Util/Logger/WorkerLoggerTest.php
deleted file mode 100644
index 06fae3c381..0000000000
--- a/tests/src/Util/Logger/WorkerLoggerTest.php
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Test\src\Util\Logger;
-
-use Friendica\Test\MockedTest;
-use Friendica\Util\Logger\WorkerLogger;
-use Psr\Log\LoggerInterface;
-
-class WorkerLoggerTest extends MockedTest
-{
-	private function assertUid($uid, $length = 7)
-	{
-		self::assertRegExp('/^[a-zA-Z0-9]{' . $length . '}+$/', $uid);
-	}
-
-	/**
-	 * Test the a id with length zero
-	 *
-	 */
-	public function testGetWorkerIdZero()
-	{
-		$this->expectException(\Error::class);
-		
-		$logger = \Mockery::mock(LoggerInterface::class);
-		new WorkerLogger($logger, 'test', 0);
-	}
-
-	/**
-	 * Test the generated Uid
-	 */
-	public function testGetWorkerId()
-	{
-		$logger = \Mockery::mock(LoggerInterface::class);
-		for ($i = 1; $i < 14; $i++) {
-			$workLogger = new WorkerLogger($logger, 'test', $i);
-			$uid = $workLogger->getWorkerId();
-			self::assertUid($uid, $i);
-		}
-	}
-
-	public function dataTest()
-	{
-		return [
-			'info' => [
-				'func' => 'info',
-				'msg' => 'the alert',
-				'context' => [],
-			],
-			'alert' => [
-				'func' => 'alert',
-				'msg' => 'another alert',
-				'context' => ['test' => 'it'],
-			],
-			'critical' => [
-				'func' => 'critical',
-				'msg' => 'Critical msg used',
-				'context' => ['test' => 'it', 'more' => 0.24545],
-			],
-			'error' => [
-				'func' => 'error',
-				'msg' => 21345623,
-				'context' => ['test' => 'it', 'yet' => true],
-			],
-			'warning' => [
-				'func' => 'warning',
-				'msg' => 'another alert' . 123523 . 324.54534 . 'test',
-				'context' => ['test' => 'it', 2 => 'nope'],
-			],
-			'notice' => [
-				'func' => 'notice',
-				'msg' => 'Notice' . ' alert' . true . 'with' . '\'strange\'' . 1.24. 'behavior',
-				'context' => ['test' => 'it'],
-			],
-			'debug' => [
-				'func' => 'debug',
-				'msg' => 'at last a debug',
-				'context' => ['test' => 'it'],
-			],
-		];
-	}
-
-	/**
-	 * Test the WorkerLogger with different log calls
-	 * @dataProvider dataTest
-	 */
-	public function testEmergency($func, $msg, $context = [])
-	{
-		$logger = \Mockery::mock(LoggerInterface::class);
-		$workLogger = new WorkerLogger($logger, 'test');
-		$testContext = $context;
-		$testContext['worker_id'] = $workLogger->getWorkerId();
-		$testContext['worker_cmd'] = 'test';
-		self::assertUid($testContext['worker_id']);
-		$logger
-			->shouldReceive($func)
-			->with($msg, $testContext)
-			->once();
-		$workLogger->$func($msg, $context);
-	}
-
-	/**
-	 * Test the WorkerLogger with
-	 */
-	public function testLog()
-	{
-		$logger = \Mockery::mock(LoggerInterface::class);
-		$workLogger = new WorkerLogger($logger, 'test');
-		$context = $testContext = ['test' => 'it'];
-		$testContext['worker_id'] = $workLogger->getWorkerId();
-		$testContext['worker_cmd'] = 'test';
-		self::assertUid($testContext['worker_id']);
-		$logger
-			->shouldReceive('log')
-			->with('debug', 'a test', $testContext)
-			->once();
-		$workLogger->log('debug', 'a test', $context);
-	}
-}