diff --git a/Dockerfile b/Dockerfile index 1ad8eb9..ea0f1bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.0-cli-alpine3.13 +FROM php:8.2-cli-alpine3.21 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 --no-cache --virtual .phpize_deps $PHPIZE_DEPS \ + && apk add linux-headers \ + && pecl install xdebug-3.4.5 \ + && docker-php-ext-enable xdebug \ + && apk del linux-headers ${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 1cd4c9f..c3ed8e7 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,9 @@ } ], "require": { - "php": "^7.4|^8.0", + "php": "^8.2", "ext-json": "*", - "monolog/monolog": "^1.25|^2.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..e8c913a 100644 --- a/src/Context/NormalizeMessageProcessor.php +++ b/src/Context/NormalizeMessageProcessor.php @@ -3,20 +3,44 @@ namespace PcComponentes\DddLogging\Context; +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(array $record): array + public function __invoke(LogRecord $record): LogRecord { if (false === \array_key_exists('message', $record['context'])) { return $record; } - if (false === \is_string($record['context']['message'])) { - $record['context']['message'] = \json_encode($record['context']['message']); + $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 $record; + return new LogRecord( + $record->datetime, + $record->channel, + $record->level, + $record->message, + $context, + $record->extra, + ); } } diff --git a/src/DomainTrace/DomainTraceProcessor.php b/src/DomainTrace/DomainTraceProcessor.php index 6d85650..c44919d 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,23 +17,24 @@ public function __construct(Tracker $tracker) $this->tracker = $tracker; } - public function __invoke(array $record): array + public function __invoke(LogRecord $record): LogRecord { $messageId = $this->getMessageId($record); - $record['extra']['correlation_id'] = $this->tracker->correlationId($messageId); - $record['extra']['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; } - - private function getMessageId(array $record): ?Uuid + + private function getMessageId(LogRecord $record): ?Uuid { if (false === \array_key_exists('message', $record['context'])) { return null; } $message = $record['context']['message']; + if (false === $message instanceof Message) { return null; } diff --git a/src/ExceptionCatcher/TraceOfExceptionProcessor.php b/src/ExceptionCatcher/TraceOfExceptionProcessor.php index 9cfa7ba..0e8ee7f 100644 --- a/src/ExceptionCatcher/TraceOfExceptionProcessor.php +++ b/src/ExceptionCatcher/TraceOfExceptionProcessor.php @@ -3,31 +3,43 @@ 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): LogRecord { 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'], - JSON_THROW_ON_ERROR + 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, ); } - 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..6b6daef 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): LogRecord { if (false === \array_key_exists('message', $record['context'])) { return $record; @@ -40,7 +41,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/Hostname/HostnameProcessor.php b/src/Hostname/HostnameProcessor.php index 369f113..db00a5d 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): LogRecord { $record['extra']['hostname'] = $this->host; diff --git a/src/Info/InfoProcessor.php b/src/Info/InfoProcessor.php deleted file mode 100644 index 72629c5..0000000 --- a/src/Info/InfoProcessor.php +++ /dev/null @@ -1,54 +0,0 @@ -messageInfo($record); - $record = $this->aggregateInfo($record); - - return $record; - } - - private function messageInfo(array $record): array - { - $message = $record['context']['message']; - - if (false === $message instanceof Message) { - 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']); - - return $record; - } - - private function aggregateInfo(array $record): array - { - $message = $record['context']['message']; - - if (false === $message instanceof AggregateMessage) { - return $record; - } - - $record['extra']['aggregate_id'] = $message->aggregateId(); - $record['extra']['aggregate_version'] = $message->aggregateVersion(); - $record['extra']['occurred_on'] = $message->occurredOn()->format(\DateTime::ATOM); - - return $record; - } -} diff --git a/src/MonologIteratorProcessor.php b/src/MonologIteratorProcessor.php index a3a3f73..5bd5be8 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): LogRecord { foreach ($this->processors as $processor) { $record = $processor($record); diff --git a/src/OccurredOn/OccurredOnProcessor.php b/src/OccurredOn/OccurredOnProcessor.php index 903d827..e0c9489 100644 --- a/src/OccurredOn/OccurredOnProcessor.php +++ b/src/OccurredOn/OccurredOnProcessor.php @@ -3,35 +3,26 @@ namespace PcComponentes\DddLogging\OccurredOn; +use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; use PcComponentes\Ddd\Domain\Model\DomainEvent; +use PcComponentes\Ddd\Domain\Model\ValueObject\DateTimeValueObject; final class OccurredOnProcessor implements ProcessorInterface { - public function __invoke(array $record): array - { - if (false === \array_key_exists('message', $record['context'])) { - return $record; - } + private const TIME_FORMAT = 'Y-m-d\TH:i:s.uP'; - $message = $record['context']['message']; + public function __invoke(LogRecord $record): LogRecord + { + $message = $record['context']['message'] ?? null; if ($message instanceof DomainEvent) { - $occurredOn = \sprintf( - '%d%d', - $message->occurredOn()->getTimestamp(), - $message->occurredOn()->format('v') - ); - $record['occurred_on'] = \intval($occurredOn); + $record['extra']['occurred_on'] = $message->occurredOn()->format(self::TIME_FORMAT); return $record; } - $record['occurred_on'] = \intval( - \round( - \microtime(true) * 1000, - ) - ); + $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 ab29cfd..f1ff3f0 100644 --- a/tests/Context/NormalizeContextProcessorTest.php +++ b/tests/Context/NormalizeContextProcessorTest.php @@ -3,16 +3,20 @@ namespace PcComponentes\DddLogging\Tests\Context; +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; final class NormalizeContextProcessorTest extends TestCase { public function testShouldReturnedRecordWithoutMessage() { - $record = [ - 'context' => [] - ]; + $record = LogRecordMother::default(); $result = (new NormalizeMessageProcessor())($record); @@ -21,18 +25,117 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithEncodedMessage() { - $record = [ - 'context' => [ - 'message' => [ - 'This is a message', - ], + $record = LogRecordMother::withContext([ + 'message' => [ + 'This is a message', ], - ]; + ]); - $expectedEncodedMessage = \json_encode($record['context']['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->assertEquals($expectedEncodedMessage, $result['context']['message']); + $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, + ); + + $record = LogRecordMother::withContext([ + 'message' => $aggregateMessage, + ],); + + $result = (new NormalizeMessageProcessor())($record); + + $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/DomainTrace/DomainTraceProcessorTest.php b/tests/DomainTrace/DomainTraceProcessorTest.php index 4cff21e..ee9f5bf 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 @@ -30,7 +29,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['extra']['trace']['correlation_id']); + $this->assertEquals($replyTo, $record['extra']['trace']['reply_to']); } } \ No newline at end of file diff --git a/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php b/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php index 6650738..4f341e5 100644 --- a/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php +++ b/tests/ExceptionCatcher/TraceOfExceptionProcessorTest.php @@ -3,17 +3,16 @@ 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; 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' => [ - 'exception' => $exceptionMock - ] - ]; + $record = LogRecordMother::withContext( + [ + 'exception' => $exceptionMock, + ], + ); $exceptionMock ->expects($this->atLeastOnce()) @@ -43,20 +42,36 @@ public function testShouldReturnedRecordWithExceptionTraceContext() { $trace = [ 'method 1', - 'method 2' + 'method 2', ]; - $record = [ - 'context' => [ - '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']); + $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('#00 ', $recordResult['context']['exception']['trace']); + $this->assertStringContainsString( + 'testShouldReturnedRecordWithThrowableStringTraceContext', + $recordResult['context']['exception']['trace'], + ); } } diff --git a/tests/ExecutionTime/ExecutionTimeProcessorTest.php b/tests/ExecutionTime/ExecutionTimeProcessorTest.php index 10153e6..0e1cd18 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,9 @@ public function testShouldReturnedRecordWithoutMessage() public function testShouldReturnedRecordWithoutDDDMessage() { - $record = [ - 'context' => [ - 'message' => [] - ], - ]; + $record = LogRecordMother::withContext([ + 'message' => [], + ]); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); @@ -73,11 +70,9 @@ public function testShouldReturnedRecordWithExecutionTime() ->method('getDuration') ->willReturn($milliseconds); - $record = [ - 'context' => [ - 'message' => $messageMock - ], - ]; + $record = LogRecordMother::withContext([ + 'message' => $messageMock, + ],); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); @@ -111,15 +106,13 @@ public function testShouldReturnedZeroExecutionTimeWhenLogicExceptionOccurred() ->method('getDuration') ->willThrowException(new \LogicException()); - $record = [ - 'context' => [ - 'message' => $messageMock - ], - ]; + $record = LogRecordMother::withContext([ + 'message' => $messageMock, + ],); $result = (new ExecutionTimeProcessor($this->stopwatchMock))($record); $this->assertArrayHasKey('execution_time', $result['extra']); $this->assertEquals(0, $result['extra']['execution_time']); } -} \ No newline at end of file +} 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 deleted file mode 100644 index 18ded92..0000000 --- a/tests/Info/InfoProcessorTest.php +++ /dev/null @@ -1,153 +0,0 @@ - [], - ]; - - $result = (new InfoProcessor())($record); - - $this->assertEquals($record, $result); - } - - public function testShouldReturnedRecordWithoutDDDMessage() - { - $record = [ - 'context' => [ - 'message' => [] - ], - ]; - - $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 = [ - 'context' => [ - 'message' => $simpleMessage, - ], - ]; - - $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']); - } - - 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 = [ - 'context' => [ - 'message' => $aggregateMessage, - ], - ]; - - $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']); - } -} - -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/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..6e71718 100644 --- a/tests/OccurredOn/OccurredOnProcessorTest.php +++ b/tests/OccurredOn/OccurredOnProcessorTest.php @@ -5,81 +5,44 @@ 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' => [] - ]; - - $result = (new OccurredOnProcessor())($record); - - $this->assertEquals($record, $result); - } - public function testShouldReturnedRecordWithOccurredOn() { - $record = [ - 'context' => [ - 'message' => [], - ] - ]; + $record = LogRecordMother::default(); $result = (new OccurredOnProcessor())($record); - $this->assertArrayHasKey('occurred_on', $result); - $this->assertIsInt($result['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; //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'; + $expectedValue = '2020-02-28T17:57:14.678000+00:00'; + $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); - - $record = [ - 'context' => [ - 'message' => $domainEventMock - ] - ]; + ->willReturn($occurredOn); - $result = (new OccurredOnProcessor())($record); - $this->assertArrayHasKey('occurred_on', $result); - $this->assertEquals( - $this->expectedOccurredOn( - $timestamp, - $milliseconds - ), - $result['occurred_on'] + $record = LogRecordMother::withContext( + [ + 'message' => $domainEventMock, + ], ); - } - private function expectedOccurredOn(int $timestamp, string $milliseconds) - { - return \intval( - \sprintf( - '%d%d', - $timestamp, - $milliseconds - ) - ); + $result = (new OccurredOnProcessor())($record); + $this->assertArrayHasKey('occurred_on', $result['extra']); + $this->assertSame($expectedValue, $result['extra']['occurred_on']); } }