Skip to content

Commit

Permalink
Upgrade to monolog3
Browse files Browse the repository at this point in the history
  • Loading branch information
jderusse committed Jan 25, 2024
1 parent 50c380a commit 848de7e
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 48 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"email": "[email protected]"
}],
"require": {
"monolog/monolog": "^2.0",
"monolog/monolog": "^3.0",
"nyholm/dsn": "^2.0",
"nyholm/psr7": "^1.5",
"open-telemetry/api": ">=1.0.2",
Expand Down
43 changes: 33 additions & 10 deletions spec/Tracing/Instrumentation/LogHandler/TracingHandlerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
namespace spec\Instrumentation\Tracing\Instrumentation\LogHandler;

use Instrumentation\Tracing\Instrumentation\MainSpanContextInterface;
use Monolog\Logger;
use Monolog\DateTimeImmutable;
use Monolog\Level;
use Monolog\LogRecord;
use OpenTelemetry\API\Trace\SpanInterface;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use PhpSpec\ObjectBehavior;
Expand All @@ -21,13 +23,20 @@ public function it_adds_event_from_all_channels(
MainSpanContextInterface $mainSpanContext,
SpanInterface $span
): void {
$this->beConstructedWith($tracerProvider, $mainSpanContext, Logger::INFO, []);
$this->beConstructedWith($tracerProvider, $mainSpanContext, Level::Info, []);

$mainSpanContext->getMainSpan()->willReturn($span);
$span->addEvent(Argument::any())->willReturn($span);

$this->handle(['message' => 'Error from channel "foo"', 'channel' => 'foo', 'level' => Logger::ERROR, 'extra' => [], 'context' => []]);
$this->handle(['message' => 'Error from channel "bar"', 'channel' => 'bar', 'level' => Logger::ERROR, 'extra' => [], 'context' => []]);
$record = new LogRecord(
new DateTimeImmutable(true),
'',
Level::Error,
'',
);

$this->handle($record->with(['message' => 'Error from channel "foo"', 'channel' => 'foo']));
$this->handle($record->with(['message' => 'Error from channel "bar"', 'channel' => 'bar']));

$span->addEvent('Error from channel "foo"')->shouldHaveBeenCalled();
$span->addEvent('Error from channel "bar"')->shouldHaveBeenCalled();
Expand All @@ -38,13 +47,20 @@ public function it_adds_event_from_specific_channel_only(
MainSpanContextInterface $mainSpanContext,
SpanInterface $span
): void {
$this->beConstructedWith($tracerProvider, $mainSpanContext, Logger::INFO, ['foo']);
$this->beConstructedWith($tracerProvider, $mainSpanContext, Level::Info, ['foo']);

$mainSpanContext->getMainSpan()->willReturn($span);
$span->addEvent(Argument::any())->willReturn($span);

$this->handle(['message' => 'Error from channel "foo"', 'channel' => 'foo', 'level' => Logger::ERROR, 'extra' => [], 'context' => []]);
$this->handle(['message' => 'Error from channel "bar"', 'channel' => 'bar', 'level' => Logger::ERROR, 'extra' => [], 'context' => []]);
$record = new LogRecord(
new DateTimeImmutable(true),
'',
Level::Error,
'',
);

$this->handle($record->with(['message' => 'Error from channel "foo"', 'channel' => 'foo']));
$this->handle($record->with(['message' => 'Error from channel "bar"', 'channel' => 'bar']));

$span->addEvent('Error from channel "foo"')->shouldHaveBeenCalled();
$span->addEvent('Error from channel "bar"')->shouldNotHaveBeenCalled();
Expand All @@ -55,13 +71,20 @@ public function it_ignores_event_from_specific_channel(
MainSpanContextInterface $mainSpanContext,
SpanInterface $span
): void {
$this->beConstructedWith($tracerProvider, $mainSpanContext, Logger::INFO, ['!foo']);
$this->beConstructedWith($tracerProvider, $mainSpanContext, Level::Info, ['!foo']);

$mainSpanContext->getMainSpan()->willReturn($span);
$span->addEvent(Argument::any())->willReturn($span);

$this->handle(['message' => 'Error from channel "foo"', 'channel' => 'foo', 'level' => Logger::ERROR, 'extra' => [], 'context' => []]);
$this->handle(['message' => 'Error from channel "bar"', 'channel' => 'bar', 'level' => Logger::ERROR, 'extra' => [], 'context' => []]);
$record = new LogRecord(
new DateTimeImmutable(true),
'',
Level::Error,
'',
);

$this->handle($record->with(['message' => 'Error from channel "foo"', 'channel' => 'foo']));
$this->handle($record->with(['message' => 'Error from channel "bar"', 'channel' => 'bar']));

$span->addEvent('Error from channel "foo"')->shouldNotHaveBeenCalled();
$span->addEvent('Error from channel "bar"')->shouldHaveBeenCalled();
Expand Down
7 changes: 3 additions & 4 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
namespace Instrumentation\DependencyInjection;

use Monolog\Level;
use Monolog\Logger;
use OpenTelemetry\SemConv\ResourceAttributes;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
Expand Down Expand Up @@ -90,9 +89,9 @@ public function getConfigTreeBuilder(): TreeBuilder
->addDefaultsIfNotSet()
->children()
->enumNode('level')
->defaultValue(Logger::INFO)
->values(method_exists(Logger::class, 'getLevels') ? Logger::getLevels() : Level::cases()) // @phpstan-ignore-line
->info(sprintf('One of the %s levels.', Logger::class))
->defaultValue(Level::Info)
->values(Level::cases())
->info(sprintf('One of the %s levels.', Level::class))
->end()
->arrayNode('channels')
->defaultValue([])
Expand Down
3 changes: 2 additions & 1 deletion src/Logging/Formatter/JsonFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
namespace Instrumentation\Logging\Formatter;

use Monolog\Formatter\JsonFormatter as BaseJsonFormatter;
use Monolog\LogRecord;
use Monolog\Utils;

class JsonFormatter extends BaseJsonFormatter
{
private ?int $lengthLimit = null;

public function format(array $record): string
public function format(LogRecord $record): string
{
$normalized = $this->normalize($record);

Expand Down
15 changes: 6 additions & 9 deletions src/Logging/Processor/NormalizeExceptionProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@
namespace Instrumentation\Logging\Processor;

use Instrumentation\Semantics\Normalizer\ExceptionNormalizer;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;

class NormalizeExceptionProcessor
class NormalizeExceptionProcessor implements ProcessorInterface
{
/**
* @param array<mixed> $record
*
* @return array<mixed>
*/
public function __invoke(array $record): array
public function __invoke(LogRecord $record): LogRecord
{
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
$record['context']['exception'] = ExceptionNormalizer::normalizeException($record['context']['exception']);
if (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) {
$record->context['exception'] = ExceptionNormalizer::normalizeException($record->context['exception']);

Check failure on line 19 in src/Logging/Processor/NormalizeExceptionProcessor.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1)

Readonly property Monolog\LogRecord::$context is assigned outside of its declaring class.
}

return $record;
Expand Down
32 changes: 16 additions & 16 deletions src/Logging/Processor/TraceContextProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

namespace Instrumentation\Logging\Processor;

use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use OpenTelemetry\SDK\Trace\Span;

class TraceContextProcessor
class TraceContextProcessor implements ProcessorInterface
{
/**
* @param array{trace:array<string>,span:array<string>,sampled:array<string>,operation:array<string>} $map
Expand All @@ -18,12 +20,7 @@ public function __construct(private array $map)
{
}

/**
* @param array<mixed> $record
*
* @return array<mixed>
*/
public function __invoke(array $record): array
public function __invoke(LogRecord $record): LogRecord
{
$span = Span::getCurrent();
$spanContext = $span->getContext();
Expand All @@ -32,28 +29,31 @@ public function __invoke(array $record): array
return $record;
}

$this->setRecordKey($record, $this->map['trace'], $spanContext->getTraceId());
$this->setRecordKey($record, $this->map['span'], $spanContext->getSpanId());
$this->setRecordKey($record, $this->map['sampled'], $spanContext->isSampled());
$record = $this->withRecordKey($record, $this->map['trace'], $spanContext->getTraceId());
$record = $this->withRecordKey($record, $this->map['span'], $spanContext->getSpanId());
$record = $this->withRecordKey($record, $this->map['sampled'], $spanContext->isSampled());

if ($span instanceof Span) {
$this->setRecordKey($record, $this->map['operation'], $span->getName());
$record = $this->withRecordKey($record, $this->map['operation'], $span->getName());
}

return $record;
}

/**
* @param array<string,mixed> $record
* @param array<string> $keys
* @param string|bool|int $value
* @param LogRecord $record
* @param array<string> $keys
* @param string|bool|int $value
*/
private function setRecordKey(array &$record, array $keys, $value): void
private function withRecordKey(LogRecord $record, array $keys, $value): LogRecord
{
$temp = &$record;
$recordAsArray = $record->toArray();
$temp = &$recordAsArray;
foreach ($keys as $key) {
$temp = &$temp[$key];
}
$temp = $value;

return $record->with($recordAsArray);
}
}
16 changes: 9 additions & 7 deletions src/Tracing/Instrumentation/LogHandler/TracingHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

use Instrumentation\Tracing\Instrumentation\MainSpanContextInterface;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Level;
use Monolog\Logger;
use Monolog\LogRecord;
use Monolog\Processor\PsrLogMessageProcessor;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\SDK\Trace\Span;
Expand All @@ -29,7 +31,7 @@ class TracingHandler extends AbstractProcessingHandler
/**
* @param array<string> $channels
*/
public function __construct(protected TracerProviderInterface $tracerProvider, protected MainSpanContextInterface $mainSpanContext, $level = Logger::INFO, private array $channels = [], private string $strategy = self::STRATEGY_MAIN_SPAN, bool $bubble = true)
public function __construct(protected TracerProviderInterface $tracerProvider, protected MainSpanContextInterface $mainSpanContext, $level = Level::Info, private array $channels = [], private string $strategy = self::STRATEGY_MAIN_SPAN, bool $bubble = true)
{
parent::__construct($level, $bubble);

Expand All @@ -43,13 +45,13 @@ public function __construct(protected TracerProviderInterface $tracerProvider, p
$this->channels = array_filter($this->channels, fn (string $channel) => !str_starts_with($channel, '!'));
}

protected function write(array $record): void
protected function write(LogRecord $record): void
{
if ($this->channels && !\in_array($record['channel'], $this->channels)) {
if ($this->channels && !\in_array($record->channel, $this->channels)) {
return;
}

if ($this->excludedChannels && \in_array($record['channel'], $this->excludedChannels)) {
if ($this->excludedChannels && \in_array($record->channel, $this->excludedChannels)) {
return;
}

Expand All @@ -59,10 +61,10 @@ protected function write(array $record): void
default => throw new \InvalidArgumentException(sprintf('Unkown strategy "%s".', $this->strategy))
};

if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
$span->recordException($record['context']['exception'], ['raw_stacktrace' => $record['context']['exception']->getTraceAsString()]);
if (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) {
$span->recordException($record->context['exception'], ['raw_stacktrace' => $record->context['exception']->getTraceAsString()]);
} else {
$span->addEvent($record['message']);
$span->addEvent($record->message);
}
}
}

0 comments on commit 848de7e

Please sign in to comment.