From a4119f9e327e9434d8f4a566657bdd5294c9e0e2 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Tue, 21 Jan 2025 10:35:16 +1100 Subject: [PATCH] support refactored otlp export config (#1477) upstream config now splits otlp exporters into otlp_http and otlp_grpc * use const, remove insecure from otlp_http config * Apply suggestions from code review Co-authored-by: Tobias Bachert * set default endpoints, fix review feedback * move endpoint out of yaml anchor * convert timeouts from millis to seconds --------- Co-authored-by: Tobias Bachert --- composer.json | 13 +- src/API/Common/Time/ClockInterface.php | 1 + ...Otlp.php => LogRecordExporterOtlpGrpc.php} | 17 +- .../Logs/LogRecordExporterOtlpHttp.php | 85 ++++++++++ ...terOtlp.php => MetricExporterOtlpGrpc.php} | 16 +- .../Metrics/MetricExporterOtlpHttp.php | 102 ++++++++++++ ...orterOtlp.php => SpanExporterOtlpGrpc.php} | 17 +- .../Trace/SpanExporterOtlpHttp.php | 85 ++++++++++ .../Trace/SpanExporterZipkin.php | 5 +- src/Config/SDK/composer.json | 9 +- .../Config/configurations/anchors.yaml | 12 +- .../Config/configurations/kitchen-sink.yaml | 154 +++++++++++++++--- 12 files changed, 452 insertions(+), 64 deletions(-) rename src/Config/SDK/ComponentProvider/Logs/{LogRecordExporterOtlp.php => LogRecordExporterOtlpGrpc.php} (87%) create mode 100644 src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlpHttp.php rename src/Config/SDK/ComponentProvider/Metrics/{MetricExporterOtlp.php => MetricExporterOtlpGrpc.php} (89%) create mode 100644 src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlpHttp.php rename src/Config/SDK/ComponentProvider/Trace/{SpanExporterOtlp.php => SpanExporterOtlpGrpc.php} (87%) create mode 100644 src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlpHttp.php diff --git a/composer.json b/composer.json index 1bd398734..3f55b60ea 100644 --- a/composer.json +++ b/composer.json @@ -44,12 +44,14 @@ "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-cloudtrace": "1.0.x-dev", "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" + "open-telemetry/sem-conv": "1.0.x-dev", + "open-telemetry/transport-grpc": "1.0.x-dev" }, "autoload": { "psr-4": { @@ -137,18 +139,21 @@ "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\\SpanExporterOtlpGrpc", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterOtlpHttp", "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\\MetricExporterOtlpGrpc", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterOtlpHttp", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricReaderPeriodic", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterConsole", - "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlpGrpc", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlpHttp", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorBatch", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorSimple", diff --git a/src/API/Common/Time/ClockInterface.php b/src/API/Common/Time/ClockInterface.php index f16fbbf5d..b4a953c11 100644 --- a/src/API/Common/Time/ClockInterface.php +++ b/src/API/Common/Time/ClockInterface.php @@ -9,6 +9,7 @@ interface ClockInterface public const NANOS_PER_SECOND = 1_000_000_000; public const NANOS_PER_MILLISECOND = 1_000_000; public const NANOS_PER_MICROSECOND = 1_000; + public const MILLIS_PER_SECOND = 1_000; /** * Returns the current epoch wall-clock timestamp in nanoseconds diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlpGrpc.php similarity index 87% rename from src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php rename to src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlpGrpc.php index e580e7782..79540c094 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlpGrpc.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Logs; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\API\Common\Time\ClockInterface; use OpenTelemetry\API\Signals; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; @@ -23,11 +24,11 @@ * @implements ComponentProvider */ #[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] -final class LogRecordExporterOtlp implements ComponentProvider +#[PackageDependency('open-telemetry/transport-grpc', '^1')] +final class LogRecordExporterOtlpGrpc implements ComponentProvider { /** * @param array{ - * protocol: 'http/protobuf'|'http/json'|'grpc', * endpoint: string, * certificate: ?string, * client_key: ?string, @@ -41,8 +42,7 @@ final class LogRecordExporterOtlp implements ComponentProvider */ public function createPlugin(array $properties, Context $context): LogRecordExporterInterface { - $protocol = $properties['protocol']; - + $protocol = Protocols::GRPC; $headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']); return new LogsExporter(Registry::transportFactory($protocol)->create( @@ -50,7 +50,7 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo contentType: Protocols::contentType($protocol), headers: $headers, compression: $properties['compression'], - timeout: $properties['timeout'], + timeout: $properties['timeout'] / ClockInterface::MILLIS_PER_SECOND, cacert: $properties['certificate'], cert: $properties['client_certificate'], key: $properties['client_certificate'], @@ -59,11 +59,10 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = $builder->arrayNode('otlp'); + $node = $builder->arrayNode('otlp_grpc'); $node ->children() - ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() - ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('endpoint')->defaultValue('http://localhost:4317')->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() @@ -77,7 +76,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil ->end() ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->enumNode('compression')->values(['gzip'])->defaultNull()->end() - ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->integerNode('timeout')->min(0)->defaultValue(10000)->end() ->booleanNode('insecure')->defaultNull()->end() ->end() ; diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlpHttp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlpHttp.php new file mode 100644 index 000000000..9a6c23279 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlpHttp.php @@ -0,0 +1,85 @@ + + */ +#[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] +final class LogRecordExporterOtlpHttp implements ComponentProvider +{ + /** + * @param array{ + * endpoint: string, + * certificate: ?string, + * client_key: ?string, + * client_certificate: ?string, + * headers: list, + * headers_list: ?string, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * encoding: 'protobuf'|'json', + * } $properties + */ + public function createPlugin(array $properties, Context $context): LogRecordExporterInterface + { + $headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']); + + return new LogsExporter(Registry::transportFactory('http')->create( + endpoint: $properties['endpoint'], + contentType: match ($properties['encoding']) { + 'protobuf' => ContentTypes::PROTOBUF, + 'json' => ContentTypes::JSON, + }, + headers: $headers, + compression: $properties['compression'], + timeout: $properties['timeout'] / ClockInterface::MILLIS_PER_SECOND, + cacert: $properties['certificate'], + cert: $properties['client_certificate'], + key: $properties['client_certificate'], + )); + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + $node = $builder->arrayNode('otlp_http'); + $node + ->children() + ->enumNode('encoding')->defaultValue('protobuf')->values(['protobuf', 'json'])->end() + ->scalarNode('endpoint')->defaultValue('http://localhost:4318/v1/logs')->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') + ->arrayPrototype() + ->children() + ->scalarNode('name')->isRequired()->cannotBeEmpty()->end() + ->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->end() + ->end() + ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->enumNode('compression')->values(['gzip'])->defaultNull()->end() + ->integerNode('timeout')->min(0)->defaultValue(10000)->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlpGrpc.php similarity index 89% rename from src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php rename to src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlpGrpc.php index f92872b49..8260539fd 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlpGrpc.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Metrics; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\API\Common\Time\ClockInterface; use OpenTelemetry\API\Signals; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; @@ -24,11 +25,11 @@ * @implements ComponentProvider */ #[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] -final class MetricExporterOtlp implements ComponentProvider +#[PackageDependency('open-telemetry/transport-grpc', '^1')] +final class MetricExporterOtlpGrpc implements ComponentProvider { /** * @param array{ - * protocol: 'http/protobuf'|'http/json'|'grpc', * endpoint: string, * certificate: ?string, * client_key: ?string, @@ -44,7 +45,7 @@ final class MetricExporterOtlp implements ComponentProvider */ public function createPlugin(array $properties, Context $context): MetricExporterInterface { - $protocol = $properties['protocol']; + $protocol = Protocols::GRPC; $headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']); @@ -59,7 +60,7 @@ public function createPlugin(array $properties, Context $context): MetricExporte contentType: Protocols::contentType($protocol), headers: $headers, compression: $properties['compression'], - timeout: $properties['timeout'], + timeout: $properties['timeout'] / ClockInterface::MILLIS_PER_SECOND, cacert: $properties['certificate'], cert: $properties['client_certificate'], key: $properties['client_certificate'], @@ -68,11 +69,10 @@ public function createPlugin(array $properties, Context $context): MetricExporte public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = $builder->arrayNode('otlp'); + $node = $builder->arrayNode('otlp_grpc'); $node ->children() - ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() - ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('endpoint')->defaultValue('http://localhost:4317')->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() @@ -86,7 +86,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil ->end() ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->enumNode('compression')->values(['gzip'])->defaultNull()->validate()->always(Validation::ensureString())->end()->end() - ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->integerNode('timeout')->min(0)->defaultValue(10000)->end() ->booleanNode('insecure')->defaultNull()->end() ->enumNode('temporality_preference') ->values(['cumulative', 'delta', 'lowmemory']) diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlpHttp.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlpHttp.php new file mode 100644 index 000000000..0690a5913 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlpHttp.php @@ -0,0 +1,102 @@ + + */ +#[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] +final class MetricExporterOtlpHttp implements ComponentProvider +{ + /** + * @param array{ + * encoding: 'protobuf'|'json', + * endpoint: string, + * certificate: ?string, + * client_key: ?string, + * client_certificate: ?string, + * headers: list, + * headers_list: ?string, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * temporality_preference: 'cumulative'|'delta'|'lowmemory', + * default_histogram_aggregation: 'explicit_bucket_histogram|base2_exponential_bucket_histogram', + * } $properties + */ + public function createPlugin(array $properties, Context $context): MetricExporterInterface + { + $headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']); + + $temporality = match ($properties['temporality_preference']) { + 'cumulative' => Temporality::CUMULATIVE, + 'delta' => Temporality::DELTA, + 'lowmemory' => null, + }; + + return new MetricExporter(Registry::transportFactory('http')->create( + endpoint: $properties['endpoint'], + contentType: match ($properties['encoding']) { + 'protobuf' => ContentTypes::PROTOBUF, + 'json' => ContentTypes::JSON, + }, + headers: $headers, + compression: $properties['compression'], + timeout: $properties['timeout'] / ClockInterface::MILLIS_PER_SECOND, + cacert: $properties['certificate'], + cert: $properties['client_certificate'], + key: $properties['client_certificate'], + ), $temporality); + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + $node = $builder->arrayNode('otlp_http'); + $node + ->children() + ->enumNode('encoding')->defaultValue('protobuf')->values(['protobuf', 'json'])->end() + ->scalarNode('endpoint')->defaultValue('http://localhost:4318/v1/metrics')->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') + ->arrayPrototype() + ->children() + ->scalarNode('name')->isRequired()->cannotBeEmpty()->end() + ->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->end() + ->end() + ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->enumNode('compression')->values(['gzip'])->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->integerNode('timeout')->min(0)->defaultValue(10000)->end() + ->enumNode('temporality_preference') + ->values(['cumulative', 'delta', 'lowmemory']) + ->defaultValue('cumulative') + ->end() + ->enumNode('default_histogram_aggregation') + ->values(['explicit_bucket_histogram', 'base2_exponential_bucket_histogram']) + ->defaultValue('explicit_bucket_histogram') + ->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlpGrpc.php similarity index 87% rename from src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php rename to src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlpGrpc.php index 83140c5fd..45fd6dde0 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlpGrpc.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\API\Common\Time\ClockInterface; use OpenTelemetry\API\Signals; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; @@ -23,11 +24,11 @@ * @implements ComponentProvider */ #[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] -final class SpanExporterOtlp implements ComponentProvider +#[PackageDependency('open-telemetry/transport-grpc', '^1')] +final class SpanExporterOtlpGrpc implements ComponentProvider { /** * @param array{ - * protocol: 'http/protobuf'|'http/json'|'grpc', * endpoint: string, * certificate: ?string, * client_key: ?string, @@ -41,8 +42,7 @@ final class SpanExporterOtlp implements ComponentProvider */ public function createPlugin(array $properties, Context $context): SpanExporterInterface { - $protocol = $properties['protocol']; - + $protocol = Protocols::GRPC; $headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']); return new SpanExporter(Registry::transportFactory($protocol)->create( @@ -50,7 +50,7 @@ public function createPlugin(array $properties, Context $context): SpanExporterI contentType: Protocols::contentType($protocol), headers: $headers, compression: $properties['compression'], - timeout: $properties['timeout'], + timeout: $properties['timeout'] / ClockInterface::MILLIS_PER_SECOND, cacert: $properties['certificate'], cert: $properties['client_certificate'], key: $properties['client_certificate'], @@ -59,11 +59,10 @@ public function createPlugin(array $properties, Context $context): SpanExporterI public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition { - $node = $builder->arrayNode('otlp'); + $node = $builder->arrayNode('otlp_grpc'); $node ->children() - ->enumNode('protocol')->isRequired()->values(['http/protobuf', 'http/json', 'grpc'])->end() - ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() + ->scalarNode('endpoint')->defaultValue('http://localhost:4317')->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() @@ -77,7 +76,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil ->end() ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() ->enumNode('compression')->values(['gzip'])->defaultNull()->end() - ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->integerNode('timeout')->min(0)->defaultValue(10000)->end() ->booleanNode('insecure')->defaultNull()->end() ->end() ; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlpHttp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlpHttp.php new file mode 100644 index 000000000..ab8433b87 --- /dev/null +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlpHttp.php @@ -0,0 +1,85 @@ + + */ +#[PackageDependency('open-telemetry/exporter-otlp', '^1.0.5')] +final class SpanExporterOtlpHttp implements ComponentProvider +{ + /** + * @param array{ + * endpoint: string, + * certificate: ?string, + * client_key: ?string, + * client_certificate: ?string, + * headers: list, + * headers_list: ?string, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * encoding: 'protobuf'|'json', + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanExporterInterface + { + $headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']); + + return new SpanExporter(Registry::transportFactory('http')->create( + endpoint: $properties['endpoint'], + contentType: match ($properties['encoding']) { + 'protobuf' => ContentTypes::PROTOBUF, + 'json' => ContentTypes::JSON, + }, + headers: $headers, + compression: $properties['compression'], + timeout: $properties['timeout'] / ClockInterface::MILLIS_PER_SECOND, + cacert: $properties['certificate'], + cert: $properties['client_certificate'], + key: $properties['client_certificate'], + )); + } + + public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $builder): ArrayNodeDefinition + { + $node = $builder->arrayNode('otlp_http'); + $node + ->children() + ->enumNode('encoding')->defaultValue('protobuf')->values(['protobuf', 'json'])->end() + ->scalarNode('endpoint')->defaultValue('http://localhost:4318/v1/traces')->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') + ->arrayPrototype() + ->children() + ->scalarNode('name')->isRequired()->cannotBeEmpty()->end() + ->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->end() + ->end() + ->end() + ->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end() + ->enumNode('compression')->values(['gzip'])->defaultNull()->end() + ->integerNode('timeout')->min(0)->defaultValue(10000)->end() + ->end() + ; + + return $node; + } +} diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php index 4451ef151..09cc19a19 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\API\Common\Time\ClockInterface; use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; use OpenTelemetry\Config\SDK\Configuration\Context; @@ -32,7 +33,7 @@ public function createPlugin(array $properties, Context $context): SpanExporterI return new Zipkin\Exporter(Registry::transportFactory('http')->create( endpoint: $properties['endpoint'], contentType: 'application/json', - timeout: $properties['timeout'], + timeout: $properties['timeout'] / ClockInterface::MILLIS_PER_SECOND, )); } @@ -42,7 +43,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil $node ->children() ->scalarNode('endpoint')->isRequired()->validate()->always(Validation::ensureString())->end()->end() - ->integerNode('timeout')->min(0)->defaultValue(10)->end() + ->integerNode('timeout')->min(0)->defaultValue(10000)->end() ->end() ; diff --git a/src/Config/SDK/composer.json b/src/Config/SDK/composer.json index ebb5c691d..8a71d42ec 100644 --- a/src/Config/SDK/composer.json +++ b/src/Config/SDK/composer.json @@ -51,18 +51,21 @@ "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\\SpanExporterOtlpGrpc", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Trace\\SpanExporterOtlpHttp", "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\\MetricExporterOtlpGrpc", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricExporterOtlpHttp", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Metrics\\MetricReaderPeriodic", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterConsole", - "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlp", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlpGrpc", + "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordExporterOtlpHttp", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorBatch", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Logs\\LogRecordProcessorSimple", diff --git a/tests/Integration/Config/configurations/anchors.yaml b/tests/Integration/Config/configurations/anchors.yaml index ec042a129..1cd3f926e 100644 --- a/tests/Integration/Config/configurations/anchors.yaml +++ b/tests/Integration/Config/configurations/anchors.yaml @@ -3,8 +3,7 @@ file_format: "0.3" exporters: otlp: &otlp-exporter - protocol: http/protobuf - endpoint: http://localhost:4318 + encoding: protobuf certificate: /app/cert.pem client_key: /app/cert.pem client_certificate: /app/cert.pem @@ -18,9 +17,10 @@ logger_provider: processors: - batch: exporter: - otlp: + otlp_http: # expand the otlp-exporter anchor <<: *otlp-exporter + endpoint: http://localhost:4318/v1/logs meter_provider: readers: @@ -28,9 +28,10 @@ meter_provider: interval: 5000 timeout: 30000 exporter: - otlp: + otlp_http: # expand the otlp-exporter anchor and add metric specific configuration <<: *otlp-exporter + endpoint: http://localhost:4318/v1/metrics temporality_preference: delta tracer_provider: @@ -39,9 +40,10 @@ tracer_provider: processors: - batch: exporter: - otlp: + otlp_http: # expand the otlp-exporter anchor <<: *otlp-exporter + endpoint: http://localhost:4318/v1/traces propagator: composite: [] \ No newline at end of file diff --git a/tests/Integration/Config/configurations/kitchen-sink.yaml b/tests/Integration/Config/configurations/kitchen-sink.yaml index 0f214721d..539d9dcca 100644 --- a/tests/Integration/Config/configurations/kitchen-sink.yaml +++ b/tests/Integration/Config/configurations/kitchen-sink.yaml @@ -41,12 +41,8 @@ logger_provider: max_export_batch_size: 512 # Configure exporter. exporter: - # Configure exporter to be OTLP. - otlp: - # Configure protocol. Values include: http/protobuf, http/json, grpc. - protocol: http/protobuf - # Configure endpoint. - # If .protocol is http/protobuf or http/json, the signal specific path must be included (i.e. http://localhost:4318/v1/{signal}). If .protocol is grpc, a path should not be included (i.e. http://localhost:4317). + # Configure exporter to be OTLP with HTTP transport. + otlp_http: endpoint: http://localhost:4318/v1/logs # Configure certificate. Absolute path to certificate file. # If omitted or null, system default certificate verification is used for secure connections. @@ -72,7 +68,43 @@ logger_provider: # Configure max time (in milliseconds) to wait for each export. # If omitted or null, 10000 is used. timeout: 10000 - # Configure client transport security for the exporter's connection. Only applicable when .protocol is grpc and .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # Configure the encoding used for messages. Values include: protobuf, json. Implementations may not support json. + # If omitted or null, protobuf is used. + encoding: protobuf + - # Configure a batch log record processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with gRPC transport. + otlp_grpc: + # Configure endpoint. + # If omitted or null, http://localhost:4317 is used. + endpoint: http://localhost:4317 + # Configure certificate. Absolute path to certificate file. + # If omitted or null, system default certificate verification is used for secure connections. + certificate: /app/cert.pem + # Configure mTLS private client key. Absolute path to client key in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key: /app/cert.pem + # Configure mTLS client certificate. Absolute path to certificate file. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. # If omitted or null, false is used. insecure: false - # Configure a simple log record processor. @@ -145,12 +177,10 @@ meter_provider: timeout: 30000 # Configure exporter. exporter: - # Configure exporter to be OTLP. - otlp: - # Configure protocol. Values include: http/protobuf, http/json, grpc. - protocol: http/protobuf - # Configure endpoint. - # If .protocol is http/protobuf or http/json, the signal specific path must be included (i.e. http://localhost:4318/v1/{signal}). If .protocol is grpc, a path should not be included (i.e. http://localhost:4317). + # Configure exporter to be OTLP with HTTP transport. + otlp_http: + # Configure endpoint, including the metric specific path. + # If omitted or null, http://localhost:4318/v1/metrics is used. endpoint: http://localhost:4318/v1/metrics # Configure certificate. Absolute path to certificate file. # If omitted or null, system default certificate verification is used for secure connections. @@ -176,9 +206,9 @@ meter_provider: # Configure max time (in milliseconds) to wait for each export. # If omitted or null, 10000 is used. timeout: 10000 - # Configure client transport security for the exporter's connection. Only applicable when .protocol is grpc and .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. - # If omitted or null, false is used. - insecure: false + # Configure the encoding used for messages. Values include: protobuf, json. Implementations may not support json. + # If omitted or null, protobuf is used. + encoding: protobuf # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. # If omitted or null, cumulative is used. temporality_preference: delta @@ -189,6 +219,48 @@ meter_provider: producers: - # Configure metric producer to be prometheus. prometheus: + - # Configure a periodic metric reader. + periodic: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with gRPC transport. + otlp_grpc: + # Configure endpoint. + # If omitted or null, http://localhost:4317 is used. + endpoint: http://localhost:4317 + # Configure certificate. Absolute path to certificate file. + # If omitted or null, system default certificate verification is used for secure connections. + certificate: /app/cert.pem + # Configure mTLS private client key. Absolute path to client key in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key: /app/cert.pem + # Configure mTLS client certificate. Absolute path to certificate file. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # If omitted or null, false is used. + insecure: false + # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, cumulative is used. + temporality_preference: delta + # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, explicit_bucket_histogram is used. + default_histogram_aggregation: base2_exponential_bucket_histogram - # Configure a periodic metric reader. periodic: # Configure exporter. @@ -216,7 +288,7 @@ meter_provider: meter_version: 1.0.0 # Configure meter schema url selection criteria. # If omitted or null, all meter schema URLs match. - meter_schema_url: https://opentelemetry.io/schemas/1.16.0 + meter_schema_url: https://opentelemetry.io/schemas/1.27.0 # Configure view stream. stream: # Configure metric name of the resulting stream(s). @@ -293,12 +365,10 @@ tracer_provider: max_export_batch_size: 512 # Configure exporter. exporter: - # Configure exporter to be OTLP. - otlp: - # Configure protocol. Values include: http/protobuf, http/json, grpc. - protocol: http/protobuf - # Configure endpoint. - # If .protocol is http/protobuf or http/json, the signal specific path must be included (i.e. http://localhost:4318/v1/{signal}). If .protocol is grpc, a path should not be included (i.e. http://localhost:4317). + # Configure exporter to be OTLP with HTTP transport. + otlp_http: + # Configure endpoint, including the trace specific path. + # If omitted or null, http://localhost:4318/v1/traces is used. endpoint: http://localhost:4318/v1/traces # Configure certificate. Absolute path to certificate file. # If omitted or null, system default certificate verification is used for secure connections. @@ -324,7 +394,43 @@ tracer_provider: # Configure max time (in milliseconds) to wait for each export. # If omitted or null, 10000 is used. timeout: 10000 - # Configure client transport security for the exporter's connection. Only applicable when .protocol is grpc and .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # Configure the encoding used for messages. Values include: protobuf, json. Implementations may not support json. + # If omitted or null, protobuf is used. + encoding: protobuf + - # Configure a batch span processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with gRPC transport. + otlp_grpc: + # Configure endpoint. + # If omitted or null, http://localhost:4317 is used. + endpoint: http://localhost:4317 + # Configure certificate. Absolute path to certificate file. + # If omitted or null, system default certificate verification is used for secure connections. + certificate: /app/cert.pem + # Configure mTLS private client key. Absolute path to client key in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key: /app/cert.pem + # Configure mTLS client certificate. Absolute path to certificate file. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. # If omitted or null, false is used. insecure: false - # Configure a batch span processor.