From 29bf4c297d3af9d3c34ccad03e2625ad7e6d5bd9 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Mon, 23 Mar 2026 19:06:42 +0100 Subject: [PATCH] Allow span suppression strategy configuration using file-based and env-based config --- composer.json | 9 ++++ .../DistributionConfigurationSdk.php | 51 +++++++++++++++++++ .../ComponentProvider/OpenTelemetrySdk.php | 13 +++++ .../Trace/SpanSuppressionStrategySemConv.php | 37 ++++++++++++++ .../Trace/SpanSuppressionStrategySpanKind.php | 35 +++++++++++++ src/Config/SDK/composer.json | 8 ++- src/SDK/Common/Configuration/Variables.php | 1 + .../DistributionConfiguration.php | 9 ++++ .../Distribution/DistributionProperties.php | 15 ++++++ .../Distribution/DistributionRegistry.php | 25 +++++++++ .../Common/Distribution/SdkDistribution.php | 16 ++++++ .../DistributionConfigurationSdk.php | 41 +++++++++++++++ .../Trace/SpanSuppressionStrategySemConv.php | 33 ++++++++++++ .../Trace/SpanSuppressionStrategySpanKind.php | 31 +++++++++++ src/SDK/SdkAutoloader.php | 26 ++++++++++ src/SDK/composer.json | 9 +++- 16 files changed, 355 insertions(+), 4 deletions(-) create mode 100644 src/Config/SDK/ComponentProvider/Distribution/DistributionConfigurationSdk.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySemConv.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySpanKind.php create mode 100644 src/SDK/Common/Distribution/DistributionConfiguration.php create mode 100644 src/SDK/Common/Distribution/DistributionProperties.php create mode 100644 src/SDK/Common/Distribution/DistributionRegistry.php create mode 100644 src/SDK/Common/Distribution/SdkDistribution.php create mode 100644 src/SDK/ConfigEnv/Distribution/DistributionConfigurationSdk.php create mode 100644 src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySemConv.php create mode 100644 src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySpanKind.php diff --git a/composer.json b/composer.json index c87b044c2..932694a2b 100644 --- a/composer.json +++ b/composer.json @@ -147,6 +147,8 @@ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterZipkin", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorBatch", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorSimple", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanSuppressionStrategySemConv", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanSuppressionStrategySpanKind", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\AggregationResolverDefault", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterConsole", @@ -172,6 +174,8 @@ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Instrumentation\\General\\HttpConfigProvider", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Instrumentation\\General\\PeerConfigProvider", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Distribution\\DistributionConfigurationSdk", + "OpenTelemetry\\Example\\ExampleConfigProvider", "OpenTelemetry\\Tests\\Integration\\Config\\ComponentProvider\\Detector\\Container", @@ -188,6 +192,11 @@ "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderHttpConfig", "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderPeerConfig", + "OpenTelemetry\\SDK\\ConfigEnv\\Trace\\SpanSuppressionStrategySemConv", + "OpenTelemetry\\SDK\\ConfigEnv\\Trace\\SpanSuppressionStrategySpanKind", + + "OpenTelemetry\\SDK\\ConfigEnv\\Distribution\\DistributionConfigurationSdk", + "OpenTelemetry\\Example\\ExampleConfigLoader" ], "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ diff --git a/src/Config/SDK/ComponentProvider/Distribution/DistributionConfigurationSdk.php b/src/Config/SDK/ComponentProvider/Distribution/DistributionConfigurationSdk.php new file mode 100644 index 000000000..5c407936d --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Distribution/DistributionConfigurationSdk.php @@ -0,0 +1,51 @@ + + */ +final class DistributionConfigurationSdk implements ComponentProvider +{ + /** + * @param array{ + * "span_suppression_strategy/development": ?ComponentPlugin, + * } $properties + * @param Context $context + * @return DistributionConfiguration + */ + #[Override] + public function createPlugin(array $properties, Context $context): DistributionConfiguration + { + return new SdkDistribution( + spanSuppressionStrategy: $properties['span_suppression_strategy/development']?->create($context) ?? new NoopSuppressionStrategy(), + ); + } + + #[Override] + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + $node = $builder->arrayNode('opentelemetry_php'); + $node + ->children() + ->append($registry->component('span_suppression_strategy/development', SpanSuppressionStrategy::class)) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index a94f759b7..230a80325 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -18,6 +18,9 @@ use OpenTelemetry\Context\Propagation\ResponsePropagatorInterface; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Common\Distribution\DistributionConfiguration; +use OpenTelemetry\SDK\Common\Distribution\DistributionRegistry; +use OpenTelemetry\SDK\Common\Distribution\SdkDistribution; use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; use OpenTelemetry\SDK\Common\InstrumentationScope\Configurator; use OpenTelemetry\SDK\Logs\EventLoggerProvider; @@ -169,6 +172,7 @@ final class OpenTelemetrySdk implements ComponentProvider * }> * }, * }, + * distribution: list>, * } $properties */ #[\Override] @@ -194,6 +198,13 @@ public function createPlugin(array $properties, Context $context): SdkBuilder return $sdkBuilder; } + $distributionProperties = new DistributionRegistry(); + foreach ($properties['distribution'] as $distributionConfiguration) { + $distributionProperties->add($distributionConfiguration->create($context)); + } + + $distributionConfiguration = $distributionProperties->getDistributionConfiguration(SdkDistribution::class) ?? new SdkDistribution(); + //priorities: 1. attributes 2. attributes_list, 3. detected (after applying include/exclude) $schemaUrl = $properties['resource']['schema_url']; /** @var ResourceDetectorInterface[] $detectors */ @@ -277,6 +288,7 @@ public function createPlugin(array $properties, Context $context): SdkBuilder linkCountLimit: $properties['tracer_provider']['limits']['link_count_limit'], ), configurator: $configurator, + spanSuppressionStrategy: $distributionConfiguration->spanSuppressionStrategy, ); // @@ -419,6 +431,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil ->append($this->getMeterProviderConfig($registry, $builder)) ->append($this->getLoggerProviderConfig($registry, $builder)) ->append($this->getExperimentalResponsePropagatorConfig($registry, $builder)) + ->append($registry->componentMap('distribution', DistributionConfiguration::class)->defaultValue([])) ->end(); return $node; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySemConv.php b/src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySemConv.php new file mode 100644 index 000000000..d8339aa57 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySemConv.php @@ -0,0 +1,37 @@ + + */ +final class SpanSuppressionStrategySemConv implements ComponentProvider +{ + /** + * @param array{} $properties + */ + #[Override] + public function createPlugin(array $properties, Context $context): SpanSuppressionStrategy + { + return new SemanticConventionSuppressionStrategy(ServiceLoader::load(SemanticConventionResolver::class)); + } + + #[Override] + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + return $builder->arrayNode('semconv'); + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySpanKind.php b/src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySpanKind.php new file mode 100644 index 000000000..8ba22f43b --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanSuppressionStrategySpanKind.php @@ -0,0 +1,35 @@ + + */ +final class SpanSuppressionStrategySpanKind implements ComponentProvider +{ + /** + * @param array{} $properties + */ + #[Override] + public function createPlugin(array $properties, Context $context): SpanSuppressionStrategy + { + return new SpanKindSuppressionStrategy(); + } + + #[Override] + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + return $builder->arrayNode('spankind'); + } +} diff --git a/src/Config/SDK/composer.json b/src/Config/SDK/composer.json index 87de6d155..fb9f04aaf 100644 --- a/src/Config/SDK/composer.json +++ b/src/Config/SDK/composer.json @@ -20,7 +20,7 @@ "php": "^8.1", "open-telemetry/api": "^1.8", "open-telemetry/context": "^1.4", - "open-telemetry/sdk": "^1.8", + "open-telemetry/sdk": "^1.14", "symfony/config": "^5.4 || ^6.4 || ^7.0 || ^8.0", "tbachert/spi": "^1.0.5" }, @@ -59,6 +59,8 @@ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterZipkin", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorBatch", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorSimple", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanSuppressionStrategySemConv", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanSuppressionStrategySpanKind", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\AggregationResolverDefault", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterConsole", @@ -82,7 +84,9 @@ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Detector\\Service", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Instrumentation\\General\\HttpConfigProvider", - "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Instrumentation\\General\\PeerConfigProvider" + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Instrumentation\\General\\PeerConfigProvider", + + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Distribution\\DistributionConfigurationSdk" ], "OpenTelemetry\\Config\\SDK\\Configuration\\Environment\\EnvSourceProvider": [ "OpenTelemetry\\Config\\SDK\\Configuration\\Environment\\Adapter\\SymfonyDotenvProvider", diff --git a/src/SDK/Common/Configuration/Variables.php b/src/SDK/Common/Configuration/Variables.php index 9761342e1..9e7585955 100644 --- a/src/SDK/Common/Configuration/Variables.php +++ b/src/SDK/Common/Configuration/Variables.php @@ -143,4 +143,5 @@ interface Variables public const OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN = 'OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN'; public const OTEL_CONFIG_FILE = 'OTEL_CONFIG_FILE'; public const OTEL_EXPERIMENTAL_RESPONSE_PROPAGATORS = 'OTEL_EXPERIMENTAL_RESPONSE_PROPAGATORS'; + public const OTEL_EXPERIMENTAL_SPAN_SUPPRESSION_STRATEGY = 'OTEL_EXPERIMENTAL_SPAN_SUPPRESSION_STRATEGY'; } diff --git a/src/SDK/Common/Distribution/DistributionConfiguration.php b/src/SDK/Common/Distribution/DistributionConfiguration.php new file mode 100644 index 000000000..5de042fa1 --- /dev/null +++ b/src/SDK/Common/Distribution/DistributionConfiguration.php @@ -0,0 +1,9 @@ + $distribution + * @return C|null + */ + public function getDistributionConfiguration(string $distribution): ?DistributionConfiguration; +} diff --git a/src/SDK/Common/Distribution/DistributionRegistry.php b/src/SDK/Common/Distribution/DistributionRegistry.php new file mode 100644 index 000000000..379b21b00 --- /dev/null +++ b/src/SDK/Common/Distribution/DistributionRegistry.php @@ -0,0 +1,25 @@ +distributionConfigurations[$distributionConfiguration::class] = $distributionConfiguration; + + return $this; + } + + #[Override] + public function getDistributionConfiguration(string $distribution): ?DistributionConfiguration + { + return $this->distributionConfigurations[$distribution] ?? null; + } +} diff --git a/src/SDK/Common/Distribution/SdkDistribution.php b/src/SDK/Common/Distribution/SdkDistribution.php new file mode 100644 index 000000000..9258e9e6a --- /dev/null +++ b/src/SDK/Common/Distribution/SdkDistribution.php @@ -0,0 +1,16 @@ + + */ +final class DistributionConfigurationSdk implements EnvComponentLoader +{ + #[Override] + public function load(EnvResolver $env, EnvComponentLoaderRegistry $registry, Context $context): DistributionConfiguration + { + $spanSuppressionStrategyName = $env->string(Variables::OTEL_EXPERIMENTAL_SPAN_SUPPRESSION_STRATEGY) ?? 'none'; + + return new SdkDistribution( + spanSuppressionStrategy: match ($spanSuppressionStrategyName) { + 'none' => new NoopSuppressionStrategy(), + default => $registry->load(SpanSuppressionStrategy::class, $spanSuppressionStrategyName, $env, $context), + }, + ); + } + + #[Override] + public function name(): string + { + return self::class; + } +} diff --git a/src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySemConv.php b/src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySemConv.php new file mode 100644 index 000000000..e1dd4b243 --- /dev/null +++ b/src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySemConv.php @@ -0,0 +1,33 @@ + + */ +final class SpanSuppressionStrategySemConv implements EnvComponentLoader +{ + #[Override] + public function load(EnvResolver $env, EnvComponentLoaderRegistry $registry, Context $context): SpanSuppressionStrategy + { + return new SemanticConventionSuppressionStrategy(ServiceLoader::load(SemanticConventionResolver::class)); + } + + #[Override] + public function name(): string + { + return 'semconv'; + } +} diff --git a/src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySpanKind.php b/src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySpanKind.php new file mode 100644 index 000000000..e70c38fcf --- /dev/null +++ b/src/SDK/ConfigEnv/Trace/SpanSuppressionStrategySpanKind.php @@ -0,0 +1,31 @@ + + */ +final class SpanSuppressionStrategySpanKind implements EnvComponentLoader +{ + #[Override] + public function load(EnvResolver $env, EnvComponentLoaderRegistry $registry, Context $context): SpanSuppressionStrategy + { + return new SpanKindSuppressionStrategy(); + } + + #[Override] + public function name(): string + { + return 'spankind'; + } +} diff --git a/src/SDK/SdkAutoloader.php b/src/SDK/SdkAutoloader.php index 6dc53ba1d..3232f1dc1 100644 --- a/src/SDK/SdkAutoloader.php +++ b/src/SDK/SdkAutoloader.php @@ -34,6 +34,10 @@ use OpenTelemetry\SDK\Common\Configuration\EnvComponentLoaderRegistry; use OpenTelemetry\SDK\Common\Configuration\EnvResolver; use OpenTelemetry\SDK\Common\Configuration\Variables; +use OpenTelemetry\SDK\Common\Distribution\DistributionConfiguration; +use OpenTelemetry\SDK\Common\Distribution\DistributionProperties; +use OpenTelemetry\SDK\Common\Distribution\DistributionRegistry; +use OpenTelemetry\SDK\Common\Distribution\SdkDistribution; use OpenTelemetry\SDK\Common\Util\ShutdownHandler; use OpenTelemetry\SDK\Logs\EventLoggerProviderFactory; use OpenTelemetry\SDK\Logs\LoggerProviderFactory; @@ -97,6 +101,9 @@ private static function environmentBasedInitializer(Configurator $configurator): } $emitMetrics = Configuration::getBoolean(Variables::OTEL_PHP_INTERNAL_METRICS_ENABLED); + $distributionProperties = self::loadDistributionPropertiesFromEnv(); + $distributionConfiguration = $distributionProperties->getDistributionConfiguration(SdkDistribution::class) ?? new SdkDistribution(); + $resource = ResourceInfoFactory::defaultResource(); $exporter = (new ExporterFactory())->create(); $meterProvider = (new MeterProviderFactory())->create($resource); @@ -105,6 +112,7 @@ private static function environmentBasedInitializer(Configurator $configurator): ->addSpanProcessor($spanProcessor) ->setResource($resource) ->setSampler((new SamplerFactory())->create()) + ->setSpanSuppressionStrategy($distributionConfiguration->spanSuppressionStrategy) ->build(); $loggerProvider = (new LoggerProviderFactory())->create($emitMetrics ? $meterProvider : null, $resource); @@ -186,6 +194,24 @@ private static function registerInstrumentations(): void } } + private static function loadDistributionPropertiesFromEnv(): DistributionProperties + { + $loaderRegistry = new EnvComponentLoaderRegistry(); + foreach (ServiceLoader::load(EnvComponentLoader::class) as $loader) { + $loaderRegistry->register($loader); + } + + $env = new EnvResolver(); + $context = new \OpenTelemetry\API\Configuration\Context(); + + $configuration = new DistributionRegistry(); + foreach ($loaderRegistry->loadAll(DistributionConfiguration::class, $env, $context) as $distribution) { + $configuration->add($distribution); + } + + return $configuration; + } + private static function loadConfigPropertiesFromEnv(): ConfigProperties { $loaderRegistry = new EnvComponentLoaderRegistry(); diff --git a/src/SDK/composer.json b/src/SDK/composer.json index 6ef44c9ae..7812d0661 100644 --- a/src/SDK/composer.json +++ b/src/SDK/composer.json @@ -55,7 +55,7 @@ }, "extra": { "branch-alias": { - "dev-main": "1.12.x-dev" + "dev-main": "1.14.x-dev" }, "spi": { "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ @@ -63,7 +63,12 @@ ], "OpenTelemetry\\API\\Configuration\\ConfigEnv\\EnvComponentLoader": [ "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderHttpConfig", - "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderPeerConfig" + "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderPeerConfig", + + "OpenTelemetry\\SDK\\ConfigEnv\\Trace\\SpanSuppressionStrategySemConv", + "OpenTelemetry\\SDK\\ConfigEnv\\Trace\\SpanSuppressionStrategySpanKind", + + "OpenTelemetry\\SDK\\ConfigEnv\\Distribution\\DistributionConfigurationSdk" ], "OpenTelemetry\\SDK\\Common\\Configuration\\Resolver\\ResolverInterface": [ "OpenTelemetry\\SDK\\Common\\Configuration\\Resolver\\SdkConfigurationResolver"