Skip to content

Commit 270f6fc

Browse files
committed
feat(Instrumentation/Console): exclude commands from being traced when instrumentation type is auto
1 parent fc6cbdd commit 270f6fc

15 files changed

Lines changed: 213 additions & 7 deletions
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
8+
class SetConsoleTracingExcludeCommandsPass implements CompilerPassInterface
9+
{
10+
public function process(ContainerBuilder $container): void
11+
{
12+
if (false === $container->hasParameter('open_telemetry.instrumentation.console.tracing.exclude_commands')) {
13+
return;
14+
}
15+
16+
if (false === $container->hasDefinition('open_telemetry.instrumentation.console.trace.event_subscriber')) {
17+
return;
18+
}
19+
20+
$excludeCommands = $container->getParameter('open_telemetry.instrumentation.console.tracing.exclude_commands');
21+
$container->getDefinition('open_telemetry.instrumentation.console.trace.event_subscriber')
22+
->addMethodCall('setExcludeCommands', [$excludeCommands]);
23+
}
24+
}

src/DependencyInjection/Configuration.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ private function addInstrumentationSection(ArrayNodeDefinition $node): void
9191
->defaultValue(InstrumentationTypeEnum::Auto->value)
9292
->values(array_map(fn (InstrumentationTypeEnum $type) => $type->value, InstrumentationTypeEnum::cases()))
9393
->end()
94-
->append($this->getTracingInstrumentationNode())
94+
->append($this->getTracingInstrumentationNode(
95+
(new ArrayNodeDefinition('exclude_commands'))
96+
->info('Exclude commands from auto instrumentation')
97+
->scalarPrototype()->cannotBeEmpty()->end()
98+
))
9599
->append($this->getMeteringInstrumentationNode())
96100
->end()
97101
->end()

src/DependencyInjection/OpenTelemetryExtension.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
* @phpstan-type TracingInstrumentationConfig array{
2525
* enabled: bool,
2626
* tracer: ?string,
27-
* exclude_paths?: string[]
27+
* exclude_paths?: string[],
28+
* exclude_commands?: string[]
2829
* }
2930
* @phpstan-type MeteringInstrumentationConfig array{
3031
* enabled: bool,
@@ -271,6 +272,17 @@ private function setTracingInstrumentationParams(ContainerBuilder $container, st
271272
}
272273
}
273274

275+
if ('console' === $name) {
276+
if (isset($config['tracing']['exclude_commands'])
277+
&& 0 < \count($config['tracing']['exclude_commands'])
278+
) {
279+
$container->setParameter(
280+
sprintf('open_telemetry.instrumentation.%s.tracing.exclude_commands', $name),
281+
$config['tracing']['exclude_commands'],
282+
);
283+
}
284+
}
285+
274286
$container->setParameter(
275287
sprintf('open_telemetry.instrumentation.%s.tracing.tracer', $name),
276288
$config['tracing']['tracer'] ?? 'default_tracer',

src/Instrumentation/Symfony/Console/TraceableConsoleEventSubscriber.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
final class TraceableConsoleEventSubscriber implements EventSubscriberInterface, ServiceSubscriberInterface, InstrumentationTypeInterface
2626
{
2727
private InstrumentationTypeEnum $instrumentationType = InstrumentationTypeEnum::Auto;
28+
/**
29+
* @var string[]
30+
*/
31+
private array $excludeCommands = [];
2832

2933
public function __construct(
3034
private readonly TracerInterface $tracer,
@@ -148,7 +152,16 @@ private function getTracer(Command $command): TracerInterface
148152

149153
private function isAutoTraceable(Command $command): bool
150154
{
151-
return InstrumentationTypeEnum::Auto === $this->instrumentationType;
155+
if (InstrumentationTypeEnum::Auto !== $this->instrumentationType) {
156+
return false;
157+
}
158+
159+
$combinedExcludeCommands = implode('|', $this->excludeCommands);
160+
if (preg_match("#{$combinedExcludeCommands}#", $command->getName())) {
161+
return false;
162+
}
163+
164+
return true;
152165
}
153166

154167
private function isAttributeTraceable(Command $command): bool
@@ -168,4 +181,12 @@ public function setInstrumentationType(InstrumentationTypeEnum $type): void
168181
{
169182
$this->instrumentationType = $type;
170183
}
184+
185+
/**
186+
* @param string[] $excludeCommands
187+
*/
188+
public function setExcludeCommands(array $excludeCommands): void
189+
{
190+
$this->excludeCommands = $excludeCommands;
191+
}
171192
}

src/OpenTelemetryBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Composer\InstalledVersions;
66
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\Compiler\CacheInstrumentationPass;
77
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\Compiler\HttpClientInstrumentationPass;
8+
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\Compiler\SetConsoleTracingExcludeCommandsPass;
89
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\Compiler\SetHttpKernelTracingExcludePathsPass;
910
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\Compiler\SetInstrumentationTypePass;
1011
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\Compiler\TracerLocatorPass;
@@ -32,6 +33,7 @@ public function build(ContainerBuilder $container): void
3233
$container->addCompilerPass(new CacheInstrumentationPass());
3334
$container->addCompilerPass(new HttpClientInstrumentationPass());
3435
$container->addCompilerPass(new SetHttpKernelTracingExcludePathsPass());
36+
$container->addCompilerPass(new SetConsoleTracingExcludeCommandsPass());
3537

3638
$container->addCompilerPass(new TracerLocatorPass());
3739
}

tests/Functional/Application/config/packages/open_telemetry.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ open_telemetry:
9595
when@auto:
9696
open_telemetry:
9797
instrumentation:
98+
console:
99+
type: auto
100+
tracing:
101+
enabled: true
102+
exclude_commands:
103+
- dummy
98104
http_kernel:
99105
type: auto
100106
tracing:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace App\Command;
4+
5+
use Symfony\Component\Console\Attribute\AsCommand;
6+
use Symfony\Component\Console\Command\Command;
7+
use Symfony\Component\Console\Input\InputInterface;
8+
use Symfony\Component\Console\Output\OutputInterface;
9+
10+
#[AsCommand('auto-command')]
11+
class AutoCommand extends Command
12+
{
13+
protected function execute(InputInterface $input, OutputInterface $output): int
14+
{
15+
return Command::SUCCESS;
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace App\Command;
4+
5+
use Symfony\Component\Console\Attribute\AsCommand;
6+
use Symfony\Component\Console\Command\Command;
7+
use Symfony\Component\Console\Input\InputInterface;
8+
use Symfony\Component\Console\Output\OutputInterface;
9+
10+
#[AsCommand('dummy-command')]
11+
class DummyCommand extends Command
12+
{
13+
protected function execute(InputInterface $input, OutputInterface $output): int
14+
{
15+
return Command::SUCCESS;
16+
}
17+
}

tests/Functional/Instrumentation/ConsoleTracingTest.php renamed to tests/Functional/Instrumentation/Console/ConsoleAttributeTracingTest.php

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

3-
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\Tests\Functional\Instrumentation;
3+
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\Tests\Functional\Instrumentation\Console;
44

55
use App\Kernel;
66
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Tests\Functional\TracingTestCaseTrait;
@@ -13,7 +13,7 @@
1313
use Zalas\PHPUnit\Globals\Attribute\Env;
1414

1515
#[Env('KERNEL_CLASS', Kernel::class)]
16-
class ConsoleTracingTest extends KernelTestCase
16+
class ConsoleAttributeTracingTest extends KernelTestCase
1717
{
1818
use TracingTestCaseTrait;
1919

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\Tests\Functional\Instrumentation\Console;
4+
5+
use App\Kernel;
6+
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Tests\Functional\TracingTestCaseTrait;
7+
use OpenTelemetry\SDK\Trace\StatusData;
8+
use Symfony\Bundle\FrameworkBundle\Console\Application;
9+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
10+
use Symfony\Component\Console\Tester\ApplicationTester;
11+
use Zalas\PHPUnit\Globals\Attribute\Env;
12+
13+
#[Env('KERNEL_CLASS', Kernel::class)]
14+
#[Env('APP_ENV', 'auto')]
15+
class ConsoleAutoTracingTest extends KernelTestCase
16+
{
17+
use TracingTestCaseTrait;
18+
19+
public function testSuccess(): void
20+
{
21+
$kernel = self::bootKernel();
22+
23+
$application = new Application($kernel);
24+
$application->setAutoExit(false);
25+
26+
$tester = new ApplicationTester($application);
27+
28+
$tester->run(['command' => 'auto-command']);
29+
self::assertSame(0, $tester->getStatusCode());
30+
31+
self::assertSpansCount(1);
32+
33+
$mainSpan = self::getSpans()[0];
34+
self::assertSpanName($mainSpan, 'auto-command');
35+
self::assertSpanStatus($mainSpan, StatusData::ok());
36+
self::assertSpanAttributes($mainSpan, [
37+
'code.function.name' => 'execute',
38+
'code.namespace' => 'App\Command\AutoCommand',
39+
'symfony.console.exit_code' => 0,
40+
]);
41+
self::assertSpanEventsCount($mainSpan, 0);
42+
}
43+
44+
public function testExcluded(): void
45+
{
46+
$kernel = self::bootKernel();
47+
48+
$application = new Application($kernel);
49+
$application->setAutoExit(false);
50+
51+
$tester = new ApplicationTester($application);
52+
53+
$tester->run(['command' => 'dummy-command']);
54+
self::assertSame(0, $tester->getStatusCode());
55+
56+
self::assertSpansCount(0);
57+
}
58+
}

0 commit comments

Comments
 (0)