diff --git a/composer.json b/composer.json index e127ff8fc..1bd398734 100644 --- a/composer.json +++ b/composer.json @@ -155,7 +155,13 @@ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Instrumentation\\General\\HttpConfigProvider", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Instrumentation\\General\\PeerConfigProvider", - "OpenTelemetry\\Example\\ExampleConfigProvider" + "OpenTelemetry\\Example\\ExampleConfigProvider", + + "OpenTelemetry\\Tests\\Integration\\Config\\ComponentProvider\\Metrics\\AggregationResolverExplicitBucketHistogram", + "OpenTelemetry\\Tests\\Integration\\Config\\ComponentProvider\\Metrics\\MetricExporterPrometheus", + "OpenTelemetry\\Tests\\Integration\\Config\\ComponentProvider\\Metrics\\MetricReaderPull", + "OpenTelemetry\\Tests\\Integration\\Config\\ComponentProvider\\Propagator\\TextMapPropagatorXray", + "OpenTelemetry\\Tests\\Integration\\Config\\ComponentProvider\\Propagator\\TextMapPropagatorOtTrace" ], "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" diff --git a/examples/instrumentation/otel-sdk.yaml b/examples/instrumentation/otel-sdk.yaml index 53ce87914..70a188a75 100644 --- a/examples/instrumentation/otel-sdk.yaml +++ b/examples/instrumentation/otel-sdk.yaml @@ -1,12 +1,18 @@ file_format: '0.3' +propagator: + composite: [] + tracer_provider: processors: - simple: exporter: - console: {} + console: + sampler: + always_on: instrumentation: + general: php: example_instrumentation: span_name: ${EXAMPLE_INSTRUMENTATION_SPAN_NAME:-example span} diff --git a/examples/load_config.yaml b/examples/load_config.yaml index 0535a6dbb..528780799 100644 --- a/examples/load_config.yaml +++ b/examples/load_config.yaml @@ -18,11 +18,11 @@ tracer_provider: sampler: parent_based: root: - always_on: {} + always_on: processors: - simple: exporter: - console: {} + console: - batch: exporter: otlp: *otlp-exporter @@ -30,7 +30,7 @@ meter_provider: readers: - periodic: exporter: - console: {} + console: - periodic: exporter: otlp: @@ -40,7 +40,7 @@ logger_provider: processors: - simple: exporter: - console: {} + console: - batch: exporter: otlp: *otlp-exporter diff --git a/examples/src/ExampleConfigProvider.php b/examples/src/ExampleConfigProvider.php index 1cffd3f93..42b84f550 100644 --- a/examples/src/ExampleConfigProvider.php +++ b/examples/src/ExampleConfigProvider.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Config\SDK\Configuration\Validation; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -34,16 +35,16 @@ public function createPlugin(array $properties, Context $context): Instrumentati /** * @psalm-suppress UndefinedInterfaceMethod,PossiblyNullReference */ - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $root = new ArrayNodeDefinition('example_instrumentation'); - $root + $node = $builder->arrayNode('example_instrumentation'); + $node ->children() ->scalarNode('span_name')->isRequired()->validate()->always(Validation::ensureString())->end()->end() ->end() ->canBeDisabled() ; - return $root; + return $node; } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 569545a4d..807247557 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -38,6 +38,7 @@ parameters: message: "#Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeParentInterface::.*#" paths: - src/Config/SDK + - tests/Integration/Config - message: "#Cannot call method .* on null#" paths: diff --git a/psalm.xml.dist b/psalm.xml.dist index ed0d7ffc9..0ac60dbed 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -37,19 +37,32 @@ + + + + + + + + + + + + + @@ -57,5 +70,15 @@ + + + + + + + + + + diff --git a/src/Config/SDK/ComponentProvider/Instrumentation/General/HttpConfigProvider.php b/src/Config/SDK/ComponentProvider/Instrumentation/General/HttpConfigProvider.php index 541a99ca4..7434d64dd 100644 --- a/src/Config/SDK/ComponentProvider/Instrumentation/General/HttpConfigProvider.php +++ b/src/Config/SDK/ComponentProvider/Instrumentation/General/HttpConfigProvider.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -21,22 +22,22 @@ public function createPlugin(array $properties, Context $context): GeneralInstru return new HttpConfig($properties); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('http'); + $node = $builder->arrayNode('http'); $node ->children() - ->append($this->capturedHeaders('client')) - ->append($this->capturedHeaders('server')) + ->append($this->capturedHeaders('client', $builder)) + ->append($this->capturedHeaders('server', $builder)) ->end() ; return $node; } - private function capturedHeaders(string $name): ArrayNodeDefinition + private function capturedHeaders(string $name, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition($name); + $node = $builder->arrayNode($name); $node ->children() ->arrayNode('request_captured_headers') diff --git a/src/Config/SDK/ComponentProvider/Instrumentation/General/PeerConfigProvider.php b/src/Config/SDK/ComponentProvider/Instrumentation/General/PeerConfigProvider.php index f9273a422..fc08b1a4e 100644 --- a/src/Config/SDK/ComponentProvider/Instrumentation/General/PeerConfigProvider.php +++ b/src/Config/SDK/ComponentProvider/Instrumentation/General/PeerConfigProvider.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -21,9 +22,9 @@ public function createPlugin(array $properties, Context $context): GeneralInstru return new PeerConfig($properties); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('peer'); + $node = $builder->arrayNode('peer'); $node ->children() ->arrayNode('service_mapping') diff --git a/src/Config/SDK/ComponentProvider/InstrumentationConfigurationRegistry.php b/src/Config/SDK/ComponentProvider/InstrumentationConfigurationRegistry.php index 44f4ae4c7..a156bebec 100644 --- a/src/Config/SDK/ComponentProvider/InstrumentationConfigurationRegistry.php +++ b/src/Config/SDK/ComponentProvider/InstrumentationConfigurationRegistry.php @@ -12,6 +12,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @internal @@ -24,7 +25,7 @@ class InstrumentationConfigurationRegistry implements ComponentProvider * @param array{ * instrumentation: array{ * php: list>, - * general: list> + * general: list> * } * } $properties */ @@ -43,18 +44,16 @@ public function createPlugin(array $properties, Context $context): Configuration return $configurationRegistry; } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $root = new ArrayNodeDefinition('open_telemetry'); + $root = $builder->arrayNode('open_telemetry'); $root ->ignoreExtraKeys() ->children() ->arrayNode('instrumentation') ->ignoreExtraKeys() - ->children() - ->append($registry->componentList('php', InstrumentationConfiguration::class)) - ->append($registry->componentList('general', GeneralInstrumentationConfiguration::class)) - ->end() + ->append($registry->componentMap('php', InstrumentationConfiguration::class)) + ->append($registry->componentMap('general', GeneralInstrumentationConfiguration::class)) ->end() ->end() ; diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php index ced5b222f..2341cd95b 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php @@ -11,6 +11,7 @@ use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; use OpenTelemetry\SDK\Registry; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -28,8 +29,8 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('console'); + return $builder->arrayNode('console'); } } diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php index 753f23ab2..e580e7782 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php @@ -17,6 +17,7 @@ use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; use OpenTelemetry\SDK\Registry; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -35,6 +36,7 @@ final class LogRecordExporterOtlp implements ComponentProvider * headers_list: ?string, * compression: 'gzip'|null, * timeout: int<0, max>, + * insecure: ?bool, * } $properties */ public function createPlugin(array $properties, Context $context): LogRecordExporterInterface @@ -55,9 +57,9 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('otlp'); + $node = $builder->arrayNode('otlp'); $node ->children() ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() @@ -76,6 +78,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->enumNode('compression')->values(['gzip'])->defaultNull()->end() ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->booleanNode('insecure')->defaultNull()->end() ->end() ; diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php index 0691827b8..9d57e2261 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; use OpenTelemetry\SDK\Logs\Processor\BatchLogRecordProcessor; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -41,9 +42,9 @@ public function createPlugin(array $properties, Context $context): LogRecordProc ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('batch'); + $node = $builder->arrayNode('batch'); $node ->children() ->integerNode('schedule_delay')->min(0)->defaultValue(5000)->end() diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php index 08db3119c..0b5b11378 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php @@ -12,6 +12,7 @@ use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -30,9 +31,9 @@ public function createPlugin(array $properties, Context $context): LogRecordProc ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('simple'); + $node = $builder->arrayNode('simple'); $node ->children() ->append($registry->component('exporter', LogRecordExporterInterface::class)->isRequired()) diff --git a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php index b55668f26..0aa7d0558 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php +++ b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderInterface; use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderTrait; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -27,8 +28,8 @@ public function createPlugin(array $properties, Context $context): DefaultAggreg }; } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('default'); + return $builder->arrayNode('default'); } } diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php index 9dc844ed2..7812dee34 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Metrics\MetricExporter\ConsoleMetricExporter; use OpenTelemetry\SDK\Metrics\MetricExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -24,8 +25,8 @@ public function createPlugin(array $properties, Context $context): MetricExporte return new ConsoleMetricExporter(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('console'); + return $builder->arrayNode('console'); } } diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php index 536a10a00..f92872b49 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php @@ -18,6 +18,7 @@ use OpenTelemetry\SDK\Metrics\MetricExporterInterface; use OpenTelemetry\SDK\Registry; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -36,8 +37,9 @@ final class MetricExporterOtlp implements ComponentProvider * headers_list: ?string, * compression: 'gzip'|null, * timeout: int<0, max>, + * insecure: ?bool, * temporality_preference: 'cumulative'|'delta'|'lowmemory', - * default_histogram_aggregation: 'explicit_bucket_histogram', + * default_histogram_aggregation: 'explicit_bucket_histogram|base2_exponential_bucket_histogram', * } $properties */ public function createPlugin(array $properties, Context $context): MetricExporterInterface @@ -64,9 +66,9 @@ public function createPlugin(array $properties, Context $context): MetricExporte ), $temporality); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('otlp'); + $node = $builder->arrayNode('otlp'); $node ->children() ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() @@ -85,12 +87,13 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->enumNode('compression')->values(['gzip'])->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->booleanNode('insecure')->defaultNull()->end() ->enumNode('temporality_preference') ->values(['cumulative', 'delta', 'lowmemory']) ->defaultValue('cumulative') ->end() ->enumNode('default_histogram_aggregation') - ->values(['explicit_bucket_histogram']) + ->values(['explicit_bucket_histogram', 'base2_exponential_bucket_histogram']) ->defaultValue('explicit_bucket_histogram') ->end() ->end() diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php index b6d75eba1..7595bbfc6 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php @@ -12,6 +12,7 @@ use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader; use OpenTelemetry\SDK\Metrics\MetricReaderInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -23,6 +24,7 @@ final class MetricReaderPeriodic implements ComponentProvider * interval: int<0, max>, * timeout: int<0, max>, * exporter: ComponentPlugin, + * producers: array, * } $properties */ public function createPlugin(array $properties, Context $context): MetricReaderInterface @@ -32,14 +34,16 @@ public function createPlugin(array $properties, Context $context): MetricReaderI ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('periodic'); + $node = $builder->arrayNode('periodic'); $node ->children() ->integerNode('interval')->min(0)->defaultValue(5000)->end() ->integerNode('timeout')->min(0)->defaultValue(30000)->end() ->append($registry->component('exporter', MetricExporterInterface::class)->isRequired()) + ->arrayNode('producers') //@todo + ->variablePrototype()->end() ->end() ; diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index c1cf6a9c2..917ebbbc7 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -42,6 +42,7 @@ use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use OpenTelemetry\SDK\Trace\TracerProvider; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @internal @@ -57,6 +58,7 @@ final class OpenTelemetrySdk implements ComponentProvider * resource: array{ * attributes: array, * attributes_list: ?string, + * detectors: array, * schema_url: ?string, * }, * attribute_limits: array{ @@ -81,7 +83,10 @@ final class OpenTelemetrySdk implements ComponentProvider * stream: array{ * name: ?string, * description: ?string, - * attribute_keys: list, + * attribute_keys: array{ + * included: list, + * excluded: list, + * }, * aggregation: ?ComponentPlugin, * }, * selector: array{ @@ -203,8 +208,9 @@ public function createPlugin(array $properties, Context $context): SdkBuilder if (isset($view['stream']['description'])) { $viewTemplate = $viewTemplate->withDescription($view['stream']['description']); } - if ($view['stream']['attribute_keys']) { - $viewTemplate = $viewTemplate->withAttributeKeys($view['stream']['attribute_keys']); + // TODO Add support for excluded keys to view template + if ($view['stream']['attribute_keys']['included']) { + $viewTemplate = $viewTemplate->withAttributeKeys($view['stream']['attribute_keys']['included']); } if (isset($view['stream']['aggregation'])) { // TODO Add support for aggregation providers in views to allow usage of advisory @@ -253,9 +259,9 @@ public function createPlugin(array $properties, Context $context): SdkBuilder return $sdkBuilder; } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('open_telemetry'); + $node = $builder->arrayNode('open_telemetry'); $node ->addDefaultsIfNotSet() ->ignoreExtraKeys() @@ -267,20 +273,20 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->validate()->ifNotInArray(['0.3'])->thenInvalid('unsupported version')->end() ->end() ->booleanNode('disabled')->defaultFalse()->end() - ->append($this->getResourceConfig()) - ->append($this->getAttributeLimitsConfig()) + ->append($this->getResourceConfig($builder)) + ->append($this->getAttributeLimitsConfig($builder)) ->append($registry->component('propagator', TextMapPropagatorInterface::class)) - ->append($this->getTracerProviderConfig($registry)) - ->append($this->getMeterProviderConfig($registry)) - ->append($this->getLoggerProviderConfig($registry)) + ->append($this->getTracerProviderConfig($registry, $builder)) + ->append($this->getMeterProviderConfig($registry, $builder)) + ->append($this->getLoggerProviderConfig($registry, $builder)) ->end(); return $node; } - private function getResourceConfig(): ArrayNodeDefinition + private function getResourceConfig(NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('resource'); + $node = $builder->arrayNode('resource'); $node ->addDefaultsIfNotSet() ->children() @@ -297,15 +303,19 @@ private function getResourceConfig(): ArrayNodeDefinition ->end() ->end() ->scalarNode('attributes_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->arrayNode('detectors') + ->variablePrototype()->end() + ->end() + ->scalarNode('attributes_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('schema_url')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->end(); return $node; } - private function getAttributeLimitsConfig(): ArrayNodeDefinition + private function getAttributeLimitsConfig(NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('attribute_limits'); + $node = $builder->arrayNode('attribute_limits'); $node ->addDefaultsIfNotSet() ->children() @@ -316,9 +326,9 @@ private function getAttributeLimitsConfig(): ArrayNodeDefinition return $node; } - private function getTracerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + private function getTracerProviderConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('tracer_provider'); + $node = $builder->arrayNode('tracer_provider'); $node ->addDefaultsIfNotSet() ->children() @@ -334,19 +344,27 @@ private function getTracerProviderConfig(ComponentProviderRegistry $registry): A ->end() ->end() ->append($registry->component('sampler', SamplerInterface::class)) - ->append($registry->componentArrayList('processors', SpanProcessorInterface::class)) + ->append($registry->componentList('processors', SpanProcessorInterface::class)) ->end() ; return $node; } - private function getMeterProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + private function getMeterProviderConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('meter_provider'); + $node = $builder->arrayNode('meter_provider'); $node ->addDefaultsIfNotSet() ->children() + ->enumNode('exemplar_filter') + ->values([ + 'trace_based', + 'always_on', + 'always_off', + ]) + ->defaultValue('trace_based') + ->end() ->arrayNode('views') ->arrayPrototype() ->children() @@ -356,7 +374,14 @@ private function getMeterProviderConfig(ComponentProviderRegistry $registry): Ar ->scalarNode('name')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('description')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->arrayNode('attribute_keys') - ->scalarPrototype()->validate()->always(Validation::ensureString())->end()->end() + ->children() + ->arrayNode('included') + ->scalarPrototype()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->arrayNode('excluded') + ->scalarPrototype()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->end() ->end() ->append($registry->component('aggregation', DefaultAggregationProviderInterface::class)) ->end() @@ -385,16 +410,16 @@ private function getMeterProviderConfig(ComponentProviderRegistry $registry): Ar ->end() ->end() ->end() - ->append($registry->componentArrayList('readers', MetricReaderInterface::class)) + ->append($registry->componentList('readers', MetricReaderInterface::class)) ->end() ; return $node; } - private function getLoggerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + private function getLoggerProviderConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('logger_provider'); + $node = $builder->arrayNode('logger_provider'); $node ->addDefaultsIfNotSet() ->children() @@ -405,7 +430,7 @@ private function getLoggerProviderConfig(ComponentProviderRegistry $registry): A ->integerNode('attribute_count_limit')->min(0)->defaultNull()->end() ->end() ->end() - ->append($registry->componentArrayList('processors', LogRecordProcessorInterface::class)) + ->append($registry->componentList('processors', LogRecordProcessorInterface::class)) ->end() ; diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php index ccd5152a2..e48ecde51 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\Extension\Propagator\B3\B3Propagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -26,8 +27,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag return B3Propagator::getB3SingleHeaderInstance(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('b3'); + return $builder->arrayNode('b3'); } } diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php index 67fb1fb2d..024078a01 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\Extension\Propagator\B3\B3Propagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -26,8 +27,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag return B3Propagator::getB3MultiHeaderInstance(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('b3multi'); + return $builder->arrayNode('b3multi'); } } diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php index 15b846873..031214187 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -24,8 +25,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag return BaggagePropagator::getInstance(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('baggage'); + return $builder->arrayNode('baggage'); } } diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php index 0e7f21cbf..e640bafcb 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\Propagation\MultiTextMapPropagator; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -30,7 +31,7 @@ public function createPlugin(array $properties, Context $context): TextMapPropag return new MultiTextMapPropagator($propagators); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { return $registry->componentNames('composite', TextMapPropagatorInterface::class); } diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php index 988200cab..39eed7948 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\Extension\Propagator\Jaeger\JaegerPropagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -26,8 +27,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag return JaegerPropagator::getInstance(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('jaeger'); + return $builder->arrayNode('jaeger'); } } diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php index fd03c8805..556b34563 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -24,8 +25,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag return TraceContextPropagator::getInstance(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('tracecontext'); + return $builder->arrayNode('tracecontext'); } } diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php index 4aacbfb6f..24d429b34 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Trace\Sampler\AlwaysOffSampler; use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -24,8 +25,8 @@ public function createPlugin(array $properties, Context $context): SamplerInterf return new AlwaysOffSampler(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('always_off'); + return $builder->arrayNode('always_off'); } } diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php index 494762168..ef1a63631 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler; use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -24,8 +25,8 @@ public function createPlugin(array $properties, Context $context): SamplerInterf return new AlwaysOnSampler(); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('always_on'); + return $builder->arrayNode('always_on'); } } diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php index 83b7dc0ea..725c6f39f 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Trace\Sampler\ParentBased; use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -39,9 +40,9 @@ public function createPlugin(array $properties, Context $context): SamplerInterf ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('parent_based'); + $node = $builder->arrayNode('parent_based'); $node ->children() ->append($registry->component('root', SamplerInterface::class)->isRequired()) diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php index d4f53b04c..5b4130429 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Trace\Sampler\TraceIdRatioBasedSampler; use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -28,9 +29,9 @@ public function createPlugin(array $properties, Context $context): SamplerInterf ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('trace_id_ratio_based'); + $node = $builder->arrayNode('trace_id_ratio_based'); $node ->children() ->floatNode('ratio')->min(0)->max(1)->isRequired()->end() diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php index d50d8642a..6596b014d 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php @@ -11,6 +11,7 @@ use OpenTelemetry\SDK\Trace\SpanExporter\ConsoleSpanExporter; use OpenTelemetry\SDK\Trace\SpanExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -28,8 +29,8 @@ public function createPlugin(array $properties, Context $context): SpanExporterI )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('console'); + return $builder->arrayNode('console'); } } diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php index 29a6f1661..83140c5fd 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php @@ -17,6 +17,7 @@ use OpenTelemetry\SDK\Registry; use OpenTelemetry\SDK\Trace\SpanExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -35,6 +36,7 @@ final class SpanExporterOtlp implements ComponentProvider * headers_list: ?string, * compression: 'gzip'|null, * timeout: int<0, max>, + * insecure: ?bool, * } $properties */ public function createPlugin(array $properties, Context $context): SpanExporterInterface @@ -55,9 +57,9 @@ public function createPlugin(array $properties, Context $context): SpanExporterI )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('otlp'); + $node = $builder->arrayNode('otlp'); $node ->children() ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() @@ -67,7 +69,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->arrayNode('headers') ->arrayPrototype() - ->children() + ->children() ->scalarNode('name')->isRequired()->cannotBeEmpty()->end() ->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->end() @@ -76,6 +78,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->enumNode('compression')->values(['gzip'])->defaultNull()->end() ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->booleanNode('insecure')->defaultNull()->end() ->end() ; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php index 7db846444..4451ef151 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Registry; use OpenTelemetry\SDK\Trace\SpanExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -35,9 +36,9 @@ public function createPlugin(array $properties, Context $context): SpanExporterI )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('zipkin'); + $node = $builder->arrayNode('zipkin'); $node ->children() ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php index 72fd58a4e..2602c49b5 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php @@ -13,6 +13,7 @@ use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor; use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -41,9 +42,9 @@ public function createPlugin(array $properties, Context $context): SpanProcessor ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('batch'); + $node = $builder->arrayNode('batch'); $node ->children() ->integerNode('schedule_delay')->min(0)->defaultValue(5000)->end() diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php index e86e2ab6e..19852287c 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php @@ -12,6 +12,7 @@ use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * @implements ComponentProvider @@ -30,9 +31,9 @@ public function createPlugin(array $properties, Context $context): SpanProcessor ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('simple'); + $node = $builder->arrayNode('simple'); $node ->children() ->append($registry->component('exporter', SpanExporterInterface::class)->isRequired()) diff --git a/src/Config/SDK/Configuration/ComponentProvider.php b/src/Config/SDK/Configuration/ComponentProvider.php index 57b65ae78..77c8a7ae9 100644 --- a/src/Config/SDK/Configuration/ComponentProvider.php +++ b/src/Config/SDK/Configuration/ComponentProvider.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Config\SDK\Configuration; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** * A component provider is responsible for interpreting configuration and returning an @@ -28,12 +29,12 @@ public function createPlugin(array $properties, Context $context): mixed; * Returns an array node describing the properties of this component provider. * * @param ComponentProviderRegistry $registry registry containing all available component providers + * @param NodeBuilder $builder node builder used to create configuration nodes * @return ArrayNodeDefinition array node describing the properties * * @see ComponentProviderRegistry::component() * @see ComponentProviderRegistry::componentList() - * @see ComponentProviderRegistry::componentArrayList() * @see ComponentProviderRegistry::componentNames() */ - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition; + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition; } diff --git a/src/Config/SDK/Configuration/ComponentProviderRegistry.php b/src/Config/SDK/Configuration/ComponentProviderRegistry.php index 6121a979b..5945fedc4 100644 --- a/src/Config/SDK/Configuration/ComponentProviderRegistry.php +++ b/src/Config/SDK/Configuration/ComponentProviderRegistry.php @@ -50,16 +50,16 @@ public function component(string $name, string $type): NodeDefinition; public function componentList(string $name, string $type): ArrayNodeDefinition; /** - * Creates a node to specify a list of component plugins represented as an array. + * Creates a node to specify a map of component plugins. * * `$name: list>` * * ``` * $name: - * - provider1: + * provider1: * property: value * anotherProperty: value - * - provider2: + * provider2: * property: value * anotherProperty: value * ``` @@ -67,7 +67,7 @@ public function componentList(string $name, string $type): ArrayNodeDefinition; * @param string $name name of configuration node * @param string $type type of the component plugin */ - public function componentArrayList(string $name, string $type): ArrayNodeDefinition; + public function componentMap(string $name, string $type): ArrayNodeDefinition; /** * Creates a node to specify a list of component plugin names. * diff --git a/src/Config/SDK/Configuration/ConfigurationFactory.php b/src/Config/SDK/Configuration/ConfigurationFactory.php index 61a3323dc..98b00a958 100644 --- a/src/Config/SDK/Configuration/ConfigurationFactory.php +++ b/src/Config/SDK/Configuration/ConfigurationFactory.php @@ -14,13 +14,20 @@ use OpenTelemetry\Config\SDK\Configuration\Internal\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Internal\ConfigurationLoader; use OpenTelemetry\Config\SDK\Configuration\Internal\EnvSubstitutionNormalization; +use OpenTelemetry\Config\SDK\Configuration\Internal\NodeDefinition\ArrayNodeDefinition; +use OpenTelemetry\Config\SDK\Configuration\Internal\NodeDefinition\BooleanNodeDefinition; +use OpenTelemetry\Config\SDK\Configuration\Internal\NodeDefinition\FloatNodeDefinition; +use OpenTelemetry\Config\SDK\Configuration\Internal\NodeDefinition\IntegerNodeDefinition; +use OpenTelemetry\Config\SDK\Configuration\Internal\NodeDefinition\ScalarNodeDefinition; +use OpenTelemetry\Config\SDK\Configuration\Internal\NodeDefinition\StringNodeDefinition; +use OpenTelemetry\Config\SDK\Configuration\Internal\NodeDefinition\VariableNodeDefinition; use OpenTelemetry\Config\SDK\Configuration\Internal\ResourceCollection; use OpenTelemetry\Config\SDK\Configuration\Internal\TrackingEnvReader; -use OpenTelemetry\Config\SDK\Configuration\Internal\TreatNullAsUnsetNormalization; use OpenTelemetry\Config\SDK\Configuration\Loader\YamlExtensionFileLoader; use OpenTelemetry\Config\SDK\Configuration\Loader\YamlSymfonyFileLoader; use function serialize; use function sprintf; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\DelegatingLoader; @@ -123,18 +130,31 @@ class_exists(VarExporter::class) private function compileFactory(): CompiledConfigurationFactory { - $registry = new ComponentProviderRegistry(); + $envReader = new TrackingEnvReader($this->envReader); + $normalizations = [ + // Parse MUST perform environment variable substitution. + new EnvSubstitutionNormalization($envReader), + ]; + + $builder = new NodeBuilder(); + $builder->setNodeClass('variable', VariableNodeDefinition::class); + $builder->setNodeClass('scalar', ScalarNodeDefinition::class); + $builder->setNodeClass('boolean', BooleanNodeDefinition::class); + $builder->setNodeClass('integer', IntegerNodeDefinition::class); + $builder->setNodeClass('float', FloatNodeDefinition::class); + $builder->setNodeClass('array', ArrayNodeDefinition::class); + $builder->setNodeClass('string', StringNodeDefinition::class); + + $registry = new ComponentProviderRegistry($normalizations, $builder); + foreach ($this->componentProviders as $provider) { $registry->register($provider); } - $root = $this->rootComponent->getConfig($registry); - - $envReader = new TrackingEnvReader($this->envReader); - // Parse MUST perform environment variable substitution. - (new EnvSubstitutionNormalization($envReader))->apply($root); - // Parse MUST interpret null as equivalent to unset. - (new TreatNullAsUnsetNormalization())->apply($root); + $root = $this->rootComponent->getConfig($registry, $builder); + foreach ($normalizations as $normalization) { + $normalization->apply($root); + } $node = $root->getNode(forceRootNode: true); diff --git a/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNull.php b/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNull.php deleted file mode 100644 index 452ef33de..000000000 --- a/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNull.php +++ /dev/null @@ -1,34 +0,0 @@ -getName()); - foreach (get_object_vars($node) as $property => $value) { - $defaultNull->$property = $value; - } - - return $defaultNull; - } - - public function hasDefaultValue(): bool - { - return true; - } - - public function getDefaultValue(): mixed - { - return null; - } -} diff --git a/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNullDefinition.php b/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNullDefinition.php deleted file mode 100644 index 8ec05d01a..000000000 --- a/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNullDefinition.php +++ /dev/null @@ -1,24 +0,0 @@ -> */ + /** @var iterable iterable */ + private readonly iterable $normalizations; + private readonly NodeBuilder $builder; + /** @var array> */ private array $providers = []; - /** @var array> */ - private array $recursionProtection = []; private ?ResourceCollection $resources = null; + /** + * @param iterable $normalizations + */ + public function __construct(iterable $normalizations, NodeBuilder $builder) + { + $this->normalizations = $normalizations; + $this->builder = $builder; + } + public function register(ComponentProvider $provider): void { - $name = self::loadName($provider); + $config = $provider->getConfig($this, $this->builder); + + $name = self::loadName($config); $type = self::loadType($provider); if (isset($this->providers[$type][$name])) { throw new LogicException(sprintf('Duplicate component provider registered for "%s" "%s"', $type, $name)); } - $this->providers[$type][$name] = $provider; + $this->providers[$type][$name] = new ComponentProviderRegistryEntry($provider, $config); } public function trackResources(?ResourceCollection $resources): void @@ -54,14 +68,7 @@ public function trackResources(?ResourceCollection $resources): void public function component(string $name, string $type): NodeDefinition { - if (!$this->getProviders($type)) { - return (new VariableNodeDefinition($name)) - ->info(sprintf('Component "%s"', $type)) - ->defaultNull() - ->validate()->always()->thenInvalid(sprintf('Component "%s" cannot be configured, it does not have any associated provider', $type))->end(); - } - - $node = new ArrayNodeDefaultNullDefinition($name); + $node = $this->builder->arrayNode($name); $this->applyToArrayNode($node, $type); return $node; @@ -69,121 +76,103 @@ public function component(string $name, string $type): NodeDefinition public function componentList(string $name, string $type): ArrayNodeDefinition { - $node = new ArrayNodeDefinition($name); - $this->applyToArrayNode($node, $type, true); + $node = $this->builder->arrayNode($name); + $this->applyToArrayNode($node->arrayPrototype(), $type); return $node; } - public function componentArrayList(string $name, string $type): ArrayNodeDefinition + public function componentMap(string $name, string $type): ArrayNodeDefinition { - $node = new ArrayNodeDefinition($name); - $this->applyToArrayNode($node->arrayPrototype(), $type); + $node = $this->builder->arrayNode($name); + $node->info(sprintf('Component "%s"', $type)); + $node->performNoDeepMerging(); + $node->ignoreExtraKeys(false); + $node->validate()->always(function (array|null $value) use ($type): array { + $components = []; + foreach ($value ?? [] as $name => $config) { + $components[] = $this->process($type, $name, [$name => $config]); + } + + return $components; + }); return $node; } public function componentNames(string $name, string $type): ArrayNodeDefinition { - $node = new ArrayNodeDefinition($name); - - $providers = $this->getProviders($type); - foreach ($providers as $providerName => $provider) { - try { - $provider->getConfig(new ComponentProviderRegistry())->getNode(true)->finalize([]); - } catch (InvalidConfigurationException) { - unset($providers[$providerName]); + $node = $this->builder->arrayNode($name); + $node->scalarPrototype()->validate()->always(Validation::ensureString())->end()->end(); + $node->validate()->always(function (array $value) use ($type): array { + $plugins = []; + foreach ($value as $name) { + $plugins[] = $this->process($type, $name, []); } - } - if ($providers) { - $node->enumPrototype()->values(array_keys($providers))->end(); - $node->validate()->always(function (array $value) use ($type): array { - $plugins = []; - foreach ($value as $name) { - $provider = $this->providers[$type][$name]; - $this->resources?->addClassResource($provider); - - $plugins[] = new ComponentPlugin([], $provider); - } - - return $plugins; - }); - } + return $plugins; + }); return $node; } - private function applyToArrayNode(ArrayNodeDefinition $node, string $type, bool $forceArray = false): void + private function applyToArrayNode(ArrayNodeDefinition $node, string $type): void { $node->info(sprintf('Component "%s"', $type)); $node->performNoDeepMerging(); + $node->ignoreExtraKeys(false); + $node->validate()->always(function (array $value) use ($type): ComponentPlugin { + if (count($value) !== 1) { + throw new InvalidArgumentException(sprintf( + 'Component "%s" must have exactly one provider defined, got %s', + $type, + implode(', ', array_map(json_encode(...), array_keys($value)) ?: ['none']) + )); + } - foreach ($this->getProviders($type) as $name => $provider) { - $this->recursionProtection[$type][$name] = true; + return $this->process($type, array_key_first($value), $value); + }); + } + + private function process(string $type, string $name, mixed $configs): ComponentPlugin + { + if (!$provider = $this->providers[$type][$name] ?? null) { + throw new InvalidArgumentException(sprintf( + 'Component "%s" uses unknown provider "%s", available providers are %s', + $type, + $name, + implode(', ', array_map(json_encode(...), array_keys($this->providers[$type] ?? [])) ?: ['none']) + )); + } - try { - $node->children()->append($provider->getConfig($this)); - } finally { - unset($this->recursionProtection[$type][$name]); + if (!$provider->node instanceof NodeInterface) { + foreach ($this->normalizations as $normalization) { + $normalization->apply($provider->node); } + $provider->node = $provider->node->getNode(forceRootNode: true); } - if ($forceArray) { - // if the config was a map rather than an array, force it back to an array - $node->validate()->always(function (array $value) use ($type): array { - $validated = []; - foreach ($value as $name => $v) { - $provider = $this->providers[$type][$name]; - $this->resources?->addClassResource($provider); - $validated[] = new ComponentPlugin($v, $this->providers[$type][$name]); - } - - return $validated; - }); - } else { - $node->validate()->always(function (array $value) use ($type): ComponentPlugin { - if (count($value) !== 1) { - throw new InvalidArgumentException(sprintf( - 'Component "%s" must have exactly one element defined, got %s', - $type, - implode(', ', array_map(json_encode(...), array_keys($value)) ?: ['none']) - )); - } - - $name = array_key_first($value); - $provider = $this->providers[$type][$name]; - $this->resources?->addClassResource($provider); - - return new ComponentPlugin($value[$name], $this->providers[$type][$name]); - }); + try { + $componentConfig = (new Processor())->process($provider->node, $configs); + } catch (InvalidConfigurationException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } - } - /** - * Returns all registered providers for a specific component type. - * - * @param string $type the component type to load providers for - * @return array component providers indexed by their name - */ - private function getProviders(string $type): array - { - return array_diff_key( - $this->providers[$type] ?? [], - $this->recursionProtection[$type] ?? [], - ); + $this->resources?->addClassResource($provider); + + return new ComponentPlugin($componentConfig, $provider->componentProvider); } /** * @psalm-suppress PossiblyNullFunctionCall,InaccessibleProperty */ - private static function loadName(ComponentProvider $provider): string + private static function loadName(NodeDefinition $node): string { - static $accessor; //@todo inaccessible property $node->name - /** @phpstan-ignore-next-line */ + static $accessor; + // @phpstan-ignore-next-line $accessor ??= (static fn (NodeDefinition $node): ?string => $node->name)->bindTo(null, NodeDefinition::class); - return $accessor($provider->getConfig(new ComponentProviderRegistry())); + return $accessor($node); } private static function loadType(ComponentProvider $provider): string diff --git a/src/Config/SDK/Configuration/Internal/ComponentProviderRegistryEntry.php b/src/Config/SDK/Configuration/Internal/ComponentProviderRegistryEntry.php new file mode 100644 index 000000000..c075cad2a --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ComponentProviderRegistryEntry.php @@ -0,0 +1,18 @@ +getName()); + foreach (get_object_vars($node) as $property => $value) { + $_node->$property = $value; + } + + return $_node; + } + + public function setDefaultValue(mixed $value): void + { + $this->defaultValue = $value; + $this->defaultValueSet = true; + } + + public function hasDefaultValue(): bool + { + return $this->defaultValueSet || parent::hasDefaultValue(); + } + + public function getDefaultValue(): mixed + { + return $this->defaultValueSet + ? $this->defaultValue + : parent::getDefaultValue(); + } + + public function setAllowEmptyValue(bool $boolean): void + { + $this->allowEmptyValue = $boolean; + } +} diff --git a/src/Config/SDK/Configuration/Internal/Node/BooleanNode.php b/src/Config/SDK/Configuration/Internal/Node/BooleanNode.php new file mode 100644 index 000000000..bc316f83b --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/Node/BooleanNode.php @@ -0,0 +1,10 @@ +allowEmptyValue && $this->defaultValueSet) { + $value = $this->defaultValue; + } + + /** @noinspection PhpMultipleClassDeclarationsInspection */ + return parent::preNormalize($value); + } + + protected function normalizeValue(mixed $value): mixed + { + if ($value === null) { + return null; + } + + /** @noinspection PhpMultipleClassDeclarationsInspection */ + return parent::normalizeValue($value); + } + + protected function mergeValues(mixed $leftSide, mixed $rightSide): mixed + { + if (null === $rightSide) { + return $leftSide; + } + if (null === $leftSide) { + return $rightSide; + } + + /** @noinspection PhpMultipleClassDeclarationsInspection */ + return parent::mergeValues($leftSide, $rightSide); + } + + protected function validateType(mixed $value): void + { + if ($value === null && $this->allowEmptyValue) { + return; + } + + /** @noinspection PhpMultipleClassDeclarationsInspection */ + parent::validateType($value); + } + + public function finalizeValue(mixed $value): mixed + { + if ($value === null) { + return null; + } + + /** @noinspection PhpMultipleClassDeclarationsInspection */ + return parent::finalizeValue($value); + } + + protected function isValueEmpty(mixed $value): bool + { + return $value === null; + } +} diff --git a/src/Config/SDK/Configuration/Internal/Node/PrototypedArrayNode.php b/src/Config/SDK/Configuration/Internal/Node/PrototypedArrayNode.php new file mode 100644 index 000000000..e6b580a20 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/Node/PrototypedArrayNode.php @@ -0,0 +1,47 @@ +getName()); + foreach (get_object_vars($node) as $property => $value) { + $_node->$property = $value; + } + + return $_node; + } + + public function setDefaultValue(mixed $value): void + { + $this->defaultValue_ = $value; + $this->defaultValueSet = true; + } + + public function hasDefaultValue(): bool + { + return $this->defaultValueSet || parent::hasDefaultValue(); + } + + public function getDefaultValue(): mixed + { + return $this->defaultValueSet + ? $this->defaultValue_ + : parent::getDefaultValue(); + } + + public function setAllowEmptyValue(bool $boolean): void + { + $this->allowEmptyValue = $boolean; + } +} diff --git a/src/Config/SDK/Configuration/Internal/Node/ScalarNode.php b/src/Config/SDK/Configuration/Internal/Node/ScalarNode.php new file mode 100644 index 000000000..5a66a84df --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/Node/ScalarNode.php @@ -0,0 +1,10 @@ +getPath(), get_debug_type($value))); + if ($hint = $this->getInfo()) { + $ex->addHint($hint); + } + $ex->setPath($this->getPath()); + + throw $ex; + } + + parent::validateType($value); + } +} diff --git a/src/Config/SDK/Configuration/Internal/Node/VariableNode.php b/src/Config/SDK/Configuration/Internal/Node/VariableNode.php new file mode 100644 index 000000000..7efacb0b7 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/Node/VariableNode.php @@ -0,0 +1,10 @@ +nullEquivalent = null; + } + + protected function createNode(): NodeInterface + { + $node = parent::createNode(); + + /** @phpstan-ignore-next-line */ + $node = match (true) { + $node instanceof \Symfony\Component\Config\Definition\PrototypedArrayNode => PrototypedArrayNode::fromNode($node), + $node instanceof \Symfony\Component\Config\Definition\ArrayNode => ArrayNode::fromNode($node), + }; + + $node->setAllowEmptyValue($this->allowEmptyValue); + if ($this->defaultValueSet) { + $node->setDefaultValue($this->defaultValue); + } + + return $node; + } + + public function defaultValue(mixed $value): static + { + $this->defaultValueSet = true; + $this->defaultValue = $value; + + return $this; + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/BooleanNodeDefinition.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/BooleanNodeDefinition.php new file mode 100644 index 000000000..9201eb069 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/BooleanNodeDefinition.php @@ -0,0 +1,20 @@ +name, $this->parent, $this->pathSeparator); + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/EnumNodeDefinition.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/EnumNodeDefinition.php new file mode 100644 index 000000000..e78b696ba --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/EnumNodeDefinition.php @@ -0,0 +1,22 @@ +name, $this->parent, $node->getValues(), $this->pathSeparator); + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/FloatNodeDefinition.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/FloatNodeDefinition.php new file mode 100644 index 000000000..cafc10ff6 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/FloatNodeDefinition.php @@ -0,0 +1,20 @@ +name, $this->parent, $this->min, $this->max, $this->pathSeparator); + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/IntegerNodeDefinition.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/IntegerNodeDefinition.php new file mode 100644 index 000000000..c62b32252 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/IntegerNodeDefinition.php @@ -0,0 +1,20 @@ +name, $this->parent, $this->min, $this->max, $this->pathSeparator); + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/NodeDefinitionTrait.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/NodeDefinitionTrait.php new file mode 100644 index 000000000..e568ee05e --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/NodeDefinitionTrait.php @@ -0,0 +1,29 @@ +allowEmptyValue = false; + + return $this; + } + + public function defaultValue(mixed $value): static + { + /** + * If a property has a default value defined (i.e. is _not_ required) and is + * missing or present but null, Create MUST ensure the SDK component is configured + * with the default value. + **/ + $this->validate()->ifNull()->then(static function () use ($value): mixed { + return $value; + }); + + return parent::defaultValue($value); + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/ScalarNodeDefinition.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/ScalarNodeDefinition.php new file mode 100644 index 000000000..96cefab49 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/ScalarNodeDefinition.php @@ -0,0 +1,20 @@ +name, $this->parent, $this->pathSeparator); + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/StringNodeDefinition.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/StringNodeDefinition.php new file mode 100644 index 000000000..de4b88545 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/StringNodeDefinition.php @@ -0,0 +1,21 @@ +name, $this->parent, $this->pathSeparator); + } +} diff --git a/src/Config/SDK/Configuration/Internal/NodeDefinition/VariableNodeDefinition.php b/src/Config/SDK/Configuration/Internal/NodeDefinition/VariableNodeDefinition.php new file mode 100644 index 000000000..61db25e90 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/NodeDefinition/VariableNodeDefinition.php @@ -0,0 +1,20 @@ +name, $this->parent, $this->pathSeparator); + } +} diff --git a/src/Config/SDK/Configuration/Internal/Normalization.php b/src/Config/SDK/Configuration/Internal/Normalization.php new file mode 100644 index 000000000..a7425959c --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/Normalization.php @@ -0,0 +1,15 @@ +getChildNodeDefinitions() as $childNode) { - $this->doApply($childNode); - } - } - - private function doApply(NodeDefinition $node): void - { - $node->beforeNormalization()->ifNull()->thenUnset()->end(); - - if ($node instanceof ParentNodeDefinitionInterface) { - foreach ($node->getChildNodeDefinitions() as $childNode) { - $this->doApply($childNode); - } - } - } -} diff --git a/src/Config/SDK/Configuration/Validation.php b/src/Config/SDK/Configuration/Validation.php index b0f7898a7..de488c02b 100644 --- a/src/Config/SDK/Configuration/Validation.php +++ b/src/Config/SDK/Configuration/Validation.php @@ -36,6 +36,24 @@ public static function ensureString(): Closure }; } + /** + * @psalm-suppress InvalidReturnType,InvalidReturnStatement + */ + public static function ensureNumber(): Closure + { + + return static function (mixed $value): null|int|float { + if ($value === null) { + return null; + } + if (!is_numeric($value)) { + throw new InvalidArgumentException('must be of type numeric'); + } + + return $value; + }; + } + /** * @psalm-suppress ArgumentTypeCoercion */ diff --git a/src/SDK/Metrics/Stream/DeltaStorage.php b/src/SDK/Metrics/Stream/DeltaStorage.php index 066d2d948..52c987c4b 100644 --- a/src/SDK/Metrics/Stream/DeltaStorage.php +++ b/src/SDK/Metrics/Stream/DeltaStorage.php @@ -14,7 +14,7 @@ */ final class DeltaStorage { - private Delta $head; + private readonly Delta $head; public function __construct(private readonly AggregationInterface $aggregation) { diff --git a/tests/Integration/Config/ComponentProvider/Metrics/AggregationResolverExplicitBucketHistogram.php b/tests/Integration/Config/ComponentProvider/Metrics/AggregationResolverExplicitBucketHistogram.php new file mode 100644 index 000000000..7293d7c06 --- /dev/null +++ b/tests/Integration/Config/ComponentProvider/Metrics/AggregationResolverExplicitBucketHistogram.php @@ -0,0 +1,49 @@ + + */ +final class AggregationResolverExplicitBucketHistogram implements ComponentProvider +{ + /** + * @param array{ + * boundaries: array, + * record_min_max: bool, + * } $properties + */ + public function createPlugin(array $properties, Context $context): DefaultAggregationProviderInterface + { + return new class() implements DefaultAggregationProviderInterface { + use DefaultAggregationProviderTrait; + }; + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + $node = $builder->arrayNode('explicit_bucket_histogram'); + $node + ->children() + ->arrayNode('boundaries') + ->prototype('scalar') + ->validate()->always(Validation::ensureNumber())->end() + ->end() + ->end() + ->booleanNode('record_min_max')->defaultTrue()->end() + ->end(); + + return $node; + } +} diff --git a/tests/Integration/Config/ComponentProvider/Metrics/MetricExporterPrometheus.php b/tests/Integration/Config/ComponentProvider/Metrics/MetricExporterPrometheus.php new file mode 100644 index 000000000..e5b6b80f6 --- /dev/null +++ b/tests/Integration/Config/ComponentProvider/Metrics/MetricExporterPrometheus.php @@ -0,0 +1,74 @@ + + */ +final class MetricExporterPrometheus implements ComponentProvider +{ + /** + * @param array{ + * host: string, + * port: int, + * without_units: bool, + * without_type_suffix: bool, + * without_scope_info: bool, + * with_resource_constant_labels: array{ + * included: list, + * excluded: list, + * }, + * } $properties + */ + public function createPlugin(array $properties, Context $context): MetricExporterInterface + { + return new class() implements MetricExporterInterface { + public function export(iterable $batch): bool + { + return true; + } + + public function shutdown(): bool + { + return true; + } + }; + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + $node = $builder->arrayNode('prometheus'); + $node + ->children() + ->scalarNode('host')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('port')->isRequired()->validate()->always(Validation::ensureNumber())->end()->end() + ->booleanNode('without_units')->defaultFalse()->end() + ->booleanNode('without_type_suffix')->defaultFalse()->end() + ->booleanNode('without_scope_info')->defaultFalse()->end() + ->booleanNode('without_scope_trace')->defaultFalse()->end() + ->arrayNode('with_resource_constant_labels') + ->children() + ->arrayNode('included') + ->scalarPrototype()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->arrayNode('excluded') + ->scalarPrototype()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->end() + ->end() + ->end() + ; + + return $node; + } +} diff --git a/tests/Integration/Config/ComponentProvider/Metrics/MetricReaderPull.php b/tests/Integration/Config/ComponentProvider/Metrics/MetricReaderPull.php new file mode 100644 index 000000000..e5cf21c7c --- /dev/null +++ b/tests/Integration/Config/ComponentProvider/Metrics/MetricReaderPull.php @@ -0,0 +1,61 @@ + + */ +final class MetricReaderPull implements ComponentProvider +{ + /** + * @param array{ + * exporter: ComponentPlugin, + * producers: array, + * } $properties + */ + public function createPlugin(array $properties, Context $context): MetricReaderInterface + { + return new class() implements MetricReaderInterface { + public function collect(): bool + { + return true; + } + + public function shutdown(): bool + { + return true; + } + + public function forceFlush(): bool + { + return true; + } + }; + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + $node = $builder->arrayNode('pull'); + $node + ->children() + ->append($registry->component('exporter', MetricExporterInterface::class)->isRequired()) + ->arrayNode('producers') //@todo + ->variablePrototype()->end() + ->end() + ->end() + ; + + return $node; + } +} diff --git a/tests/Integration/Config/ComponentProvider/Propagator/TextMapPropagatorOtTrace.php b/tests/Integration/Config/ComponentProvider/Propagator/TextMapPropagatorOtTrace.php new file mode 100644 index 000000000..e5f2f1dc1 --- /dev/null +++ b/tests/Integration/Config/ComponentProvider/Propagator/TextMapPropagatorOtTrace.php @@ -0,0 +1,47 @@ + + */ +final class TextMapPropagatorOtTrace implements ComponentProvider +{ + public function createPlugin(array $properties, Context $context): TextMapPropagatorInterface + { + return new class() implements TextMapPropagatorInterface { + public function fields(): array + { + return []; + } + + public function inject(mixed &$carrier, ?PropagationSetterInterface $setter = null, ?ContextInterface $context = null): void + { + //no-op + } + + public function extract($carrier, ?PropagationGetterInterface $getter = null, ?ContextInterface $context = null): ContextInterface + { + return $context ?? Ctx::getCurrent(); + } + }; + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + return $builder->arrayNode('ottrace'); + } +} diff --git a/tests/Integration/Config/ComponentProvider/Propagator/TextMapPropagatorXray.php b/tests/Integration/Config/ComponentProvider/Propagator/TextMapPropagatorXray.php new file mode 100644 index 000000000..f7954c6b8 --- /dev/null +++ b/tests/Integration/Config/ComponentProvider/Propagator/TextMapPropagatorXray.php @@ -0,0 +1,47 @@ + + */ +final class TextMapPropagatorXray implements ComponentProvider +{ + public function createPlugin(array $properties, Context $context): TextMapPropagatorInterface + { + return new class() implements TextMapPropagatorInterface { + public function fields(): array + { + return []; + } + + public function inject(mixed &$carrier, ?PropagationSetterInterface $setter = null, ?ContextInterface $context = null): void + { + //no-op + } + + public function extract($carrier, ?PropagationGetterInterface $getter = null, ?ContextInterface $context = null): ContextInterface + { + return $context ?? Ctx::getCurrent(); + } + }; + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + return $builder->arrayNode('xray'); + } +} diff --git a/tests/Integration/Config/configurations/anchors.yaml b/tests/Integration/Config/configurations/anchors.yaml index ea6121ac1..ec042a129 100644 --- a/tests/Integration/Config/configurations/anchors.yaml +++ b/tests/Integration/Config/configurations/anchors.yaml @@ -34,9 +34,14 @@ meter_provider: temporality_preference: delta tracer_provider: + sampler: + always_off: processors: - batch: exporter: otlp: # expand the otlp-exporter anchor <<: *otlp-exporter + +propagator: + composite: [] \ No newline at end of file diff --git a/tests/Integration/Config/configurations/kitchen-sink.yaml b/tests/Integration/Config/configurations/kitchen-sink.yaml index e0dcaf557..0f214721d 100644 --- a/tests/Integration/Config/configurations/kitchen-sink.yaml +++ b/tests/Integration/Config/configurations/kitchen-sink.yaml @@ -5,396 +5,467 @@ # # Configuration values are set to their defaults when default values are defined. -# The file format version +# The file format version. +# The yaml format is documented at +# https://github.com/open-telemetry/opentelemetry-configuration/tree/main/schema file_format: "0.3" - -# Configure if the SDK is disabled or not. This is not required to be provided -# to ensure the SDK isn't disabled, the default value when this is not provided -# is for the SDK to be enabled. -# -# Environment variable: OTEL_SDK_DISABLED +# Configure if the SDK is disabled or not. +# If omitted or null, false is used. disabled: false - # Configure general attribute limits. See also tracer_provider.limits, logger_provider.limits. attribute_limits: - # Configure max attribute value size. - # - # Environment variable: OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT - attribute_value_length_limit: 4096 - # Configure max attribute count. - # - # Environment variable: OTEL_ATTRIBUTE_COUNT_LIMIT - attribute_count_limit: 128 - + # Configure max attribute value size. + # If omitted or null, there is no limit. + attribute_value_length_limit: 4096 + # Configure max attribute count. + # If omitted or null, 128 is used. + attribute_count_limit: 128 # Configure logger provider. +# If omitted, a noop logger provider is used. logger_provider: - # Configure log record processors. - processors: - # Configure a batch log record processor. - - batch: - # Configure delay interval (in milliseconds) between two consecutive exports. - # - # Environment variable: OTEL_BLRP_SCHEDULE_DELAY - schedule_delay: 5000 - # Configure maximum allowed time (in milliseconds) to export data. - # - # Environment variable: OTEL_BLRP_EXPORT_TIMEOUT - export_timeout: 30000 - # Configure maximum queue size. - # - # Environment variable: OTEL_BLRP_MAX_QUEUE_SIZE - max_queue_size: 2048 - # Configure maximum batch size. - # - # Environment variable: OTEL_BLRP_MAX_EXPORT_BATCH_SIZE - max_export_batch_size: 512 - # Configure exporter. - # - # Environment variable: OTEL_LOGS_EXPORTER - exporter: - # Configure exporter to be OTLP. - otlp: - # Configure protocol. - # - # Environment variable: OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_LOGS_PROTOCOL - protocol: http/protobuf - # Configure endpoint. - # - # Environment variable: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_ENDPOINT - endpoint: http://localhost:4318 - # Configure certificate. - # - # Environment variable: OTEL_EXPORTER_OTLP_CERTIFICATE, OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE - certificate: /app/cert.pem - # Configure mTLS private client key. - # - # Environment variable: OTEL_EXPORTER_OTLP_CLIENT_KEY, OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY - client_key: /app/cert.pem - # Configure mTLS client certificate. - # - # Environment variable: OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE - client_certificate: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - headers_list: "api-key=1234" - # Configure compression. - # - # Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_LOGS_COMPRESSION - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # - # Environment variable: OTEL_EXPORTER_OTLP_TIMEOUT, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT - timeout: 10000 - # Configure log record limits. See also attribute_limits. - limits: - # Configure max log record attribute value size. Overrides attribute_limits.attribute_value_length_limit. - # - # Environment variable: OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT - attribute_value_length_limit: 4096 - # Configure max log record attribute count. Overrides attribute_limits.attribute_count_limit. - # - # Environment variable: OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT - attribute_count_limit: 128 - + # Configure log record processors. + processors: + - # Configure a batch log record processor. + batch: + # Configure delay interval (in milliseconds) between two consecutive exports. + # If omitted or null, 1000 is used. + schedule_delay: 5000 + # Configure maximum allowed time (in milliseconds) to export data. + # If omitted or null, 30000 is used. + export_timeout: 30000 + # Configure maximum queue size. + # If omitted or null, 2048 is used. + max_queue_size: 2048 + # Configure maximum batch size. + # If omitted or null, 512 is used. + max_export_batch_size: 512 + # Configure exporter. + exporter: + # Configure exporter to be OTLP. + otlp: + # Configure protocol. Values include: http/protobuf, http/json, grpc. + protocol: http/protobuf + # Configure endpoint. + # If .protocol is http/protobuf or http/json, the signal specific path must be included (i.e. http://localhost:4318/v1/{signal}). If .protocol is grpc, a path should not be included (i.e. http://localhost:4317). + endpoint: http://localhost:4318/v1/logs + # Configure certificate. Absolute path to certificate file. + # If omitted or null, system default certificate verification is used for secure connections. + certificate: /app/cert.pem + # Configure mTLS private client key. Absolute path to client key in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key: /app/cert.pem + # Configure mTLS client certificate. Absolute path to certificate file. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. Only applicable when .protocol is grpc and .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # If omitted or null, false is used. + insecure: false + - # Configure a simple log record processor. + simple: + # Configure exporter. + exporter: + # Configure exporter to be console. + console: + # Configure log record limits. See also attribute_limits. + limits: + # Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. + # If omitted or null, there is no limit. + attribute_value_length_limit: 4096 + # Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. + # If omitted or null, 128 is used. + attribute_count_limit: 128 # Configure meter provider. +# If omitted, a noop meter provider is used. meter_provider: - # Configure metric readers. - readers: - # Configure a periodic metric reader. - - periodic: - # Configure delay interval (in milliseconds) between start of two consecutive exports. - # - # Environment variable: OTEL_METRIC_EXPORT_INTERVAL - interval: 5000 - # Configure maximum allowed time (in milliseconds) to export data. - # - # Environment variable: OTEL_METRIC_EXPORT_TIMEOUT - timeout: 30000 - # Configure exporter. - # - # Environment variable: OTEL_METRICS_EXPORTER - exporter: - # Configure exporter to be OTLP. - otlp: - # Configure protocol. - # - # Environment variable: OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_METRICS_PROTOCOL - protocol: http/protobuf - # Configure endpoint. - # - # Environment variable: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT - endpoint: http://localhost:4318 - # Configure certificate. - # - # Environment variable: OTEL_EXPORTER_OTLP_CERTIFICATE, OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE - certificate: /app/cert.pem - # Configure mTLS private client key. - # - # Environment variable: OTEL_EXPORTER_OTLP_CLIENT_KEY, OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY - client_key: /app/cert.pem - # Configure mTLS client certificate. - # - # Environment variable: OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE - client_certificate: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - headers_list: "api-key=1234" - # Configure compression. - # - # Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_METRICS_COMPRESSION - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # - # Environment variable: OTEL_EXPORTER_OTLP_TIMEOUT, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT - timeout: 10000 - # Configure temporality preference. - # - # Environment variable: OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE - temporality_preference: delta - # Configure a periodic metric reader. - - periodic: - # Configure exporter. - exporter: - # Configure exporter to be console. - console: {} - # Configure views. Each view has a selector which determines the instrument(s) it applies to, and a configuration for the resulting stream(s). - views: - # Configure a view. - - selector: - # Configure instrument name selection criteria. - instrument_name: my-instrument - # Configure instrument type selection criteria. - instrument_type: histogram - # Configure the instrument unit selection criteria. - unit: ms - # Configure meter name selection criteria. - meter_name: my-meter - # Configure meter version selection criteria. - meter_version: 1.0.0 - # Configure meter schema url selection criteria. - meter_schema_url: https://opentelemetry.io/schemas/1.16.0 - # Configure stream. - stream: - # Configure metric name of the resulting stream(s). - name: new_instrument_name - # Configure metric description of the resulting stream(s). - description: new_description - # Configure aggregation of the resulting stream(s). Known values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. - aggregation: ~ - # Configure attribute keys retained in the resulting stream(s). - attribute_keys: - - key1 - - key2 - + # Configure metric readers. + readers: + - # Configure a pull based metric reader. + pull: + # Configure exporter. + exporter: + # Configure exporter to be prometheus. + prometheus: + # Configure host. + # If omitted or null, localhost is used. + host: localhost + # Configure port. + # If omitted or null, 9464 is used. + port: 9464 + # Configure Prometheus Exporter to produce metrics without a unit suffix or UNIT metadata. + # If omitted or null, false is used. + without_units: false + # Configure Prometheus Exporter to produce metrics without a type suffix. + # If omitted or null, false is used. + without_type_suffix: false + # Configure Prometheus Exporter to produce metrics without a scope info metric. + # If omitted or null, false is used. + without_scope_info: false + # Configure Prometheus Exporter to add resource attributes as metrics attributes. + with_resource_constant_labels: + # Configure resource attributes to be included. + # Attribute keys from resources are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, no resource attributes are included. + included: + - "service*" + # Configure resource attributes to be excluded. Applies after .with_resource_constant_labels.included (i.e. excluded has higher priority than included). + # Attribute keys from resources are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, .included resource attributes are included. + excluded: + - "service.attr1" + # Configure metric producers. + producers: + - # Configure metric producer to be opencensus. + opencensus: + - # Configure a periodic metric reader. + periodic: + # Configure delay interval (in milliseconds) between start of two consecutive exports. + # If omitted or null, 60000 is used. + interval: 60000 + # Configure maximum allowed time (in milliseconds) to export data. + # If omitted or null, 30000 is used. + timeout: 30000 + # Configure exporter. + exporter: + # Configure exporter to be OTLP. + otlp: + # Configure protocol. Values include: http/protobuf, http/json, grpc. + protocol: http/protobuf + # Configure endpoint. + # If .protocol is http/protobuf or http/json, the signal specific path must be included (i.e. http://localhost:4318/v1/{signal}). If .protocol is grpc, a path should not be included (i.e. http://localhost:4317). + endpoint: http://localhost:4318/v1/metrics + # Configure certificate. Absolute path to certificate file. + # If omitted or null, system default certificate verification is used for secure connections. + certificate: /app/cert.pem + # Configure mTLS private client key. Absolute path to client key in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key: /app/cert.pem + # Configure mTLS client certificate. Absolute path to certificate file. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. Only applicable when .protocol is grpc and .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # If omitted or null, false is used. + insecure: false + # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, cumulative is used. + temporality_preference: delta + # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, explicit_bucket_histogram is used. + default_histogram_aggregation: base2_exponential_bucket_histogram + # Configure metric producers. + producers: + - # Configure metric producer to be prometheus. + prometheus: + - # Configure a periodic metric reader. + periodic: + # Configure exporter. + exporter: + # Configure exporter to be console. + console: + # Configure views. Each view has a selector which determines the instrument(s) it applies to, and a configuration for the resulting stream(s). + views: + - # Configure view selector. Selection criteria is additive as described in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#instrument-selection-criteria. + selector: + # Configure instrument name selection criteria. + # If omitted or null, all instrument names match. + instrument_name: my-instrument + # Configure instrument type selection criteria. + # If omitted or null, all instrument types match. + instrument_type: histogram + # Configure the instrument unit selection criteria. + # If omitted or null, all instrument units match. + unit: ms + # Configure meter name selection criteria. + # If omitted or null, all meter names match. + meter_name: my-meter + # Configure meter version selection criteria. + # If omitted or null, all meter versions match. + meter_version: 1.0.0 + # Configure meter schema url selection criteria. + # If omitted or null, all meter schema URLs match. + meter_schema_url: https://opentelemetry.io/schemas/1.16.0 + # Configure view stream. + stream: + # Configure metric name of the resulting stream(s). + # If omitted or null, the instrument's original name is used. + name: new_instrument_name + # Configure metric description of the resulting stream(s). + # If omitted or null, the instrument's origin description is used. + description: new_description + # Configure aggregation of the resulting stream(s). Values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#aggregation. + # If omitted, default is used. + aggregation: + # Configure aggregation to be explicit_bucket_histogram. + explicit_bucket_histogram: + # Configure bucket boundaries. + # If omitted, [0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000] is used. + boundaries: + [ + 0.0, + 5.0, + 10.0, + 25.0, + 50.0, + 75.0, + 100.0, + 250.0, + 500.0, + 750.0, + 1000.0, + 2500.0, + 5000.0, + 7500.0, + 10000.0 + ] + # Configure record min and max. + # If omitted or null, true is used. + record_min_max: true + # Configure attribute keys retained in the resulting stream(s). + attribute_keys: + # Configure list of attribute keys to include in the resulting stream(s). All other attributes are dropped. + # If omitted, all attributes are included. + included: + - key1 + - key2 + # Configure list of attribute keys to exclude from the resulting stream(s). Applies after .attribute_keys.included (i.e. excluded has higher priority than included). + # If omitted, .attribute_keys.included are included. + excluded: + - key3 + # Configure the exemplar filter. Values include: trace_based, always_on, always_off. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration. + # If omitted or null, trace_based is used. + exemplar_filter: trace_based # Configure text map context propagators. -# -# Environment variable: OTEL_PROPAGATORS +# If omitted, tracecontext and baggage are used. propagator: - composite: [tracecontext, baggage, b3, b3multi, jaeger] - + # Configure the set of propagators to include in the composite text map propagator. Built-in values include: tracecontext, baggage, b3, b3multi, jaeger, none. Known third party values include: xray, ottrace. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration. + composite: [ tracecontext, baggage, b3, b3multi, jaeger, xray, ottrace ] # Configure tracer provider. +# If omitted, a noop tracer provider is used. tracer_provider: - # Configure span processors. - processors: - # Configure a batch span processor. - - batch: - # Configure delay interval (in milliseconds) between two consecutive exports. - # - # Environment variable: OTEL_BSP_SCHEDULE_DELAY - schedule_delay: 5000 - # Configure maximum allowed time (in milliseconds) to export data. - # - # Environment variable: OTEL_BSP_EXPORT_TIMEOUT - export_timeout: 30000 - # Configure maximum queue size. - # - # Environment variable: OTEL_BSP_MAX_QUEUE_SIZE - max_queue_size: 2048 - # Configure maximum batch size. - # - # Environment variable: OTEL_BSP_MAX_EXPORT_BATCH_SIZE - max_export_batch_size: 512 - # Configure exporter. - # - # Environment variable: OTEL_TRACES_EXPORTER - exporter: - # Configure exporter to be OTLP. - otlp: - # Configure protocol. - # - # Environment variable: OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_TRACES_PROTOCOL - protocol: http/protobuf - # Configure endpoint. - # - # Environment variable: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT - endpoint: http://localhost:4318 - # Configure certificate. - # - # Environment variable: OTEL_EXPORTER_OTLP_CERTIFICATE, OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE - certificate: /app/cert.pem - # Configure mTLS private client key. - # - # Environment variable: OTEL_EXPORTER_OTLP_CLIENT_KEY, OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY - client_key: /app/cert.pem - # Configure mTLS client certificate. - # - # Environment variable: OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE - client_certificate: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - headers_list: "api-key=1234" - # Configure compression. - # - # Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_TRACES_COMPRESSION - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # - # Environment variable: OTEL_EXPORTER_OTLP_TIMEOUT, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT - timeout: 10000 - # Configure a batch span processor. - - batch: - # Configure exporter. - # - # Environment variable: OTEL_TRACES_EXPORTER - exporter: - # Configure exporter to be zipkin. - zipkin: - # Configure endpoint. - # - # Environment variable: OTEL_EXPORTER_ZIPKIN_ENDPOINT - endpoint: http://localhost:9411/api/v2/spans - # Configure max time (in milliseconds) to wait for each export. - # - # Environment variable: OTEL_EXPORTER_ZIPKIN_TIMEOUT - timeout: 10000 - # Configure a simple span processor. - - simple: - # Configure exporter. - exporter: - # Configure exporter to be console. - console: {} - # Configure span limits. See also attribute_limits. - limits: - # Configure max span attribute value size. Overrides attribute_limits.attribute_value_length_limit. - # - # Environment variable: OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT - attribute_value_length_limit: 4096 - # Configure max span attribute count. Overrides attribute_limits.attribute_count_limit. - # - # Environment variable: OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT - attribute_count_limit: 128 - # Configure max span event count. - # - # Environment variable: OTEL_SPAN_EVENT_COUNT_LIMIT - event_count_limit: 128 - # Configure max span link count. - # - # Environment variable: OTEL_SPAN_LINK_COUNT_LIMIT - link_count_limit: 128 - # Configure max attributes per span event. - # - # Environment variable: OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT - event_attribute_count_limit: 128 - # Configure max attributes per span link. - # - # Environment variable: OTEL_LINK_ATTRIBUTE_COUNT_LIMIT - link_attribute_count_limit: 128 - # Configure the sampler. - sampler: - # Configure sampler to be parent_based. Known values include: always_off, always_on, jaeger_remote, parent_based, trace_id_ratio_based. - # - # Environment variable: OTEL_TRACES_SAMPLER=parentbased_* - parent_based: - # Configure root sampler. - # - # Environment variable: OTEL_TRACES_SAMPLER=parentbased_traceidratio - root: - # Configure sampler to be trace_id_ratio_based. - trace_id_ratio_based: - # Configure trace_id_ratio. - # - # Environment variable: OTEL_TRACES_SAMPLER_ARG=traceidratio=0.0001 - ratio: 0.0001 - # Configure remote_parent_sampled sampler. - remote_parent_sampled: - # Configure sampler to be always_on. - always_on: {} - # Configure remote_parent_not_sampled sampler. - remote_parent_not_sampled: - # Configure sampler to be always_off. - always_off: {} - # Configure local_parent_sampled sampler. - local_parent_sampled: - # Configure sampler to be always_on. - always_on: {} - # Configure local_parent_not_sampled sampler. - local_parent_not_sampled: - # Configure sampler to be always_off. - always_off: {} - + # Configure span processors. + processors: + - # Configure a batch span processor. + batch: + # Configure delay interval (in milliseconds) between two consecutive exports. + # If omitted or null, 5000 is used. + schedule_delay: 5000 + # Configure maximum allowed time (in milliseconds) to export data. + # If omitted or null, 30000 is used. + export_timeout: 30000 + # Configure maximum queue size. + # If omitted or null, 2048 is used. + max_queue_size: 2048 + # Configure maximum batch size. + # If omitted or null, 512 is used. + max_export_batch_size: 512 + # Configure exporter. + exporter: + # Configure exporter to be OTLP. + otlp: + # Configure protocol. Values include: http/protobuf, http/json, grpc. + protocol: http/protobuf + # Configure endpoint. + # If .protocol is http/protobuf or http/json, the signal specific path must be included (i.e. http://localhost:4318/v1/{signal}). If .protocol is grpc, a path should not be included (i.e. http://localhost:4317). + endpoint: http://localhost:4318/v1/traces + # Configure certificate. Absolute path to certificate file. + # If omitted or null, system default certificate verification is used for secure connections. + certificate: /app/cert.pem + # Configure mTLS private client key. Absolute path to client key in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key: /app/cert.pem + # Configure mTLS client certificate. Absolute path to certificate file. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. Only applicable when .protocol is grpc and .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # If omitted or null, false is used. + insecure: false + - # Configure a batch span processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be zipkin. + zipkin: + # Configure endpoint. + # If omitted or null, http://localhost:9411/api/v2/spans is used. + endpoint: http://localhost:9411/api/v2/spans + # Configure max time (in milliseconds) to wait for each export. + # If omitted or null, 10000 is used. + timeout: 10000 + - # Configure a simple span processor. + simple: + # Configure exporter. + exporter: + # Configure exporter to be console. + console: + # Configure span limits. See also attribute_limits. + limits: + # Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. + # If omitted or null, there is no limit. + attribute_value_length_limit: 4096 + # Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. + # If omitted or null, 128 is used. + attribute_count_limit: 128 + # Configure max span event count. + # If omitted or null, 128 is used. + event_count_limit: 128 + # Configure max span link count. + # If omitted or null, 128 is used. + link_count_limit: 128 + # Configure max attributes per span event. + # If omitted or null, 128 is used. + event_attribute_count_limit: 128 + # Configure max attributes per span link. + # If omitted or null, 128 is used. + link_attribute_count_limit: 128 + # Configure the sampler. + # If omitted, parent based sampler with a root of always_on is used. + sampler: + # Configure sampler to be parent_based. + parent_based: + # Configure root sampler. + # If omitted or null, always_on is used. + root: + # Configure sampler to be trace_id_ratio_based. + trace_id_ratio_based: + # Configure trace_id_ratio. + # If omitted or null, 1.0 is used. + ratio: 0.0001 + # Configure remote_parent_sampled sampler. + # If omitted or null, always_on is used. + remote_parent_sampled: + # Configure sampler to be always_on. + always_on: + # Configure remote_parent_not_sampled sampler. + # If omitted or null, always_off is used. + remote_parent_not_sampled: + # Configure sampler to be always_off. + always_off: + # Configure local_parent_sampled sampler. + # If omitted or null, always_on is used. + local_parent_sampled: + # Configure sampler to be always_on. + always_on: + # Configure local_parent_not_sampled sampler. + # If omitted or null, always_off is used. + local_parent_not_sampled: + # Configure sampler to be always_off. + always_off: # Configure resource for all signals. +# If omitted, the default resource is used. resource: - # Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. - # Entries must contain .name nand .value, and may optionally include .type, which defaults ot "string" if not set. The value must match the type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. + # Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. + # Entries must contain .name and .value, and may optionally include .type. If an entry's .type omitted or null, string is used. + # The .value's type must match the .type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. + attributes: + - name: service.name + value: unknown_service + - name: string_key + value: value + type: string + - name: bool_key + value: true + type: bool + - name: int_key + value: 1 + type: int + - name: double_key + value: 1.1 + type: double + - name: string_array_key + value: [ "value1", "value2" ] + type: string_array + - name: bool_array_key + value: [ true, false ] + type: bool_array + - name: int_array_key + value: [ 1, 2 ] + type: int_array + - name: double_array_key + value: [ 1.1, 2.2 ] + type: double_array + # Configure resource attributes. Entries have lower priority than entries from .resource.attributes. + # The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration for details. + # If omitted or null, no resource attributes are added. + attributes_list: "service.namespace=my-namespace,service.version=1.0.0" + # Configure resource detectors. + detectors: + # Configure attributes provided by resource detectors. attributes: - - name: service.name - value: unknown_service - - name: string_key - value: value - type: string - - name: bool_key - value: true - type: bool - - name: int_key - value: 1 - type: int - - name: double_key - value: 1.1 - type: double - - name: string_array_key - value: [ "value1", "value2" ] - type: string_array - - name: bool_array_key - value: [ true, false ] - type: bool_array - - name: int_array_key - value: [ 1, 2 ] - type: int_array - - name: double_array_key - value: [ 1.1, 2.2 ] - type: double_array - # Configure resource attributes. Entries have lower priority than entries from .resource.attributes. - # The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration for details. - attributes_list: "service.namespace=my-namespace,service.version=1.0.0" - # Configure the resource schema URL. - schema_url: https://opentelemetry.io/schemas/1.27.0 - + # Configure list of attribute key patterns to include from resource detectors. + # Attribute keys from resource detectors are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, all attributes are included. + included: + - process.* + # Configure list of attribute key patterns to exclude from resource detectors. Applies after .resource.detectors.attributes.included (i.e. excluded has higher priority than included). + # Attribute keys from resource detectors are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, .included attributes are included. + excluded: + - process.command_args + # Configure resource schema URL. + # If omitted or null, no schema URL is used. + schema_url: https://opentelemetry.io/schemas/1.27.0 # Configure instrumentation. instrumentation: # Configure general SemConv options that may apply to multiple languages and instrumentations. - # # Instrumenation may merge general config options with the language specific configuration at .instrumentation.. general: # Configure instrumentations following the peer semantic conventions. - # # See peer semantic conventions: https://opentelemetry.io/docs/specs/semconv/attributes-registry/peer/ peer: # Configure the service mapping for instrumentations following peer.service semantic conventions. - # # Each entry is a key value pair where "peer" defines the IP address and "service" defines the corresponding logical name of the service. - # # See peer.service semantic conventions: https://opentelemetry.io/docs/specs/semconv/general/attributes/#general-remote-service-attributes service_mapping: - peer: 1.2.3.4 @@ -402,7 +473,6 @@ instrumentation: - peer: 2.3.4.5 service: BarService # Configure instrumentations following the http semantic conventions. - # # See http semantic conventions: https://opentelemetry.io/docs/specs/semconv/http/ http: # Configure instrumentations following the http client semantic conventions. @@ -425,10 +495,6 @@ instrumentation: response_captured_headers: - Content-Type - Content-Encoding - # Configure language-specific instrumentation libraries. - # - # Keys may refer to instrumentation libraries or collections of related configuration. Because there is no central schema defining the keys or their contents, instrumentation must carefully document their schema and avoid key collisions with other instrumentations. - # # Configure C++ language-specific instrumentation libraries. cpp: # Configure the instrumentation corresponding to key "example". diff --git a/tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php b/tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php index c018ade61..5f797ec05 100644 --- a/tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php +++ b/tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php @@ -21,6 +21,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; use Symfony\Component\Yaml\Yaml; #[CoversClass(ConfigurationFactory::class)] @@ -56,7 +57,7 @@ public function createPlugin(array $properties, Context $context): mixed /** * @psalm-suppress UndefinedInterfaceMethod,PossiblyNullReference */ - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { $node = new ArrayNodeDefinition('env_substitution'); /** @phpstan-ignore-next-line */ @@ -126,7 +127,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit combo_string_key: foo value 1.1 # Interpreted as type string, tag URI tag:yaml.org,2002:str string_key_with_default: fallback # Interpreted as type string, tag URI tag:yaml.org,2002:str # undefined_key removed as null is treated as unset - # undefined_key: # Interpreted as type null, tag URI tag:yaml.org,2002:null + undefined_key: # Interpreted as type null, tag URI tag:yaml.org,2002:null ${STRING_VALUE}: value # Interpreted as type string, tag URI tag:yaml.org,2002:str YAML), self::getPropertiesFromPlugin($parsed), @@ -166,16 +167,23 @@ public function test_env_substitution_non_string(): void $this->assertSame(2048, self::getPropertiesFromPlugin($parsed)['attribute_limits']['attribute_value_length_limit']); } - public function test_treat_null_as_unset(): void + /** + * If a property has a default value defined (i.e. is _not_ required) and is + * missing or present but null, Create MUST ensure the SDK component is configured + * with the default value. + */ + #[BackupGlobals(true)] + public function test_env_substitution_missing_value(): void { + unset($_SERVER['OTEL_ATTRIBUTE_COUNT_LIMIT']); $parsed = self::factory()->process([[ 'file_format' => '0.1', 'attribute_limits' => [ - 'attribute_count_limit' => null, + 'attribute_count_limit' => '${OTEL_ATTRIBUTE_COUNT_LIMIT}', ], ]]); - $this->assertInstanceOf(ComponentPlugin::class, $parsed); + $this->assertNull(self::getPropertiesFromPlugin($parsed)['attribute_limits']['attribute_value_length_limit']); $this->assertSame(128, self::getPropertiesFromPlugin($parsed)['attribute_limits']['attribute_count_limit']); } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php index dd6cab1e5..312cc7d16 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class LogRecordExporterConsole implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('console'); + return $builder->arrayNode('console'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterOtlp.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterOtlp.php index 3451f12fa..aded5c00b 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterOtlp.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterOtlp.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Config\SDK\Configuration\Validation; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class LogRecordExporterOtlp implements ComponentProvider { @@ -31,9 +32,9 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('otlp'); + $node = $builder->arrayNode('otlp'); $node ->children() ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php index 507bbec4b..854c67e18 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php @@ -12,6 +12,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class LogRecordProcessorBatch implements ComponentProvider { @@ -29,9 +30,9 @@ public function createPlugin(array $properties, Context $context): LogRecordProc throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('batch'); + $node = $builder->arrayNode('batch'); $node ->children() ->integerNode('schedule_delay')->min(0)->defaultValue(5000)->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php index ebd09bda4..5894e9dab 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php @@ -12,6 +12,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class LogRecordProcessorSimple implements ComponentProvider { @@ -25,9 +26,9 @@ public function createPlugin(array $properties, Context $context): LogRecordProc throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('simple'); + $node = $builder->arrayNode('simple'); $node ->children() ->append($registry->component('exporter', LogRecordExporter::class)->isRequired()) diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php index dd79b0d36..d682d8755 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class AggregationResolverDefault implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): AggregationRe throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('default'); + return $builder->arrayNode('default'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDrop.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDrop.php index 47f8ecd0f..7fe06b817 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDrop.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDrop.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class AggregationResolverDrop implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): AggregationRe throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('drop'); + return $builder->arrayNode('drop'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverExplicitBucketHistogram.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverExplicitBucketHistogram.php index 46c6dea60..39c5d30be 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverExplicitBucketHistogram.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverExplicitBucketHistogram.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class AggregationResolverExplicitBucketHistogram implements ComponentProvider { @@ -25,9 +26,9 @@ public function createPlugin(array $properties, Context $context): AggregationRe throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('explicit_bucket_histogram'); + $node = $builder->arrayNode('explicit_bucket_histogram'); $node ->children() ->arrayNode('boundaries') diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php index 9584331b2..dd02d469b 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class AggregationResolverLastValue implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): AggregationRe throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('last_value'); + return $builder->arrayNode('last_value'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverSum.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverSum.php index cf35357dd..5b200a938 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverSum.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverSum.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class AggregationResolverSum implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): AggregationRe throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('sum'); + return $builder->arrayNode('sum'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterConsole.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterConsole.php index 9fa404426..b62db3e4b 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterConsole.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterConsole.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class MetricExporterConsole implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): MetricExporte throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('console'); + return $builder->arrayNode('console'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterOtlp.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterOtlp.php index f710b9894..b900177ac 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterOtlp.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterOtlp.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Config\SDK\Configuration\Validation; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class MetricExporterOtlp implements ComponentProvider { @@ -33,9 +34,9 @@ public function createPlugin(array $properties, Context $context): MetricExporte throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('otlp'); + $node = $builder->arrayNode('otlp'); $node ->children() ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php index d146669cc..2f7181b97 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Config\SDK\Configuration\Validation; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class MetricExporterPrometheus implements ComponentProvider { @@ -28,9 +29,9 @@ public function createPlugin(array $properties, Context $context): MetricExporte throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('prometheus'); + $node = $builder->arrayNode('prometheus'); $node ->children() ->scalarNode('host')->defaultValue('localhost')->validate()->always(Validation::ensureString())->end()->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php index 0086bf730..1486b918a 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php @@ -12,6 +12,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class MetricReaderPeriodic implements ComponentProvider { @@ -27,9 +28,9 @@ public function createPlugin(array $properties, Context $context): MetricReader throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('periodic'); + $node = $builder->arrayNode('periodic'); $node ->children() ->integerNode('interval')->min(0)->defaultValue(5000)->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php index 115f13d36..c4258c4ad 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php @@ -12,6 +12,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class MetricReaderPull implements ComponentProvider { @@ -25,9 +26,9 @@ public function createPlugin(array $properties, Context $context): MetricReader throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('pull'); + $node = $builder->arrayNode('pull'); $node ->children() ->append($registry->component('exporter', MetricExporter::class)->isRequired()) diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php index fd951ccf6..166548d98 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php @@ -18,6 +18,7 @@ use OpenTelemetry\Config\SDK\Configuration\Validation; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class OpenTelemetryConfiguration implements ComponentProvider { @@ -79,9 +80,9 @@ public function createPlugin(array $properties, Context $context): Configuration throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('open_telemetry'); + $node = $builder->arrayNode('open_telemetry'); $node ->addDefaultsIfNotSet() ->ignoreExtraKeys() @@ -93,20 +94,20 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->validate()->ifNotInArray(['0.1'])->thenInvalid('unsupported version')->end() ->end() ->booleanNode('disabled')->defaultFalse()->end() - ->append($this->getResourceConfig()) - ->append($this->getAttributeLimitsConfig()) + ->append($this->getResourceConfig($builder)) + ->append($this->getAttributeLimitsConfig($builder)) ->append($registry->component('propagator', TextMapPropagatorInterface::class)) - ->append($this->getTracerProviderConfig($registry)) - ->append($this->getMeterProviderConfig($registry)) - ->append($this->getLoggerProviderConfig($registry)) + ->append($this->getTracerProviderConfig($registry, $builder)) + ->append($this->getMeterProviderConfig($registry, $builder)) + ->append($this->getLoggerProviderConfig($registry, $builder)) ->end(); return $node; } - private function getResourceConfig(): ArrayNodeDefinition + private function getResourceConfig(NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('resource'); + $node = $builder->arrayNode('resource'); $node ->addDefaultsIfNotSet() ->children() @@ -119,9 +120,9 @@ private function getResourceConfig(): ArrayNodeDefinition return $node; } - private function getAttributeLimitsConfig(): ArrayNodeDefinition + private function getAttributeLimitsConfig(NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('attribute_limits'); + $node = $builder->arrayNode('attribute_limits'); $node ->addDefaultsIfNotSet() ->children() @@ -132,9 +133,9 @@ private function getAttributeLimitsConfig(): ArrayNodeDefinition return $node; } - private function getTracerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + private function getTracerProviderConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('tracer_provider'); + $node = $builder->arrayNode('tracer_provider'); $node ->addDefaultsIfNotSet() ->children() @@ -150,16 +151,16 @@ private function getTracerProviderConfig(ComponentProviderRegistry $registry): A ->end() ->end() ->append($registry->component('sampler', Sampler::class)) - ->append($registry->componentArrayList('processors', SpanProcessor::class)) + ->append($registry->componentList('processors', SpanProcessor::class)) ->end() ; return $node; } - private function getMeterProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + private function getMeterProviderConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('meter_provider'); + $node = $builder->arrayNode('meter_provider'); $node ->addDefaultsIfNotSet() ->children() @@ -202,16 +203,16 @@ private function getMeterProviderConfig(ComponentProviderRegistry $registry): Ar ->end() ->end() ->end() - ->append($registry->componentArrayList('readers', MetricReader::class)) + ->append($registry->componentList('readers', MetricReader::class)) ->end() ; return $node; } - private function getLoggerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + private function getLoggerProviderConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('logger_provider'); + $node = $builder->arrayNode('logger_provider'); $node ->addDefaultsIfNotSet() ->children() @@ -222,7 +223,7 @@ private function getLoggerProviderConfig(ComponentProviderRegistry $registry): A ->integerNode('attribute_count_limit')->min(0)->defaultNull()->end() ->end() ->end() - ->append($registry->componentArrayList('processors', LogRecordProcessor::class)) + ->append($registry->componentList('processors', LogRecordProcessor::class)) ->end() ; diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php index bc71eddfb..c28403619 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorB3 implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('b3'); + return $builder->arrayNode('b3'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3Multi.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3Multi.php index d0cdfb2a8..9bfa3318e 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3Multi.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3Multi.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorB3Multi implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('b3multi'); + return $builder->arrayNode('b3multi'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorBaggage.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorBaggage.php index 78e42fa4a..4070f9e90 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorBaggage.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorBaggage.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorBaggage implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('baggage'); + return $builder->arrayNode('baggage'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorComposite.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorComposite.php index a35f9f435..43b353ee0 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorComposite.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorComposite.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorComposite implements ComponentProvider { @@ -22,7 +23,7 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { return $registry->componentNames('composite', TextMapPropagatorInterface::class); } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php index c2527079c..fd4cff2d2 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorJaeger implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('jaeger'); + return $builder->arrayNode('jaeger'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorOTTrace.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorOTTrace.php index 0318cb8db..a694f9493 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorOTTrace.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorOTTrace.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorOTTrace implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('ottrace'); + return $builder->arrayNode('ottrace'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorTraceContext.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorTraceContext.php index bf1c5ae67..a9ffaa0e7 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorTraceContext.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorTraceContext.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorTraceContext implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('tracecontext'); + return $builder->arrayNode('tracecontext'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorXRay.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorXRay.php index cce6de82a..1beeabe2b 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorXRay.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorXRay.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class TextMapPropagatorXRay implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('xray'); + return $builder->arrayNode('xray'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOff.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOff.php index d58b1a173..0240fe04a 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOff.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOff.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SamplerAlwaysOff implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): Sampler throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('always_off'); + return $builder->arrayNode('always_off'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOn.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOn.php index ace4f9572..ba218997a 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOn.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOn.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SamplerAlwaysOn implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): Sampler throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('always_on'); + return $builder->arrayNode('always_on'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerParentBased.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerParentBased.php index 213df4c8d..fb449c569 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerParentBased.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerParentBased.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SamplerParentBased implements ComponentProvider { @@ -28,9 +29,9 @@ public function createPlugin(array $properties, Context $context): Sampler throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('parent_based'); + $node = $builder->arrayNode('parent_based'); $node ->children() ->append($registry->component('root', Sampler::class)->isRequired()) diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php index 17fb86acb..310d0840f 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SamplerTraceIdRatioBased implements ComponentProvider { @@ -23,9 +24,9 @@ public function createPlugin(array $properties, Context $context): Sampler throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('trace_id_ratio_based'); + $node = $builder->arrayNode('trace_id_ratio_based'); $node ->children() ->floatNode('ratio')->min(0)->max(1)->isRequired()->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php index 43b09aa4b..cfb606de7 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php @@ -10,6 +10,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SpanExporterConsole implements ComponentProvider { @@ -21,8 +22,8 @@ public function createPlugin(array $properties, Context $context): SpanExporter throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - return new ArrayNodeDefinition('console'); + return $builder->arrayNode('console'); } } diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterOtlp.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterOtlp.php index 227c27beb..a6babfc42 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterOtlp.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterOtlp.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Config\SDK\Configuration\Validation; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SpanExporterOtlp implements ComponentProvider { @@ -31,9 +32,9 @@ public function createPlugin(array $properties, Context $context): SpanExporter throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('otlp'); + $node = $builder->arrayNode('otlp'); $node ->children() ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php index e75944e05..74318b5ef 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php @@ -11,6 +11,7 @@ use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Config\SDK\Configuration\Validation; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SpanExporterZipkin implements ComponentProvider { @@ -25,9 +26,9 @@ public function createPlugin(array $properties, Context $context): SpanExporter throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('zipkin'); + $node = $builder->arrayNode('zipkin'); $node ->children() ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php index 23b13ae39..2deeed548 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php @@ -12,6 +12,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SpanProcessorBatch implements ComponentProvider { @@ -29,9 +30,9 @@ public function createPlugin(array $properties, Context $context): SpanProcessor throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('batch'); + $node = $builder->arrayNode('batch'); $node ->children() ->integerNode('schedule_delay')->min(0)->defaultValue(5000)->end() diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php index 98345980e..02b00b52f 100644 --- a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php @@ -12,6 +12,7 @@ use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeBuilder; final class SpanProcessorSimple implements ComponentProvider { @@ -25,9 +26,9 @@ public function createPlugin(array $properties, Context $context): SpanProcessor throw new BadMethodCallException('not implemented'); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = new ArrayNodeDefinition('simple'); + $node = $builder->arrayNode('simple'); $node ->children() ->append($registry->component('exporter', SpanExporter::class)->isRequired()) diff --git a/tests/Unit/SDK/fixtures/otel-sdk.yaml b/tests/Unit/SDK/fixtures/otel-sdk.yaml index 510810ea1..4adc05b77 100644 --- a/tests/Unit/SDK/fixtures/otel-sdk.yaml +++ b/tests/Unit/SDK/fixtures/otel-sdk.yaml @@ -4,7 +4,12 @@ tracer_provider: processors: - simple: exporter: - console: {} + console: + sampler: + always_off: + +propagator: + composite: [] instrumentation: php: