chore: add deployment configurations and tests for logger and dispatcher (#17)
All checks were successful
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 1m40s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 1m36s
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 2m4s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Successful in 2m24s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 2m46s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Successful in 1m27s
🏗️✨ Build Workflow / 🖥️ 🔨 Build (push) Successful in 16m7s
🏗️✨ Build Workflow / 🖥️ 🔨 Build Migrations (push) Successful in 1m29s

Reviewed-on: #17
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
This commit was merged in pull request #17.
This commit is contained in:
2025-11-13 19:38:26 +00:00
committed by Siteworx Pro Gitea
parent 5542ad1e75
commit 7fe2722fc1
12 changed files with 477 additions and 11 deletions

View File

@@ -6,10 +6,12 @@ namespace Siteworxpro\App\Log;
use Monolog\Formatter\JsonFormatter;
use Monolog\Handler\StreamHandler;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use RoadRunner\Logger\Logger as RRLogger;
use Spiral\Goridge\RPC\RPC;
use Siteworxpro\App\Services\Facades\RoadRunnerLogger;
/**
* Logger implementation that conforms to PSR-3 (`Psr\Log\LoggerInterface`).
@@ -30,9 +32,9 @@ class Logger implements LoggerInterface
/**
* RoadRunner RPC logger instance when running under RoadRunner.
*
* @var RRLogger|null
* @var RRLogger | LoggerInterface | null
*/
private ?RRLogger $rpcLogger = null;
private RRLogger | LoggerInterface | null $rpcLogger = null;
/**
* Monolog logger used as a fallback to write JSON-formatted logs to stdout.
@@ -66,21 +68,28 @@ class Logger implements LoggerInterface
* @param string $level Minimum level to log (PSR-3 level string). Messages with
* a higher numeric value in `$levels` will be ignored.
*
* @param resource | null $streamOutput Optional stream handler for Monolog.
*
* The default is `LogLevel::DEBUG` (log everything).
*
* If `$_SERVER['RR_RPC']` is set, an RPC connection will be attempted at
* $_SERVER['RR_RPC'] and a RoadRunner RPC logger will be used.
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function __construct(private readonly string $level = LogLevel::DEBUG)
{
public function __construct(
private readonly string $level = LogLevel::DEBUG,
$streamOutput = null,
) {
if (isset($_SERVER['RR_RPC'])) {
$rpc = RPC::create($_SERVER['RR_RPC']);
$this->rpcLogger = new RRLogger($rpc);
$this->rpcLogger = RoadRunnerLogger::getFacadeRoot();
}
$this->monologLogger = new \Monolog\Logger('app_logger');
$formatter = new JsonFormatter();
$this->monologLogger->pushHandler(new StreamHandler('php://stdout')->setFormatter($formatter));
$stream = $streamOutput ?? 'php://stdout';
$this->monologLogger->pushHandler(new StreamHandler($stream)->setFormatter($formatter));
}
/**
@@ -192,7 +201,7 @@ class Logger implements LoggerInterface
*/
public function log($level, \Stringable|string $message, array $context = []): void
{
if ($this->levels[$level] > $this->levels[$this->level]) {
if (isset($this->levels[$level]) && $this->levels[$level] > $this->levels[$this->level]) {
return;
}
@@ -215,7 +224,7 @@ class Logger implements LoggerInterface
$this->rpcLogger->error((string)$message, $context);
break;
default:
$this->rpcLogger->log((string)$message, $context);
$this->rpcLogger->log($level, (string)$message, $context);
break;
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use RoadRunner\Logger\Logger;
use Siteworxpro\App\Services\Facade;
use Spiral\Goridge\RPC\RPC;
class RoadRunnerLogger extends Facade
{
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public static function getFacadeRoot(): mixed
{
$container = static::getFacadeContainer();
if ($container && $container->has(Logger::class) === false) {
$rpc = RPC::create($_SERVER['RR_RPC']);
$logger = new Logger($rpc);
$container->bind(static::getFacadeAccessor(), function () use ($logger) {
return $logger;
});
return $logger;
}
return $container->get(Logger::class);
}
protected static function getFacadeAccessor(): string
{
return Logger::class;
}
}