From e310b235fa2ea954b65f6412187af2f4c893c3f6 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 20 Jun 2024 23:10:51 +0200 Subject: [PATCH] Async logger --- src/Logger.php | 44 ++++++++++++++++++++++++++++++++++++++++--- src/Server/Server.php | 1 + 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Logger.php b/src/Logger.php index bd0bf58..45a1306 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -11,6 +11,8 @@ namespace TelegramApiServer; +use Amp\ByteStream\Pipe; +use Amp\ByteStream\WritableStream; use danog\MadelineProto; use DateTimeInterface; use Psr\Log\AbstractLogger; @@ -18,6 +20,10 @@ use Psr\Log\InvalidArgumentException; use Psr\Log\LogLevel; use TelegramApiServer\EventObservers\LogObserver; use Throwable; + +use function Amp\async; +use function Amp\ByteStream\getStdout; +use function Amp\ByteStream\pipe; use function get_class; use function gettype; use function is_object; @@ -56,6 +62,12 @@ class Logger extends AbstractLogger public int $minLevelIndex; private array $formatter; + private WritableStream $stdout; + /** + * @var array + */ + private static array $closePromises = []; + protected function __construct(string $minLevel = LogLevel::WARNING, callable $formatter = null) { if (null === $minLevel) { @@ -83,7 +95,18 @@ class Logger extends AbstractLogger } $this->minLevelIndex = self::$levels[$minLevel]; - $this->formatter = $formatter ?: [$this, 'format']; + $this->formatter = $formatter ?: $this->format(...); + $pipe = new Pipe(PHP_INT_MAX); + $this->stdout = $pipe->getSink(); + $source = $pipe->getSource(); + $promise = async(static function () use ($source, &$promise): void { + try { + pipe($source, getStdout()); + } finally { + unset(self::$closePromises[spl_object_id($promise)]); + } + }); + self::$closePromises[spl_object_id($promise)] = [$this->stdout, $promise]; } public static function getInstance(): Logger @@ -114,8 +137,23 @@ class Logger extends AbstractLogger } $formatter = $this->formatter; - /** @see Logger::format */ - echo $formatter($level, $message, $context); + $data = $formatter($level, $message, $context);; + try { + $this->stdout->write($data); + } catch (\Throwable) { + echo $data; + } + } + + /** + * @internal Internal function used to flush the log buffer on shutdown. + */ + public static function finalize(): void + { + foreach (self::$closePromises as [$stdout, $promise]) { + $stdout->close(); + $promise->await(); + } } private function format(string $level, string $message, array $context): string diff --git a/src/Server/Server.php b/src/Server/Server.php index 718c9fd..36eccf8 100644 --- a/src/Server/Server.php +++ b/src/Server/Server.php @@ -70,6 +70,7 @@ class Server info("Stopping http server"); $server->stop(); } + Logger::finalize(); } /**