From 15d064eb6370bb868fee5dc7ffc6aaaca2135034 Mon Sep 17 00:00:00 2001 From: "cristian.almohalla" Date: Wed, 20 Aug 2025 09:29:44 +0200 Subject: [PATCH 1/8] feat: change format of logged fields --- src/DomainTrace/DomainTraceProcessor.php | 5 +- src/ExecutionTime/ExecutionTimeProcessor.php | 4 +- src/Info/InfoProcessor.php | 14 +++--- src/OccurredOn/OccurredOnProcessor.php | 14 ++---- .../DomainTrace/DomainTraceProcessorTest.php | 4 +- .../ExecutionTimeProcessorTest.php | 8 ++-- tests/Info/InfoProcessorTest.php | 30 ++++++------ tests/OccurredOn/OccurredOnProcessorTest.php | 46 ++++--------------- 8 files changed, 46 insertions(+), 79 deletions(-) diff --git a/src/DomainTrace/DomainTraceProcessor.php b/src/DomainTrace/DomainTraceProcessor.php index 6d85650..bb873b5 100644 --- a/src/DomainTrace/DomainTraceProcessor.php +++ b/src/DomainTrace/DomainTraceProcessor.php @@ -20,8 +20,8 @@ public function __invoke(array $record): array { $messageId = $this->getMessageId($record); - $record['extra']['correlation_id'] = $this->tracker->correlationId($messageId); - $record['extra']['reply_to'] = $this->tracker->replyTo($messageId); + $record['context']['trace']['correlation_id'] = $this->tracker->correlationId($messageId); + $record['context']['trace']['reply_to'] = $this->tracker->replyTo($messageId); return $record; } @@ -33,6 +33,7 @@ private function getMessageId(array $record): ?Uuid } $message = $record['context']['message']; + if (false === $message instanceof Message) { return null; } diff --git a/src/ExecutionTime/ExecutionTimeProcessor.php b/src/ExecutionTime/ExecutionTimeProcessor.php index 19d8355..5128062 100644 --- a/src/ExecutionTime/ExecutionTimeProcessor.php +++ b/src/ExecutionTime/ExecutionTimeProcessor.php @@ -28,7 +28,7 @@ public function __invoke(array $record): array return $record; } - $record['extra']['execution_time'] = $this->getExecutionTime($message); + $record['context']['execution_time'] = $this->getExecutionTime($message); return $record; } @@ -40,7 +40,7 @@ private function getExecutionTime(Message $message): float try { $event = $this->stopwatch->getEvent( $message->messageId()->value(), - ); + ); $duration = $event->getDuration(); } catch (\LogicException $exception) { diff --git a/src/Info/InfoProcessor.php b/src/Info/InfoProcessor.php index 72629c5..8bfa1cc 100644 --- a/src/Info/InfoProcessor.php +++ b/src/Info/InfoProcessor.php @@ -29,10 +29,10 @@ private function messageInfo(array $record): array return $record; } - $record['extra']['message_id'] = $message->messageId()->value(); - $record['extra']['name'] = $message::messageName(); - $record['extra']['type'] = $message::messageType(); - $record['extra']['payload'] = \json_encode($record['context']['message']); + $record['context']['message_id'] = $message->messageId()->value(); + $record['context']['name'] = $message::messageName(); + $record['context']['type'] = $message::messageType(); + $record['context']['payload'] = \json_encode($message->messagePayload()); return $record; } @@ -45,9 +45,9 @@ private function aggregateInfo(array $record): array return $record; } - $record['extra']['aggregate_id'] = $message->aggregateId(); - $record['extra']['aggregate_version'] = $message->aggregateVersion(); - $record['extra']['occurred_on'] = $message->occurredOn()->format(\DateTime::ATOM); + $record['context']['aggregate_id'] = $message->aggregateId(); + $record['context']['aggregate_version'] = $message->aggregateVersion(); + $record['context']['occurred_on'] = $message->occurredOn()->format(\DateTime::ATOM); return $record; } diff --git a/src/OccurredOn/OccurredOnProcessor.php b/src/OccurredOn/OccurredOnProcessor.php index 903d827..837cd8c 100644 --- a/src/OccurredOn/OccurredOnProcessor.php +++ b/src/OccurredOn/OccurredOnProcessor.php @@ -5,6 +5,7 @@ use Monolog\Processor\ProcessorInterface; use PcComponentes\Ddd\Domain\Model\DomainEvent; +use PcComponentes\Ddd\Domain\Model\ValueObject\DateTimeValueObject; final class OccurredOnProcessor implements ProcessorInterface { @@ -17,21 +18,12 @@ public function __invoke(array $record): array $message = $record['context']['message']; if ($message instanceof DomainEvent) { - $occurredOn = \sprintf( - '%d%d', - $message->occurredOn()->getTimestamp(), - $message->occurredOn()->format('v') - ); - $record['occurred_on'] = \intval($occurredOn); + $record['occurred_on'] = (int) $message->occurredOn()->format('Uv'); return $record; } - $record['occurred_on'] = \intval( - \round( - \microtime(true) * 1000, - ) - ); + $record['occurred_on'] = (int) DateTimeValueObject::now()->format('Uv'); return $record; } diff --git a/tests/DomainTrace/DomainTraceProcessorTest.php b/tests/DomainTrace/DomainTraceProcessorTest.php index 4cff21e..dd698d6 100644 --- a/tests/DomainTrace/DomainTraceProcessorTest.php +++ b/tests/DomainTrace/DomainTraceProcessorTest.php @@ -30,7 +30,7 @@ public function testShouldAddedReplyToAndCorrelationIdToRecord() $record = (new DomainTraceProcessor($trackerMock))($record); - $this->assertEquals($correlationId, $record['extra']['correlation_id']); - $this->assertEquals($replyTo, $record['extra']['reply_to']); + $this->assertEquals($correlationId, $record['context']['trace']['correlation_id']); + $this->assertEquals($replyTo, $record['context']['trace']['reply_to']); } } \ No newline at end of file diff --git a/tests/ExecutionTime/ExecutionTimeProcessorTest.php b/tests/ExecutionTime/ExecutionTimeProcessorTest.php index 10153e6..1295894 100644 --- a/tests/ExecutionTime/ExecutionTimeProcessorTest.php +++ b/tests/ExecutionTime/ExecutionTimeProcessorTest.php @@ -81,8 +81,8 @@ public function testShouldReturnedRecordWithExecutionTime() $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); - $this->assertArrayHasKey('execution_time', $result['extra']); - $this->assertEquals($milliseconds / 1000, $result['extra']['execution_time']); + $this->assertArrayHasKey('execution_time', $result['context']); + $this->assertEquals($milliseconds / 1000, $result['context']['execution_time']); } public function testShouldReturnedZeroExecutionTimeWhenLogicExceptionOccurred() @@ -119,7 +119,7 @@ public function testShouldReturnedZeroExecutionTimeWhenLogicExceptionOccurred() $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); - $this->assertArrayHasKey('execution_time', $result['extra']); - $this->assertEquals(0, $result['extra']['execution_time']); + $this->assertArrayHasKey('execution_time', $result['context']); + $this->assertEquals(0, $result['context']['execution_time']); } } \ No newline at end of file diff --git a/tests/Info/InfoProcessorTest.php b/tests/Info/InfoProcessorTest.php index 18ded92..9d5fc66 100644 --- a/tests/Info/InfoProcessorTest.php +++ b/tests/Info/InfoProcessorTest.php @@ -54,14 +54,14 @@ public function testShouldReturnedRecordWithDDDMessageInfo() $result = (new InfoProcessor())($record); - $this->assertArrayHasKey('extra', $result); - $this->assertArrayHasKey('message_id', $result['extra']); - $this->assertEquals($stringUuid, $result['extra']['message_id']); - $this->assertArrayHasKey('name', $result['extra']); - $this->assertEquals(SimpleMessageMock::messageName(), $result['extra']['name']); - $this->assertArrayHasKey('type', $result['extra']); - $this->assertEquals(SimpleMessageMock::messageType(), $result['extra']['type']); - $this->assertArrayHasKey('payload', $result['extra']); + $this->assertArrayHasKey('context', $result); + $this->assertArrayHasKey('message_id', $result['context']); + $this->assertEquals($stringUuid, $result['context']['message_id']); + $this->assertArrayHasKey('name', $result['context']); + $this->assertEquals(SimpleMessageMock::messageName(), $result['context']['name']); + $this->assertArrayHasKey('type', $result['context']); + $this->assertEquals(SimpleMessageMock::messageType(), $result['context']['type']); + $this->assertArrayHasKey('payload', $result['context']); } public function testShouldReturnedWithAggregateMessageInfo() @@ -96,13 +96,13 @@ public function testShouldReturnedWithAggregateMessageInfo() $result = (new InfoProcessor())($record); - $this->assertArrayHasKey('extra', $result); - $this->assertArrayHasKey('aggregate_id', $result['extra']); - $this->assertEquals($aggregateIdMock, $result['extra']['aggregate_id']); - $this->assertArrayHasKey('aggregate_version', $result['extra']); - $this->assertEquals($aggregateMessage->aggregateVersion(), $result['extra']['aggregate_version']); - $this->assertArrayHasKey('occurred_on', $result['extra']); - $this->assertEquals($aggregateMessage->occurredOn()->format(\DateTime::ATOM), $result['extra']['occurred_on']); + $this->assertArrayHasKey('context', $result); + $this->assertArrayHasKey('aggregate_id', $result['context']); + $this->assertEquals($aggregateIdMock, $result['context']['aggregate_id']); + $this->assertArrayHasKey('aggregate_version', $result['context']); + $this->assertEquals($aggregateMessage->aggregateVersion(), $result['context']['aggregate_version']); + $this->assertArrayHasKey('occurred_on', $result['context']); + $this->assertEquals($aggregateMessage->occurredOn()->format(\DateTime::ATOM), $result['context']['occurred_on']); } } diff --git a/tests/OccurredOn/OccurredOnProcessorTest.php b/tests/OccurredOn/OccurredOnProcessorTest.php index 048a5c8..fd446f0 100644 --- a/tests/OccurredOn/OccurredOnProcessorTest.php +++ b/tests/OccurredOn/OccurredOnProcessorTest.php @@ -12,7 +12,7 @@ final class OccurredOnProcessorTest extends TestCase public function testShouldReturnedRecordWithoutMessage() { $record = [ - 'context' => [] + 'context' => [], ]; $result = (new OccurredOnProcessor())($record); @@ -25,7 +25,7 @@ public function testShouldReturnedRecordWithOccurredOn() $record = [ 'context' => [ 'message' => [], - ] + ], ]; $result = (new OccurredOnProcessor())($record); @@ -36,50 +36,24 @@ public function testShouldReturnedRecordWithOccurredOn() public function testShouldReturnedRecordWithDomainEventOccurredOn() { - $timestamp = 1582912634; //1582913896 876 - $milliseconds = '678'; - $occurredOnMock = $this->createMock(\DateTime::class); - $occurredOnMock - ->expects($this->once()) - ->method('getTimestamp') - ->willReturn($timestamp); - $occurredOnMock - ->expects($this->once()) - ->method('format') - ->with('v') - ->willReturn($milliseconds); + $timestamp = '1582912634.678'; + $expectedTimestamp = '1582912634678'; + $occurredOn = \DateTimeImmutable::createFromFormat('U.v', $timestamp, new \DateTimeZone('UTC')); $domainEventMock = $this->createMock(DomainEvent::class); $domainEventMock - ->expects($this->exactly(2)) + ->expects($this->once()) ->method('occurredOn') - ->willReturn($occurredOnMock); + ->willReturn($occurredOn); $record = [ 'context' => [ - 'message' => $domainEventMock - ] + 'message' => $domainEventMock, + ], ]; $result = (new OccurredOnProcessor())($record); $this->assertArrayHasKey('occurred_on', $result); - $this->assertEquals( - $this->expectedOccurredOn( - $timestamp, - $milliseconds - ), - $result['occurred_on'] - ); - } - - private function expectedOccurredOn(int $timestamp, string $milliseconds) - { - return \intval( - \sprintf( - '%d%d', - $timestamp, - $milliseconds - ) - ); + $this->assertEquals($expectedTimestamp, $result['occurred_on']); } } From c92f109081675a9a19ebe9eb3fc956bacacf079f Mon Sep 17 00:00:00 2001 From: Javier Esteban Date: Thu, 21 Aug 2025 11:16:57 +0200 Subject: [PATCH 2/8] feat: upgrade to monolog 3 --- Dockerfile | 13 ++++----- Makefile | 5 +++- README.md | 12 +++++++- composer.json | 4 +-- src/Context/NormalizeMessageProcessor.php | 20 ++++++++++--- src/DomainTrace/DomainTraceProcessor.php | 5 ++-- .../TraceOfExceptionProcessor.php | 26 ++++++++++++----- src/ExecutionTime/ExecutionTimeProcessor.php | 3 +- src/Hostname/HostnameProcessor.php | 3 +- src/Info/InfoProcessor.php | 7 +++-- src/MonologIteratorProcessor.php | 3 +- src/OccurredOn/OccurredOnProcessor.php | 7 +++-- .../Context/NormalizeContextProcessorTest.php | 11 ++++--- .../DomainTrace/DomainTraceProcessorTest.php | 5 ++-- .../TraceOfExceptionProcessorTest.php | 16 +++++----- .../ExecutionTimeProcessorTest.php | 20 +++++-------- tests/HostName/HostNameProcessorTest.php | 3 +- tests/Info/InfoProcessorTest.php | 21 +++++--------- tests/Mock/LogRecordMother.php | 29 +++++++++++++++++++ tests/OccurredOn/OccurredOnProcessorTest.php | 24 +++++++-------- 20 files changed, 145 insertions(+), 92 deletions(-) create mode 100644 tests/Mock/LogRecordMother.php diff --git a/Dockerfile b/Dockerfile index 1ad8eb9..2ea94c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.0-cli-alpine3.13 +FROM php:8.4-fpm-alpine RUN apk add --no-cache \ libzip-dev \ @@ -9,12 +9,11 @@ RUN apk add --no-cache \ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer -RUN apk add --no-cache --virtual .phpize_deps $PHPIZE_DEPS && \ - pecl install xdebug-3.0.4 && \ - docker-php-ext-enable xdebug && \ - rm -rf /usr/share/php8 && \ - rm -rf /tmp/pear && \ - apk del .phpize_deps +RUN apk add --update linux-headers &&\ + apk --no-cache add pcre-dev ${PHPIZE_DEPS} \ + && pecl install xdebug \ + && docker-php-ext-enable xdebug \ + && apk del pcre-dev ${PHPIZE_DEPS} ENV PATH /var/app/bin:/var/app/vendor/bin:$PATH diff --git a/Makefile b/Makefile index d76e651..8351f9b 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,9 @@ bash: logs: docker compose logs -f ${DOCKER_PHP_SERVICE} +composer-show: + docker compose run --rm -u ${UID}:${GID} ${DOCKER_PHP_SERVICE} composer show + .PHONY: tests tests: - docker compose run --rm -u ${UID}:${GID} ${DOCKER_PHP_SERVICE} phpunit \ No newline at end of file + docker compose run --rm -u ${UID}:${GID} ${DOCKER_PHP_SERVICE} phpunit diff --git a/README.md b/README.md index 5545664..095ef7a 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,14 @@ La idea del middleware es muy simple. Para construirlo, requiere de cuatro depen - Serializador de excepciones, para logear si llega a ocurrir, la foto de la excepción disparada. ## Tracker -Esta clase sirve para meter en el registro de logs el ID de una posible operación "padre", para posteriormente poder sacar trazas de tipo "árbol" por un sistema que sea capaz de centralizar estos logs. \ No newline at end of file +Esta clase sirve para meter en el registro de logs el ID de una posible operación "padre", para posteriormente poder sacar trazas de tipo "árbol" por un sistema que sea capaz de centralizar estos logs. + +## Comandos de desarrollo + +### Ver versiones de paquetes instalados +Para ver qué versiones de paquetes tiene instalado Composer, ejecuta: +```bash +make composer-show +``` + +Este comando mostrará una lista de todos los paquetes instalados junto con sus versiones actuales. diff --git a/composer.json b/composer.json index 095fce1..dede794 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,9 @@ } ], "require": { - "php": "^7.4|^8.0", + "php": "^8.4", "ext-json": "*", - "monolog/monolog": "^1.25|^2.0|^3.0", + "monolog/monolog": "^3.0", "pccomponentes/ddd": "^2.1|^3.0|^4.0", "symfony/http-kernel": "^4.4|^5.0|^6.0|^7.0", "symfony/messenger": "^4.4|^5.0|^6.0|^7.0", diff --git a/src/Context/NormalizeMessageProcessor.php b/src/Context/NormalizeMessageProcessor.php index 26c0546..b6c7260 100644 --- a/src/Context/NormalizeMessageProcessor.php +++ b/src/Context/NormalizeMessageProcessor.php @@ -3,20 +3,32 @@ namespace PcComponentes\DddLogging\Context; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; final class NormalizeMessageProcessor implements ProcessorInterface { - public function __invoke(array $record): array + public function __invoke(LogRecord $record) { + $returnRecord = $record; if (false === \array_key_exists('message', $record['context'])) { - return $record; + return $returnRecord; } if (false === \is_string($record['context']['message'])) { - $record['context']['message'] = \json_encode($record['context']['message']); + $context = $record['context']; + $context['message'] = \json_encode($record['context']['message']); + + $returnRecord = new LogRecord( + $record->datetime, + $record->channel, + $record->level, + $record->message, + $context, + $record->extra, + ); } - return $record; + return $returnRecord; } } diff --git a/src/DomainTrace/DomainTraceProcessor.php b/src/DomainTrace/DomainTraceProcessor.php index 6d85650..1675ad6 100644 --- a/src/DomainTrace/DomainTraceProcessor.php +++ b/src/DomainTrace/DomainTraceProcessor.php @@ -3,6 +3,7 @@ namespace PcComponentes\DddLogging\DomainTrace; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; use PcComponentes\Ddd\Domain\Model\ValueObject\Uuid; use PcComponentes\Ddd\Util\Message\Message; @@ -16,7 +17,7 @@ public function __construct(Tracker $tracker) $this->tracker = $tracker; } - public function __invoke(array $record): array + public function __invoke(LogRecord $record) { $messageId = $this->getMessageId($record); @@ -26,7 +27,7 @@ public function __invoke(array $record): array return $record; } - private function getMessageId(array $record): ?Uuid + private function getMessageId(LogRecord $record): ?Uuid { if (false === \array_key_exists('message', $record['context'])) { return null; diff --git a/src/ExceptionCatcher/TraceOfExceptionProcessor.php b/src/ExceptionCatcher/TraceOfExceptionProcessor.php index 9cfa7ba..d79cf84 100644 --- a/src/ExceptionCatcher/TraceOfExceptionProcessor.php +++ b/src/ExceptionCatcher/TraceOfExceptionProcessor.php @@ -3,31 +3,41 @@ namespace PcComponentes\DddLogging\ExceptionCatcher; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; use PcComponentes\DddLogging\Util\AssocSerializer; final class TraceOfExceptionProcessor implements ProcessorInterface { - public function __invoke(array $record): array + public function __invoke(LogRecord $record) { if (false === \array_key_exists('exception', $record['context'])) { return $record; } - $exception = $record['context']['exception']; - $record['context']['exception'] = AssocSerializer::from($record['context']['exception']); + $context = $record->context; + + $exception = $context['exception']; + $context['exception'] = AssocSerializer::from($context['exception']); if ($exception instanceof \JsonSerializable) { - $record['context']['exception']['data'] = \json_encode($exception, JSON_THROW_ON_ERROR); + $context['exception']['data'] = \json_encode($exception, JSON_THROW_ON_ERROR); } - if (true === \array_key_exists('trace', $record['context']['exception'])) { - $record['context']['exception']['trace'] = \json_encode( - $record['context']['exception']['trace'], + if (true === \array_key_exists('trace', $context['exception'])) { + $context['exception']['trace'] = \json_encode( + $context['exception']['trace'], JSON_THROW_ON_ERROR ); } - return $record; + return new LogRecord( + $record->datetime, + $record->channel, + $record->level, + $record->message, + $context, + $record->extra, + );; } } diff --git a/src/ExecutionTime/ExecutionTimeProcessor.php b/src/ExecutionTime/ExecutionTimeProcessor.php index 19d8355..bd0ed00 100644 --- a/src/ExecutionTime/ExecutionTimeProcessor.php +++ b/src/ExecutionTime/ExecutionTimeProcessor.php @@ -3,6 +3,7 @@ namespace PcComponentes\DddLogging\ExecutionTime; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; use PcComponentes\Ddd\Util\Message\Message; use Symfony\Component\Stopwatch\Stopwatch; @@ -16,7 +17,7 @@ public function __construct(Stopwatch $stopwatch) $this->stopwatch = $stopwatch; } - public function __invoke(array $record): array + public function __invoke(LogRecord $record) { if (false === \array_key_exists('message', $record['context'])) { return $record; diff --git a/src/Hostname/HostnameProcessor.php b/src/Hostname/HostnameProcessor.php index 369f113..c980ecc 100644 --- a/src/Hostname/HostnameProcessor.php +++ b/src/Hostname/HostnameProcessor.php @@ -3,6 +3,7 @@ namespace PcComponentes\DddLogging\Hostname; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; final class HostnameProcessor implements ProcessorInterface @@ -14,7 +15,7 @@ public function __construct() $this->host = \gethostname(); } - public function __invoke(array $record): array + public function __invoke(LogRecord $record) { $record['extra']['hostname'] = $this->host; diff --git a/src/Info/InfoProcessor.php b/src/Info/InfoProcessor.php index 72629c5..9af4a8f 100644 --- a/src/Info/InfoProcessor.php +++ b/src/Info/InfoProcessor.php @@ -3,13 +3,14 @@ namespace PcComponentes\DddLogging\Info; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; use PcComponentes\Ddd\Util\Message\AggregateMessage; use PcComponentes\Ddd\Util\Message\Message; final class InfoProcessor implements ProcessorInterface { - public function __invoke(array $record) + public function __invoke(LogRecord $record) { if (false === \array_key_exists('message', $record['context'])) { return $record; @@ -21,7 +22,7 @@ public function __invoke(array $record) return $record; } - private function messageInfo(array $record): array + private function messageInfo(LogRecord $record): LogRecord { $message = $record['context']['message']; @@ -37,7 +38,7 @@ private function messageInfo(array $record): array return $record; } - private function aggregateInfo(array $record): array + private function aggregateInfo(LogRecord $record): LogRecord { $message = $record['context']['message']; diff --git a/src/MonologIteratorProcessor.php b/src/MonologIteratorProcessor.php index a3a3f73..707d346 100644 --- a/src/MonologIteratorProcessor.php +++ b/src/MonologIteratorProcessor.php @@ -3,6 +3,7 @@ namespace PcComponentes\DddLogging; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; final class MonologIteratorProcessor implements ProcessorInterface @@ -14,7 +15,7 @@ public function __construct(ProcessorInterface ...$processors) $this->processors = $processors; } - public function __invoke(array $record) + public function __invoke(LogRecord $record) { foreach ($this->processors as $processor) { $record = $processor($record); diff --git a/src/OccurredOn/OccurredOnProcessor.php b/src/OccurredOn/OccurredOnProcessor.php index 903d827..e016885 100644 --- a/src/OccurredOn/OccurredOnProcessor.php +++ b/src/OccurredOn/OccurredOnProcessor.php @@ -3,12 +3,13 @@ namespace PcComponentes\DddLogging\OccurredOn; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; use PcComponentes\Ddd\Domain\Model\DomainEvent; final class OccurredOnProcessor implements ProcessorInterface { - public function __invoke(array $record): array + public function __invoke(LogRecord $record) { if (false === \array_key_exists('message', $record['context'])) { return $record; @@ -22,12 +23,12 @@ public function __invoke(array $record): array $message->occurredOn()->getTimestamp(), $message->occurredOn()->format('v') ); - $record['occurred_on'] = \intval($occurredOn); + $record['extra']['occurred_on'] = \intval($occurredOn); return $record; } - $record['occurred_on'] = \intval( + $record['extra']['occurred_on'] = \intval( \round( \microtime(true) * 1000, ) diff --git a/tests/Context/NormalizeContextProcessorTest.php b/tests/Context/NormalizeContextProcessorTest.php index ab29cfd..e2fb87b 100644 --- a/tests/Context/NormalizeContextProcessorTest.php +++ b/tests/Context/NormalizeContextProcessorTest.php @@ -3,16 +3,16 @@ namespace PcComponentes\DddLogging\Tests\Context; +use Monolog\LogRecord; use PcComponentes\DddLogging\Context\NormalizeMessageProcessor; +use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; final class NormalizeContextProcessorTest extends TestCase { public function testShouldReturnedRecordWithoutMessage() { - $record = [ - 'context' => [] - ]; + $record = LogRecordMother::default(); $result = (new NormalizeMessageProcessor())($record); @@ -21,13 +21,12 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithEncodedMessage() { - $record = [ - 'context' => [ + $record = LogRecordMother::withContext([ 'message' => [ 'This is a message', ], ], - ]; + ); $expectedEncodedMessage = \json_encode($record['context']['message']); diff --git a/tests/DomainTrace/DomainTraceProcessorTest.php b/tests/DomainTrace/DomainTraceProcessorTest.php index 4cff21e..42792d3 100644 --- a/tests/DomainTrace/DomainTraceProcessorTest.php +++ b/tests/DomainTrace/DomainTraceProcessorTest.php @@ -5,6 +5,7 @@ use PcComponentes\DddLogging\DomainTrace\DomainTraceProcessor; use PcComponentes\DddLogging\DomainTrace\Tracker; +use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; final class DomainTraceProcessorTest extends TestCase @@ -13,9 +14,7 @@ public function testShouldAddedReplyToAndCorrelationIdToRecord() { $correlationId = "correlation_id_value"; $replyTo = "reply_to_value"; - $record = [ - 'context' => [], - ]; + $record = LogRecordMother::default(); $trackerMock = $this->createMock(Tracker::class); $trackerMock diff --git a/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php b/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php index 6650738..cdc254d 100644 --- a/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php +++ b/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php @@ -5,15 +5,14 @@ use Pccomponentes\Apixception\Core\Exception\SerializableException; use PcComponentes\DddLogging\ExceptionCatcher\TraceOfExceptionProcessor; +use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; final class TraceOfExceptionProcessorTest extends TestCase { public function testShouldReturnedRecordWithoutExceptionContext() { - $record = [ - 'context' => [] - ]; + $record = LogRecordMother::default(); $recordResult = (new TraceOfExceptionProcessor())($record); @@ -23,11 +22,11 @@ public function testShouldReturnedRecordWithoutExceptionContext() public function testShouldReturnedRecordWithExceptionContext() { $exceptionMock = $this->createMock(\JsonSerializable::class); - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( + [ 'exception' => $exceptionMock ] - ]; + ); $exceptionMock ->expects($this->atLeastOnce()) @@ -46,13 +45,12 @@ public function testShouldReturnedRecordWithExceptionTraceContext() 'method 2' ]; - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( [ 'exception' => [ 'trace' => $trace ] ] - ]; + ); $recordResult = (new TraceOfExceptionProcessor())($record); diff --git a/tests/ExecutionTime/ExecutionTimeProcessorTest.php b/tests/ExecutionTime/ExecutionTimeProcessorTest.php index 10153e6..0b59886 100644 --- a/tests/ExecutionTime/ExecutionTimeProcessorTest.php +++ b/tests/ExecutionTime/ExecutionTimeProcessorTest.php @@ -6,6 +6,7 @@ use PcComponentes\Ddd\Domain\Model\ValueObject\Uuid; use PcComponentes\Ddd\Util\Message\Message; use PcComponentes\DddLogging\ExecutionTime\ExecutionTimeProcessor; +use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Stopwatch\Stopwatch; @@ -23,9 +24,7 @@ public function setUp(): void public function testShouldReturnedRecordWithoutMessage() { - $record = [ - 'context' => [], - ]; + $record = LogRecordMother::default(); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); @@ -34,11 +33,10 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithoutDDDMessage() { - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( [ 'message' => [] ], - ]; + ); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); @@ -73,11 +71,10 @@ public function testShouldReturnedRecordWithExecutionTime() ->method('getDuration') ->willReturn($milliseconds); - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( [ 'message' => $messageMock ], - ]; + ); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); @@ -111,11 +108,10 @@ public function testShouldReturnedZeroExecutionTimeWhenLogicExceptionOccurred() ->method('getDuration') ->willThrowException(new \LogicException()); - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( [ 'message' => $messageMock ], - ]; + ); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); diff --git a/tests/HostName/HostNameProcessorTest.php b/tests/HostName/HostNameProcessorTest.php index 036cfec..bec5ab5 100644 --- a/tests/HostName/HostNameProcessorTest.php +++ b/tests/HostName/HostNameProcessorTest.php @@ -4,13 +4,14 @@ namespace PcComponentes\DddLogging\Tests\HostName; use PcComponentes\DddLogging\Hostname\HostnameProcessor; +use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; final class HostNameProcessorTest extends TestCase { public function testShouldReturnedRecordWithHostname() { - $result = (new HostnameProcessor())([]); + $result = (new HostnameProcessor())(LogRecordMother::default()); $this->assertArrayHasKey('extra', $result); $this->assertArrayHasKey('hostname', $result['extra']); diff --git a/tests/Info/InfoProcessorTest.php b/tests/Info/InfoProcessorTest.php index 18ded92..95363d3 100644 --- a/tests/Info/InfoProcessorTest.php +++ b/tests/Info/InfoProcessorTest.php @@ -9,15 +9,14 @@ use PcComponentes\Ddd\Util\Message\SimpleMessage; use PcComponentes\Ddd\Util\Message\ValueObject\AggregateId; use PcComponentes\DddLogging\Info\InfoProcessor; +use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; final class InfoProcessorTest extends TestCase { public function testShouldReturnedRecordWithoutMessage() { - $record = [ - 'context' => [], - ]; + $record = LogRecordMother::default(); $result = (new InfoProcessor())($record); @@ -26,11 +25,7 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithoutDDDMessage() { - $record = [ - 'context' => [ - 'message' => [] - ], - ]; + $record = LogRecordMother::default(); $result = (new InfoProcessor())($record); @@ -46,11 +41,10 @@ public function testShouldReturnedRecordWithDDDMessageInfo() ->willReturn($stringUuid); $simpleMessage = SimpleMessageMock::fromPayload($messageIdMock, []); - $record = [ - 'context' => [ + $record = LogRecordMother::withContext([ 'message' => $simpleMessage, ], - ]; + ); $result = (new InfoProcessor())($record); @@ -88,11 +82,10 @@ public function testShouldReturnedWithAggregateMessageInfo() 1 ); - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( [ 'message' => $aggregateMessage, ], - ]; + ); $result = (new InfoProcessor())($record); diff --git a/tests/Mock/LogRecordMother.php b/tests/Mock/LogRecordMother.php new file mode 100644 index 0000000..112fc10 --- /dev/null +++ b/tests/Mock/LogRecordMother.php @@ -0,0 +1,29 @@ +context = $context; + + return $logRecord; + } +} \ No newline at end of file diff --git a/tests/OccurredOn/OccurredOnProcessorTest.php b/tests/OccurredOn/OccurredOnProcessorTest.php index 048a5c8..d46a54c 100644 --- a/tests/OccurredOn/OccurredOnProcessorTest.php +++ b/tests/OccurredOn/OccurredOnProcessorTest.php @@ -5,15 +5,14 @@ use PcComponentes\Ddd\Domain\Model\DomainEvent; use PcComponentes\DddLogging\OccurredOn\OccurredOnProcessor; +use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; final class OccurredOnProcessorTest extends TestCase { public function testShouldReturnedRecordWithoutMessage() { - $record = [ - 'context' => [] - ]; + $record = LogRecordMother::default(); $result = (new OccurredOnProcessor())($record); @@ -22,16 +21,16 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithOccurredOn() { - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( + [ 'message' => [], ] - ]; + ); $result = (new OccurredOnProcessor())($record); - $this->assertArrayHasKey('occurred_on', $result); - $this->assertIsInt($result['occurred_on']); + + $this->assertIsInt($result['extra']['occurred_on']); } public function testShouldReturnedRecordWithDomainEventOccurredOn() @@ -55,20 +54,19 @@ public function testShouldReturnedRecordWithDomainEventOccurredOn() ->method('occurredOn') ->willReturn($occurredOnMock); - $record = [ - 'context' => [ + $record = LogRecordMother::withContext( + [ 'message' => $domainEventMock ] - ]; + ); $result = (new OccurredOnProcessor())($record); - $this->assertArrayHasKey('occurred_on', $result); $this->assertEquals( $this->expectedOccurredOn( $timestamp, $milliseconds ), - $result['occurred_on'] + $result['extra']['occurred_on'] ); } From 136c603515e9f99352a16e4fa5dd703b0a0483e9 Mon Sep 17 00:00:00 2001 From: Javier Esteban Date: Thu, 21 Aug 2025 11:20:09 +0200 Subject: [PATCH 3/8] feat: downgrade to php 8.2 --- Dockerfile | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2ea94c2..c37be5c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.4-fpm-alpine +FROM php:8.2-fpm-alpine RUN apk add --no-cache \ libzip-dev \ diff --git a/composer.json b/composer.json index dede794..c3ed8e7 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ } ], "require": { - "php": "^8.4", + "php": "^8.2", "ext-json": "*", "monolog/monolog": "^3.0", "pccomponentes/ddd": "^2.1|^3.0|^4.0", From a0b124a00ca20582e74e52f103c5fd6f0306f7cb Mon Sep 17 00:00:00 2001 From: "cristian.almohalla" Date: Thu, 21 Aug 2025 12:44:38 +0200 Subject: [PATCH 4/8] refactor: docker image --- Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index c37be5c..ea0f1bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.2-fpm-alpine +FROM php:8.2-cli-alpine3.21 RUN apk add --no-cache \ libzip-dev \ @@ -9,11 +9,11 @@ RUN apk add --no-cache \ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer -RUN apk add --update linux-headers &&\ - apk --no-cache add pcre-dev ${PHPIZE_DEPS} \ - && pecl install xdebug \ +RUN apk add --no-cache --virtual .phpize_deps $PHPIZE_DEPS \ + && apk add linux-headers \ + && pecl install xdebug-3.4.5 \ && docker-php-ext-enable xdebug \ - && apk del pcre-dev ${PHPIZE_DEPS} + && apk del linux-headers ${PHPIZE_DEPS} ENV PATH /var/app/bin:/var/app/vendor/bin:$PATH From 803c90e7779fa1d9e3f5b65ec934aa0aa68ee948 Mon Sep 17 00:00:00 2001 From: "cristian.almohalla" Date: Thu, 21 Aug 2025 12:59:22 +0200 Subject: [PATCH 5/8] refactor: change logged fields --- src/Context/NormalizeMessageProcessor.php | 1 + src/DomainTrace/DomainTraceProcessor.php | 4 +- src/ExecutionTime/ExecutionTimeProcessor.php | 2 +- src/Info/InfoProcessor.php | 14 +++--- .../DomainTrace/DomainTraceProcessorTest.php | 4 +- .../ExecutionTimeProcessorTest.php | 31 ++++++------- tests/Info/InfoProcessorTest.php | 46 +++++++++---------- tests/OccurredOn/OccurredOnProcessorTest.php | 4 +- 8 files changed, 52 insertions(+), 54 deletions(-) diff --git a/src/Context/NormalizeMessageProcessor.php b/src/Context/NormalizeMessageProcessor.php index b6c7260..bb14b4e 100644 --- a/src/Context/NormalizeMessageProcessor.php +++ b/src/Context/NormalizeMessageProcessor.php @@ -11,6 +11,7 @@ final class NormalizeMessageProcessor implements ProcessorInterface public function __invoke(LogRecord $record) { $returnRecord = $record; + if (false === \array_key_exists('message', $record['context'])) { return $returnRecord; } diff --git a/src/DomainTrace/DomainTraceProcessor.php b/src/DomainTrace/DomainTraceProcessor.php index 3955ef2..a2f0252 100644 --- a/src/DomainTrace/DomainTraceProcessor.php +++ b/src/DomainTrace/DomainTraceProcessor.php @@ -21,8 +21,8 @@ public function __invoke(LogRecord $record) { $messageId = $this->getMessageId($record); - $record['context']['trace']['correlation_id'] = $this->tracker->correlationId($messageId); - $record['context']['trace']['reply_to'] = $this->tracker->replyTo($messageId); + $record['extra']['trace']['correlation_id'] = $this->tracker->correlationId($messageId); + $record['extra']['trace']['reply_to'] = $this->tracker->replyTo($messageId); return $record; } diff --git a/src/ExecutionTime/ExecutionTimeProcessor.php b/src/ExecutionTime/ExecutionTimeProcessor.php index 2b4046d..d8843bb 100644 --- a/src/ExecutionTime/ExecutionTimeProcessor.php +++ b/src/ExecutionTime/ExecutionTimeProcessor.php @@ -29,7 +29,7 @@ public function __invoke(LogRecord $record) return $record; } - $record['context']['execution_time'] = $this->getExecutionTime($message); + $record['extra']['execution_time'] = $this->getExecutionTime($message); return $record; } diff --git a/src/Info/InfoProcessor.php b/src/Info/InfoProcessor.php index 165e270..89b7a84 100644 --- a/src/Info/InfoProcessor.php +++ b/src/Info/InfoProcessor.php @@ -30,10 +30,10 @@ private function messageInfo(LogRecord $record): LogRecord return $record; } - $record['context']['message_id'] = $message->messageId()->value(); - $record['context']['name'] = $message::messageName(); - $record['context']['type'] = $message::messageType(); - $record['context']['payload'] = \json_encode($message->messagePayload()); + $record['extra']['message']['message_id'] = $message->messageId()->value(); + $record['extra']['message']['name'] = $message::messageName(); + $record['extra']['message']['type'] = $message::messageType(); + $record['extra']['message']['payload'] = \json_encode($message->messagePayload()); return $record; } @@ -46,9 +46,9 @@ private function aggregateInfo(LogRecord $record): LogRecord return $record; } - $record['context']['aggregate_id'] = $message->aggregateId(); - $record['context']['aggregate_version'] = $message->aggregateVersion(); - $record['context']['occurred_on'] = $message->occurredOn()->format(\DateTime::ATOM); + $record['extra']['message']['aggregate_id'] = $message->aggregateId(); + $record['extra']['message']['aggregate_version'] = $message->aggregateVersion(); + $record['extra']['message']['occurred_on'] = $message->occurredOn()->format(\DateTime::ATOM); return $record; } diff --git a/tests/DomainTrace/DomainTraceProcessorTest.php b/tests/DomainTrace/DomainTraceProcessorTest.php index b2c98da..ee9f5bf 100644 --- a/tests/DomainTrace/DomainTraceProcessorTest.php +++ b/tests/DomainTrace/DomainTraceProcessorTest.php @@ -29,7 +29,7 @@ public function testShouldAddedReplyToAndCorrelationIdToRecord() $record = (new DomainTraceProcessor($trackerMock))($record); - $this->assertEquals($correlationId, $record['context']['trace']['correlation_id']); - $this->assertEquals($replyTo, $record['context']['trace']['reply_to']); + $this->assertEquals($correlationId, $record['extra']['trace']['correlation_id']); + $this->assertEquals($replyTo, $record['extra']['trace']['reply_to']); } } \ No newline at end of file diff --git a/tests/ExecutionTime/ExecutionTimeProcessorTest.php b/tests/ExecutionTime/ExecutionTimeProcessorTest.php index 7a102ab..0e1cd18 100644 --- a/tests/ExecutionTime/ExecutionTimeProcessorTest.php +++ b/tests/ExecutionTime/ExecutionTimeProcessorTest.php @@ -33,10 +33,9 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithoutDDDMessage() { - $record = LogRecordMother::withContext( [ - 'message' => [] - ], - ); + $record = LogRecordMother::withContext([ + 'message' => [], + ]); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); @@ -71,15 +70,14 @@ public function testShouldReturnedRecordWithExecutionTime() ->method('getDuration') ->willReturn($milliseconds); - $record = LogRecordMother::withContext( [ - 'message' => $messageMock - ], - ); + $record = LogRecordMother::withContext([ + 'message' => $messageMock, + ],); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); - $this->assertArrayHasKey('execution_time', $result['context']); - $this->assertEquals($milliseconds / 1000, $result['context']['execution_time']); + $this->assertArrayHasKey('execution_time', $result['extra']); + $this->assertEquals($milliseconds / 1000, $result['extra']['execution_time']); } public function testShouldReturnedZeroExecutionTimeWhenLogicExceptionOccurred() @@ -108,14 +106,13 @@ public function testShouldReturnedZeroExecutionTimeWhenLogicExceptionOccurred() ->method('getDuration') ->willThrowException(new \LogicException()); - $record = LogRecordMother::withContext( [ - 'message' => $messageMock - ], - ); + $record = LogRecordMother::withContext([ + 'message' => $messageMock, + ],); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); - $this->assertArrayHasKey('execution_time', $result['context']); - $this->assertEquals(0, $result['context']['execution_time']); + $this->assertArrayHasKey('execution_time', $result['extra']); + $this->assertEquals(0, $result['extra']['execution_time']); } -} \ No newline at end of file +} diff --git a/tests/Info/InfoProcessorTest.php b/tests/Info/InfoProcessorTest.php index 78ec6e4..15f929c 100644 --- a/tests/Info/InfoProcessorTest.php +++ b/tests/Info/InfoProcessorTest.php @@ -42,20 +42,20 @@ public function testShouldReturnedRecordWithDDDMessageInfo() $simpleMessage = SimpleMessageMock::fromPayload($messageIdMock, []); $record = LogRecordMother::withContext([ - 'message' => $simpleMessage, - ], - ); + 'message' => $simpleMessage, + ],); $result = (new InfoProcessor())($record); - $this->assertArrayHasKey('context', $result); - $this->assertArrayHasKey('message_id', $result['context']); - $this->assertEquals($stringUuid, $result['context']['message_id']); - $this->assertArrayHasKey('name', $result['context']); - $this->assertEquals(SimpleMessageMock::messageName(), $result['context']['name']); - $this->assertArrayHasKey('type', $result['context']); - $this->assertEquals(SimpleMessageMock::messageType(), $result['context']['type']); - $this->assertArrayHasKey('payload', $result['context']); + $this->assertArrayHasKey('extra', $result); + $this->assertArrayHasKey('message', $result['extra']); + $this->assertArrayHasKey('message_id', $result['extra']['message']); + $this->assertEquals($stringUuid, $result['extra']['message']['message_id']); + $this->assertArrayHasKey('name', $result['extra']['message']); + $this->assertEquals(SimpleMessageMock::messageName(), $result['extra']['message']['name']); + $this->assertArrayHasKey('type', $result['extra']['message']); + $this->assertEquals(SimpleMessageMock::messageType(), $result['extra']['message']['type']); + $this->assertArrayHasKey('payload', $result['extra']['message']); } public function testShouldReturnedWithAggregateMessageInfo() @@ -79,23 +79,23 @@ public function testShouldReturnedWithAggregateMessageInfo() $aggregateIdMock, $occurredOn, [], - 1 + 1, ); - $record = LogRecordMother::withContext( [ - 'message' => $aggregateMessage, - ], - ); + $record = LogRecordMother::withContext([ + 'message' => $aggregateMessage, + ],); $result = (new InfoProcessor())($record); - $this->assertArrayHasKey('context', $result); - $this->assertArrayHasKey('aggregate_id', $result['context']); - $this->assertEquals($aggregateIdMock, $result['context']['aggregate_id']); - $this->assertArrayHasKey('aggregate_version', $result['context']); - $this->assertEquals($aggregateMessage->aggregateVersion(), $result['context']['aggregate_version']); - $this->assertArrayHasKey('occurred_on', $result['context']); - $this->assertEquals($aggregateMessage->occurredOn()->format(\DateTime::ATOM), $result['context']['occurred_on']); + $this->assertArrayHasKey('extra', $result); + $this->assertArrayHasKey('message', $result['extra']); + $this->assertArrayHasKey('aggregate_id', $result['extra']['message']); + $this->assertEquals($aggregateIdMock, $result['extra']['message']['aggregate_id']); + $this->assertArrayHasKey('aggregate_version', $result['extra']['message']); + $this->assertEquals($aggregateMessage->aggregateVersion(), $result['extra']['message']['aggregate_version']); + $this->assertArrayHasKey('occurred_on', $result['extra']['message']); + $this->assertEquals($aggregateMessage->occurredOn()->format(\DateTime::ATOM), $result['extra']['message']['occurred_on']); } } diff --git a/tests/OccurredOn/OccurredOnProcessorTest.php b/tests/OccurredOn/OccurredOnProcessorTest.php index 9c84a37..a8a379f 100644 --- a/tests/OccurredOn/OccurredOnProcessorTest.php +++ b/tests/OccurredOn/OccurredOnProcessorTest.php @@ -52,7 +52,7 @@ public function testShouldReturnedRecordWithDomainEventOccurredOn() ); $result = (new OccurredOnProcessor())($record); - $this->assertArrayHasKey('occurred_on', $result); - $this->assertEquals($expectedTimestamp, $result['occurred_on']); + $this->assertArrayHasKey('occurred_on', $result['extra']); + $this->assertEquals($expectedTimestamp, $result['extra']['occurred_on']); } } From 3b15c1ddc729af53ea2596d04d342597599a0d72 Mon Sep 17 00:00:00 2001 From: "cristian.almohalla" Date: Thu, 21 Aug 2025 13:03:46 +0200 Subject: [PATCH 6/8] refactor: processors return type --- src/Context/NormalizeMessageProcessor.php | 2 +- src/DomainTrace/DomainTraceProcessor.php | 4 ++-- src/ExceptionCatcher/TraceOfExceptionProcessor.php | 8 ++++---- src/ExecutionTime/ExecutionTimeProcessor.php | 2 +- src/Hostname/HostnameProcessor.php | 2 +- src/Info/InfoProcessor.php | 2 +- src/MonologIteratorProcessor.php | 2 +- src/OccurredOn/OccurredOnProcessor.php | 6 +++--- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Context/NormalizeMessageProcessor.php b/src/Context/NormalizeMessageProcessor.php index bb14b4e..a944e75 100644 --- a/src/Context/NormalizeMessageProcessor.php +++ b/src/Context/NormalizeMessageProcessor.php @@ -8,7 +8,7 @@ final class NormalizeMessageProcessor implements ProcessorInterface { - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { $returnRecord = $record; diff --git a/src/DomainTrace/DomainTraceProcessor.php b/src/DomainTrace/DomainTraceProcessor.php index a2f0252..c44919d 100644 --- a/src/DomainTrace/DomainTraceProcessor.php +++ b/src/DomainTrace/DomainTraceProcessor.php @@ -17,7 +17,7 @@ public function __construct(Tracker $tracker) $this->tracker = $tracker; } - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { $messageId = $this->getMessageId($record); @@ -26,7 +26,7 @@ public function __invoke(LogRecord $record) return $record; } - + private function getMessageId(LogRecord $record): ?Uuid { if (false === \array_key_exists('message', $record['context'])) { diff --git a/src/ExceptionCatcher/TraceOfExceptionProcessor.php b/src/ExceptionCatcher/TraceOfExceptionProcessor.php index d79cf84..6d9a667 100644 --- a/src/ExceptionCatcher/TraceOfExceptionProcessor.php +++ b/src/ExceptionCatcher/TraceOfExceptionProcessor.php @@ -9,7 +9,7 @@ final class TraceOfExceptionProcessor implements ProcessorInterface { - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { if (false === \array_key_exists('exception', $record['context'])) { return $record; @@ -21,13 +21,13 @@ public function __invoke(LogRecord $record) $context['exception'] = AssocSerializer::from($context['exception']); if ($exception instanceof \JsonSerializable) { - $context['exception']['data'] = \json_encode($exception, JSON_THROW_ON_ERROR); + $context['exception']['data'] = \json_encode($exception, \JSON_THROW_ON_ERROR); } if (true === \array_key_exists('trace', $context['exception'])) { $context['exception']['trace'] = \json_encode( $context['exception']['trace'], - JSON_THROW_ON_ERROR + \JSON_THROW_ON_ERROR, ); } @@ -38,6 +38,6 @@ public function __invoke(LogRecord $record) $record->message, $context, $record->extra, - );; + ); } } diff --git a/src/ExecutionTime/ExecutionTimeProcessor.php b/src/ExecutionTime/ExecutionTimeProcessor.php index d8843bb..6b6daef 100644 --- a/src/ExecutionTime/ExecutionTimeProcessor.php +++ b/src/ExecutionTime/ExecutionTimeProcessor.php @@ -17,7 +17,7 @@ public function __construct(Stopwatch $stopwatch) $this->stopwatch = $stopwatch; } - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { if (false === \array_key_exists('message', $record['context'])) { return $record; diff --git a/src/Hostname/HostnameProcessor.php b/src/Hostname/HostnameProcessor.php index c980ecc..db00a5d 100644 --- a/src/Hostname/HostnameProcessor.php +++ b/src/Hostname/HostnameProcessor.php @@ -15,7 +15,7 @@ public function __construct() $this->host = \gethostname(); } - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { $record['extra']['hostname'] = $this->host; diff --git a/src/Info/InfoProcessor.php b/src/Info/InfoProcessor.php index 89b7a84..0c78356 100644 --- a/src/Info/InfoProcessor.php +++ b/src/Info/InfoProcessor.php @@ -10,7 +10,7 @@ final class InfoProcessor implements ProcessorInterface { - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { if (false === \array_key_exists('message', $record['context'])) { return $record; diff --git a/src/MonologIteratorProcessor.php b/src/MonologIteratorProcessor.php index 707d346..5bd5be8 100644 --- a/src/MonologIteratorProcessor.php +++ b/src/MonologIteratorProcessor.php @@ -15,7 +15,7 @@ public function __construct(ProcessorInterface ...$processors) $this->processors = $processors; } - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { foreach ($this->processors as $processor) { $record = $processor($record); diff --git a/src/OccurredOn/OccurredOnProcessor.php b/src/OccurredOn/OccurredOnProcessor.php index 439e2b5..87d4b97 100644 --- a/src/OccurredOn/OccurredOnProcessor.php +++ b/src/OccurredOn/OccurredOnProcessor.php @@ -10,7 +10,7 @@ final class OccurredOnProcessor implements ProcessorInterface { - public function __invoke(LogRecord $record) + public function __invoke(LogRecord $record): LogRecord { if (false === \array_key_exists('message', $record['context'])) { return $record; @@ -19,12 +19,12 @@ public function __invoke(LogRecord $record) $message = $record['context']['message']; if ($message instanceof DomainEvent) { - $record['extra']['occurred_on'] = (int) $message->occurredOn()->format('Uv'); + $record['extra']['occurred_on'] = (int)$message->occurredOn()->format('Uv'); return $record; } - $record['extra']['occurred_on'] = (int) DateTimeValueObject::now()->format('Uv'); + $record['extra']['occurred_on'] = (int)DateTimeValueObject::now()->format('Uv'); return $record; } From 9164ac53f4224c7d0fa8d8692423414fdf11af94 Mon Sep 17 00:00:00 2001 From: "cristian.almohalla" Date: Tue, 26 Aug 2025 12:52:57 +0200 Subject: [PATCH 7/8] - refactor: change extra.occurred_on type from millisecond timestamp (int) to ISO 8601 date string ('Y-m-d\TH:i:s.uP') - refactor: NormalizeMessageProcessor now generates a context.message object with keys: - message_id - type - payload (JSON string) - aggregate_id (for events only) - aggregate_version (for events only) - refactor: remove src/Info/InfoProcessor.php (removed duplicate data) - fix: context.exception.trace was unnecessarily JSON-encoded, making traces hard to read - feat: improve context.exception.trace format and reduce verbosity --- src/Context/NormalizeMessageProcessor.php | 43 ++++-- .../TraceOfExceptionProcessor.php | 4 +- src/Info/InfoProcessor.php | 55 ------- src/OccurredOn/OccurredOnProcessor.php | 6 +- src/Util/AssocSerializer.php | 29 +++- .../Context/NormalizeContextProcessorTest.php | 118 +++++++++++++- .../TraceOfExceptionProcessorTest.php | 41 +++-- tests/Info/InfoProcessorTest.php | 146 ------------------ tests/OccurredOn/OccurredOnProcessorTest.php | 11 +- 9 files changed, 205 insertions(+), 248 deletions(-) delete mode 100644 src/Info/InfoProcessor.php delete mode 100644 tests/Info/InfoProcessorTest.php diff --git a/src/Context/NormalizeMessageProcessor.php b/src/Context/NormalizeMessageProcessor.php index a944e75..e8c913a 100644 --- a/src/Context/NormalizeMessageProcessor.php +++ b/src/Context/NormalizeMessageProcessor.php @@ -5,31 +5,42 @@ use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; +use PcComponentes\Ddd\Util\Message\AggregateMessage; +use PcComponentes\Ddd\Util\Message\Message; final class NormalizeMessageProcessor implements ProcessorInterface { public function __invoke(LogRecord $record): LogRecord { - $returnRecord = $record; - if (false === \array_key_exists('message', $record['context'])) { - return $returnRecord; + return $record; } - if (false === \is_string($record['context']['message'])) { - $context = $record['context']; - $context['message'] = \json_encode($record['context']['message']); - - $returnRecord = new LogRecord( - $record->datetime, - $record->channel, - $record->level, - $record->message, - $context, - $record->extra, - ); + $context = $record['context']; + $message = $context['message']; + + if (false === ($message instanceof Message)) { + return $record; + } + + $context['message'] = [ + 'message_id' => $message->messageId()->value(), + 'type' => $message::messageType(), + 'payload' => \json_encode($message->messagePayload()), + ]; + + if ($message instanceof AggregateMessage) { + $context['message']['aggregate_id'] = $message->aggregateId(); + $context['message']['aggregate_version'] = $message->aggregateVersion(); } - return $returnRecord; + return new LogRecord( + $record->datetime, + $record->channel, + $record->level, + $record->message, + $context, + $record->extra, + ); } } diff --git a/src/ExceptionCatcher/TraceOfExceptionProcessor.php b/src/ExceptionCatcher/TraceOfExceptionProcessor.php index 6d9a667..0e8ee7f 100644 --- a/src/ExceptionCatcher/TraceOfExceptionProcessor.php +++ b/src/ExceptionCatcher/TraceOfExceptionProcessor.php @@ -24,7 +24,9 @@ public function __invoke(LogRecord $record): LogRecord $context['exception']['data'] = \json_encode($exception, \JSON_THROW_ON_ERROR); } - if (true === \array_key_exists('trace', $context['exception'])) { + if (true === \array_key_exists('trace', $context['exception']) + && false === \is_string($context['exception']['trace']) + ) { $context['exception']['trace'] = \json_encode( $context['exception']['trace'], \JSON_THROW_ON_ERROR, diff --git a/src/Info/InfoProcessor.php b/src/Info/InfoProcessor.php deleted file mode 100644 index 0c78356..0000000 --- a/src/Info/InfoProcessor.php +++ /dev/null @@ -1,55 +0,0 @@ -messageInfo($record); - $record = $this->aggregateInfo($record); - - return $record; - } - - private function messageInfo(LogRecord $record): LogRecord - { - $message = $record['context']['message']; - - if (false === $message instanceof Message) { - return $record; - } - - $record['extra']['message']['message_id'] = $message->messageId()->value(); - $record['extra']['message']['name'] = $message::messageName(); - $record['extra']['message']['type'] = $message::messageType(); - $record['extra']['message']['payload'] = \json_encode($message->messagePayload()); - - return $record; - } - - private function aggregateInfo(LogRecord $record): LogRecord - { - $message = $record['context']['message']; - - if (false === $message instanceof AggregateMessage) { - return $record; - } - - $record['extra']['message']['aggregate_id'] = $message->aggregateId(); - $record['extra']['message']['aggregate_version'] = $message->aggregateVersion(); - $record['extra']['message']['occurred_on'] = $message->occurredOn()->format(\DateTime::ATOM); - - return $record; - } -} diff --git a/src/OccurredOn/OccurredOnProcessor.php b/src/OccurredOn/OccurredOnProcessor.php index 87d4b97..11dcddb 100644 --- a/src/OccurredOn/OccurredOnProcessor.php +++ b/src/OccurredOn/OccurredOnProcessor.php @@ -10,6 +10,8 @@ final class OccurredOnProcessor implements ProcessorInterface { + private const TIME_FORMAT = 'Y-m-d\TH:i:s.uP'; + public function __invoke(LogRecord $record): LogRecord { if (false === \array_key_exists('message', $record['context'])) { @@ -19,12 +21,12 @@ public function __invoke(LogRecord $record): LogRecord $message = $record['context']['message']; if ($message instanceof DomainEvent) { - $record['extra']['occurred_on'] = (int)$message->occurredOn()->format('Uv'); + $record['extra']['occurred_on'] = $message->occurredOn()->format(self::TIME_FORMAT); return $record; } - $record['extra']['occurred_on'] = (int)DateTimeValueObject::now()->format('Uv'); + $record['extra']['occurred_on'] = DateTimeValueObject::now()->format(self::TIME_FORMAT); return $record; } diff --git a/src/Util/AssocSerializer.php b/src/Util/AssocSerializer.php index 8ab5a93..8397490 100644 --- a/src/Util/AssocSerializer.php +++ b/src/Util/AssocSerializer.php @@ -33,15 +33,34 @@ private static function throwable(\Throwable $throwable): array 'code' => $throwable->getCode(), 'file' => $throwable->getFile(), 'line' => $throwable->getLine(), - 'trace' => $throwable->getTraceAsString(), + 'trace' => self::trace($throwable), ]; } + private static function trace(\Throwable $throwable): string + { + $trace = $throwable->getTrace(); + $traceLenght = \count($trace); + $pagLenght = \strlen((string)$traceLenght); + + $result = []; + + foreach ($trace as $key => $step) { + $result[] = \sprintf( + "#%s %s(%s)%s%s()", + \str_pad((string)$key, $pagLenght, '0', \STR_PAD_LEFT), + $step['file'] ?? '', + $step['line'] ?? '', + $step['type'] ?? '', + $step['function'] ?? '', + ); + } + + return \implode(\PHP_EOL, $result); + } + private static function basic($anything): array { - return \json_decode( - \json_encode($anything), - true, - ); + return \json_decode(\json_encode($anything), true); } } diff --git a/tests/Context/NormalizeContextProcessorTest.php b/tests/Context/NormalizeContextProcessorTest.php index e2fb87b..f1ff3f0 100644 --- a/tests/Context/NormalizeContextProcessorTest.php +++ b/tests/Context/NormalizeContextProcessorTest.php @@ -3,7 +3,11 @@ namespace PcComponentes\DddLogging\Tests\Context; -use Monolog\LogRecord; +use PcComponentes\Ddd\Domain\Model\ValueObject\DateTimeValueObject; +use PcComponentes\Ddd\Domain\Model\ValueObject\Uuid; +use PcComponentes\Ddd\Util\Message\AggregateMessage; +use PcComponentes\Ddd\Util\Message\SimpleMessage; +use PcComponentes\Ddd\Util\Message\ValueObject\AggregateId; use PcComponentes\DddLogging\Context\NormalizeMessageProcessor; use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; @@ -22,16 +26,116 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithEncodedMessage() { $record = LogRecordMother::withContext([ - 'message' => [ - 'This is a message', - ], + 'message' => [ + 'This is a message', ], + ]); + + $result = (new NormalizeMessageProcessor())($record); + + $this->assertEquals($record, $result); + } + + public function testShouldReturnedRecordWithDDDMessage() + { + $stringUuid = '04e6de1e-c5b9-42fc-ad43-e1ec4e64e121'; + $messageId = Uuid::from($stringUuid); + $simpleMessage = SimpleMessageMock::fromPayload($messageId, []); + + $record = LogRecordMother::withContext([ + 'message' => $simpleMessage, + ],); + + $result = (new NormalizeMessageProcessor())($record); + + $this->assertArrayHasKey('context', $result); + $this->assertArrayHasKey('message', $result['context']); + $this->assertArrayHasKey('message_id', $result['context']['message']); + $this->assertEquals($stringUuid, $result['context']['message']['message_id']); + $this->assertArrayHasKey('type', $result['context']['message']); + $this->assertEquals(SimpleMessageMock::messageType(), $result['context']['message']['type']); + $this->assertArrayHasKey('payload', $result['context']['message']); + } + + public function testShouldReturnedWithAggregateMessageInfo() + { + $stringMessageUuid = '04e6de1e-c5b9-42fc-ad43-e1ec4e64e121'; + $stringAggregateUuid = '575f378a-e0b4-4197-89c3-5c3065fdaf1e'; + $occurredOn = DateTimeValueObject::from('now'); + + $messageId = Uuid::from($stringMessageUuid); + $aggregateId = AggregateId::from($stringAggregateUuid); + + $aggregateMessage = AggregateMessageMock::fromPayload( + $messageId, + $aggregateId, + $occurredOn, + [], + 1, ); - $expectedEncodedMessage = \json_encode($record['context']['message']); + $record = LogRecordMother::withContext([ + 'message' => $aggregateMessage, + ],); $result = (new NormalizeMessageProcessor())($record); - $this->assertEquals($expectedEncodedMessage, $result['context']['message']); + $this->assertArrayHasKey('context', $result); + $this->assertArrayHasKey('message', $result['context']); + $this->assertArrayHasKey('aggregate_id', $result['context']['message']); + $this->assertArrayHasKey('message_id', $result['context']['message']); + $this->assertEquals($stringMessageUuid, $result['context']['message']['message_id']); + $this->assertArrayHasKey('type', $result['context']['message']); + $this->assertEquals(AggregateMessageMock::messageType(), $result['context']['message']['type']); + $this->assertArrayHasKey('payload', $result['context']['message']); + $this->assertEquals($aggregateId, $result['context']['message']['aggregate_id']); + $this->assertArrayHasKey('aggregate_version', $result['context']['message']); + $this->assertEquals($aggregateMessage->aggregateVersion(), $result['context']['message']['aggregate_version']); + } +} + +class SimpleMessageMock extends SimpleMessage +{ + public static function messageName(): string + { + return 'message_name'; + } + + public static function messageVersion(): string + { + return 'message_version'; + } + + public static function messageType(): string + { + return 'message_type'; + } + + protected function assertPayload(): void + { + // TODO: Implement assertPayload() method. + } +} + +class AggregateMessageMock extends AggregateMessage +{ + public static function messageName(): string + { + return 'aggregate_message_name'; + } + + public static function messageVersion(): string + { + return 'aggregate_message_version'; + } + + public static function messageType(): string + { + return 'aggregate_message_type'; + } + + protected function assertPayload(): void + { + // TODO: Implement assertPayload() method. } -} \ No newline at end of file +} diff --git a/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php b/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php index cdc254d..4f341e5 100644 --- a/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php +++ b/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php @@ -3,7 +3,7 @@ namespace PcComponentes\DddLogging\Tests\ExceptionCatcher; -use Pccomponentes\Apixception\Core\Exception\SerializableException; +use _PHPStan_b8e553790\Symfony\Component\Console\Exception\LogicException; use PcComponentes\DddLogging\ExceptionCatcher\TraceOfExceptionProcessor; use PcComponentes\DddLogging\Tests\Mock\LogRecordMother; use PHPUnit\Framework\TestCase; @@ -24,8 +24,8 @@ public function testShouldReturnedRecordWithExceptionContext() $exceptionMock = $this->createMock(\JsonSerializable::class); $record = LogRecordMother::withContext( [ - 'exception' => $exceptionMock - ] + 'exception' => $exceptionMock, + ], ); $exceptionMock @@ -42,19 +42,36 @@ public function testShouldReturnedRecordWithExceptionTraceContext() { $trace = [ 'method 1', - 'method 2' + 'method 2', ]; - $record = LogRecordMother::withContext( [ - 'exception' => [ - 'trace' => $trace - ] - ] - ); + $record = LogRecordMother::withContext([ + 'exception' => [ + 'trace' => $trace, + ], + ]); + + $recordResult = (new TraceOfExceptionProcessor())($record); + + $this->assertStringContainsString('method 1', $recordResult['context']['exception']['trace']); + $this->assertStringContainsString('method 2', $recordResult['context']['exception']['trace']); + } + + public function testShouldReturnedRecordWithThrowableStringTraceContext() + { + $exception = new LogicException(); + + $record = LogRecordMother::withContext([ + 'exception' => $exception, + ]); $recordResult = (new TraceOfExceptionProcessor())($record); - $this->assertStringContainsString('method 1',$recordResult['context']['exception']['trace']); - $this->assertStringContainsString('method 2',$recordResult['context']['exception']['trace']); + + $this->assertStringContainsString('#00 ', $recordResult['context']['exception']['trace']); + $this->assertStringContainsString( + 'testShouldReturnedRecordWithThrowableStringTraceContext', + $recordResult['context']['exception']['trace'], + ); } } diff --git a/tests/Info/InfoProcessorTest.php b/tests/Info/InfoProcessorTest.php deleted file mode 100644 index 15f929c..0000000 --- a/tests/Info/InfoProcessorTest.php +++ /dev/null @@ -1,146 +0,0 @@ -assertEquals($record, $result); - } - - public function testShouldReturnedRecordWithoutDDDMessage() - { - $record = LogRecordMother::default(); - - $result = (new InfoProcessor())($record); - - $this->assertEquals($record, $result); - } - - public function testShouldReturnedRecordWithDDDMessageInfo() - { - $stringUuid = '04e6de1e-c5b9-42fc-ad43-e1ec4e64e121'; - $messageIdMock = $this->createMock(Uuid::class); - $messageIdMock - ->method('value') - ->willReturn($stringUuid); - $simpleMessage = SimpleMessageMock::fromPayload($messageIdMock, []); - - $record = LogRecordMother::withContext([ - 'message' => $simpleMessage, - ],); - - $result = (new InfoProcessor())($record); - - $this->assertArrayHasKey('extra', $result); - $this->assertArrayHasKey('message', $result['extra']); - $this->assertArrayHasKey('message_id', $result['extra']['message']); - $this->assertEquals($stringUuid, $result['extra']['message']['message_id']); - $this->assertArrayHasKey('name', $result['extra']['message']); - $this->assertEquals(SimpleMessageMock::messageName(), $result['extra']['message']['name']); - $this->assertArrayHasKey('type', $result['extra']['message']); - $this->assertEquals(SimpleMessageMock::messageType(), $result['extra']['message']['type']); - $this->assertArrayHasKey('payload', $result['extra']['message']); - } - - public function testShouldReturnedWithAggregateMessageInfo() - { - $stringMessageUuid = '04e6de1e-c5b9-42fc-ad43-e1ec4e64e121'; - $stringAggregateUuid = '575f378a-e0b4-4197-89c3-5c3065fdaf1e'; - $occurredOn = DateTimeValueObject::from('now'); - - $messageIdMock = $this->createMock(Uuid::class); - $messageIdMock - ->method('value') - ->willReturn($stringMessageUuid); - - $aggregateIdMock = $this->createMock(AggregateId::class); - $aggregateIdMock - ->method('value') - ->willReturn($stringAggregateUuid); - - $aggregateMessage = AggregateMessageMock::fromPayload( - $messageIdMock, - $aggregateIdMock, - $occurredOn, - [], - 1, - ); - - $record = LogRecordMother::withContext([ - 'message' => $aggregateMessage, - ],); - - $result = (new InfoProcessor())($record); - - $this->assertArrayHasKey('extra', $result); - $this->assertArrayHasKey('message', $result['extra']); - $this->assertArrayHasKey('aggregate_id', $result['extra']['message']); - $this->assertEquals($aggregateIdMock, $result['extra']['message']['aggregate_id']); - $this->assertArrayHasKey('aggregate_version', $result['extra']['message']); - $this->assertEquals($aggregateMessage->aggregateVersion(), $result['extra']['message']['aggregate_version']); - $this->assertArrayHasKey('occurred_on', $result['extra']['message']); - $this->assertEquals($aggregateMessage->occurredOn()->format(\DateTime::ATOM), $result['extra']['message']['occurred_on']); - } -} - -class SimpleMessageMock extends SimpleMessage -{ - public static function messageName(): string - { - return 'message_name'; - } - - public static function messageVersion(): string - { - return 'message_version'; - } - - public static function messageType(): string - { - return 'message_type'; - } - - protected function assertPayload(): void - { - // TODO: Implement assertPayload() method. - } -} - -class AggregateMessageMock extends AggregateMessage -{ - public static function messageName(): string - { - return 'aggregate_message_name'; - } - - public static function messageVersion(): string - { - return 'aggregate_message_version'; - } - - public static function messageType(): string - { - return 'aggregate_message_type'; - } - - protected function assertPayload(): void - { - // TODO: Implement assertPayload() method. - } -} diff --git a/tests/OccurredOn/OccurredOnProcessorTest.php b/tests/OccurredOn/OccurredOnProcessorTest.php index a8a379f..0fea295 100644 --- a/tests/OccurredOn/OccurredOnProcessorTest.php +++ b/tests/OccurredOn/OccurredOnProcessorTest.php @@ -29,14 +29,17 @@ public function testShouldReturnedRecordWithOccurredOn() $result = (new OccurredOnProcessor())($record); - - $this->assertIsInt($result['extra']['occurred_on']); + $this->assertTrue(false !== \DateTimeImmutable::createFromFormat( + 'Y-m-d\TH:i:s.uP', + $result['extra']['occurred_on'], + new \DateTimeZone('UTC'), + )); } public function testShouldReturnedRecordWithDomainEventOccurredOn() { $timestamp = '1582912634.678'; - $expectedTimestamp = '1582912634678'; + $expectedValue = '2020-02-28T17:57:14.678000+00:00'; $occurredOn = \DateTimeImmutable::createFromFormat('U.v', $timestamp, new \DateTimeZone('UTC')); $domainEventMock = $this->createMock(DomainEvent::class); @@ -53,6 +56,6 @@ public function testShouldReturnedRecordWithDomainEventOccurredOn() $result = (new OccurredOnProcessor())($record); $this->assertArrayHasKey('occurred_on', $result['extra']); - $this->assertEquals($expectedTimestamp, $result['extra']['occurred_on']); + $this->assertSame($expectedValue, $result['extra']['occurred_on']); } } From 16b8b8ce10d0a09d7bbed794afdb789f841d3878 Mon Sep 17 00:00:00 2001 From: "cristian.almohalla" Date: Tue, 26 Aug 2025 14:30:04 +0200 Subject: [PATCH 8/8] feat: add occurred_on timestamp to all log records for enhanced traceability --- src/OccurredOn/OccurredOnProcessor.php | 6 +----- tests/OccurredOn/OccurredOnProcessorTest.php | 15 +-------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/OccurredOn/OccurredOnProcessor.php b/src/OccurredOn/OccurredOnProcessor.php index 11dcddb..e0c9489 100644 --- a/src/OccurredOn/OccurredOnProcessor.php +++ b/src/OccurredOn/OccurredOnProcessor.php @@ -14,11 +14,7 @@ final class OccurredOnProcessor implements ProcessorInterface public function __invoke(LogRecord $record): LogRecord { - if (false === \array_key_exists('message', $record['context'])) { - return $record; - } - - $message = $record['context']['message']; + $message = $record['context']['message'] ?? null; if ($message instanceof DomainEvent) { $record['extra']['occurred_on'] = $message->occurredOn()->format(self::TIME_FORMAT); diff --git a/tests/OccurredOn/OccurredOnProcessorTest.php b/tests/OccurredOn/OccurredOnProcessorTest.php index 0fea295..6e71718 100644 --- a/tests/OccurredOn/OccurredOnProcessorTest.php +++ b/tests/OccurredOn/OccurredOnProcessorTest.php @@ -10,22 +10,9 @@ final class OccurredOnProcessorTest extends TestCase { - public function testShouldReturnedRecordWithoutMessage() - { - $record = LogRecordMother::default(); - - $result = (new OccurredOnProcessor())($record); - - $this->assertEquals($record, $result); - } - public function testShouldReturnedRecordWithOccurredOn() { - $record = LogRecordMother::withContext( - [ - 'message' => [], - ], - ); + $record = LogRecordMother::default(); $result = (new OccurredOnProcessor())($record);