Merge pull request #2090 from acelaya-forks/feature/propagate-job-request-id

Forward request ID from sync request process to async job processes
This commit is contained in:
Alejandro Celaya 2024-04-07 11:30:47 +02:00 committed by GitHub
commit 75f6f8dd18
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 84 additions and 3 deletions

View file

@ -27,6 +27,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
This has been achieved by introducing a new table which tracks slotted visits counts. We can then `SUM` all counts for certain short URL, avoiding `COUNT(visits)` aggregates which are much less performant when there are a lot of visits.
* [#2049](https://github.com/shlinkio/shlink/issues/2049) Request ID is now propagated to the background tasks/jobs scheduled during a request.
This allows for a better traceability, as the logs generated during those jobs will have a matching UUID as the logs generated during the request the triggered the job.
### Deprecated
* *Nothing*

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
use Mezzio\Application;
use Psr\Container\ContainerInterface;
use Shlinkio\Shlink\Common\Middleware\RequestIdMiddleware;
use Shlinkio\Shlink\EventDispatcher\RoadRunner\RoadRunnerTaskConsumerToListener;
use Spiral\RoadRunner\Http\PSR7Worker;
@ -27,6 +28,9 @@ use function Shlinkio\Shlink\Config\env;
}
}
} else {
$container->get(RoadRunnerTaskConsumerToListener::class)->listenForTasks();
$requestIdMiddleware = $container->get(RequestIdMiddleware::class);
$container->get(RoadRunnerTaskConsumerToListener::class)->listenForTasks(
fn (string $requestId) => $requestIdMiddleware->setCurrentRequestId($requestId),
);
}
})();

View file

@ -43,9 +43,9 @@
"pugx/shortid-php": "^1.1",
"ramsey/uuid": "^4.7",
"shlinkio/doctrine-specification": "^2.1.1",
"shlinkio/shlink-common": "^6.0",
"shlinkio/shlink-common": "dev-main#3cb0845 as 6.1",
"shlinkio/shlink-config": "^3.0",
"shlinkio/shlink-event-dispatcher": "^4.0",
"shlinkio/shlink-event-dispatcher": "dev-main#a2a5d6f as 4.1",
"shlinkio/shlink-importer": "^5.3.1",
"shlinkio/shlink-installer": "^9.0",
"shlinkio/shlink-ip-geolocation": "^4.0",

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink;
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
use Laminas\ServiceManager\Factory\InvokableFactory;
use Monolog\Level;
use Monolog\Logger;
@ -13,6 +14,8 @@ use Shlinkio\Shlink\Common\Logger\LoggerFactory;
use Shlinkio\Shlink\Common\Logger\LoggerType;
use Shlinkio\Shlink\Common\Middleware\AccessLogMiddleware;
use Shlinkio\Shlink\Common\Middleware\RequestIdMiddleware;
use Shlinkio\Shlink\Core\EventDispatcher\Helper\RequestIdProvider;
use Shlinkio\Shlink\EventDispatcher\Util\RequestIdProviderInterface;
use function Shlinkio\Shlink\Config\runningInRoadRunner;
@ -44,14 +47,20 @@ return (static function (): array {
'Logger_Shlink' => [LoggerFactory::class, 'Shlink'],
'Logger_Access' => [LoggerFactory::class, 'Access'],
NullLogger::class => InvokableFactory::class,
RequestIdProvider::class => ConfigAbstractFactory::class,
],
'aliases' => [
'logger' => 'Logger_Shlink',
Logger::class => 'Logger_Shlink',
LoggerInterface::class => 'Logger_Shlink',
AccessLogMiddleware::LOGGER_SERVICE_NAME => 'Logger_Access',
RequestIdProviderInterface::class => RequestIdProvider::class,
],
],
ConfigAbstractFactory::class => [
RequestIdProvider::class => [RequestIdMiddleware::class],
],
];
})();

View file

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\EventDispatcher\Helper;
use Shlinkio\Shlink\Common\Middleware\RequestIdMiddleware;
use Shlinkio\Shlink\EventDispatcher\Util\RequestIdProviderInterface;
readonly class RequestIdProvider implements RequestIdProviderInterface
{
public function __construct(private RequestIdMiddleware $requestIdMiddleware)
{
}
public function currentRequestId(): string
{
return $this->requestIdMiddleware->currentRequestId();
}
}

View file

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\EventDispatcher\Helper;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequestFactory;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Common\Middleware\RequestIdMiddleware;
use Shlinkio\Shlink\Core\EventDispatcher\Helper\RequestIdProvider;
class RequestIdProviderTest extends TestCase
{
private RequestIdProvider $provider;
private RequestIdMiddleware $middleware;
protected function setUp(): void
{
$this->middleware = new RequestIdMiddleware();
$this->provider = new RequestIdProvider($this->middleware);
}
#[Test]
public function requestIdTrackedByMiddlewareIsForwarded(): void
{
$initialId = $this->middleware->currentRequestId();
self::assertEquals($initialId, $this->provider->currentRequestId());
$handler = $this->createMock(RequestHandlerInterface::class);
$handler->method('handle')->willReturn(new Response());
$this->middleware->process(ServerRequestFactory::fromGlobals(), $handler);
$idAfterProcessingRequest = $this->middleware->currentRequestId();
self::assertNotEquals($idAfterProcessingRequest, $initialId);
self::assertEquals($idAfterProcessingRequest, $this->provider->currentRequestId());
$manuallySetId = 'foobar';
$this->middleware->setCurrentRequestId($manuallySetId);
self::assertNotEquals($manuallySetId, $idAfterProcessingRequest);
self::assertEquals($manuallySetId, $this->provider->currentRequestId());
}
}