Skip to content

Commit cb84fec

Browse files
committed
chore(messenger): add trace parent in dispatched messages (AMQP)
1 parent 2efbd3d commit cb84fec

File tree

7 files changed

+136
-1
lines changed

7 files changed

+136
-1
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@
3333
"open-telemetry/sdk": "^1",
3434
"open-telemetry/sem-conv": "^1",
3535
"open-telemetry/symfony-sdk-bundle": "^0",
36+
"symfony/amqp-messenger": "^7.2",
3637
"symfony/config": "^7.2",
3738
"symfony/dependency-injection": "^7.2",
3839
"symfony/event-dispatcher": "^7.2",
40+
"symfony/messenger": "^7.2",
3941
"zenstruck/dsn": "^0.2",
4042
"zenstruck/uri": "^2.3"
4143
},
@@ -67,7 +69,6 @@
6769
"symfony/http-client": "^7.2",
6870
"symfony/http-kernel": "^7.2",
6971
"symfony/mailer": "^7.2",
70-
"symfony/messenger": "^7.2",
7172
"symfony/monolog-bundle": "^3.10",
7273
"symfony/phpunit-bridge": "^7.2",
7374
"symfony/runtime": "^7.2",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Messenger\Amqp;
6+
7+
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Context\Propagator\TraceStampPropagator;
8+
use OpenTelemetry\Context\Context;
9+
use OpenTelemetry\Context\Propagation\MultiTextMapPropagator;
10+
use Psr\Log\LoggerInterface;
11+
use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpStamp;
12+
use Symfony\Component\Messenger\Envelope;
13+
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
14+
use Symfony\Component\Messenger\Middleware\StackInterface;
15+
16+
/**
17+
* Be aware the app consuming the message must be able to denormalize the stamp.
18+
*/
19+
readonly class AddStampForPropagationMiddleware implements MiddlewareInterface
20+
{
21+
public function __construct(
22+
private MultiTextMapPropagator $propagator,
23+
private ?LoggerInterface $logger = null,
24+
) {}
25+
26+
public function handle(Envelope $envelope, StackInterface $stack): Envelope
27+
{
28+
if ($envelope->last(AmqpStamp::class) !== null) {
29+
$this->onMessageSent($envelope);
30+
}
31+
32+
return $stack->next()->handle($envelope, $stack);
33+
}
34+
35+
private function onMessageSent(Envelope &$envelope): void
36+
{
37+
$scope = Context::storage()->scope();
38+
39+
if ($scope === null) {
40+
$this->logger?->debug('No active scope');
41+
}
42+
43+
$this->propagator->inject($envelope, new TraceStampPropagator(), Context::getCurrent());
44+
$this->logger?->debug('Trace stamp added to envelope for propagation');
45+
}
46+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Messenger;
6+
7+
use Symfony\Component\Messenger\Stamp\StampInterface;
8+
9+
/**
10+
* @doc: https://www.w3.org/TR/trace-context/
11+
*
12+
* You can see how the trace parent generated here: https://github.com/open-telemetry/opentelemetry-php/blob/main/src/API/Trace/Propagation/TraceContextPropagator.php
13+
*/
14+
readonly class TraceStamp implements StampInterface
15+
{
16+
public function __construct(
17+
private string $traceParent,
18+
) {
19+
}
20+
21+
public function getTraceParent(): string
22+
{
23+
return $this->traceParent;
24+
}
25+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Context\Propagator;
6+
7+
use OpenTelemetry\API\Baggage\Propagation\BaggagePropagator;
8+
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
9+
use OpenTelemetry\Context\Propagation\MultiTextMapPropagator;
10+
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator;
11+
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
12+
use OpenTelemetry\SDK\Registry;
13+
14+
class PropagatorFactory
15+
{
16+
/**
17+
* Default propagators from https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration
18+
*/
19+
public static function createDefault(): MultiTextMapPropagator
20+
{
21+
return new MultiTextMapPropagator([
22+
BaggagePropagator::getInstance(),
23+
TraceContextPropagator::getInstance()
24+
]);
25+
}
26+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Context\Propagator;
6+
7+
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Messenger\TraceStamp;
8+
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
9+
use OpenTelemetry\Context\Propagation\PropagationSetterInterface;
10+
use Symfony\Component\Messenger\Envelope;
11+
12+
class TraceStampPropagator implements PropagationSetterInterface
13+
{
14+
/**
15+
* @param mixed $carrier
16+
*/
17+
public function set(&$carrier, string $key, string $value): void
18+
{
19+
if (!$carrier instanceof Envelope) {
20+
throw new \InvalidArgumentException(sprintf('The carrier for trace stamp propagation must be instance of %s', Envelope::class));
21+
}
22+
23+
if ($key !== TraceContextPropagator::TRACEPARENT) {
24+
return;
25+
}
26+
27+
$carrier = $carrier->with(new TraceStamp($value));
28+
}
29+
}

src/Resources/config/services.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Context\Propagator\HeadersPropagator as HeadersPropagationGetter;
4+
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Context\Propagator\PropagatorFactory;
45
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\ExporterDsn;
56
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\OtlpExporterOptions;
67
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Resource\ResourceInfoFactory;
@@ -33,6 +34,7 @@
3334

3435
->set('open_telemetry.propagator_text_map.noop', NoopTextMapPropagator::class)
3536
->set('open_telemetry.propagator_text_map.multi', MultiTextMapPropagator::class)
37+
->factory([PropagatorFactory::class, 'createDefault'])
3638

3739
->set('open_telemetry.propagation_getter.headers', HeadersPropagationGetter::class)
3840
->set('open_telemetry.propagation_getter.sanitize_combined_headers', SanitizeCombinedHeadersPropagationGetter::class)

src/Resources/config/services_tracing_instrumentation.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\HttpKernel\TraceableHttpKernelEventSubscriber;
1010
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Mailer\TraceableMailer;
1111
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Mailer\TraceableMailerTransport;
12+
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Messenger\Amqp\AddStampForPropagationMiddleware;
1213
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Messenger\TraceableMessengerMiddleware;
1314
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Messenger\TraceableMessengerTransport;
1415
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\Messenger\TraceableMessengerTransportFactory;
@@ -103,6 +104,11 @@
103104
->tag('monolog.logger', ['channel' => 'open_telemetry'])
104105
->alias('messenger.middleware.open_telemetry_tracer', 'open_telemetry.instrumentation.messenger.trace.middleware')
105106

107+
->set('open_telemetry.instrumentation.messenger.propagation.amqp.middleware', AddStampForPropagationMiddleware::class)
108+
->arg('$propagator', service('open_telemetry.propagator_text_map.multi'))
109+
->tag('messenger.middleware')
110+
->tag('monolog.logger', ['channel' => 'open_telemetry'])
111+
106112
// Twig
107113
->set('open_telemetry.instrumentation.twig.trace.extension', TraceableTwigExtension::class)
108114
->arg('$tracer', service('open_telemetry.traces.default_tracer'))

0 commit comments

Comments
 (0)