Skip to content

Commit fb79a4b

Browse files
committed
Allow arbitary generation of span names based on the route matched
1 parent a80cd45 commit fb79a4b

File tree

9 files changed

+216
-19
lines changed

9 files changed

+216
-19
lines changed

src/DependencyInjection/Configuration.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ public function getConfigTreeBuilder(): TreeBuilder
2828
->end()
2929
->end()
3030
->end()
31+
->arrayNode('name_generator')
32+
->canBeEnabled()
33+
->children()
34+
->scalarNode('max_length')->defaultValue(64)->end()
35+
->arrayNode('command')
36+
->useAttributeAsKey('name')
37+
->scalarPrototype()->end()
38+
->end()
39+
->arrayNode('request')
40+
->useAttributeAsKey('name')
41+
->scalarPrototype()->end()
42+
->end()
43+
->end()
44+
->end()
3145
->end();
3246
// @formatter:on
3347

src/DependencyInjection/JaegerExtension.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<?php
2-
32
declare(strict_types=1);
43

54
namespace Jaeger\Symfony\DependencyInjection;
@@ -8,6 +7,7 @@
87
use Symfony\Component\DependencyInjection\ContainerBuilder;
98
use Symfony\Component\DependencyInjection\Extension\Extension;
109
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
10+
use Symfony\Component\DependencyInjection\Reference;
1111

1212
class JaegerExtension extends Extension
1313
{
@@ -18,13 +18,26 @@ public function load(array $configs, ContainerBuilder $container)
1818
new FileLocator(__DIR__ . '/../Resources')
1919
);
2020
$loader->load('services.yml');
21-
2221
$configuration = new Configuration();
2322
$config = $this->processConfiguration($configuration, $configs);
24-
2523
if ($this->isConfigEnabled($container, $config['denylist'])) {
2624
$container->setParameter('jaeger.sampler.operation_denylist', $config['denylist']['operation_names']);
2725
$loader->load('denylist.yml');
2826
}
27+
if ($this->isConfigEnabled($container, $config['name_generator'])) {
28+
$container->setParameter('jaeger.name.max_length', (int)$config['name_generator']['max_length']);
29+
foreach ($config['name_generator']['request'] as $item => $alias) {
30+
$container->getDefinition('jaeger.name.generator.request')->addMethodCall(
31+
'add',
32+
[$item, new Reference($alias)]
33+
);
34+
}
35+
foreach ($config['name_generator']['command'] as $item => $alias) {
36+
$container->getDefinition('jaeger.name.generator.command')->addMethodCall(
37+
'add',
38+
[$item, new Reference($alias)]
39+
);
40+
}
41+
}
2942
}
3043
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Jaeger\Symfony\Name\Generator;
4+
5+
abstract class AbstractGeneratorDecorator implements NameGeneratorInterface
6+
{
7+
private NameGeneratorInterface $generator;
8+
9+
public function __construct(NameGeneratorInterface $generator)
10+
{
11+
$this->generator = $generator;
12+
}
13+
14+
public function generate(): string
15+
{
16+
return $this->generator->generate();
17+
}
18+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Jaeger\Symfony\Name\Generator;
4+
5+
use Symfony\Component\Console\Event\ConsoleCommandEvent;
6+
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
7+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8+
9+
class CommandNameGenerator implements NameGeneratorInterface, EventSubscriberInterface
10+
{
11+
private array $generators;
12+
13+
private string $name;
14+
15+
public function __construct(array $generators = [])
16+
{
17+
$this->generators = $generators;
18+
}
19+
20+
public function add(string $regexp, NameGeneratorInterface $generator): CommandNameGenerator
21+
{
22+
$this->generators[sprintf('/%s/', $regexp)] = $generator;
23+
24+
return $this;
25+
}
26+
27+
public static function getSubscribedEvents(): array
28+
{
29+
return [ConsoleCommandEvent::class => ['onCommand', 30], ConsoleTerminateEvent::class => ['onTerminate'],];
30+
}
31+
32+
public function onCommand(ConsoleCommandEvent $event): void
33+
{
34+
if (null === $event->getCommand()) {
35+
return;
36+
}
37+
38+
$this->name = (string)$event->getCommand()->getName();
39+
}
40+
41+
public function onTerminate(): CommandNameGenerator
42+
{
43+
$this->name = '';
44+
45+
return $this;
46+
}
47+
48+
public function generate(): string
49+
{
50+
foreach ($this->generators as $regexp => $generator) {
51+
if (false === \preg_match($regexp, $this->name)) {
52+
continue;
53+
}
54+
55+
return $generator->generate();
56+
}
57+
58+
return '';
59+
}
60+
}

src/Name/Generator/DefaultNameGenerator.php

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111

1212
class DefaultNameGenerator implements NameGeneratorInterface, EventSubscriberInterface
1313
{
14-
private $name = '';
15-
16-
public const MAX_LENGTH = 64;
14+
private string $name = '';
1715

1816
public static function getSubscribedEvents(): array
1917
{
@@ -27,29 +25,23 @@ public static function getSubscribedEvents(): array
2725

2826
public function onCommand(ConsoleCommandEvent $event): void
2927
{
30-
$this->name = $event->getCommand()->getName();
31-
}
32-
33-
public function setName(string $name)
34-
{
35-
if (self::MAX_LENGTH < strlen($name)) {
36-
$name = substr($name, 0, self::MAX_LENGTH);
28+
if (null === $event->getCommand()) {
29+
return;
3730
}
38-
$this->name = $name;
31+
32+
$this->name = (string)$event->getCommand()->getName();
3933
}
4034

4135
public function onRequest(RequestEvent $event): void
4236
{
4337
$request = $event->getRequest();
4438
if (null !== ($fragment = $request->attributes->get('is_fragment'))) {
45-
$name = ($controller = $request->attributes->get('_controller', null))
39+
$this->name = ($controller = $request->attributes->get('_controller', null))
4640
? sprintf('fragment.%s', $controller)
4741
: 'fragment';
48-
$this->setName($name);
49-
5042
return;
5143
}
52-
$this->setName($request->attributes->get('_route', $request->getRequestUri()));
44+
$this->name = $request->attributes->get('_route', $request->getRequestUri());
5345
}
5446

5547
public function onTerminate(): void

src/Name/Generator/NameGeneratorChain.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
class NameGeneratorChain implements NameGeneratorInterface
77
{
8-
private $queue;
8+
private \SplPriorityQueue $queue;
99

1010
public function __construct(\SplPriorityQueue $queue)
1111
{
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace Jaeger\Symfony\Name\Generator;
4+
5+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
6+
use Symfony\Component\HttpKernel\Event\RequestEvent;
7+
use Symfony\Component\HttpKernel\Event\TerminateEvent;
8+
9+
class RequestNameGenerator implements NameGeneratorInterface, EventSubscriberInterface
10+
{
11+
private array $generators;
12+
13+
private string $route;
14+
15+
public function __construct(array $generators = [])
16+
{
17+
$this->generators = $generators;
18+
}
19+
20+
public function add(string $regexp, NameGeneratorInterface $generator): RequestNameGenerator
21+
{
22+
$this->generators[sprintf('/%s/', $regexp)] = $generator;
23+
24+
return $this;
25+
}
26+
27+
public static function getSubscribedEvents(): array
28+
{
29+
return [RequestEvent::class => ['onRequest', 30], TerminateEvent::class => ['onTerminate', -16384],];
30+
}
31+
32+
public function onRequest(RequestEvent $event): void
33+
{
34+
$this->route = $event->getRequest()->attributes->get('_route', $event->getRequest()->getRequestUri());
35+
}
36+
37+
public function onTerminate(): RequestNameGenerator
38+
{
39+
$this->route = '';
40+
41+
return $this;
42+
}
43+
44+
public function generate(): string
45+
{
46+
foreach ($this->generators as $regexp => $generator) {
47+
if (1 !== \preg_match($regexp, $this->route)) {
48+
continue;
49+
}
50+
51+
return $generator->generate();
52+
}
53+
54+
return '';
55+
}
56+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Jaeger\Symfony\Name\Generator;
4+
5+
class ShortenGeneratorDecorator extends AbstractGeneratorDecorator
6+
{
7+
private int $maxLength;
8+
9+
public function __construct(NameGeneratorInterface $generator, int $maxLength)
10+
{
11+
$this->maxLength = $maxLength;
12+
parent::__construct($generator);
13+
}
14+
15+
public function shorten(string $name)
16+
{
17+
if ($this->maxLength >= strlen($name)) {
18+
return $name;
19+
}
20+
21+
return \substr($name, 0, $this->maxLength);
22+
}
23+
24+
public function generate(): string
25+
{
26+
return $this->shorten(parent::generate());
27+
}
28+
}

src/Resources/services.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ parameters:
1212
env(JAEGER_DEBUG_COOKIE): 'debug'
1313
env(JAEGER_SERVICE_NAME): '%service_name%'
1414
env(JAEGER_SPAN_BATCH): '16'
15+
jaeger.name.max_length: 64
16+
1517
services:
1618
spl.stack:
1719
class: SplStack
@@ -130,12 +132,26 @@ services:
130132
tags:
131133
- {name: 'kernel.event_subscriber' }
132134
- {name: 'jaeger.name.generator', priority: -1}
135+
jaeger.name.generator.request:
136+
class: Jaeger\Symfony\Name\Generator\RequestNameGenerator
137+
tags:
138+
- {name: 'kernel.event_subscriber' }
139+
- {name: 'jaeger.name.generator', priority: 1}
140+
jaeger.name.generator.command:
141+
class: Jaeger\Symfony\Name\Generator\CommandNameGenerator
142+
tags:
143+
- {name: 'kernel.event_subscriber' }
144+
- {name: 'jaeger.name.generator', priority: 1}
133145
jaeger.name.generator.chain:
134146
class: Jaeger\Symfony\Name\Generator\NameGeneratorChain
135147
arguments:
136148
- '@spl.priority.queue'
137149
jaeger.name.generator:
138150
alias: 'jaeger.name.generator.chain'
151+
jaeger.name.generator.shorten:
152+
class: Jaeger\Symfony\Name\Generator\ShortenGeneratorDecorator
153+
decorates: '@jaeger.name.generator'
154+
arguments: ['@jaeger.name.generator.shorten.inner', '%jaeger.name.max_length%']
139155
jaeger.span.handler.background:
140156
class: Jaeger\Symfony\Bridge\BackgroundSpanHandler
141157
arguments: ['@jaeger.tracer']

0 commit comments

Comments
 (0)