Skip to content

Commit 5d9767e

Browse files
committed
Added Contextextractors
1 parent a4b7c82 commit 5d9767e

File tree

7 files changed

+237
-41
lines changed

7 files changed

+237
-41
lines changed

src/Bridge/ContextInjector.php

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,24 @@
33

44
namespace Jaeger\Symfony\Bridge;
55

6-
use Jaeger\Codec\CodecInterface;
7-
use Jaeger\Codec\CodecRegistry;
6+
use Jaeger\Symfony\Context\Extractor\ContextExtractorInterface;
87
use Jaeger\Tracer\InjectableInterface;
9-
use Jaeger\Tracer\TracerInterface;
108
use Symfony\Component\Console\ConsoleEvents;
119
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
12-
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
13-
use Symfony\Component\HttpKernel\HttpKernelInterface;
1410
use Symfony\Component\HttpKernel\KernelEvents;
1511

1612
class ContextInjector implements EventSubscriberInterface
1713
{
1814
private $injectable;
1915

20-
private $tracer;
21-
22-
/**
23-
* @var CodecInterface[]
24-
*/
25-
private $registry;
26-
27-
private $format;
28-
29-
private $envName;
30-
31-
private $headerName;
16+
private $extractor;
3217

3318
public function __construct(
3419
InjectableInterface $injectable,
35-
TracerInterface $tracer,
36-
CodecRegistry $registry,
37-
string $format,
38-
string $envName,
39-
string $headerName
20+
ContextExtractorInterface $extractor
4021
) {
4122
$this->injectable = $injectable;
42-
$this->tracer = $tracer;
43-
$this->registry = $registry;
44-
$this->format = $format;
45-
$this->envName = $envName;
46-
$this->headerName = $headerName;
23+
$this->extractor = $extractor;
4724
}
4825

4926
public static function getSubscribedEvents()
@@ -54,26 +31,23 @@ public static function getSubscribedEvents()
5431
];
5532
}
5633

57-
public function onCommand()
34+
public function inject(): ContextInjector
5835
{
59-
if (($data = $_ENV[$this->envName] ?? null)
60-
&& $context = $this->registry[$this->format]->decode($data)) {
61-
$this->injectable->assign($context);
36+
if (null === ($context = $this->extractor->extract())) {
37+
return $this;
6238
}
63-
39+
$this->injectable->assign($context);
6440

6541
return $this;
6642
}
6743

68-
public function onRequest(GetResponseEvent $event)
44+
public function onCommand()
6945
{
70-
$request = $event->getRequest();
71-
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()
72-
&& $request->headers->has($this->headerName)
73-
&& ($context = $this->registry[$this->format]->decode($request->headers->get($this->headerName)))) {
74-
$this->injectable->assign($context);
75-
}
46+
return $this->inject();
47+
}
7648

77-
return $this;
49+
public function onRequest()
50+
{
51+
return $this->inject();
7852
}
7953
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Jaeger\Symfony\Context\Extractor;
5+
6+
use Jaeger\Span\Context\SpanContext;
7+
8+
class ContextExtractorChain implements ContextExtractorInterface
9+
{
10+
private $queue;
11+
12+
public function __construct(\SplPriorityQueue $queue)
13+
{
14+
$this->queue = $queue;
15+
}
16+
17+
public function add(ContextExtractorInterface $extractor, int $priority = 0): ContextExtractorChain
18+
{
19+
$this->queue->insert($extractor, $priority);
20+
21+
return $this;
22+
}
23+
24+
public function extract(): ?SpanContext
25+
{
26+
$queue = clone $this->queue;
27+
while (false === $queue->isEmpty()) {
28+
if (null !== ($context = $queue->extract()->extract())) {
29+
return $context;
30+
}
31+
}
32+
33+
return null;
34+
}
35+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Jaeger\Symfony\Context\Extractor;
5+
6+
use Jaeger\Span\Context\SpanContext;
7+
8+
interface ContextExtractorInterface
9+
{
10+
public function extract() : ?SpanContext;
11+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Jaeger\Symfony\Context\Extractor;
5+
6+
use Jaeger\Codec\CodecInterface;
7+
use Jaeger\Codec\CodecRegistry;
8+
use Jaeger\Span\Context\SpanContext;
9+
use Symfony\Component\Console\ConsoleEvents;
10+
11+
class EnvContextExtractor implements ContextExtractorInterface
12+
{
13+
/**
14+
* @var CodecInterface[]
15+
*/
16+
private $registry;
17+
18+
private $format;
19+
20+
private $envName;
21+
22+
private $context;
23+
24+
public function __construct(CodecRegistry $registry, string $format, string $envName)
25+
{
26+
$this->registry = $registry;
27+
$this->format = $format;
28+
$this->envName = $envName;
29+
}
30+
31+
public function extract(): ?SpanContext
32+
{
33+
return $this->context;
34+
}
35+
36+
public static function getSubscribedEvents()
37+
{
38+
return [
39+
ConsoleEvents::COMMAND => ['onCommand', 2048],
40+
];
41+
}
42+
43+
public function onCommand()
44+
{
45+
if (null === ($data = $_ENV[$this->envName] ?? null)) {
46+
return $this;
47+
}
48+
49+
if (null === ($context = $this->registry[$this->format]->decode($data))) {
50+
return $this;
51+
}
52+
$this->context = $context;
53+
54+
return $this;
55+
}
56+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Jaeger\Symfony\Context\Extractor;
5+
6+
use Jaeger\Codec\CodecInterface;
7+
use Jaeger\Codec\CodecRegistry;
8+
use Jaeger\Span\Context\SpanContext;
9+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
10+
use Symfony\Component\HttpKernel\HttpKernelInterface;
11+
use Symfony\Component\HttpKernel\KernelEvents;
12+
13+
class HeaderContextExtractor implements ContextExtractorInterface
14+
{
15+
/**
16+
* @var CodecInterface[]
17+
*/
18+
private $registry;
19+
20+
private $format;
21+
22+
private $headerName;
23+
24+
private $context;
25+
26+
public function __construct(CodecRegistry $registry, string $format, string $headerName)
27+
{
28+
$this->registry = $registry;
29+
$this->format = $format;
30+
$this->headerName = $headerName;
31+
}
32+
33+
public function extract(): ?SpanContext
34+
{
35+
return $this->context;
36+
}
37+
38+
public static function getSubscribedEvents()
39+
{
40+
return [
41+
KernelEvents::REQUEST => ['onRequest', 2048],
42+
];
43+
}
44+
45+
public function onRequest(GetResponseEvent $event)
46+
{
47+
$request = $event->getRequest();
48+
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
49+
$this->context = null;
50+
51+
return $this;
52+
}
53+
54+
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()
55+
&& $request->headers->has($this->headerName)
56+
&& ($context = $this->registry[$this->format]->decode($request->headers->get($this->headerName)))) {
57+
$this->context = $context;
58+
59+
return $this;
60+
}
61+
62+
return $this;
63+
}
64+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Jaeger\Symfony\Resources\DependencyInjection;
5+
6+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\Reference;
9+
10+
class ExtractorChainCompilerPass implements CompilerPassInterface
11+
{
12+
public function process(ContainerBuilder $container)
13+
{
14+
if (false === $container->hasDefinition('jaeger.context.extractor.chain')) {
15+
throw new \RuntimeException(
16+
sprintf('Required service %s is missing from container', 'jaeger.context.extractor.chain')
17+
);
18+
}
19+
20+
$definition = $container->getDefinition('jaeger.context.extractor.chain');
21+
foreach ($container->findTaggedServiceIds('jaeger.context.extractor') as $id => $tags) {
22+
foreach ($tags as $tag) {
23+
if (false === array_key_exists('alias', $tag)) {
24+
throw new \RuntimeException(
25+
sprintf('Required tag field %s is missing from definition', 'alias')
26+
);
27+
}
28+
$priority = $tag['priority'] ?? 0;
29+
$definition->addMethodCall('add', [new Reference($id), $priority]);
30+
}
31+
}
32+
}
33+
}

src/Resources/config/services.yml

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ services:
1111
spl.stack:
1212
class: SplStack
1313
shared: false
14+
spl.priority.queue:
15+
class: SplPriorityQueue
16+
shared: false
1417
id.generator.random:
1518
class: Jaeger\Id\RandomIntGenerator
1619
id.generator.span: '@id.generator.random'
@@ -68,13 +71,33 @@ services:
6871
class: Jaeger\Symfony\Bridge\ContextInjector
6972
arguments:
7073
- '@jaeger.tracer'
71-
- '@jaeger.tracer'
74+
- '@jaeger.context.extractor'
75+
tags:
76+
- {name: 'kernel.event_subscriber' }
77+
jaeger.context.extractor.env:
78+
class: Jaeger\Symfony\Context\Extractor\EnvContextExtractor
79+
arguments:
7280
- '@jaeger.codec.registry'
7381
- '%env(JAEGER_CONTEXT_FORMAT)%'
7482
- '%env(JAEGER_CONTEXT_ENV)%'
83+
tags:
84+
- {name: 'kernel.event_subscriber' }
85+
- {name: 'jaeger.context.extractor'}
86+
jaeger.context.extractor.header:
87+
class: Jaeger\Symfony\Context\Extractor\HeaderContextExtractor
88+
arguments:
89+
- '@jaeger.codec.registry'
90+
- '%env(JAEGER_CONTEXT_FORMAT)%'
7591
- '%env(JAEGER_CONTEXT_HEADER)%'
7692
tags:
7793
- {name: 'kernel.event_subscriber' }
94+
- {name: 'jaeger.context.extractor'}
95+
jaeger.context.extractor.chain:
96+
class: Jaeger\Symfony\Context\Extractor\ContextExtractorChain
97+
arguments:
98+
- '@spl.priority.queue'
99+
jaeger.context.extractor:
100+
alias: '@jaeger.context.extractor.chain'
78101
request.span.listener:
79102
class: Jaeger\Symfony\Bridge\RequestSpanListener
80103
arguments:

0 commit comments

Comments
 (0)