Skip to content

Commit

Permalink
Add Support for Context Arrays in Logging (#4)
Browse files Browse the repository at this point in the history
Added an ability to send context with log message
  • Loading branch information
butschster authored Dec 22, 2023
1 parent d622d68 commit 555a319
Show file tree
Hide file tree
Showing 6 changed files with 305 additions and 98 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"require": {
"php": ">=8.1",
"ext-json": "*",
"spiral/goridge": "^3.1 || ^4.0"
"spiral/goridge": "^3.1 || ^4.0",
"roadrunner-php/roadrunner-api-dto": "^1.4"
},
"autoload": {
"psr-4": {
Expand Down
13 changes: 7 additions & 6 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false"
colors="true" processIsolation="false" stopOnFailure="false" stopOnError="false" stderr="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" cacheDirectory=".phpunit.cache"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd" cacheDirectory=".phpunit.cache"
backupStaticProperties="false">
<coverage>
<include>
<directory>src</directory>
</include>
</coverage>
<coverage/>
<testsuites>
<testsuite name="Test Suite">
<directory suffix="Test.php">tests</directory>
Expand All @@ -17,4 +13,9 @@
<ini name="error_reporting" value="-1"/>
<ini name="memory_limit" value="-1"/>
</php>
<source>
<include>
<directory>src</directory>
</include>
</source>
</phpunit>
14 changes: 14 additions & 0 deletions src/LogLevel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace RoadRunner\Logger;

enum LogLevel
{
case Error;
case Warning;
case Info;
case Debug;
case Log;
}
130 changes: 103 additions & 27 deletions src/Logger.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,118 @@

namespace RoadRunner\Logger;

use RoadRunner\AppLogger\DTO\V1\LogAttrs;
use RoadRunner\AppLogger\DTO\V1\LogEntry;
use RoadRunner\Logger\Exception\LoggerException;
use Spiral\Goridge\RPC\Codec\ProtobufCodec;
use Spiral\Goridge\RPC\CodecInterface;
use Spiral\Goridge\RPC\Exception\ServiceException;
use Spiral\Goridge\RPC\RPCInterface;

/**
* @psalm-type TMessage = string|\Stringable
* @psalm-type TContext = array<string, mixed>
*/
final class Logger
{
private readonly RPCInterface $rpc;
private readonly CodecInterface $codec;

public function __construct(RPCInterface $rpc)
{
$this->rpc = $rpc->withServicePrefix('app');
$this->codec = new ProtobufCodec();
}

public function error(string $message): void
/**
* Log an emergency message to the logs.
*
* @param TMessage $message
* @param TContext $context
*/
public function error(string|\Stringable $message, array $context = []): void
{
try {
$this->rpc->call('Error', $message);
} catch (ServiceException $e) {
$this->handleError($e);
}
$this->send(LogLevel::Error, $message, $context);
}

public function warning(string $message): void
/**
* Log a warning message to the logs.
*
* @param TMessage $message
* @param TContext $context
*/
public function warning(string|\Stringable $message, array $context = []): void
{
try {
$this->rpc->call('Warning', $message);
} catch (ServiceException $e) {
$this->handleError($e);
}
$this->send(LogLevel::Warning, $message, $context);
}

public function info(string $message): void
/**
* Log an informational message to the logs.
*
* @param TMessage $message
* @param TContext $context
*/
public function info(string $message, array $context = []): void
{
try {
$this->rpc->call('Info', $message);
} catch (ServiceException $e) {
$this->handleError($e);
}
$this->send(LogLevel::Info, $message, $context);
}

public function debug(string $message): void
/**
* Log a debug message to the logs.
*
* @param TMessage $message
* @param TContext $context
*/
public function debug(string|\Stringable $message, array $context = []): void
{
try {
$this->rpc->call('Debug', $message);
} catch (ServiceException $e) {
$this->handleError($e);
}
$this->send(LogLevel::Debug, $message, $context);
}

public function log(string $message): void
/**
* Log a message to the logs.
*
* @param TMessage $message
* @param TContext $context
*/
public function log(string|\Stringable $message, array $context = []): void
{
$this->send(LogLevel::Log, $message, $context);
}

/**
* @param TContext $context
* @throws LoggerException
*/
private function send(LogLevel $level, string|\Stringable $message, array $context = []): void
{
try {
$this->rpc->call('Log', $message);
if ($context === []) {
$this->rpc->call($level->name, (string)$message);
} else {
$attrs = [];

foreach ($context as $key => $value) {
try {
$attrs[] = new LogAttrs(data: [
'key' => $key,
'value' => $this->prepareValue($value),
]);
} catch (\Throwable) {
// We can't log this value, so we just skip it.
}
}

$level = $level->name . 'WithContext';
$this->rpc
->withCodec($this->codec)
->call(
$level,
new LogEntry([
'message' => (string)$message,
'log_attrs' => $attrs,
]),
);
}
} catch (ServiceException $e) {
$this->handleError($e);
}
Expand All @@ -68,6 +128,22 @@ private function handleError(ServiceException $e): never
{
$message = \str_replace(["\t", "\n"], ' ', $e->getMessage());

throw new Exception\LoggerException($message, (int)$e->getCode(), $e);
throw new Exception\LoggerException($message, $e->getCode(), $e);
}

/**
* @throws \Throwable
*/
private function prepareValue(mixed $value): string
{
if (\is_string($value)) {
return $value;
}

if ($value instanceof \Stringable) {
return (string)$value;
}

return \json_encode($value, JSON_THROW_ON_ERROR);
}
}
Loading

0 comments on commit 555a319

Please sign in to comment.