Skip to content

Commit 7d84ab3

Browse files
authored
Allow console trace id be set via env vars (#27)
1 parent 6561a17 commit 7d84ab3

17 files changed

Lines changed: 207 additions & 49 deletions

File tree

docs/configuration/tracecontext.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ return static function (SymfonyTraceConfig $config): void {
3232
$config->enableMonolog(true);
3333

3434
// Whether to add the request id to console commands, defaults to true
35-
$config->enableConsole(true);
35+
$config->console()->enabled(true);
36+
37+
// Optional, set console trace id based on env var. defaults to null
38+
$config->console()->traceId(env('TRACE_ID'));
3639

3740
// Whether to add the request id to message bus events, defaults to false
3841
$config->enableMessenger(false);

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: "#^Parameter \\#1 \\$mergedConfig \\(array\\{traceMode\\: 'tracecontext'\\|'traceid', traceid\\: array\\{request_header\\: string, response_header\\: string, generator_service\\: string\\|null\\}, trust_request_header\\: bool, send_response_header\\: bool, storage_service\\: string\\|null, enable_monolog\\: bool, enable_console\\: bool, enable_messenger\\: bool, \\.\\.\\.\\}\\) of method DR\\\\SymfonyTraceBundle\\\\DependencyInjection\\\\SymfonyTraceExtension\\:\\:loadInternal\\(\\) should be contravariant with parameter \\$mergedConfig \\(array\\) of method Symfony\\\\Component\\\\HttpKernel\\\\DependencyInjection\\\\ConfigurableExtension\\:\\:loadInternal\\(\\)$#"
4+
message: "#^Parameter \\#1 \\$mergedConfig \\(array\\{traceMode\\: 'tracecontext'\\|'traceid', traceid\\: array\\{request_header\\: string, response_header\\: string, generator_service\\: string\\|null\\}, trust_request_header\\: bool, send_response_header\\: bool, storage_service\\: string\\|null, enable_monolog\\: bool, enable_console\\: bool, console\\: array\\{enabled\\: bool, trace_id\\: string\\|null\\}, \\.\\.\\.\\}\\) of method DR\\\\SymfonyTraceBundle\\\\DependencyInjection\\\\SymfonyTraceExtension\\:\\:loadInternal\\(\\) should be contravariant with parameter \\$mergedConfig \\(array\\) of method Symfony\\\\Component\\\\HttpKernel\\\\DependencyInjection\\\\ConfigurableExtension\\:\\:loadInternal\\(\\)$#"
55
count: 1
66
path: src/DependencyInjection/SymfonyTraceExtension.php
77

src/DependencyInjection/Configuration.php

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Sentry\State\HubInterface;
88
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
9+
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
910
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
1011
use Symfony\Component\Config\Definition\ConfigurationInterface;
1112

@@ -16,7 +17,7 @@
1617
class Configuration implements ConfigurationInterface
1718
{
1819
public const TRACEMODE_TRACECONTEXT = 'tracecontext';
19-
public const TRACEMODE_TRACEID = 'traceid';
20+
public const TRACEMODE_TRACEID = 'traceid';
2021

2122
public function getConfigTreeBuilder(): TreeBuilder
2223
{
@@ -69,7 +70,21 @@ public function getConfigTreeBuilder(): TreeBuilder
6970
->end()
7071
->booleanNode('enable_console')
7172
->info('Whether to add the trace id to console commands, defaults to true')
72-
->defaultTrue()
73+
->defaultNull()
74+
->setDeprecated('digitalrevolution/symfony-trace-bundle', '0.6.0')
75+
->end()
76+
->arrayNode('console')
77+
->addDefaultsIfNotSet()
78+
->children()
79+
->booleanNode('enabled')
80+
->info('Whether to add the trace id to console commands, defaults to true')
81+
->defaultTrue()
82+
->end()
83+
->scalarNode('trace_id')
84+
->info('Option to set the `Trace-Id` to use for console commands from env var. Defaults to null.')
85+
->defaultNull()
86+
->end()
87+
->end()
7388
->end()
7489
->booleanNode('enable_messenger')
7590
->info('Whether to add the trace id to message bus events, defaults to false')
@@ -79,37 +94,53 @@ public function getConfigTreeBuilder(): TreeBuilder
7994
->info('Whether or not to enable the twig `trace_id()` and `transaction_id()` functions. Only works if TwigBundle is present.')
8095
->defaultTrue()
8196
->end()
82-
->arrayNode('http_client')
83-
->addDefaultsIfNotSet()
84-
->children()
85-
->booleanNode('enabled')
86-
->info('Whether or not to enable the trace id aware http client')
87-
->defaultTrue()
88-
->end()
89-
->booleanNode('tag_default_client')
90-
->info('Whether or not to tag the default http client')
91-
->defaultFalse()
92-
->end()
93-
->scalarNode('header')
94-
->info('The header the bundle set in the request in the http client')
95-
->defaultValue('X-Trace-Id')
96-
->end()
97+
->append($this->createHttpClientConfiguration())
98+
->append($this->createSentryConfiguration())
99+
;
100+
101+
return $tree;
102+
}
103+
104+
private function createHttpClientConfiguration(): NodeDefinition
105+
{
106+
$node = (new TreeBuilder('http_client'))->getRootNode();
107+
$node
108+
->addDefaultsIfNotSet()
109+
->children()
110+
->booleanNode('enabled')
111+
->info('Whether or not to enable the trace id aware http client')
112+
->defaultTrue()
113+
->end()
114+
->booleanNode('tag_default_client')
115+
->info('Whether or not to tag the default http client')
116+
->defaultFalse()
117+
->end()
118+
->scalarNode('header')
119+
->info('The header the bundle set in the request in the http client')
120+
->defaultValue('X-Trace-Id')
97121
->end()
98122
->end()
99-
->arrayNode('sentry')
100-
->addDefaultsIfNotSet()
101-
->children()
102-
->booleanNode('enabled')
123+
->end();
124+
125+
return $node;
126+
}
127+
128+
private function createSentryConfiguration(): NodeDefinition
129+
{
130+
$node = (new TreeBuilder('sentry'))->getRootNode();
131+
$node
132+
->addDefaultsIfNotSet()
133+
->children()
134+
->booleanNode('enabled')
103135
->info('Whether or not to enable passing trace and transaction id to Sentry')
104136
->defaultFalse()
105137
->end()
106138
->scalarNode('hub_service')
107139
->info('The service id of the Sentry Hub. Defaults to Sentry\State\HubInterface')
108140
->defaultValue(HubInterface::class)
109141
->end()
110-
->end()
111-
;
142+
->end();
112143

113-
return $tree;
144+
return $node;
114145
}
115146
}

src/DependencyInjection/SymfonyTraceExtension.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
* storage_service: ?string,
4444
* enable_monolog: bool,
4545
* enable_console: bool,
46+
* console: array{
47+
* enabled: bool,
48+
* trace_id: ?string
49+
* },
4650
* enable_messenger: bool,
4751
* enable_twig: bool,
4852
* http_client: array{
@@ -167,11 +171,18 @@ private function configureMonolog(array $mergedConfig, ContainerBuilder $contain
167171
*/
168172
private function configureConsole(array $mergedConfig, ContainerBuilder $container): void
169173
{
170-
if (class_exists(Application::class) === false || $mergedConfig['enable_console'] === false) {
174+
$enabled = $mergedConfig['enable_console'] ?? $mergedConfig['console']['enabled'];
175+
if (class_exists(Application::class) === false || $enabled === false) {
171176
return;
172177
}
173178
$container->register(CommandSubscriber::class)
174-
->setArguments([new Reference(TraceStorageInterface::class), new Reference(TraceServiceInterface::class)])
179+
->setArguments(
180+
[
181+
new Reference(TraceStorageInterface::class),
182+
new Reference(TraceServiceInterface::class),
183+
$mergedConfig['console']['trace_id']
184+
]
185+
)
175186
->setPublic(false)
176187
->addTag('kernel.event_subscriber');
177188
}

src/EventSubscriber/CommandSubscriber.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
*/
1515
final class CommandSubscriber implements EventSubscriberInterface
1616
{
17-
public function __construct(private readonly TraceStorageInterface $storage, private readonly TraceServiceInterface $service)
18-
{
17+
public function __construct(
18+
private readonly TraceStorageInterface $storage,
19+
private readonly TraceServiceInterface $service,
20+
private readonly ?string $traceId,
21+
) {
1922
}
2023

2124
/**
@@ -33,6 +36,12 @@ public function onCommand(): void
3336
return;
3437
}
3538

39+
if ($this->traceId !== null && $this->traceId !== '') {
40+
$this->storage->setTrace($this->service->createTraceFrom($this->traceId));
41+
42+
return;
43+
}
44+
3645
$this->storage->setTrace($this->service->createNewTrace());
3746
}
3847
}

src/Service/TraceContext/TraceContextParser.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99

1010
class TraceContextParser
1111
{
12+
public static function isValid(string $traceParent): bool
13+
{
14+
return preg_match('/^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$/i', $traceParent) === 1;
15+
}
16+
1217
public static function parseTraceContext(string $traceParent, string $traceState): TraceContext
1318
{
1419
$traceContext = self::parseTraceParent($traceParent);

src/Service/TraceContext/TraceContextService.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ public function supports(Request $request): bool
2929
return false;
3030
}
3131

32-
$traceParent = $request->headers->get(self::HEADER_TRACEPARENT, '');
33-
34-
return preg_match('/^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$/i', $traceParent) === 1;
32+
return TraceContextParser::isValid($request->headers->get(self::HEADER_TRACEPARENT, ''));
3533
}
3634

3735
public function createNewTrace(): TraceContext
@@ -43,10 +41,22 @@ public function createNewTrace(): TraceContext
4341
return $trace;
4442
}
4543

44+
public function createTraceFrom(string $traceParent): TraceContext
45+
{
46+
if (TraceContextParser::isValid($traceParent) === false) {
47+
return $this->createNewTrace();
48+
}
49+
50+
$trace = TraceContextParser::parseTraceContext($traceParent, '');
51+
$trace->setTransactionId($this->generator->generateTransactionId());
52+
53+
return $trace;
54+
}
55+
4656
public function getRequestTrace(Request $request): TraceContext
4757
{
48-
$traceParent = $request->headers->get(self::HEADER_TRACEPARENT, '');
49-
$traceState = $request->headers->get(self::HEADER_TRACESTATE, '');
58+
$traceParent = $request->headers->get(self::HEADER_TRACEPARENT, '');
59+
$traceState = $request->headers->get(self::HEADER_TRACESTATE, '');
5060

5161
$trace = TraceContextParser::parseTraceContext($traceParent, $traceState);
5262
$trace->setTransactionId($this->generator->generateTransactionId());
@@ -66,8 +76,7 @@ public function handleResponse(Response $response, TraceContext $context): void
6676

6777
public function handleClientRequest(TraceContext $trace, string $method, string $url, array $options = []): array
6878
{
69-
$traceParent = $this->renderTraceParent($trace);
70-
$options['headers'][self::HEADER_TRACEPARENT] = $traceParent;
79+
$options['headers'][self::HEADER_TRACEPARENT] = $this->renderTraceParent($trace);
7180

7281
$traceState = $this->renderTraceState($trace);
7382
if ($traceState !== '') {

src/Service/TraceId/TraceIdService.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ public function createNewTrace(): TraceContext
3737
return $trace;
3838
}
3939

40+
public function createTraceFrom(string $traceId): TraceContext
41+
{
42+
$trace = new TraceContext();
43+
$trace->setTraceId($traceId);
44+
$trace->setTransactionId($this->generator->generateTransactionId());
45+
46+
return $trace;
47+
}
48+
4049
public function getRequestTrace(Request $request): TraceContext
4150
{
4251
$trace = new TraceContext();

src/Service/TraceServiceInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
interface TraceServiceInterface
1212
{
1313
public function supports(Request $request): bool;
14+
1415
public function createNewTrace(): TraceContext;
1516

17+
public function createTraceFrom(string $traceId): TraceContext;
18+
1619
public function getRequestTrace(Request $request): TraceContext;
20+
1721
public function handleResponse(Response $response, TraceContext $context): void;
1822

1923
public function handleClientRequest(TraceContext $trace, string $method, string $url, array $options = []): array;

tests/Functional/App/config/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
parameters:
22
secret: dev
33
locale: en
4+
env(TRACE_ID): null
45

56
framework:
67
test: ~

0 commit comments

Comments
 (0)