From 1f30d5f587904323e9fecc59b1908e9566b04025 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Sun, 21 Jan 2024 17:03:56 +0100 Subject: [PATCH 01/15] [Draft] Add configuration model [skip ci] --- composer.json | 12 +- examples/load_config.php | 27 +++ examples/load_config.yaml | 20 ++ .../ComponentProvider/OpenTelemetrySdk.php | 184 ++++++++++++++++++ .../Trace/SamplerAlwaysOff.php | 23 +++ .../Trace/SamplerAlwaysOn.php | 23 +++ .../Trace/SamplerParentBased.php | 50 +++++ .../Trace/SamplerTraceIdRatioBased.php | 34 ++++ .../Trace/SpanExporterConsole.php | 27 +++ .../Trace/SpanExporterOtlp.php | 70 +++++++ .../Trace/SpanExporterZipkin.php | 42 ++++ .../Trace/SpanProcessorBatch.php | 51 +++++ .../Trace/SpanProcessorSimple.php | 36 ++++ src/Config/SDK/Configuration.php | 50 +++++ src/Config/SDK/composer.json | 48 +++++ 15 files changed, 696 insertions(+), 1 deletion(-) create mode 100644 examples/load_config.php create mode 100644 examples/load_config.yaml create mode 100644 src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php create mode 100644 src/Config/SDK/Configuration.php create mode 100644 src/Config/SDK/composer.json diff --git a/composer.json b/composer.json index 79ee954d8..9a9636403 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "require": { "php": "^8.1", "google/protobuf": "^3.22", + "open-telemetry/sdk-configuration": "^1.0-dev", "php-http/discovery": "^1.14", "psr/http-client-implementation": "^1.0", "psr/http-factory-implementation": "^1.0", @@ -18,12 +19,19 @@ "symfony/polyfill-mbstring": "^1.23", "symfony/polyfill-php82": "^1.26" }, + "repositories": [ + { + "type": "path", + "url": "src/Config/SDK" + } + ], "config": { "sort-packages": true, "allow-plugins": { "composer/package-versions-deprecated": true, "php-http/discovery": true, - "symfony/runtime": true + "symfony/runtime": true, + "tbachert/spi": true } }, "authors": [ @@ -35,6 +43,8 @@ "replace": { "open-telemetry/api": "self.version", "open-telemetry/context": "self.version", + "open-telemetry/exporter-otlp": "1.0.x-dev", + "open-telemetry/exporter-zipkin": "1.0.x-dev", "open-telemetry/gen-otlp-protobuf": "self.version", "open-telemetry/sdk": "self.version", "open-telemetry/sdk-contrib": "self.version", diff --git a/examples/load_config.php b/examples/load_config.php new file mode 100644 index 000000000..16a50765a --- /dev/null +++ b/examples/load_config.php @@ -0,0 +1,27 @@ +create() + ->setAutoShutdown(true) + ->build(); + +$tracer = $sdk->getTracerProvider()->getTracer('demo'); +$meter = $sdk->getMeterProvider()->getMeter('demo'); +$logger = $sdk->getLoggerProvider()->getLogger('demo'); + +$tracer->spanBuilder('root')->startSpan()->end(); +$meter->createCounter('cnt')->add(1); + +$eventLogger = new EventLogger($logger, 'my-domain'); +$eventLogger->logEvent('foo', new LogRecord('hello, otel')); + +echo 'Finished!' . PHP_EOL; diff --git a/examples/load_config.yaml b/examples/load_config.yaml new file mode 100644 index 000000000..342a0bc66 --- /dev/null +++ b/examples/load_config.yaml @@ -0,0 +1,20 @@ +file_format: '0.1' + +resource: + attributes: + service.name: opentelemetry-demo + +tracer_provider: + sampler: + parent_based: + root: + always_on: {} + processors: + - simple: + exporter: + console: {} + - batch: + exporter: + otlp: + protocol: http/protobuf + endpoint: http://collector:4318 diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php new file mode 100644 index 000000000..6338d3414 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -0,0 +1,184 @@ +, + * attribute_count_limit: ?int<0, max>, + * }, + * propagator: ?ComponentPlugin, + * tracer_provider: array{ + * limits: array{ + * attribute_value_length_limit: ?int<0, max>, + * attribute_count_limit: ?int<0, max>, + * event_count_limit: ?int<0, max>, + * link_count_limit: ?int<0, max>, + * event_attribute_count_limit: ?int<0, max>, + * link_attribute_count_limit: ?int<0, max>, + * }, + * sampler: ?ComponentPlugin, + * processors: list>, + * }, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SdkBuilder { + $sdkBuilder = new SdkBuilder(); + + $propagator = $properties['propagator']?->create($context) ?? NoopTextMapPropagator::getInstance(); + $sdkBuilder->setPropagator($propagator); + + if ($properties['disabled']) { + return $sdkBuilder; + } + + $resource = ResourceInfoFactory::defaultResource() + ->merge(ResourceInfo::create( + attributes: Attributes::create($properties['resource']['attributes']), + schemaUrl: $properties['resource']['schema_url'], + )); + + $spanProcessors = []; + foreach ($properties['tracer_provider']['processors'] as $processor) { + $spanProcessors[] = $processor->create($context); + } + + $tracerProvider = new TracerProvider( + spanProcessors: $spanProcessors, + sampler: $properties['tracer_provider']['sampler']?->create($context) ?? new ParentBased(new AlwaysOnSampler()), + resource: $resource, + spanLimits: new SpanLimits( + attributesFactory: Attributes::factory( + attributeCountLimit: $properties['tracer_provider']['limits']['attribute_count_limit'] + ?? $properties['attribute_limits']['attribute_count_limit'], + attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] + ?? $properties['attribute_limits']['attribute_value_length_limit'], + ), + eventAttributesFactory: Attributes::factory( + attributeCountLimit: $properties['tracer_provider']['limits']['event_attribute_count_limit'] + ?? $properties['tracer_provider']['limits']['attribute_count_limit'] + ?? $properties['attribute_limits']['attribute_count_limit'], + attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] + ?? $properties['attribute_limits']['attribute_value_length_limit'], + ), + linkAttributesFactory: Attributes::factory( + attributeCountLimit: $properties['tracer_provider']['limits']['link_attribute_count_limit'] + ?? $properties['tracer_provider']['limits']['attribute_count_limit'] + ?? $properties['attribute_limits']['attribute_count_limit'], + attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] + ?? $properties['attribute_limits']['attribute_value_length_limit'], + ), + eventCountLimit: $properties['tracer_provider']['limits']['event_count_limit'], + linkCountLimit: $properties['tracer_provider']['limits']['link_count_limit'], + ), + ); + + $sdkBuilder->setTracerProvider($tracerProvider); + + return $sdkBuilder; + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('open_telemetry'); + $node + ->addDefaultsIfNotSet() + ->ignoreExtraKeys() + ->children() + ->scalarNode('file_format') + ->isRequired() + ->example('0.1') + ->validate()->always(Validation::ensureString())->end() + ->validate()->ifNotInArray(['0.1'])->thenInvalid('unsupported version')->end() + ->end() + ->booleanNode('disabled')->defaultFalse()->end() + ->append($this->getResourceConfig()) + ->append($this->getAttributeLimitsConfig()) + ->append($registry->component('propagator', TextMapPropagatorInterface::class)) + ->append($this->getTracerProviderConfig($registry)) + # ->append($this->getMeterProviderConfig($registry)) + # ->append($this->getLoggerProviderConfig($registry)) + ->end(); + + return $node; + } + + private function getResourceConfig(): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('resource'); + $node + ->addDefaultsIfNotSet() + ->children() + ->arrayNode('attributes') + ->variablePrototype()->end() + ->end() + ->scalarNode('schema_url')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->end(); + + return $node; + } + + private function getAttributeLimitsConfig(): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('attribute_limits'); + $node + ->addDefaultsIfNotSet() + ->children() + ->integerNode('attribute_value_length_limit')->min(0)->defaultValue(4096)->end() + ->integerNode('attribute_count_limit')->min(0)->defaultValue(128)->end() + ->end(); + + return $node; + } + + private function getTracerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('tracer_provider'); + $node + ->addDefaultsIfNotSet() + ->children() + ->arrayNode('limits') + ->addDefaultsIfNotSet() + ->children() + ->integerNode('attribute_value_length_limit')->min(0)->defaultNull()->end() + ->integerNode('attribute_count_limit')->min(0)->defaultNull()->end() + ->integerNode('event_count_limit')->min(0)->defaultValue(128)->end() + ->integerNode('link_count_limit')->min(0)->defaultValue(128)->end() + ->integerNode('event_attribute_count_limit')->min(0)->defaultNull()->end() + ->integerNode('link_attribute_count_limit')->min(0)->defaultNull()->end() + ->end() + ->end() + ->append($registry->component('sampler', SamplerInterface::class)) + ->append($registry->componentList('processors', SpanProcessorInterface::class)) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php new file mode 100644 index 000000000..1a7e3ea7b --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php @@ -0,0 +1,23 @@ +, + * remote_parent_sampled: ?ComponentPlugin, + * remote_parent_not_sampled: ?ComponentPlugin, + * local_parent_sampled: ?ComponentPlugin, + * local_parent_not_sampled: ?ComponentPlugin, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SamplerInterface { + return new ParentBased( + root: $properties['root']->create($context), + remoteParentSampler: $properties['remote_parent_sampled']?->create($context) ?? new AlwaysOnSampler(), + remoteParentNotSampler: $properties['remote_parent_not_sampled']?->create($context) ?? new AlwaysOffSampler(), + localParentSampler: $properties['local_parent_sampled']?->create($context) ?? new AlwaysOnSampler(), + localParentNotSampler: $properties['local_parent_not_sampled']?->create($context) ?? new AlwaysOffSampler(), + ); + } + + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('parent_based'); + $node + ->children() + ->append($registry->component('root', SamplerInterface::class)->isRequired()) + ->append($registry->component('remote_parent_sampled', SamplerInterface::class)) + ->append($registry->component('remote_parent_not_sampled', SamplerInterface::class)) + ->append($registry->component('local_parent_sampled', SamplerInterface::class)) + ->append($registry->component('local_parent_not_sampled', SamplerInterface::class)) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php new file mode 100644 index 000000000..7bf428e67 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php @@ -0,0 +1,34 @@ +children() + ->floatNode('ratio')->min(0)->max(1)->isRequired()->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php new file mode 100644 index 000000000..96fb67524 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php @@ -0,0 +1,27 @@ +create( + endpoint: 'php://stdout', + contentType: 'application/json', + )); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + return new ArrayNodeDefinition('console'); + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php new file mode 100644 index 000000000..4df9f248e --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php @@ -0,0 +1,70 @@ +, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanExporterInterface { + $protocol = $properties['protocol']; + $path = str_starts_with($protocol, 'grpc/') + ? OtlpUtil::method(Signals::TRACE) + : '/v1/traces'; + + return new SpanExporter(Registry::transportFactory($protocol)->create( + endpoint: $properties['endpoint'] . $path, + contentType: Protocols::contentType($protocol), + headers: $properties['headers'], + compression: $properties['compression'], + timeout: $properties['timeout'], + cacert: $properties['certificate'], + cert: $properties['client_certificate'], + key: $properties['client_certificate'], + )); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('otlp'); + $node + ->children() + ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() + ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->arrayNode('headers') + ->scalarPrototype()->end() + ->end() + ->enumNode('compression')->values(['gzip'])->defaultNull()->end() + ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php new file mode 100644 index 000000000..39cff4825 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php @@ -0,0 +1,42 @@ +, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanExporterInterface { + return new Zipkin\Exporter(Registry::transportFactory('http')->create( + endpoint: $properties['endpoint'], + contentType: 'application/json', + timeout: $properties['timeout'], + )); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('zipkin'); + $node + ->children() + ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php new file mode 100644 index 000000000..e7cb90f33 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php @@ -0,0 +1,51 @@ +, + * export_timeout: int<0, max>, + * max_queue_size: int<0, max>, + * max_export_batch_size: int<0, max>, + * exporter: ComponentPlugin, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanProcessorInterface { + return new BatchSpanProcessor( + exporter: $properties['exporter']->create($context), + clock: ClockFactory::getDefault(), + maxQueueSize: $properties['max_queue_size'], + scheduledDelayMillis: $properties['schedule_delay'], + exportTimeoutMillis: $properties['export_timeout'], + maxExportBatchSize: $properties['max_export_batch_size'], + meterProvider: $context->meterProvider, + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('batch'); + $node + ->children() + ->integerNode('schedule_delay')->min(0)->defaultValue(5000)->end() + ->integerNode('export_timeout')->min(0)->defaultValue(30000)->end() + ->integerNode('max_queue_size')->min(0)->defaultValue(2048)->end() + ->integerNode('max_export_batch_size')->min(0)->defaultValue(512)->end() + ->append($registry->component('exporter', SpanExporterInterface::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php new file mode 100644 index 000000000..991753042 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php @@ -0,0 +1,36 @@ +, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanProcessorInterface { + return new SimpleSpanProcessor( + exporter: $properties['exporter']->create($context), + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('simple'); + $node + ->children() + ->append($registry->component('exporter', SpanExporterInterface::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/Configuration.php b/src/Config/SDK/Configuration.php new file mode 100644 index 000000000..f5746357a --- /dev/null +++ b/src/Config/SDK/Configuration.php @@ -0,0 +1,50 @@ + $sdkPlugin + */ + private function __construct( + private readonly ComponentPlugin $sdkPlugin, + ) {} + + public function create(Context $context = new Context()): SdkBuilder { + return $this->sdkPlugin->create($context); + } + + public static function parseFile( + string|array $file, + ?string $cacheFile = null, + bool $debug = true, + ): Configuration { + return new self(self::factory()->parseFile($file, $cacheFile, $debug)); + } + + /** + * @return ConfigurationFactory + */ + private static function factory(): ConfigurationFactory { + static $factory; + return $factory ??= new ConfigurationFactory( + ServiceLoader::load(ComponentProvider::class), + new OpenTelemetrySdk(), + new EnvSourceReader([ + new ArrayEnvSource($_SERVER), + new PhpIniEnvSource(), + ]), + ); + } +} diff --git a/src/Config/SDK/composer.json b/src/Config/SDK/composer.json new file mode 100644 index 000000000..829d3a100 --- /dev/null +++ b/src/Config/SDK/composer.json @@ -0,0 +1,48 @@ +{ + "name": "open-telemetry/sdk-configuration", + "description": "SDK configuration for OpenTelemetry PHP.", + "keywords": ["opentelemetry", "otel", "sdk", "configuration"], + "type": "library", + "support": { + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php", + "docs": "https://opentelemetry.io/docs/php", + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V" + }, + "license": "Apache-2.0", + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "require": { + "php": "^8.1", + "open-telemetry/sdk": "^1.0", + "tbachert/otel-sdk-configuration": "^0.1", + "tbachert/spi": "^0.2" + }, + "autoload": { + "psr-4": { + "OpenTelemetry\\Config\\SDK\\": "" + } + }, + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + }, + "spi": { + "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerAlwaysOff", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerAlwaysOn", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerParentBased", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerTraceIdRatioBased", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterConsole", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterZipkin", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorBatch", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorSimple" + ] + } + } +} From 593dfbca06f8ebd0e72beb4239c8dd2214f1bd81 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Tue, 5 Mar 2024 19:48:32 +0100 Subject: [PATCH 02/15] [Draft] Add metrics and logs configuration model [skip ci] --- examples/load_config.yaml | 28 ++- .../Logs/LogRecordExporterConsole.php | 27 +++ .../Logs/LogRecordExporterOtlp.php | 66 ++++++ .../Logs/LogRecordProcessorBatch.php | 53 +++++ .../Logs/LogRecordProcessorSimple.php | 36 +++ .../Metrics/AggregationResolverDefault.php | 26 +++ .../Metrics/MetricExporterConsole.php | 27 +++ .../Metrics/MetricExporterOtlp.php | 83 +++++++ .../Metrics/MetricReaderPeriodic.php | 40 ++++ .../ComponentProvider/OpenTelemetrySdk.php | 219 +++++++++++++++++- .../Propagator/TextMapPropagatorB3.php | 25 ++ .../Propagator/TextMapPropagatorB3Multi.php | 25 ++ .../Propagator/TextMapPropagatorBaggage.php | 23 ++ .../Propagator/TextMapPropagatorComposite.php | 29 +++ .../Propagator/TextMapPropagatorJaeger.php | 25 ++ .../TextMapPropagatorTraceContext.php | 23 ++ .../Trace/SpanExporterOtlp.php | 7 +- src/Config/SDK/composer.json | 19 +- src/Contrib/Otlp/OtlpUtil.php | 12 + 19 files changed, 778 insertions(+), 15 deletions(-) create mode 100644 src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php create mode 100644 src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php create mode 100644 src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php create mode 100644 src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php create mode 100644 src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php create mode 100644 src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php create mode 100644 src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php create mode 100644 src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php create mode 100644 src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php create mode 100644 src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php create mode 100644 src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php create mode 100644 src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php create mode 100644 src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php create mode 100644 src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php diff --git a/examples/load_config.yaml b/examples/load_config.yaml index 342a0bc66..9e1901de8 100644 --- a/examples/load_config.yaml +++ b/examples/load_config.yaml @@ -4,6 +4,14 @@ resource: attributes: service.name: opentelemetry-demo +propagators: + composite: [ tracecontext, baggage ] + +exporters: + otlp: &otlp-exporter + protocol: http/protobuf + endpoint: http://collector:4318 + tracer_provider: sampler: parent_based: @@ -14,7 +22,23 @@ tracer_provider: exporter: console: {} - batch: + exporter: + otlp: *otlp-exporter +meter_provider: + readers: + - periodic: + exporter: + console: {} + - periodic: exporter: otlp: - protocol: http/protobuf - endpoint: http://collector:4318 + <<: *otlp-exporter + temporality_preference: lowmemory +logger_provider: + processors: + - simple: + exporter: + console: {} + - batch: + exporter: + otlp: *otlp-exporter diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php new file mode 100644 index 000000000..2de8afb33 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php @@ -0,0 +1,27 @@ +create( + endpoint: 'php://stdout', + contentType: 'application/json', + )); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + return new ArrayNodeDefinition('console'); + } +} diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php new file mode 100644 index 000000000..680b00f50 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php @@ -0,0 +1,66 @@ +, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * } $properties + */ + public function createPlugin(array $properties, Context $context): LogRecordExporterInterface { + $protocol = $properties['protocol']; + + return new LogsExporter(Registry::transportFactory($protocol)->create( + endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::LOGS, $protocol), + contentType: Protocols::contentType($protocol), + headers: $properties['headers'], + compression: $properties['compression'], + timeout: $properties['timeout'], + cacert: $properties['certificate'], + cert: $properties['client_certificate'], + key: $properties['client_certificate'], + )); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('otlp'); + $node + ->children() + ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() + ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->arrayNode('headers') + ->scalarPrototype()->end() + ->end() + ->enumNode('compression')->values(['gzip'])->defaultNull()->end() + ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php new file mode 100644 index 000000000..087153f14 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php @@ -0,0 +1,53 @@ +, + * export_timeout: int<0, max>, + * max_queue_size: int<0, max>, + * max_export_batch_size: int<0, max>, + * exporter: ComponentPlugin, + * } $properties + */ + public function createPlugin(array $properties, Context $context): LogRecordProcessorInterface { + return new BatchLogRecordProcessor( + exporter: $properties['exporter']->create($context), + clock: ClockFactory::getDefault(), + maxQueueSize: $properties['max_queue_size'], + scheduledDelayMillis: $properties['schedule_delay'], + exportTimeoutMillis: $properties['export_timeout'], + maxExportBatchSize: $properties['max_export_batch_size'], + meterProvider: $context->meterProvider, + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('batch'); + $node + ->children() + ->integerNode('schedule_delay')->min(0)->defaultValue(5000)->end() + ->integerNode('export_timeout')->min(0)->defaultValue(30000)->end() + ->integerNode('max_queue_size')->min(0)->defaultValue(2048)->end() + ->integerNode('max_export_batch_size')->min(0)->defaultValue(512)->end() + ->append($registry->component('exporter', LogRecordExporterInterface::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php new file mode 100644 index 000000000..faf00234f --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php @@ -0,0 +1,36 @@ +, + * } $properties + */ + public function createPlugin(array $properties, Context $context): LogRecordProcessorInterface { + return new SimpleLogRecordProcessor( + exporter: $properties['exporter']->create($context), + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('simple'); + $node + ->children() + ->append($registry->component('exporter', LogRecordExporterInterface::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php new file mode 100644 index 000000000..bf537ecef --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php @@ -0,0 +1,26 @@ +create( + endpoint: 'php://stdout', + contentType: 'application/json', + )); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + return new ArrayNodeDefinition('console'); + } +} diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php new file mode 100644 index 000000000..ad28d9ba5 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php @@ -0,0 +1,83 @@ +, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * temporality_preference: 'cumulative'|'delta'|'lowmemory', + * default_histogram_aggregation: 'explicit_bucket_histogram', + * } $properties + */ + public function createPlugin(array $properties, Context $context): MetricExporterInterface { + $protocol = $properties['protocol']; + + $temporality = match ($properties['temporality_preference']) { + 'cumulative' => Temporality::CUMULATIVE, + 'delta' => Temporality::DELTA, + 'lowmemory' => null, + }; + + return new MetricExporter(Registry::transportFactory($protocol)->create( + endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::METRICS, $protocol), + contentType: Protocols::contentType($protocol), + headers: $properties['headers'], + compression: $properties['compression'], + timeout: $properties['timeout'], + cacert: $properties['certificate'], + cert: $properties['client_certificate'], + key: $properties['client_certificate'], + ), $temporality); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('otlp'); + $node + ->children() + ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() + ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->arrayNode('headers') + ->scalarPrototype()->end() + ->end() + ->enumNode('compression')->values(['gzip'])->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->enumNode('temporality_preference') + ->values(['cumulative', 'delta', 'lowmemory']) + ->defaultValue('cumulative') + ->end() + ->enumNode('default_histogram_aggregation') + ->values(['explicit_bucket_histogram']) + ->defaultValue('explicit_bucket_histogram') + ->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php new file mode 100644 index 000000000..66742c3fb --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php @@ -0,0 +1,40 @@ +, + * timeout: int<0, max>, + * exporter: ComponentPlugin, + * } $properties + */ + public function createPlugin(array $properties, Context $context): MetricReaderInterface { + return new ExportingReader( + exporter: $properties['exporter']->create($context), + ); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('periodic'); + $node + ->children() + ->integerNode('interval')->min(0)->defaultValue(5000)->end() + ->integerNode('timeout')->min(0)->defaultValue(30000)->end() + ->append($registry->component('exporter', MetricExporterInterface::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index 6338d3414..081e6de86 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -9,6 +9,24 @@ use OpenTelemetry\Context\Propagation\NoopTextMapPropagator; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; +use OpenTelemetry\SDK\Common\Time\ClockFactory; +use OpenTelemetry\SDK\Logs\LoggerProvider; +use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; +use OpenTelemetry\SDK\Logs\Processor\MultiLogRecordProcessor; +use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderInterface; +use OpenTelemetry\SDK\Metrics\InstrumentType; +use OpenTelemetry\SDK\Metrics\MeterProvider; +use OpenTelemetry\SDK\Metrics\MetricReaderInterface; +use OpenTelemetry\SDK\Metrics\StalenessHandler\NoopStalenessHandlerFactory; +use OpenTelemetry\SDK\Metrics\View\CriteriaViewRegistry; +use OpenTelemetry\SDK\Metrics\View\SelectionCriteria\AllCriteria; +use OpenTelemetry\SDK\Metrics\View\SelectionCriteria\InstrumentationScopeNameCriteria; +use OpenTelemetry\SDK\Metrics\View\SelectionCriteria\InstrumentationScopeSchemaUrlCriteria; +use OpenTelemetry\SDK\Metrics\View\SelectionCriteria\InstrumentationScopeVersionCriteria; +use OpenTelemetry\SDK\Metrics\View\SelectionCriteria\InstrumentNameCriteria; +use OpenTelemetry\SDK\Metrics\View\SelectionCriteria\InstrumentTypeCriteria; +use OpenTelemetry\SDK\Metrics\View\ViewTemplate; use OpenTelemetry\SDK\Resource\ResourceInfo; use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\SdkBuilder; @@ -50,6 +68,32 @@ final class OpenTelemetrySdk implements ComponentProvider { * sampler: ?ComponentPlugin, * processors: list>, * }, + * meter_provider: array{ + * views: list, + * aggregation: ?ComponentPlugin, + * }, + * selector: array{ + * instrument_type: 'counter'|'histogram'|'observable_counter'|'observable_gauge'|'observable_up_down_counter'|'up_down_counter'|null, + * instrument_name: ?string, + * unit: ?string, + * meter_name: ?string, + * meter_version: ?string, + * meter_schema_url: ?string, + * }, + * }>, + * readers: list>, + * }, + * logger_provider: array{ + * limits: array{ + * attribute_value_length_limit: ?int<0, max>, + * attribute_count_limit: ?int<0, max>, + * }, + * processors: list>, + * }, * } $properties */ public function createPlugin(array $properties, Context $context): SdkBuilder { @@ -73,6 +117,8 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { $spanProcessors[] = $processor->create($context); } + // + $tracerProvider = new TracerProvider( spanProcessors: $spanProcessors, sampler: $properties['tracer_provider']['sampler']?->create($context) ?? new ParentBased(new AlwaysOnSampler()), @@ -80,30 +126,120 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { spanLimits: new SpanLimits( attributesFactory: Attributes::factory( attributeCountLimit: $properties['tracer_provider']['limits']['attribute_count_limit'] - ?? $properties['attribute_limits']['attribute_count_limit'], + ?? $properties['attribute_limits']['attribute_count_limit'] + ?? 128, attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] ?? $properties['attribute_limits']['attribute_value_length_limit'], ), eventAttributesFactory: Attributes::factory( attributeCountLimit: $properties['tracer_provider']['limits']['event_attribute_count_limit'] ?? $properties['tracer_provider']['limits']['attribute_count_limit'] - ?? $properties['attribute_limits']['attribute_count_limit'], + ?? $properties['attribute_limits']['attribute_count_limit'] + ?? 128, attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] ?? $properties['attribute_limits']['attribute_value_length_limit'], ), linkAttributesFactory: Attributes::factory( attributeCountLimit: $properties['tracer_provider']['limits']['link_attribute_count_limit'] ?? $properties['tracer_provider']['limits']['attribute_count_limit'] - ?? $properties['attribute_limits']['attribute_count_limit'], + ?? $properties['attribute_limits']['attribute_count_limit'] + ?? 128, attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] ?? $properties['attribute_limits']['attribute_value_length_limit'], ), - eventCountLimit: $properties['tracer_provider']['limits']['event_count_limit'], - linkCountLimit: $properties['tracer_provider']['limits']['link_count_limit'], + eventCountLimit: $properties['tracer_provider']['limits']['event_count_limit'] ?? 128, + linkCountLimit: $properties['tracer_provider']['limits']['link_count_limit'] ?? 128, ), ); + // + + // + + $metricReaders = []; + foreach ($properties['meter_provider']['readers'] as $reader) { + $metricReaders[] = $reader->create($context); + } + + $viewRegistry = new CriteriaViewRegistry(); + foreach ($properties['meter_provider']['views'] as $view) { + $criteria = []; + if (isset($view['selector']['instrument_type'])) { + $criteria[] = new InstrumentTypeCriteria(match ($view['selector']['instrument_type']) { + 'counter' => InstrumentType::COUNTER, + 'histogram' => InstrumentType::HISTOGRAM, + 'observable_counter' => InstrumentType::ASYNCHRONOUS_COUNTER, + 'observable_gauge' => InstrumentType::ASYNCHRONOUS_GAUGE, + 'observable_up_down_counter' => InstrumentType::ASYNCHRONOUS_UP_DOWN_COUNTER, + 'up_down_counter' => InstrumentType::UP_DOWN_COUNTER, + }); + } + if (isset($view['selector']['name'])) { + $criteria[] = new InstrumentNameCriteria($view['selector']['name']); + } + if (isset($view['selector']['unit'])) { + // TODO Add unit criteria + } + if (isset($view['selector']['meter_name'])) { + $criteria[] = new InstrumentationScopeNameCriteria($view['selector']['meter_name']); + } + if (isset($view['selector']['meter_version'])) { + $criteria[] = new InstrumentationScopeVersionCriteria($view['selector']['meter_version']); + } + if (isset($view['selector']['meter_schema_url'])) { + $criteria[] = new InstrumentationScopeSchemaUrlCriteria($view['selector']['meter_schema_url']); + } + + $viewTemplate = ViewTemplate::create(); + if (isset($view['stream']['name'])) { + $viewTemplate = $viewTemplate->withName($view['stream']['name']); + } + if (isset($view['stream']['description'])) { + $viewTemplate = $viewTemplate->withDescription($view['stream']['description']); + } + if (isset($view['stream']['attribute_keys'])) { + $viewTemplate = $viewTemplate->withAttributeKeys($view['stream']['attribute_keys']); + } + if (isset($view['stream']['aggregation'])) { + // TODO Add support for aggregation providers in views to allow usage of advisory + } + + $viewRegistry->register(new AllCriteria($criteria), $viewTemplate); + } + + $meterProvider = new MeterProvider( + contextStorage: null, + resource: $resource, + clock: ClockFactory::getDefault(), + attributesFactory: Attributes::factory(), + instrumentationScopeFactory: new InstrumentationScopeFactory(Attributes::factory()), + metricReaders: $metricReaders, + viewRegistry: $viewRegistry, + exemplarFilter: null, + stalenessHandlerFactory: new NoopStalenessHandlerFactory(), + ); + + // + + // + + $logRecordProcessors = []; + foreach ($properties['logger_provider']['processors'] as $processor) { + $logRecordProcessors[] = $processor->create($context); + } + + // TODO Allow injecting log record attributes factory + $loggerProvider = new LoggerProvider( + processor: new MultiLogRecordProcessor($logRecordProcessors), + instrumentationScopeFactory: new InstrumentationScopeFactory(Attributes::factory()), + resource: $resource, + ); + + // + $sdkBuilder->setTracerProvider($tracerProvider); + $sdkBuilder->setMeterProvider($meterProvider); + $sdkBuilder->setLoggerProvider($loggerProvider); return $sdkBuilder; } @@ -125,8 +261,8 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit ->append($this->getAttributeLimitsConfig()) ->append($registry->component('propagator', TextMapPropagatorInterface::class)) ->append($this->getTracerProviderConfig($registry)) - # ->append($this->getMeterProviderConfig($registry)) - # ->append($this->getLoggerProviderConfig($registry)) + ->append($this->getMeterProviderConfig($registry)) + ->append($this->getLoggerProviderConfig($registry)) ->end(); return $node; @@ -181,4 +317,73 @@ private function getTracerProviderConfig(ComponentProviderRegistry $registry): A return $node; } + + private function getMeterProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('meter_provider'); + $node + ->addDefaultsIfNotSet() + ->children() + ->arrayNode('views') + ->arrayPrototype() + ->children() + ->arrayNode('stream') + ->addDefaultsIfNotSet() + ->children() + ->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() + ->end() + ->append($registry->component('aggregation', DefaultAggregationProviderInterface::class)) + ->end() + ->end() + ->arrayNode('selector') + ->addDefaultsIfNotSet() + ->children() + ->enumNode('instrument_type') + ->values([ + 'counter', + 'histogram', + 'observable_counter', + 'observable_gauge', + 'observable_up_down_counter', + 'up_down_counter', + ]) + ->defaultNull() + ->end() + ->scalarNode('instrument_name')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('unit')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('meter_name')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('meter_version')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('meter_schema_url')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->append($registry->componentList('readers', MetricReaderInterface::class)) + ->end() + ; + + return $node; + } + + private function getLoggerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + $node = new ArrayNodeDefinition('logger_provider'); + $node + ->addDefaultsIfNotSet() + ->children() + ->arrayNode('limits') + ->addDefaultsIfNotSet() + ->children() + ->integerNode('attribute_value_length_limit')->min(0)->defaultNull()->end() + ->integerNode('attribute_count_limit')->min(0)->defaultNull()->end() + ->end() + ->end() + ->append($registry->componentList('processors', LogRecordProcessorInterface::class)) + ->end() + ; + + return $node; + } } diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php new file mode 100644 index 000000000..9f33fd150 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php @@ -0,0 +1,25 @@ +> $properties + */ + public function createPlugin(array $properties, Context $context): TextMapPropagatorInterface { + $propagators = []; + foreach ($properties as $plugin) { + $propagators[] = $plugin->create($context); + } + + return new MultiTextMapPropagator($propagators); + } + + public function getConfig(ComponentProviderRegistry $registry): 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 new file mode 100644 index 000000000..75c5b41e4 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php @@ -0,0 +1,25 @@ +create( - endpoint: $properties['endpoint'] . $path, + endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::TRACE, $protocol), contentType: Protocols::contentType($protocol), headers: $properties['headers'], compression: $properties['compression'], diff --git a/src/Config/SDK/composer.json b/src/Config/SDK/composer.json index 829d3a100..b106db342 100644 --- a/src/Config/SDK/composer.json +++ b/src/Config/SDK/composer.json @@ -33,6 +33,13 @@ }, "spi": { "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3Multi", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorBaggage", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorComposite", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorJaeger", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorTraceContext", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerAlwaysOff", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerAlwaysOn", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerParentBased", @@ -41,7 +48,17 @@ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterOtlp", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterZipkin", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorBatch", - "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorSimple" + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorSimple", + + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\AggregationResolverDefault", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterConsole", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricReaderPeriodic", + + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterConsole", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorBatch", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorSimple" ] } } diff --git a/src/Contrib/Otlp/OtlpUtil.php b/src/Contrib/Otlp/OtlpUtil.php index 62feb6d91..87b97691e 100644 --- a/src/Contrib/Otlp/OtlpUtil.php +++ b/src/Contrib/Otlp/OtlpUtil.php @@ -10,6 +10,7 @@ use OpenTelemetry\SDK\Resource\Detectors\Sdk; use OpenTelemetry\SemConv\ResourceAttributes; use UnexpectedValueException; +use function explode; class OtlpUtil { @@ -37,6 +38,17 @@ public static function method(string $signal): string return self::METHODS[$signal]; } + public static function path(string $signal, string $protocol): string { + return match (explode('/', $protocol)[0]) { + 'grpc' => self::method($signal), + 'http' => match ($signal) { + Signals::TRACE => '/v1/traces', + Signals::METRICS => '/v1/metrics', + Signals::LOGS => '/v1/logs', + } + }; + } + public static function getHeaders(string $signal): array { $headers = Configuration::has(self::HEADER_VARS[$signal]) ? From f61beaa2a63847d6cac0a8a0cf8d1a224dbe4a71 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Tue, 5 Mar 2024 21:19:59 +0100 Subject: [PATCH 03/15] Remove accidentally added package dependency [skip ci] --- .../SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php index 087153f14..7ff2835e6 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php @@ -5,14 +5,12 @@ use Nevay\OTelSDK\Configuration\ComponentProvider; use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; use Nevay\OTelSDK\Configuration\Context; -use Nevay\SPI\ServiceProviderDependency\PackageDependency; use OpenTelemetry\SDK\Common\Time\ClockFactory; use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; use OpenTelemetry\SDK\Logs\Processor\BatchLogRecordProcessor; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; -#[PackageDependency('open-telemetry/exporter-otlp', '^1.0')] final class LogRecordProcessorBatch implements ComponentProvider { /** From 83d4cb0ad7b70a54c765df1a27ef7c18032331f9 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Wed, 6 Mar 2024 17:49:54 +0100 Subject: [PATCH 04/15] Fix `$properties` typehint to match config Default value available -> cannot be null. --- .../ComponentProvider/OpenTelemetrySdk.php | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index 081e6de86..1f781372d 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -53,15 +53,15 @@ final class OpenTelemetrySdk implements ComponentProvider { * }, * attribute_limits: array{ * attribute_value_length_limit: ?int<0, max>, - * attribute_count_limit: ?int<0, max>, + * attribute_count_limit: int<0, max>, * }, * propagator: ?ComponentPlugin, * tracer_provider: array{ * limits: array{ * attribute_value_length_limit: ?int<0, max>, * attribute_count_limit: ?int<0, max>, - * event_count_limit: ?int<0, max>, - * link_count_limit: ?int<0, max>, + * event_count_limit: int<0, max>, + * link_count_limit: int<0, max>, * event_attribute_count_limit: ?int<0, max>, * link_attribute_count_limit: ?int<0, max>, * }, @@ -126,29 +126,26 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { spanLimits: new SpanLimits( attributesFactory: Attributes::factory( attributeCountLimit: $properties['tracer_provider']['limits']['attribute_count_limit'] - ?? $properties['attribute_limits']['attribute_count_limit'] - ?? 128, + ?? $properties['attribute_limits']['attribute_count_limit'], attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] ?? $properties['attribute_limits']['attribute_value_length_limit'], ), eventAttributesFactory: Attributes::factory( attributeCountLimit: $properties['tracer_provider']['limits']['event_attribute_count_limit'] ?? $properties['tracer_provider']['limits']['attribute_count_limit'] - ?? $properties['attribute_limits']['attribute_count_limit'] - ?? 128, + ?? $properties['attribute_limits']['attribute_count_limit'], attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] ?? $properties['attribute_limits']['attribute_value_length_limit'], ), linkAttributesFactory: Attributes::factory( attributeCountLimit: $properties['tracer_provider']['limits']['link_attribute_count_limit'] ?? $properties['tracer_provider']['limits']['attribute_count_limit'] - ?? $properties['attribute_limits']['attribute_count_limit'] - ?? 128, + ?? $properties['attribute_limits']['attribute_count_limit'], attributeValueLengthLimit: $properties['tracer_provider']['limits']['attribute_value_length_limit'] ?? $properties['attribute_limits']['attribute_value_length_limit'], ), - eventCountLimit: $properties['tracer_provider']['limits']['event_count_limit'] ?? 128, - linkCountLimit: $properties['tracer_provider']['limits']['link_count_limit'] ?? 128, + eventCountLimit: $properties['tracer_provider']['limits']['event_count_limit'], + linkCountLimit: $properties['tracer_provider']['limits']['link_count_limit'], ), ); @@ -287,7 +284,7 @@ private function getAttributeLimitsConfig(): ArrayNodeDefinition { $node ->addDefaultsIfNotSet() ->children() - ->integerNode('attribute_value_length_limit')->min(0)->defaultValue(4096)->end() + ->integerNode('attribute_value_length_limit')->min(0)->defaultNull()->end() ->integerNode('attribute_count_limit')->min(0)->defaultValue(128)->end() ->end(); From 231ac8a28b12de4e994ca99a32ee8572ba48a1dc Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Wed, 6 Mar 2024 17:57:56 +0100 Subject: [PATCH 05/15] Add configuration example that utilizes env substitution --- examples/load_config_env.php | 32 +++++++++++++++++++++++ examples/load_config_env.yaml | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 examples/load_config_env.php create mode 100644 examples/load_config_env.yaml diff --git a/examples/load_config_env.php b/examples/load_config_env.php new file mode 100644 index 000000000..48a8f4382 --- /dev/null +++ b/examples/load_config_env.php @@ -0,0 +1,32 @@ +create() + ->setAutoShutdown(true) + ->build(); + +$tracer = $sdk->getTracerProvider()->getTracer('demo'); +$meter = $sdk->getMeterProvider()->getMeter('demo'); +$logger = $sdk->getLoggerProvider()->getLogger('demo'); + +$tracer->spanBuilder('root')->startSpan()->end(); +$meter->createCounter('cnt')->add(1); + +$eventLogger = new EventLogger($logger, 'my-domain'); +$eventLogger->logEvent('foo', new LogRecord('hello, otel')); + +echo 'Finished!' . PHP_EOL; diff --git a/examples/load_config_env.yaml b/examples/load_config_env.yaml new file mode 100644 index 000000000..b62262d29 --- /dev/null +++ b/examples/load_config_env.yaml @@ -0,0 +1,49 @@ +file_format: '0.1' + +disabled: ${OTEL_SDK_DISABLED} + +resource: + attributes: + service.name: ${OTEL_SERVICE_NAME} + +propagators: + composite: [ tracecontext, baggage ] + +attribute_limits: + attribute_value_length_limit: ${OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT} + attribute_count_limit: ${OTEL_ATTRIBUTE_COUNT_LIMIT} + +exporters: + otlp: &otlp-exporter + protocol: ${OTEL_EXPORTER_OTLP_PROTOCOL} + endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT} + certificate: ${OTEL_EXPORTER_OTLP_CERTIFICATE} + client_key: ${OTEL_EXPORTER_OTLP_CLIENT_KEY} + client_certificate: ${OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE} + compression: ${OTEL_EXPORTER_OTLP_COMPRESSION} + timeout: ${OTEL_EXPORTER_OTLP_TIMEOUT} + +tracer_provider: + sampler: + parent_based: + root: + trace_id_ratio_based: + ratio: ${OTEL_TRACES_SAMPLER_ARG} + limits: + attribute_value_length_limit: ${OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT} + attribute_count_limit: ${OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT} + event_count_limit: ${OTEL_SPAN_EVENT_COUNT_LIMIT} + link_count_limit: ${OTEL_SPAN_LINK_COUNT_LIMIT} + event_attribute_count_limit: ${OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT} + link_attribute_count_limit: ${OTEL_LINK_ATTRIBUTE_COUNT_LIMIT} + processors: + - simple: + exporter: + console: {} + - batch: + schedule_delay: ${OTEL_BSP_SCHEDULE_DELAY} + export_timeout: ${OTEL_BSP_EXPORT_TIMEOUT} + max_queue_size: ${OTEL_BSP_MAX_QUEUE_SIZE} + max_export_batch_size: ${OTEL_BSP_MAX_EXPORT_BATCH_SIZE} + exporter: + otlp: *otlp-exporter From c87b64fe68494f8ace6d8608621bff2531ba9331 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Thu, 14 Mar 2024 18:44:27 +0100 Subject: [PATCH 06/15] Fix/suppress config psalm issues --- psalm.xml.dist | 30 +++++++++++++++---- .../Metrics/MetricExporterConsole.php | 6 +--- .../ComponentProvider/OpenTelemetrySdk.php | 1 + src/Config/SDK/Configuration.php | 4 +-- src/Contrib/Otlp/Protocols.php | 3 ++ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/psalm.xml.dist b/psalm.xml.dist index b6f04150f..697293abc 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -23,13 +23,33 @@ - + - - + + - + - + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php index c85749f5e..a176c8796 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php @@ -6,7 +6,6 @@ use Nevay\OTelSDK\Configuration\Context; use OpenTelemetry\SDK\Metrics\MetricExporter\ConsoleMetricExporter; use OpenTelemetry\SDK\Metrics\MetricExporterInterface; -use OpenTelemetry\SDK\Registry; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; final class MetricExporterConsole implements ComponentProvider { @@ -15,10 +14,7 @@ final class MetricExporterConsole implements ComponentProvider { * @param array{} $properties */ public function createPlugin(array $properties, Context $context): MetricExporterInterface { - return new ConsoleMetricExporter(Registry::transportFactory('stream')->create( - endpoint: 'php://stdout', - contentType: 'application/json', - )); + return new ConsoleMetricExporter(); } public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index 1f781372d..5780c0492 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -204,6 +204,7 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { $viewRegistry->register(new AllCriteria($criteria), $viewTemplate); } + /** @psalm-suppress InvalidArgument TODO update metric reader interface */ $meterProvider = new MeterProvider( contextStorage: null, resource: $resource, diff --git a/src/Config/SDK/Configuration.php b/src/Config/SDK/Configuration.php index f5746357a..b99aae27c 100644 --- a/src/Config/SDK/Configuration.php +++ b/src/Config/SDK/Configuration.php @@ -5,9 +5,9 @@ use Nevay\OTelSDK\Configuration\ComponentProvider; use Nevay\OTelSDK\Configuration\ConfigurationFactory; use Nevay\OTelSDK\Configuration\Context; -use Nevay\OTelSDK\Configuration\Environment\ArrayEnvSource; use Nevay\OTelSDK\Configuration\Environment\EnvSourceReader; use Nevay\OTelSDK\Configuration\Environment\PhpIniEnvSource; +use Nevay\OTelSDK\Configuration\Environment\ServerEnvSource; use Nevay\SPI\ServiceLoader; use OpenTelemetry\Config\SDK\ComponentProvider\OpenTelemetrySdk; use OpenTelemetry\SDK\SdkBuilder; @@ -42,7 +42,7 @@ private static function factory(): ConfigurationFactory { ServiceLoader::load(ComponentProvider::class), new OpenTelemetrySdk(), new EnvSourceReader([ - new ArrayEnvSource($_SERVER), + new ServerEnvSource(), new PhpIniEnvSource(), ]), ); diff --git a/src/Contrib/Otlp/Protocols.php b/src/Contrib/Otlp/Protocols.php index 96b04d8bf..add00719a 100644 --- a/src/Contrib/Otlp/Protocols.php +++ b/src/Contrib/Otlp/Protocols.php @@ -27,6 +27,9 @@ public static function validate(string $protocol): void } } + /** + * @return ContentTypes::* + */ public static function contentType(string $protocol): string { self::validate($protocol); From 82205f4fd8d6a63708493a0981c8f83bf63bb018 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Thu, 14 Mar 2024 18:58:27 +0100 Subject: [PATCH 07/15] Fix/suppress config phpstan issues --- phpstan.neon.dist | 6 +++++- .../SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php | 4 ++-- .../SDK/ComponentProvider/Metrics/MetricExporterOtlp.php | 4 ++-- src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php | 8 ++++---- .../SDK/ComponentProvider/Trace/SpanExporterOtlp.php | 4 ++-- src/Contrib/Otlp/OtlpUtil.php | 6 +++++- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index fc15014fb..48d227e80 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -32,4 +32,8 @@ parameters: - message: "#Call to an undefined method .*:expects.*#" paths: - - tests \ No newline at end of file + - tests + - + message: "#Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeParentInterface::.*#" + paths: + - src/Config/SDK diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php index 680b00f50..a74dd63a8 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php @@ -19,7 +19,7 @@ final class LogRecordExporterOtlp implements ComponentProvider { /** * @param array{ - * protocol: 'http/protobuf'|'http/json'|'grpc/protobuf'|'grpc/json', + * protocol: 'http/protobuf'|'http/json'|'grpc', * endpoint: string, * certificate: ?string, * client_key: ?string, @@ -48,7 +48,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit $node = new ArrayNodeDefinition('otlp'); $node ->children() - ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() + ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php index ad28d9ba5..4cb7ef6e5 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php @@ -20,7 +20,7 @@ final class MetricExporterOtlp implements ComponentProvider { /** * @param array{ - * protocol: 'http/protobuf'|'http/json'|'grpc/protobuf'|'grpc/json', + * protocol: 'http/protobuf'|'http/json'|'grpc', * endpoint: string, * certificate: ?string, * client_key: ?string, @@ -57,7 +57,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit $node = new ArrayNodeDefinition('otlp'); $node ->children() - ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() + ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index 5780c0492..7d9d88247 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -171,8 +171,8 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { 'up_down_counter' => InstrumentType::UP_DOWN_COUNTER, }); } - if (isset($view['selector']['name'])) { - $criteria[] = new InstrumentNameCriteria($view['selector']['name']); + if (isset($view['selector']['instrument_name'])) { + $criteria[] = new InstrumentNameCriteria($view['selector']['instrument_name']); } if (isset($view['selector']['unit'])) { // TODO Add unit criteria @@ -194,7 +194,7 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { if (isset($view['stream']['description'])) { $viewTemplate = $viewTemplate->withDescription($view['stream']['description']); } - if (isset($view['stream']['attribute_keys'])) { + if ($view['stream']['attribute_keys']) { $viewTemplate = $viewTemplate->withAttributeKeys($view['stream']['attribute_keys']); } if (isset($view['stream']['aggregation'])) { @@ -211,7 +211,7 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { clock: ClockFactory::getDefault(), attributesFactory: Attributes::factory(), instrumentationScopeFactory: new InstrumentationScopeFactory(Attributes::factory()), - metricReaders: $metricReaders, + metricReaders: $metricReaders, // @phpstan-ignore-line viewRegistry: $viewRegistry, exemplarFilter: null, stalenessHandlerFactory: new NoopStalenessHandlerFactory(), diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php index eb01e93dd..198c2d97c 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php @@ -20,7 +20,7 @@ final class SpanExporterOtlp implements ComponentProvider { /** * @param array{ - * protocol: 'http/protobuf'|'http/json'|'grpc/protobuf'|'grpc/json', + * protocol: 'http/protobuf'|'http/json'|'grpc', * endpoint: string, * certificate: ?string, * client_key: ?string, @@ -49,7 +49,7 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit $node = new ArrayNodeDefinition('otlp'); $node ->children() - ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc/protobuf', 'grpc/json'])->end() + ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() diff --git a/src/Contrib/Otlp/OtlpUtil.php b/src/Contrib/Otlp/OtlpUtil.php index 87b97691e..9c82f56d8 100644 --- a/src/Contrib/Otlp/OtlpUtil.php +++ b/src/Contrib/Otlp/OtlpUtil.php @@ -38,8 +38,12 @@ public static function method(string $signal): string return self::METHODS[$signal]; } + /** + * @param 'trace'|'metrics'|'logs' $signal + * @param 'grpc'|'http/protobuf'|'http/json' $protocol + */ public static function path(string $signal, string $protocol): string { - return match (explode('/', $protocol)[0]) { + return match (explode('/', $protocol)[0]) { // @phpstan-ignore-line 'grpc' => self::method($signal), 'http' => match ($signal) { Signals::TRACE => '/v1/traces', From a264edd95260795b4d9776d52ce689c233f725e4 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Thu, 14 Mar 2024 19:13:26 +0100 Subject: [PATCH 08/15] Suppress config phan issues --- .phan/config.php | 1 + src/Contrib/Otlp/Protocols.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.phan/config.php b/.phan/config.php index 13248372a..d8c6d47e0 100644 --- a/.phan/config.php +++ b/.phan/config.php @@ -319,6 +319,7 @@ 'exclude_analysis_directory_list' => [ 'vendor/', 'proto/', + 'src/Config/SDK', ], // Enable this to enable checks of require/include statements referring to valid paths. diff --git a/src/Contrib/Otlp/Protocols.php b/src/Contrib/Otlp/Protocols.php index add00719a..736436a8f 100644 --- a/src/Contrib/Otlp/Protocols.php +++ b/src/Contrib/Otlp/Protocols.php @@ -28,7 +28,7 @@ public static function validate(string $protocol): void } /** - * @return ContentTypes::* + * @psalm-return ContentTypes::* */ public static function contentType(string $protocol): string { From 94ae3e5d073d86c19e7dff9d4967c5eb4b5d4f3f Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Thu, 14 Mar 2024 19:14:49 +0100 Subject: [PATCH 09/15] Apply cs-fixer --- examples/load_config.php | 4 ++- examples/load_config_env.php | 4 ++- .../Logs/LogRecordExporterConsole.php | 14 ++++++--- .../Logs/LogRecordExporterOtlp.php | 14 ++++++--- .../Logs/LogRecordProcessorBatch.php | 14 ++++++--- .../Logs/LogRecordProcessorSimple.php | 14 ++++++--- .../Metrics/AggregationResolverDefault.php | 16 ++++++---- .../Metrics/MetricExporterConsole.php | 14 ++++++--- .../Metrics/MetricExporterOtlp.php | 14 ++++++--- .../Metrics/MetricReaderPeriodic.php | 14 ++++++--- .../ComponentProvider/OpenTelemetrySdk.php | 29 +++++++++++++------ .../Propagator/TextMapPropagatorB3.php | 14 ++++++--- .../Propagator/TextMapPropagatorB3Multi.php | 14 ++++++--- .../Propagator/TextMapPropagatorBaggage.php | 14 ++++++--- .../Propagator/TextMapPropagatorComposite.php | 14 ++++++--- .../Propagator/TextMapPropagatorJaeger.php | 14 ++++++--- .../TextMapPropagatorTraceContext.php | 14 ++++++--- .../Trace/SamplerAlwaysOff.php | 14 ++++++--- .../Trace/SamplerAlwaysOn.php | 14 ++++++--- .../Trace/SamplerParentBased.php | 15 ++++++---- .../Trace/SamplerTraceIdRatioBased.php | 14 ++++++--- .../Trace/SpanExporterConsole.php | 14 ++++++--- .../Trace/SpanExporterOtlp.php | 15 ++++++---- .../Trace/SpanExporterZipkin.php | 14 ++++++--- .../Trace/SpanProcessorBatch.php | 14 ++++++--- .../Trace/SpanProcessorSimple.php | 14 ++++++--- src/Config/SDK/Configuration.php | 18 ++++++++---- src/Contrib/Otlp/OtlpUtil.php | 5 ++-- 28 files changed, 273 insertions(+), 113 deletions(-) diff --git a/examples/load_config.php b/examples/load_config.php index 16a50765a..591f3f583 100644 --- a/examples/load_config.php +++ b/examples/load_config.php @@ -1,4 +1,6 @@ -create( endpoint: 'php://stdout', contentType: 'application/json', )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { return new ArrayNodeDefinition('console'); } } diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php index a74dd63a8..10c5d6762 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): LogRecordExporterInterface { + public function createPlugin(array $properties, Context $context): LogRecordExporterInterface + { $protocol = $properties['protocol']; return new LogsExporter(Registry::transportFactory($protocol)->create( @@ -44,7 +49,8 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('otlp'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php index 7ff2835e6..f45ee0215 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): LogRecordProcessorInterface { + public function createPlugin(array $properties, Context $context): LogRecordProcessorInterface + { return new BatchLogRecordProcessor( exporter: $properties['exporter']->create($context), clock: ClockFactory::getDefault(), @@ -34,7 +39,8 @@ public function createPlugin(array $properties, Context $context): LogRecordProc ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('batch'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php index faf00234f..4a0ba5e3a 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): LogRecordProcessorInterface { + public function createPlugin(array $properties, Context $context): LogRecordProcessorInterface + { return new SimpleLogRecordProcessor( exporter: $properties['exporter']->create($context), ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('simple'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php index bf537ecef..636676830 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php +++ b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php @@ -1,4 +1,7 @@ -children() diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php index 66742c3fb..35464c056 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): MetricReaderInterface { + public function createPlugin(array $properties, Context $context): MetricReaderInterface + { return new ExportingReader( exporter: $properties['exporter']->create($context), ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('periodic'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index 7d9d88247..b1f78abb6 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -1,4 +1,7 @@ -create($context) ?? NoopTextMapPropagator::getInstance(); @@ -242,7 +247,8 @@ public function createPlugin(array $properties, Context $context): SdkBuilder { return $sdkBuilder; } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('open_telemetry'); $node ->addDefaultsIfNotSet() @@ -266,7 +272,8 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit return $node; } - private function getResourceConfig(): ArrayNodeDefinition { + private function getResourceConfig(): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('resource'); $node ->addDefaultsIfNotSet() @@ -280,7 +287,8 @@ private function getResourceConfig(): ArrayNodeDefinition { return $node; } - private function getAttributeLimitsConfig(): ArrayNodeDefinition { + private function getAttributeLimitsConfig(): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('attribute_limits'); $node ->addDefaultsIfNotSet() @@ -292,7 +300,8 @@ private function getAttributeLimitsConfig(): ArrayNodeDefinition { return $node; } - private function getTracerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + private function getTracerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('tracer_provider'); $node ->addDefaultsIfNotSet() @@ -316,7 +325,8 @@ private function getTracerProviderConfig(ComponentProviderRegistry $registry): A return $node; } - private function getMeterProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + private function getMeterProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('meter_provider'); $node ->addDefaultsIfNotSet() @@ -366,7 +376,8 @@ private function getMeterProviderConfig(ComponentProviderRegistry $registry): Ar return $node; } - private function getLoggerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + private function getLoggerProviderConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('logger_provider'); $node ->addDefaultsIfNotSet() diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php index 9f33fd150..68ae74680 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php @@ -1,4 +1,7 @@ -> $properties */ - public function createPlugin(array $properties, Context $context): TextMapPropagatorInterface { + public function createPlugin(array $properties, Context $context): TextMapPropagatorInterface + { $propagators = []; foreach ($properties as $plugin) { $propagators[] = $plugin->create($context); @@ -23,7 +28,8 @@ public function createPlugin(array $properties, Context $context): TextMapPropag return new MultiTextMapPropagator($propagators); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): 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 75c5b41e4..42cea1ce2 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): SamplerInterface { + public function createPlugin(array $properties, Context $context): SamplerInterface + { return new ParentBased( root: $properties['root']->create($context), remoteParentSampler: $properties['remote_parent_sampled']?->create($context) ?? new AlwaysOnSampler(), @@ -32,8 +37,8 @@ public function createPlugin(array $properties, Context $context): SamplerInterf ); } - - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('parent_based'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php index 7bf428e67..87fa5e429 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php @@ -1,4 +1,7 @@ -children() diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php index 96fb67524..b60e09158 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php @@ -1,4 +1,7 @@ -create( endpoint: 'php://stdout', contentType: 'application/json', )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { return new ArrayNodeDefinition('console'); } } diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php index 198c2d97c..909f105b9 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): SpanExporterInterface { + public function createPlugin(array $properties, Context $context): SpanExporterInterface + { $protocol = $properties['protocol']; return new SpanExporter(Registry::transportFactory($protocol)->create( @@ -45,7 +49,8 @@ public function createPlugin(array $properties, Context $context): SpanExporterI )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('otlp'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php index 39cff4825..509f7b4e2 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): SpanExporterInterface { + public function createPlugin(array $properties, Context $context): SpanExporterInterface + { return new Zipkin\Exporter(Registry::transportFactory('http')->create( endpoint: $properties['endpoint'], contentType: 'application/json', @@ -28,7 +33,8 @@ public function createPlugin(array $properties, Context $context): SpanExporterI )); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('zipkin'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php index e7cb90f33..1dae2f079 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): SpanProcessorInterface { + public function createPlugin(array $properties, Context $context): SpanProcessorInterface + { return new BatchSpanProcessor( exporter: $properties['exporter']->create($context), clock: ClockFactory::getDefault(), @@ -34,7 +39,8 @@ public function createPlugin(array $properties, Context $context): SpanProcessor ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('batch'); $node ->children() diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php index 991753042..77a1efefe 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php @@ -1,4 +1,7 @@ -, * } $properties */ - public function createPlugin(array $properties, Context $context): SpanProcessorInterface { + public function createPlugin(array $properties, Context $context): SpanProcessorInterface + { return new SimpleSpanProcessor( exporter: $properties['exporter']->create($context), ); } - public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { $node = new ArrayNodeDefinition('simple'); $node ->children() diff --git a/src/Config/SDK/Configuration.php b/src/Config/SDK/Configuration.php index b99aae27c..6a2c8eeae 100644 --- a/src/Config/SDK/Configuration.php +++ b/src/Config/SDK/Configuration.php @@ -1,4 +1,7 @@ - $sdkPlugin */ private function __construct( private readonly ComponentPlugin $sdkPlugin, - ) {} + ) { + } - public function create(Context $context = new Context()): SdkBuilder { + public function create(Context $context = new Context()): SdkBuilder + { return $this->sdkPlugin->create($context); } @@ -36,8 +42,10 @@ public static function parseFile( /** * @return ConfigurationFactory */ - private static function factory(): ConfigurationFactory { + private static function factory(): ConfigurationFactory + { static $factory; + return $factory ??= new ConfigurationFactory( ServiceLoader::load(ComponentProvider::class), new OpenTelemetrySdk(), diff --git a/src/Contrib/Otlp/OtlpUtil.php b/src/Contrib/Otlp/OtlpUtil.php index 9c82f56d8..1ed4ce64a 100644 --- a/src/Contrib/Otlp/OtlpUtil.php +++ b/src/Contrib/Otlp/OtlpUtil.php @@ -4,13 +4,13 @@ namespace OpenTelemetry\Contrib\Otlp; +use function explode; use OpenTelemetry\API\Signals; use OpenTelemetry\SDK\Common\Configuration\Configuration; use OpenTelemetry\SDK\Common\Configuration\Variables; use OpenTelemetry\SDK\Resource\Detectors\Sdk; use OpenTelemetry\SemConv\ResourceAttributes; use UnexpectedValueException; -use function explode; class OtlpUtil { @@ -42,7 +42,8 @@ public static function method(string $signal): string * @param 'trace'|'metrics'|'logs' $signal * @param 'grpc'|'http/protobuf'|'http/json' $protocol */ - public static function path(string $signal, string $protocol): string { + public static function path(string $signal, string $protocol): string + { return match (explode('/', $protocol)[0]) { // @phpstan-ignore-line 'grpc' => self::method($signal), 'http' => match ($signal) { From 149ae5c5fcc914638ce3dfd6305ef6e48840f0aa Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Thu, 14 Mar 2024 19:27:14 +0100 Subject: [PATCH 10/15] Change config package version to development version 0.x --- composer.json | 2 +- src/Config/SDK/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 9a9636403..2c8fefe88 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "require": { "php": "^8.1", "google/protobuf": "^3.22", - "open-telemetry/sdk-configuration": "^1.0-dev", + "open-telemetry/sdk-configuration": "^0.1-dev", "php-http/discovery": "^1.14", "psr/http-client-implementation": "^1.0", "psr/http-factory-implementation": "^1.0", diff --git a/src/Config/SDK/composer.json b/src/Config/SDK/composer.json index b106db342..7b6809c3f 100644 --- a/src/Config/SDK/composer.json +++ b/src/Config/SDK/composer.json @@ -29,7 +29,7 @@ }, "extra": { "branch-alias": { - "dev-main": "1.0.x-dev" + "dev-main": "0.1.x-dev" }, "spi": { "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ From 13ac0a1619273d23d6d18c54b83fcded6cdcedd6 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Thu, 14 Mar 2024 19:34:13 +0100 Subject: [PATCH 11/15] Add README --- src/Config/SDK/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/Config/SDK/README.md diff --git a/src/Config/SDK/README.md b/src/Config/SDK/README.md new file mode 100644 index 000000000..022d2ce47 --- /dev/null +++ b/src/Config/SDK/README.md @@ -0,0 +1,34 @@ +# OpenTelemetry SDK configuration + +## Installation + +```shell +composer require open-telemetry/sdk-configuration +``` + +## Usage + +### Initialization from [configuration file](https://opentelemetry.io/docs/specs/otel/configuration/file-configuration/) + +```php +$configuration = Configuration::parseFile(__DIR__ . '/kitchen-sink.yaml'); +$sdkBuilder = $configuration->create(); +``` + +#### Performance considerations + +Parsing and processing the configuration is rather expensive. It is highly recommended to provide the `$cacheFile` +parameter when running in a shared-nothing setup. + +```php +$configuration = Configuration::parseFile( + __DIR__ . '/kitchen-sink.yaml', + __DIR__ . '/var/cache/opentelemetry.php', +); +$sdkBuilder = $configuration->create(); +``` + +## Contributing + +This repository is a read-only git subtree split. +To contribute, please see the main [OpenTelemetry PHP monorepo](https://github.com/open-telemetry/opentelemetry-php). From db47d77f55ab202d84164073700cdcfd0dfd6955 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Thu, 14 Mar 2024 19:48:33 +0100 Subject: [PATCH 12/15] Add basic test --- composer.json | 2 + .../Integration/Config/ConfigurationTest.php | 28 ++ .../Config/configurations/anchors.yaml | 41 ++ .../Config/configurations/kitchen-sink.yaml | 352 ++++++++++++++++++ 4 files changed, 423 insertions(+) create mode 100644 tests/Integration/Config/ConfigurationTest.php create mode 100644 tests/Integration/Config/configurations/anchors.yaml create mode 100644 tests/Integration/Config/configurations/kitchen-sink.yaml diff --git a/composer.json b/composer.json index 2c8fefe88..42b9423f7 100644 --- a/composer.json +++ b/composer.json @@ -45,6 +45,8 @@ "open-telemetry/context": "self.version", "open-telemetry/exporter-otlp": "1.0.x-dev", "open-telemetry/exporter-zipkin": "1.0.x-dev", + "open-telemetry/extension-propagator-b3": "1.0.x-dev", + "open-telemetry/extension-propagator-jaeger": "0.0.2", "open-telemetry/gen-otlp-protobuf": "self.version", "open-telemetry/sdk": "self.version", "open-telemetry/sdk-contrib": "self.version", diff --git a/tests/Integration/Config/ConfigurationTest.php b/tests/Integration/Config/ConfigurationTest.php new file mode 100644 index 000000000..c5391ed24 --- /dev/null +++ b/tests/Integration/Config/ConfigurationTest.php @@ -0,0 +1,28 @@ +expectNotToPerformAssertions(); + Configuration::parseFile($file)->create(); + } + + public static function openTelemetryConfigurationDataProvider(): iterable + { + yield 'kitchen-sink' => [__DIR__ . '/configurations/kitchen-sink.yaml']; + yield 'anchors' => [__DIR__ . '/configurations/anchors.yaml']; + } +} diff --git a/tests/Integration/Config/configurations/anchors.yaml b/tests/Integration/Config/configurations/anchors.yaml new file mode 100644 index 000000000..18e409d1a --- /dev/null +++ b/tests/Integration/Config/configurations/anchors.yaml @@ -0,0 +1,41 @@ +# anchors.yaml demonstrates anchor substitution to reuse OTLP exporter configuration across signals. + +file_format: "0.1" +exporters: + otlp: &otlp-exporter + protocol: http/protobuf + endpoint: http://localhost:4318 + certificate: /app/cert.pem + client_key: /app/cert.pem + client_certificate: /app/cert.pem + headers: + api-key: !!str 1234 + compression: gzip + timeout: 10000 + +logger_provider: + processors: + - batch: + exporter: + otlp: + # expand the otlp-exporter anchor + <<: *otlp-exporter + +meter_provider: + readers: + - periodic: + interval: 5000 + timeout: 30000 + exporter: + otlp: + # expand the otlp-exporter anchor and add metric specific configuration + <<: *otlp-exporter + temporality_preference: delta + +tracer_provider: + processors: + - batch: + exporter: + otlp: + # expand the otlp-exporter anchor + <<: *otlp-exporter diff --git a/tests/Integration/Config/configurations/kitchen-sink.yaml b/tests/Integration/Config/configurations/kitchen-sink.yaml new file mode 100644 index 000000000..c331f6891 --- /dev/null +++ b/tests/Integration/Config/configurations/kitchen-sink.yaml @@ -0,0 +1,352 @@ +# kitchen-sink.yaml demonstrates all configurable surface area, including explanatory comments. +# +# It DOES NOT represent expected real world configuration, as it makes strange configuration +# choices in an effort to exercise the full surface area. +# +# Configuration values are set to their defaults when default values are defined. + +# The file format version +file_format: "0.1" + +# 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 +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 logger provider. +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. + # + # Environment variable: OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_LOGS_HEADERS + headers: + 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 meter provider. +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. + # + # Environment variable: OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_METRICS_HEADERS + headers: + api-key: !!str 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 text map context propagators. +# +# Environment variable: OTEL_PROPAGATORS +propagator: + composite: [tracecontext, baggage, b3, b3multi, jaeger] + +# Configure tracer provider. +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. + # + # Environment variable: OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS + headers: + api-key: !!str 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 resource for all signals. +resource: + # Configure resource attributes. + # + # Environment variable: OTEL_RESOURCE_ATTRIBUTES + attributes: + # Configure `service.name` resource attribute + # + # Environment variable: OTEL_SERVICE_NAME + service.name: !!str "unknown_service" + # Configure the resource schema URL. + schema_url: https://opentelemetry.io/schemas/1.23.1 From 69cff1c7b92cba6fec6d03476161aac1f99c9c92 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Fri, 15 Mar 2024 22:37:23 +0100 Subject: [PATCH 13/15] Fix psalm and cs --- psalm.xml.dist | 4 ++-- .../SDK/ComponentProvider/Logs/LogRecordExporterConsole.php | 3 +++ .../SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php | 3 +++ .../SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php | 3 +++ .../SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php | 3 +++ .../Metrics/AggregationResolverDefault.php | 3 +++ .../SDK/ComponentProvider/Metrics/MetricExporterConsole.php | 3 +++ .../SDK/ComponentProvider/Metrics/MetricExporterOtlp.php | 3 +++ .../SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php | 3 +++ src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php | 6 ++++-- .../ComponentProvider/Propagator/TextMapPropagatorB3.php | 3 +++ .../Propagator/TextMapPropagatorB3Multi.php | 3 +++ .../Propagator/TextMapPropagatorBaggage.php | 3 +++ .../Propagator/TextMapPropagatorComposite.php | 3 +++ .../Propagator/TextMapPropagatorJaeger.php | 3 +++ .../Propagator/TextMapPropagatorTraceContext.php | 3 +++ src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php | 3 +++ src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php | 3 +++ .../SDK/ComponentProvider/Trace/SamplerParentBased.php | 3 +++ .../ComponentProvider/Trace/SamplerTraceIdRatioBased.php | 3 +++ .../SDK/ComponentProvider/Trace/SpanExporterConsole.php | 3 +++ src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php | 3 +++ .../SDK/ComponentProvider/Trace/SpanExporterZipkin.php | 3 +++ .../SDK/ComponentProvider/Trace/SpanProcessorBatch.php | 3 +++ .../SDK/ComponentProvider/Trace/SpanProcessorSimple.php | 3 +++ src/Config/SDK/Configuration.php | 3 +++ src/Contrib/Otlp/OtlpUtil.php | 2 +- 27 files changed, 79 insertions(+), 5 deletions(-) diff --git a/psalm.xml.dist b/psalm.xml.dist index 697293abc..905e3b7d9 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -31,11 +31,11 @@ - + - + diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php index 19ced2126..a978516c5 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php @@ -12,6 +12,9 @@ use OpenTelemetry\SDK\Registry; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class LogRecordExporterConsole implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php index 10c5d6762..2be5fd161 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php @@ -17,6 +17,9 @@ use OpenTelemetry\SDK\Registry; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ #[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] final class LogRecordExporterOtlp implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php index f45ee0215..712ca871b 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php @@ -14,6 +14,9 @@ use OpenTelemetry\SDK\Logs\Processor\BatchLogRecordProcessor; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class LogRecordProcessorBatch implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php index 4a0ba5e3a..edbaaa552 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php @@ -13,6 +13,9 @@ use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class LogRecordProcessorSimple implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php index 636676830..d96cf3040 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php +++ b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php @@ -11,6 +11,9 @@ use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderTrait; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class AggregationResolverDefault implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php index 5e55d9f36..6fba58cc5 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php @@ -11,6 +11,9 @@ use OpenTelemetry\SDK\Metrics\MetricExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class MetricExporterConsole implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php index 85026fb18..5547de09c 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php @@ -18,6 +18,9 @@ use OpenTelemetry\SDK\Registry; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ #[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] final class MetricExporterOtlp implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php index 35464c056..0e77e2008 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php @@ -13,6 +13,9 @@ use OpenTelemetry\SDK\Metrics\MetricReaderInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class MetricReaderPeriodic implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index b1f78abb6..c8a11fbe1 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -43,6 +43,8 @@ /** * @internal + * + * @implements ComponentProvider */ final class OpenTelemetrySdk implements ComponentProvider { @@ -82,7 +84,7 @@ final class OpenTelemetrySdk implements ComponentProvider * }, * selector: array{ * instrument_type: 'counter'|'histogram'|'observable_counter'|'observable_gauge'|'observable_up_down_counter'|'up_down_counter'|null, - * instrument_name: ?string, + * instrument_name: ?non-empty-string, * unit: ?string, * meter_name: ?string, * meter_version: ?string, @@ -359,7 +361,7 @@ private function getMeterProviderConfig(ComponentProviderRegistry $registry): Ar ]) ->defaultNull() ->end() - ->scalarNode('instrument_name')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('instrument_name')->defaultNull()->validate()->always(Validation::ensureString())->end()->cannotBeEmpty()->end() ->scalarNode('unit')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('meter_name')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->scalarNode('meter_version')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php index 68ae74680..9640f1e32 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php @@ -12,6 +12,9 @@ use OpenTelemetry\Extension\Propagator\B3\B3Propagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ #[PackageDependency('open-telemetry/extension-propagator-b3', '^1.0.1')] final class TextMapPropagatorB3 implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php index 398feb2a1..787e99911 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php @@ -12,6 +12,9 @@ use OpenTelemetry\Extension\Propagator\B3\B3Propagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ #[PackageDependency('open-telemetry/extension-propagator-b3', '^1.0.1')] final class TextMapPropagatorB3Multi implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php index 5e8384cc2..ecfde7fa1 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php @@ -11,6 +11,9 @@ use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class TextMapPropagatorBaggage implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php index 7c2460f91..6eba5391a 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php @@ -12,6 +12,9 @@ use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class TextMapPropagatorComposite implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php index 42cea1ce2..6d8e2f4a7 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php @@ -12,6 +12,9 @@ use OpenTelemetry\Extension\Propagator\Jaeger\JaegerPropagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ #[PackageDependency('open-telemetry/extension-propagator-jaeger', '^0.0.2')] final class TextMapPropagatorJaeger implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php index 2181a548f..0913be336 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php @@ -11,6 +11,9 @@ use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class TextMapPropagatorTraceContext implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php index 2b20debb5..7da8a2d25 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php @@ -11,6 +11,9 @@ use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplerAlwaysOff implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php index 94db29364..15dbe61b6 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php @@ -11,6 +11,9 @@ use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplerAlwaysOn implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php index 21745f451..121282359 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php @@ -14,6 +14,9 @@ use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplerParentBased implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php index 87fa5e429..c66d203da 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php @@ -11,6 +11,9 @@ use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SamplerTraceIdRatioBased implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php index b60e09158..f36fe5258 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php @@ -12,6 +12,9 @@ use OpenTelemetry\SDK\Trace\SpanExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SpanExporterConsole implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php index 909f105b9..6166bd725 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php @@ -17,6 +17,9 @@ use OpenTelemetry\SDK\Trace\SpanExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ #[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] final class SpanExporterOtlp implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php index 509f7b4e2..4e13f49ea 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php @@ -14,6 +14,9 @@ use OpenTelemetry\SDK\Trace\SpanExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ #[PackageDependency('open-telemetry/exporter-zipkin', '^1.0')] final class SpanExporterZipkin implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php index 1dae2f079..3688473f0 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php @@ -14,6 +14,9 @@ use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SpanProcessorBatch implements ComponentProvider { diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php index 77a1efefe..ad15e00d4 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php @@ -13,6 +13,9 @@ use OpenTelemetry\SDK\Trace\SpanProcessorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +/** + * @implements ComponentProvider + */ final class SpanProcessorSimple implements ComponentProvider { diff --git a/src/Config/SDK/Configuration.php b/src/Config/SDK/Configuration.php index 6a2c8eeae..b06f596e7 100644 --- a/src/Config/SDK/Configuration.php +++ b/src/Config/SDK/Configuration.php @@ -31,6 +31,9 @@ public function create(Context $context = new Context()): SdkBuilder return $this->sdkPlugin->create($context); } + /** + * @param string|list $file + */ public static function parseFile( string|array $file, ?string $cacheFile = null, diff --git a/src/Contrib/Otlp/OtlpUtil.php b/src/Contrib/Otlp/OtlpUtil.php index 1ed4ce64a..3de3085d6 100644 --- a/src/Contrib/Otlp/OtlpUtil.php +++ b/src/Contrib/Otlp/OtlpUtil.php @@ -50,7 +50,7 @@ public static function path(string $signal, string $protocol): string Signals::TRACE => '/v1/traces', Signals::METRICS => '/v1/metrics', Signals::LOGS => '/v1/logs', - } + }, }; } From e617606b1a19378c046a03409e9f0c35e83102f9 Mon Sep 17 00:00:00 2001 From: Tobias Bachert Date: Fri, 15 Mar 2024 22:50:32 +0100 Subject: [PATCH 14/15] Fix composer requirement for PRs --- composer.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 42b9423f7..6a3ef6e45 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "require": { "php": "^8.1", "google/protobuf": "^3.22", - "open-telemetry/sdk-configuration": "^0.1-dev", + "open-telemetry/sdk-configuration": "@dev", "php-http/discovery": "^1.14", "psr/http-client-implementation": "^1.0", "psr/http-factory-implementation": "^1.0", @@ -41,16 +41,16 @@ } ], "replace": { - "open-telemetry/api": "self.version", - "open-telemetry/context": "self.version", + "open-telemetry/api": "1.0.x-dev", + "open-telemetry/context": "1.0.x-dev", "open-telemetry/exporter-otlp": "1.0.x-dev", "open-telemetry/exporter-zipkin": "1.0.x-dev", "open-telemetry/extension-propagator-b3": "1.0.x-dev", "open-telemetry/extension-propagator-jaeger": "0.0.2", - "open-telemetry/gen-otlp-protobuf": "self.version", - "open-telemetry/sdk": "self.version", - "open-telemetry/sdk-contrib": "self.version", - "open-telemetry/sem-conv": "self.version" + "open-telemetry/gen-otlp-protobuf": "1.0.x-dev", + "open-telemetry/sdk": "1.0.x-dev", + "open-telemetry/sdk-contrib": "1.0.x-dev", + "open-telemetry/sem-conv": "1.0.x-dev" }, "autoload": { "psr-4": { From ae980ecdbd6b363235ce819e4fc7b611e9959851 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 28 Mar 2024 13:51:49 +1100 Subject: [PATCH 15/15] gitsplit, copy spi config to root composer.json --- .gitsplit.yml | 2 ++ composer.json | 44 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/.gitsplit.yml b/.gitsplit.yml index f21429504..9f7eb8289 100644 --- a/.gitsplit.yml +++ b/.gitsplit.yml @@ -16,6 +16,8 @@ splits: target: "https://${GH_TOKEN}@github.com/opentelemetry-php/api.git" - prefix: "src/SDK" target: "https://${GH_TOKEN}@github.com/opentelemetry-php/sdk.git" + - prefix: "src/Config/SDK" + target: "https://${GH_TOKEN}@github.com/opentelemetry-php/config-sdk.git" - prefix: "src/Contrib/Otlp" target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-otlp.git" - prefix: "src/Contrib/Grpc" diff --git a/composer.json b/composer.json index 6a3ef6e45..97623072a 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,6 @@ "require": { "php": "^8.1", "google/protobuf": "^3.22", - "open-telemetry/sdk-configuration": "@dev", "php-http/discovery": "^1.14", "psr/http-client-implementation": "^1.0", "psr/http-factory-implementation": "^1.0", @@ -17,14 +16,10 @@ "psr/http-message": "^1.0.1|^2.0", "psr/log": "^1.1|^2.0|^3.0", "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php82": "^1.26" + "symfony/polyfill-php82": "^1.26", + "tbachert/otel-sdk-configuration": "^0.1", + "tbachert/spi": "^0.2" }, - "repositories": [ - { - "type": "path", - "url": "src/Config/SDK" - } - ], "config": { "sort-packages": true, "allow-plugins": { @@ -49,6 +44,7 @@ "open-telemetry/extension-propagator-jaeger": "0.0.2", "open-telemetry/gen-otlp-protobuf": "1.0.x-dev", "open-telemetry/sdk": "1.0.x-dev", + "open-telemetry/sdk-configuration": "0.1.x-dev", "open-telemetry/sdk-contrib": "1.0.x-dev", "open-telemetry/sem-conv": "1.0.x-dev" }, @@ -120,5 +116,37 @@ "ext-gmp": "To support unlimited number of synchronous metric readers", "ext-grpc": "To use the OTLP GRPC Exporter", "ext-protobuf": "For more performant protobuf/grpc exporting" + }, + "extra": { + "spi": { + "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3Multi", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorBaggage", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorComposite", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorJaeger", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorTraceContext", + + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerAlwaysOff", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerAlwaysOn", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerParentBased", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SamplerTraceIdRatioBased", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterConsole", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterZipkin", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorBatch", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanProcessorSimple", + + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\AggregationResolverDefault", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterConsole", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricReaderPeriodic", + + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterConsole", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorBatch", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorSimple" + ] + } } }