From da8cef45ed948edb82f971b377e0197a7ea7f898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Aleixo?= Date: Mon, 5 Mar 2018 00:13:38 +0000 Subject: [PATCH] Added Tests --- composer.json | 43 ++++++++++++ config/correlationid.php | 20 ++++++ phpunit.xml | 22 ++++++ src/CorrelationId.php | 33 +++++++++ src/CorrelationIdMiddleware.php | 79 +++++++++++++++++++++ src/CorrelationIdProcessor.php | 31 +++++++++ src/CorrelationIdServiceProvider.php | 15 ++++ tests/MiddlewareTest.php | 100 +++++++++++++++++++++++++++ tests/TestCase.php | 36 ++++++++++ 9 files changed, 379 insertions(+) create mode 100644 composer.json create mode 100644 config/correlationid.php create mode 100644 phpunit.xml create mode 100644 src/CorrelationId.php create mode 100644 src/CorrelationIdMiddleware.php create mode 100644 src/CorrelationIdProcessor.php create mode 100644 src/CorrelationIdServiceProvider.php create mode 100644 tests/MiddlewareTest.php create mode 100644 tests/TestCase.php diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..faa3ee5 --- /dev/null +++ b/composer.json @@ -0,0 +1,43 @@ +{ + "name": "andreja/laravel-middleware-correlation-id", + "description": "Laravel Package to use a Correlation ID Middleware", + "keywords": [ + "laravel", + "correlation-id", + "middleware", + "tracing" + ], + "homepage": "https://github.com/ajaaleixo/laravel-middleware-correlation-id", + "require": { + "php" : ">=7.0", + "webpatser/laravel-uuid": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0", + "orchestra/testbench": "^3.6" + }, + "license": "MIT", + "authors": [ + { + "name": "André Aleixo", + "email": "ajaaleixo@gmail.com" + } + ], + "autoload": { + "psr-4": { + "Ajaaleixo\\Middleware\\CorrelationId\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Ajaaleixo\\Middleware\\CorrelationId\\Test\\": "tests" + } + }, + "extra": { + "laravel": { + "providers": [ + "Ajaaleixo\\Middleware\\CorrelationId\\ServiceProvider" + ] + } + } +} diff --git a/config/correlationid.php b/config/correlationid.php new file mode 100644 index 0000000..433ce00 --- /dev/null +++ b/config/correlationid.php @@ -0,0 +1,20 @@ + true, + + /* + * Used to fetch from Headers array a correlation id + */ + 'header_name' => 'X-CORRELATION-ID', + + /* + * Used to inject within context array in logs + */ + 'param_name' => 'x_correlation_id', +]; \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..18ba69d --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,22 @@ + + + + + tests + + + + + src/ + + + \ No newline at end of file diff --git a/src/CorrelationId.php b/src/CorrelationId.php new file mode 100644 index 0000000..d237705 --- /dev/null +++ b/src/CorrelationId.php @@ -0,0 +1,33 @@ +logger = $application->get('log'); + + if (!Request::hasMacro('hasCorrelationId')) { + Request::macro('hasCorrelationId', function() { + if ($this->headers->has(CorrelationId::getHeaderName())) { + return true; + } + return false; + }); + } + if (!Request::hasMacro('getCorrelationId')) { + Request::macro('getCorrelationId', function($default = null) { + if ($this->headers->has(CorrelationId::getHeaderName())) { + return $this->headers->get(CorrelationId::getHeaderName()); + } + return $default; + }); + } + if (!Request::hasMacro('setCorrelationId')) { + Request::macro('setCorrelationId', function($cid) { + $this->headers->set(CorrelationId::getHeaderName(), (string) $cid); + return $this; + }); + } + } + + /** + * @param Request $request + * @param Closure $next + * + * @return mixed + */ + public function handle(Request $request, Closure $next) + { + // Check if the request header already has a correlation id header + if (!$request->headers->has(CorrelationId::getHeaderName())) { + $request->headers->set(CorrelationId::getHeaderName(), (string)CorrelationId::id()); + } + + if (!config('correlationid.propagates')) { + return $next($request); + } + + $processor = new CorrelationIdProcessor( + CorrelationId::getParamName(), + $request->headers->get(CorrelationId::getHeaderName()) + ); + + if ($this->logger instanceof MonologLogger) { + $this->logger->pushProcessor($processor); + } elseif (method_exists($this->logger, 'getMonolog')) { + $this->logger->getMonolog()->pushProcessor($processor); + } elseif ($this->logger->driver() instanceof IlluminateLogger) { + $logger = $this->logger->driver()->getLogger(); + if ($logger instanceof MonologLogger) { + $this->logger->pushProcessor($processor); + } + } + + return $next($request); + } +} \ No newline at end of file diff --git a/src/CorrelationIdProcessor.php b/src/CorrelationIdProcessor.php new file mode 100644 index 0000000..bdb6495 --- /dev/null +++ b/src/CorrelationIdProcessor.php @@ -0,0 +1,31 @@ +paramName = $paramName; + if ($correlationId !== null) { + $this->correlationId = (string) $correlationId; + } + } + + public function __invoke(array $record): array + { + if (!empty($this->correlationId)) { + $record['context'][$this->paramName] = $this->correlationId; + } + + return $record; + } + + public function getCorrelationId(): string + { + return $this->correlationId; + } +} \ No newline at end of file diff --git a/src/CorrelationIdServiceProvider.php b/src/CorrelationIdServiceProvider.php new file mode 100644 index 0000000..c9e0fe4 --- /dev/null +++ b/src/CorrelationIdServiceProvider.php @@ -0,0 +1,15 @@ +app['router']->aliasMiddleware('correlation_id', CorrelationIdMiddleware::class); + } +} \ No newline at end of file diff --git a/tests/MiddlewareTest.php b/tests/MiddlewareTest.php new file mode 100644 index 0000000..18d2fa4 --- /dev/null +++ b/tests/MiddlewareTest.php @@ -0,0 +1,100 @@ +correlationIdMiddleware = new CorrelationIdMiddleware($this->app); + } + + /** @test */ + public function has_macros_when_middleware_runs() + { + // Prepare + $request = $this->makeRequestWithCorrelationHeader(); + + // Test + $this->runMiddleware($this->correlationIdMiddleware, $request); + + // Assert + $this->assertTrue($request->hasMacro('hasCorrelationId')); + $this->assertTrue($request->hasMacro('getCorrelationId')); + $this->assertTrue($request->hasMacro('setCorrelationId')); + } + + /** @test */ + public function correlation_propagates_to_logs() + { + // Prepare + $request = $this->makeRequestWithCorrelationHeader(); + $correlationId = $request->header('x-correlation-id'); + $logMessage = 'This is my n log entry'; + $correlationParam = config('correlationid.param_name'); + + // Test + $this->runMiddleware($this->correlationIdMiddleware, $request); + Log::info($logMessage); + + $lastLogLine = $this->getLastLogLine(); + $this->assertContains($logMessage, $lastLogLine); + $this->assertContains($correlationId, $lastLogLine); + $this->assertContains($correlationParam, $lastLogLine); + } + + /** @test */ + public function correlation_does_not_propagate_to_logs() + { + // Prepare + $request = $this->makeRequestWithoutCorrelationHeader(); + $this->app['config']->set('correlationid.propagates', false); + $logMessage = 'This is a log without correlation id'; + $correlationParam = config('correlationid.param_name'); + + // Test + $this->runMiddleware($this->correlationIdMiddleware, $request); + Log::info($logMessage); + + $lastLogLine = $this->getLastLogLine(); + $this->assertContains($logMessage, $lastLogLine); + $this->assertNotContains($correlationParam, $lastLogLine); + } + + protected function runMiddleware($middleware, $request) + { + return $middleware->handle($request, function () { + return (new Response())->setContent(''); + }); + } + + protected function makeRequestWithCorrelationHeader() + { + $request = new Request(); + $request->headers->add([config('correlationid.header_name') => (string) Uuid::generate(4)]); + + return $request; + } + + protected function makeRequestWithoutCorrelationHeader() + { + return new Request(); + } + + protected function getLastLogLine() + { + $content = file_get_contents($this->app['config']['logging']['channels']['single']['path']); + $arrayContent = explode("\n", $content); + + return $arrayContent[count($arrayContent)-2]; + } +} \ No newline at end of file diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..c3eab23 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,36 @@ +set('correlationid', [ + 'propagates' => true, + 'header_name' => 'X-CORRELATION-ID', + 'param_name' => 'x_correlation_id', + ]); + } +} \ No newline at end of file