From 43339294f5f32c31eb8271e2612399de3d5b5279 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 15 Apr 2024 23:15:37 +1000 Subject: [PATCH] port Nevay/otel-sdk-configuration into opentelemetry-php (#1276) * port Nevay/otel-sdk-configuration into opentelemetry-php This is a lift-and-shift, except for: - changing namespaces - fixes or ignore rules required to make static analysis tools happy - commenting out one part of yaml test (unquoted hex value from env var) * fix psalm on php81 --- composer.json | 14 +- phpstan.neon.dist | 1 + psalm.xml.dist | 1 + .../Logs/LogRecordExporterConsole.php | 6 +- .../Logs/LogRecordExporterOtlp.php | 8 +- .../Logs/LogRecordProcessorBatch.php | 8 +- .../Logs/LogRecordProcessorSimple.php | 8 +- .../Metrics/AggregationResolverDefault.php | 6 +- .../Metrics/MetricExporterConsole.php | 6 +- .../Metrics/MetricExporterOtlp.php | 8 +- .../Metrics/MetricReaderPeriodic.php | 8 +- .../ComponentProvider/OpenTelemetrySdk.php | 10 +- .../Propagator/TextMapPropagatorB3.php | 6 +- .../Propagator/TextMapPropagatorB3Multi.php | 6 +- .../Propagator/TextMapPropagatorBaggage.php | 6 +- .../Propagator/TextMapPropagatorComposite.php | 8 +- .../Propagator/TextMapPropagatorJaeger.php | 6 +- .../TextMapPropagatorTraceContext.php | 6 +- .../Trace/SamplerAlwaysOff.php | 6 +- .../Trace/SamplerAlwaysOn.php | 6 +- .../Trace/SamplerParentBased.php | 8 +- .../Trace/SamplerTraceIdRatioBased.php | 6 +- .../Trace/SpanExporterConsole.php | 6 +- .../Trace/SpanExporterOtlp.php | 8 +- .../Trace/SpanExporterZipkin.php | 8 +- .../Trace/SpanProcessorBatch.php | 8 +- .../Trace/SpanProcessorSimple.php | 8 +- src/Config/SDK/Configuration.php | 14 +- .../SDK/Configuration/ComponentPlugin.php | 22 + .../SDK/Configuration/ComponentProvider.php | 39 ++ .../ComponentProviderRegistry.php | 68 +++ .../Configuration/ConfigurationFactory.php | 150 +++++++ src/Config/SDK/Configuration/Context.php | 31 ++ .../Environment/ArrayEnvSource.php | 19 + .../Configuration/Environment/EnvReader.php | 11 + .../Configuration/Environment/EnvResource.php | 22 + .../Environment/EnvResourceChecker.php | 30 ++ .../Configuration/Environment/EnvSource.php | 11 + .../Environment/EnvSourceReader.php | 31 ++ .../Environment/PhpIniEnvSource.php | 16 + .../Environment/ServerEnvSource.php | 14 + .../Internal/ArrayNodeDefaultNull.php | 35 ++ .../ArrayNodeDefaultNullDefinition.php | 25 ++ .../Internal/CompiledConfigurationFactory.php | 55 +++ .../Internal/ComponentPlugin.php | 33 ++ .../Internal/ComponentProviderRegistry.php | 187 +++++++++ .../Internal/ComposerPackageResource.php | 44 ++ .../Internal/ConfigurationLoader.php | 38 ++ .../Internal/EnvSubstitutionNormalization.php | 101 +++++ .../Internal/ResourceCollection.php | 102 +++++ .../Internal/ResourceTrackable.php | 13 + .../Internal/TrackingEnvReader.php | 37 ++ .../TreatNullAsUnsetNormalization.php | 34 ++ .../Loader/ConfigurationLoader.php | 15 + .../Loader/YamlExtensionFileLoader.php | 51 +++ .../Loader/YamlSymfonyFileLoader.php | 55 +++ src/Config/SDK/Configuration/README.md | 70 ++++ .../SDK/Configuration/ResourceCollection.php | 23 ++ src/Config/SDK/Configuration/Validation.php | 74 ++++ src/Config/SDK/composer.json | 10 +- .../ConfigurationFactoryTest.php | 242 +++++++++++ .../Logs/LogRecordExporterConsole.php | 29 ++ .../ExampleSdk/Logs/LogRecordExporterOtlp.php | 55 +++ .../Logs/LogRecordProcessorBatch.php | 48 +++ .../Logs/LogRecordProcessorSimple.php | 40 ++ .../Metrics/AggregationResolverDefault.php | 29 ++ .../Metrics/AggregationResolverDrop.php | 29 ++ ...egationResolverExplicitBucketHistogram.php | 58 +++ .../Metrics/AggregationResolverLastValue.php | 29 ++ .../Metrics/AggregationResolverSum.php | 29 ++ .../Metrics/MetricExporterConsole.php | 29 ++ .../ExampleSdk/Metrics/MetricExporterOtlp.php | 65 +++ .../Metrics/MetricExporterPrometheus.php | 47 +++ .../Metrics/MetricReaderPeriodic.php | 44 ++ .../ExampleSdk/Metrics/MetricReaderPull.php | 40 ++ .../ExampleSdk/OpenTelemetryConfiguration.php | 232 +++++++++++ .../Propagator/TextMapPropagatorB3.php | 29 ++ .../Propagator/TextMapPropagatorB3Multi.php | 29 ++ .../Propagator/TextMapPropagatorBaggage.php | 29 ++ .../Propagator/TextMapPropagatorComposite.php | 30 ++ .../Propagator/TextMapPropagatorJaeger.php | 29 ++ .../Propagator/TextMapPropagatorOTTrace.php | 29 ++ .../TextMapPropagatorTraceContext.php | 29 ++ .../Propagator/TextMapPropagatorXRay.php | 29 ++ .../ExampleSdk/Trace/SamplerAlwaysOff.php | 29 ++ .../ExampleSdk/Trace/SamplerAlwaysOn.php | 29 ++ .../ExampleSdk/Trace/SamplerParentBased.php | 47 +++ .../Trace/SamplerTraceIdRatioBased.php | 38 ++ .../ExampleSdk/Trace/SpanExporterConsole.php | 29 ++ .../ExampleSdk/Trace/SpanExporterOtlp.php | 55 +++ .../ExampleSdk/Trace/SpanExporterZipkin.php | 41 ++ .../ExampleSdk/Trace/SpanProcessorBatch.php | 48 +++ .../ExampleSdk/Trace/SpanProcessorSimple.php | 40 ++ .../Configuration/configurations/anchors.yaml | 44 ++ .../configurations/kitchen-sink.yaml | 388 ++++++++++++++++++ 95 files changed, 3633 insertions(+), 99 deletions(-) create mode 100644 src/Config/SDK/Configuration/ComponentPlugin.php create mode 100644 src/Config/SDK/Configuration/ComponentProvider.php create mode 100644 src/Config/SDK/Configuration/ComponentProviderRegistry.php create mode 100644 src/Config/SDK/Configuration/ConfigurationFactory.php create mode 100644 src/Config/SDK/Configuration/Context.php create mode 100644 src/Config/SDK/Configuration/Environment/ArrayEnvSource.php create mode 100644 src/Config/SDK/Configuration/Environment/EnvReader.php create mode 100644 src/Config/SDK/Configuration/Environment/EnvResource.php create mode 100644 src/Config/SDK/Configuration/Environment/EnvResourceChecker.php create mode 100644 src/Config/SDK/Configuration/Environment/EnvSource.php create mode 100644 src/Config/SDK/Configuration/Environment/EnvSourceReader.php create mode 100644 src/Config/SDK/Configuration/Environment/PhpIniEnvSource.php create mode 100644 src/Config/SDK/Configuration/Environment/ServerEnvSource.php create mode 100644 src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNull.php create mode 100644 src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNullDefinition.php create mode 100644 src/Config/SDK/Configuration/Internal/CompiledConfigurationFactory.php create mode 100644 src/Config/SDK/Configuration/Internal/ComponentPlugin.php create mode 100644 src/Config/SDK/Configuration/Internal/ComponentProviderRegistry.php create mode 100644 src/Config/SDK/Configuration/Internal/ComposerPackageResource.php create mode 100644 src/Config/SDK/Configuration/Internal/ConfigurationLoader.php create mode 100644 src/Config/SDK/Configuration/Internal/EnvSubstitutionNormalization.php create mode 100644 src/Config/SDK/Configuration/Internal/ResourceCollection.php create mode 100644 src/Config/SDK/Configuration/Internal/ResourceTrackable.php create mode 100644 src/Config/SDK/Configuration/Internal/TrackingEnvReader.php create mode 100644 src/Config/SDK/Configuration/Internal/TreatNullAsUnsetNormalization.php create mode 100644 src/Config/SDK/Configuration/Loader/ConfigurationLoader.php create mode 100644 src/Config/SDK/Configuration/Loader/YamlExtensionFileLoader.php create mode 100644 src/Config/SDK/Configuration/Loader/YamlSymfonyFileLoader.php create mode 100644 src/Config/SDK/Configuration/README.md create mode 100644 src/Config/SDK/Configuration/ResourceCollection.php create mode 100644 src/Config/SDK/Configuration/Validation.php create mode 100644 tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterOtlp.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDrop.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverExplicitBucketHistogram.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverSum.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterConsole.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterOtlp.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3Multi.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorBaggage.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorComposite.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorOTTrace.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorTraceContext.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorXRay.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOff.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerAlwaysOn.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerParentBased.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterOtlp.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php create mode 100644 tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php create mode 100644 tests/Unit/Config/SDK/Configuration/configurations/anchors.yaml create mode 100644 tests/Unit/Config/SDK/Configuration/configurations/kitchen-sink.yaml diff --git a/composer.json b/composer.json index b5521796a..4bb3abee2 100644 --- a/composer.json +++ b/composer.json @@ -15,9 +15,9 @@ "psr/http-client": "^1.0", "psr/http-message": "^1.0.1|^2.0", "psr/log": "^1.1|^2.0|^3.0", + "symfony/config": "^5.4 || ^6.4 || ^7.0", "symfony/polyfill-mbstring": "^1.23", "symfony/polyfill-php82": "^1.26", - "tbachert/otel-sdk-configuration": "^0.1", "tbachert/spi": "^0.2" }, "config": { @@ -75,7 +75,8 @@ "autoload-dev": { "psr-4": { "OpenTelemetry\\Tests\\": "tests/", - "OpenTelemetry\\Example\\": "examples/src/" + "OpenTelemetry\\Example\\": "examples/src/", + "ExampleSDK\\ComponentProvider\\": "tests/Unit/Config/SDK/Configuration/ExampleSdk/" } }, "require-dev": { @@ -110,16 +111,19 @@ "qossmic/deptrac-shim": "^0.24 || ^1", "rector/rector": "^1", "symfony/http-client": "^5.2", - "symfony/yaml": "^6 || ^5" + "symfony/var-exporter": "^5.4 || ^6.4 || ^7.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" }, "suggest": { "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" + "ext-protobuf": "For more performant protobuf/grpc exporting", + "ext-yaml": "Allows loading config from yaml files", + "symfony/yaml": "Allows loading config from yaml files" }, "extra": { "spi": { - "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ + "OpenTelemetry\\Config\\SDK\\Configuration\\ComponentProvider": [ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3Multi", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorBaggage", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 48d227e80..74b2971a2 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -11,6 +11,7 @@ parameters: # - ./examples TODO: Uncomment this once examples are updated excludePaths: - tests/TraceContext/W3CTestService + - tests/Unit/Config/SDK/Configuration/ExampleSdk ignoreErrors: - message: "#Call to an undefined method .*#" diff --git a/psalm.xml.dist b/psalm.xml.dist index 905e3b7d9..0fe505df9 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -13,6 +13,7 @@ + diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php index a978516c5..aab88c355 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterConsole.php @@ -4,9 +4,9 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Logs; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Logs\Exporter\ConsoleExporter; use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; use OpenTelemetry\SDK\Registry; diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php index 2be5fd161..6ee171296 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php @@ -4,12 +4,12 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Logs; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; -use Nevay\OTelSDK\Configuration\Validation; use Nevay\SPI\ServiceProviderDependency\PackageDependency; use OpenTelemetry\API\Signals; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\Validation; use OpenTelemetry\Contrib\Otlp\LogsExporter; use OpenTelemetry\Contrib\Otlp\OtlpUtil; use OpenTelemetry\Contrib\Otlp\Protocols; diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php index 712ca871b..e0b4f2ad5 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorBatch.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Logs; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Common\Time\ClockFactory; use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; diff --git a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php index edbaaa552..1e797a8d2 100644 --- a/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Logs/LogRecordProcessorSimple.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Logs; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor; diff --git a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php index d96cf3040..98ae99827 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php +++ b/src/Config/SDK/ComponentProvider/Metrics/AggregationResolverDefault.php @@ -4,9 +4,9 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Metrics; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderInterface; use OpenTelemetry\SDK\Metrics\DefaultAggregationProviderTrait; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php index 6fba58cc5..8d3f64ced 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterConsole.php @@ -4,9 +4,9 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Metrics; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Metrics\MetricExporter\ConsoleMetricExporter; use OpenTelemetry\SDK\Metrics\MetricExporterInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php index 5547de09c..b94015b26 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php @@ -4,12 +4,12 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Metrics; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; -use Nevay\OTelSDK\Configuration\Validation; use Nevay\SPI\ServiceProviderDependency\PackageDependency; use OpenTelemetry\API\Signals; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\Validation; use OpenTelemetry\Contrib\Otlp\MetricExporter; use OpenTelemetry\Contrib\Otlp\OtlpUtil; use OpenTelemetry\Contrib\Otlp\Protocols; diff --git a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php index 0e77e2008..ab865c7af 100644 --- a/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php +++ b/src/Config/SDK/ComponentProvider/Metrics/MetricReaderPeriodic.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Metrics; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Metrics\MetricExporterInterface; use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader; use OpenTelemetry\SDK\Metrics\MetricReaderInterface; diff --git a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php index c8a11fbe1..7929bee03 100644 --- a/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php +++ b/src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php @@ -4,11 +4,11 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; -use Nevay\OTelSDK\Configuration\Validation; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\Validation; use OpenTelemetry\Context\Propagation\NoopTextMapPropagator; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\SDK\Common\Attribute\Attributes; diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php index 9640f1e32..ca349743c 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Propagator; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\Extension\Propagator\B3\B3Propagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php index 787e99911..8809b7df9 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorB3Multi.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Propagator; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\Extension\Propagator\B3\B3Propagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php index ecfde7fa1..c3d05cfd3 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorBaggage.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Propagator; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; use OpenTelemetry\API\Baggage\Propagation\BaggagePropagator; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php index 6eba5391a..d3d11bd40 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorComposite.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Propagator; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\MultiTextMapPropagator; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php index 6d8e2f4a7..3d8086d52 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorJaeger.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Propagator; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use OpenTelemetry\Extension\Propagator\Jaeger\JaegerPropagator; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php index 0913be336..a55917b6f 100644 --- a/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php +++ b/src/Config/SDK/ComponentProvider/Propagator/TextMapPropagatorTraceContext.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Propagator; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php index 7da8a2d25..89090ef28 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOff.php @@ -4,9 +4,9 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Trace\Sampler\AlwaysOffSampler; use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php index 15dbe61b6..168d8b902 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerAlwaysOn.php @@ -4,9 +4,9 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler; use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php index 121282359..04438e8c0 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerParentBased.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Trace\Sampler\AlwaysOffSampler; use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler; use OpenTelemetry\SDK\Trace\Sampler\ParentBased; diff --git a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php index c66d203da..d945315f1 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php +++ b/src/Config/SDK/ComponentProvider/Trace/SamplerTraceIdRatioBased.php @@ -4,9 +4,9 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Trace\Sampler\TraceIdRatioBasedSampler; use OpenTelemetry\SDK\Trace\SamplerInterface; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php index f36fe5258..945439f2b 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterConsole.php @@ -4,9 +4,9 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Registry; use OpenTelemetry\SDK\Trace\SpanExporter\ConsoleSpanExporter; use OpenTelemetry\SDK\Trace\SpanExporterInterface; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php index 6166bd725..4823ed898 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php @@ -4,12 +4,12 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; -use Nevay\OTelSDK\Configuration\Validation; use Nevay\SPI\ServiceProviderDependency\PackageDependency; use OpenTelemetry\API\Signals; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\Validation; use OpenTelemetry\Contrib\Otlp\OtlpUtil; use OpenTelemetry\Contrib\Otlp\Protocols; use OpenTelemetry\Contrib\Otlp\SpanExporter; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php index 4e13f49ea..a5665ea46 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanExporterZipkin.php @@ -4,11 +4,11 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; -use Nevay\OTelSDK\Configuration\Validation; use Nevay\SPI\ServiceProviderDependency\PackageDependency; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\Validation; use OpenTelemetry\Contrib\Zipkin; use OpenTelemetry\SDK\Registry; use OpenTelemetry\SDK\Trace\SpanExporterInterface; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php index 3688473f0..f4da8f556 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorBatch.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Common\Time\ClockFactory; use OpenTelemetry\SDK\Trace\SpanExporterInterface; use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor; diff --git a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php index ad15e00d4..403037272 100644 --- a/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php +++ b/src/Config/SDK/ComponentProvider/Trace/SpanProcessorSimple.php @@ -4,10 +4,10 @@ namespace OpenTelemetry\Config\SDK\ComponentProvider\Trace; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ComponentProviderRegistry; -use Nevay\OTelSDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ComponentProviderRegistry; +use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\SDK\Trace\SpanExporterInterface; use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; use OpenTelemetry\SDK\Trace\SpanProcessorInterface; diff --git a/src/Config/SDK/Configuration.php b/src/Config/SDK/Configuration.php index b06f596e7..6da74ae20 100644 --- a/src/Config/SDK/Configuration.php +++ b/src/Config/SDK/Configuration.php @@ -4,15 +4,15 @@ namespace OpenTelemetry\Config\SDK; -use Nevay\OTelSDK\Configuration\ComponentPlugin; -use Nevay\OTelSDK\Configuration\ComponentProvider; -use Nevay\OTelSDK\Configuration\ConfigurationFactory; -use Nevay\OTelSDK\Configuration\Context; -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\Config\SDK\Configuration\ComponentPlugin; +use OpenTelemetry\Config\SDK\Configuration\ComponentProvider; +use OpenTelemetry\Config\SDK\Configuration\ConfigurationFactory; +use OpenTelemetry\Config\SDK\Configuration\Context; +use OpenTelemetry\Config\SDK\Configuration\Environment\EnvSourceReader; +use OpenTelemetry\Config\SDK\Configuration\Environment\PhpIniEnvSource; +use OpenTelemetry\Config\SDK\Configuration\Environment\ServerEnvSource; use OpenTelemetry\SDK\SdkBuilder; final class Configuration diff --git a/src/Config/SDK/Configuration/ComponentPlugin.php b/src/Config/SDK/Configuration/ComponentPlugin.php new file mode 100644 index 000000000..5b8c858de --- /dev/null +++ b/src/Config/SDK/Configuration/ComponentPlugin.php @@ -0,0 +1,22 @@ +` + * + * ``` + * $name: + * provider1: + * property: value + * anotherProperty: value + * ``` + * + * @param string $name name of configuration node + * @param string $type type of the component plugin + */ + public function component(string $name, string $type): NodeDefinition; + + /** + * Creates a node to specify a list of component plugin. + * + * `$name: list>` + * + * ``` + * $name: + * - provider1: + * property: value + * anotherProperty: value + * - provider2: + * property: value + * anotherProperty: value + * ``` + * + * @param string $name name of configuration node + * @param string $type type of the component plugin + */ + public function componentList(string $name, string $type): ArrayNodeDefinition; + + /** + * Creates a node to specify a list of component plugin names. + * + * The providers cannot have required properties. + * + * `$name: list>` + * + * ``` + * $name: [provider1, provider2] + * ``` + * + * @param string $name name of configuration node + * @param string $type type of the component plugin + */ + public function componentNames(string $name, string $type): ArrayNodeDefinition; +} diff --git a/src/Config/SDK/Configuration/ConfigurationFactory.php b/src/Config/SDK/Configuration/ConfigurationFactory.php new file mode 100644 index 000000000..cb4987a46 --- /dev/null +++ b/src/Config/SDK/Configuration/ConfigurationFactory.php @@ -0,0 +1,150 @@ + $componentProviders + * @param ComponentProvider $rootComponent + * @param EnvReader $envReader + */ + public function __construct( + private readonly iterable $componentProviders, + private readonly ComponentProvider $rootComponent, + private readonly EnvReader $envReader, + ) { + $this->compiledFactory = $this->compileFactory(); + } + + /** + * @param array $configs configs to process + * @param ResourceCollection|null $resources resources that can be used for cache invalidation + * @throws InvalidConfigurationException if the configuration is invalid + * @return ComponentPlugin processed component plugin + */ + public function process(array $configs, ?ResourceCollection $resources = null): ComponentPlugin + { + return $this->compiledFactory + ->process($configs, $resources); + } + + /** + * @param string|list $file path(s) to parse + * @param string|null $cacheFile path to cache parsed configuration to + * @param bool $debug will check for cache freshness if debug mode enabled + * @throws Exception if loading of a configuration file fails for any reason + * @throws InvalidConfigurationException if the configuration is invalid + * @throws Throwable if a cache file is given and a non-serializable component provider is used + * @return ComponentPlugin parsed component plugin + * + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/file-configuration.md#parse + * @psalm-suppress PossiblyNullReference + */ + public function parseFile( + string|array $file, + ?string $cacheFile = null, + bool $debug = true, + ): ComponentPlugin { + $cache = null; + $resources = null; + if ($cacheFile !== null) { + $cache = new ResourceCheckerConfigCache($cacheFile, [ + new SelfCheckingResourceChecker(), + new EnvResourceChecker($this->envReader), + ]); + if (is_file($cache->getPath()) + && ($configuration = @include $cache->getPath()) instanceof ComponentPlugin + && (!$debug || $cache->isFresh())) { + return $configuration; + } + $resources = new ResourceCollection(); + $resources->addClassResource(ComponentPlugin::class); + $resources->addClassResource(VarExporter::class); + } + + $loader = new ConfigurationLoader($resources); + $locator = new FileLocator(); + $fileLoader = new DelegatingLoader(new LoaderResolver([ + new YamlSymfonyFileLoader($loader, $locator), + new YamlExtensionFileLoader($loader, $locator), + ])); + + foreach ((array) $file as $path) { + $fileLoader->load($path); + } + + $configuration = $this->compiledFactory + ->process($loader->getConfigurations(), $resources); + + $cache?->write( + class_exists(VarExporter::class) + ? sprintf('toArray() //@todo $resources possible null + ); + + return $configuration; + } + + private function compileFactory(): CompiledConfigurationFactory + { + $registry = new ComponentProviderRegistry(); + foreach ($this->componentProviders as $provider) { + $registry->register($provider); + } + + $root = $this->rootComponent->getConfig($registry); + + $envReader = new TrackingEnvReader($this->envReader); + // Parse MUST perform environment variable substitution. + (new EnvSubstitutionNormalization($envReader))->apply($root); + // Parse MUST interpret null as equivalent to unset. + (new TreatNullAsUnsetNormalization())->apply($root); + + $node = $root->getNode(forceRootNode: true); + + return new CompiledConfigurationFactory( + $this->rootComponent, + $node, + [ + $registry, + $envReader, + ], + ); + } +} diff --git a/src/Config/SDK/Configuration/Context.php b/src/Config/SDK/Configuration/Context.php new file mode 100644 index 000000000..b6eca946c --- /dev/null +++ b/src/Config/SDK/Configuration/Context.php @@ -0,0 +1,31 @@ +env[$name] ?? null; + } +} diff --git a/src/Config/SDK/Configuration/Environment/EnvReader.php b/src/Config/SDK/Configuration/Environment/EnvReader.php new file mode 100644 index 000000000..dd8269cbd --- /dev/null +++ b/src/Config/SDK/Configuration/Environment/EnvReader.php @@ -0,0 +1,11 @@ +name; + } +} diff --git a/src/Config/SDK/Configuration/Environment/EnvResourceChecker.php b/src/Config/SDK/Configuration/Environment/EnvResourceChecker.php new file mode 100644 index 000000000..8ed780561 --- /dev/null +++ b/src/Config/SDK/Configuration/Environment/EnvResourceChecker.php @@ -0,0 +1,30 @@ +envReader->read($resource->name) === $resource->value; + } +} diff --git a/src/Config/SDK/Configuration/Environment/EnvSource.php b/src/Config/SDK/Configuration/Environment/EnvSource.php new file mode 100644 index 000000000..0085512fb --- /dev/null +++ b/src/Config/SDK/Configuration/Environment/EnvSource.php @@ -0,0 +1,11 @@ + $envSources + */ + public function __construct( + private readonly iterable $envSources, + ) { + } + + public function read(string $name): ?string + { + foreach ($this->envSources as $envSource) { + if (is_string($value = $envSource->readRaw($name)) && ($value = trim($value, " \t")) !== '') { + return $value; + } + } + + return null; + } +} diff --git a/src/Config/SDK/Configuration/Environment/PhpIniEnvSource.php b/src/Config/SDK/Configuration/Environment/PhpIniEnvSource.php new file mode 100644 index 000000000..470a86ad2 --- /dev/null +++ b/src/Config/SDK/Configuration/Environment/PhpIniEnvSource.php @@ -0,0 +1,16 @@ +getName()); + foreach (get_object_vars($node) as $property => $value) { + $defaultNull->$property = $value; + } + + return $defaultNull; + } + + public function hasDefaultValue(): bool + { + return true; + } + + public function getDefaultValue(): mixed + { + return null; + } +} diff --git a/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNullDefinition.php b/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNullDefinition.php new file mode 100644 index 000000000..45a05c4d9 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ArrayNodeDefaultNullDefinition.php @@ -0,0 +1,25 @@ + $rootComponent + * @param NodeInterface $node + * @param iterable $resourceTrackable + */ + public function __construct( + private readonly ComponentProvider $rootComponent, + private readonly NodeInterface $node, + private readonly iterable $resourceTrackable, + ) { + } + + /** + * @param array $configs configs to process + * @param ResourceCollection|null $resources resources that can be used for cache invalidation + * @throws InvalidConfigurationException if the configuration is invalid + * @return ComponentPlugin processed component plugin + */ + public function process(array $configs, ?ResourceCollection $resources = null): ComponentPlugin + { + $resources?->addClassResource($this->rootComponent::class); + foreach ($this->resourceTrackable as $trackable) { + $trackable->trackResources($resources); + } + + try { + $properties = (new Processor())->process($this->node, $configs); + } finally { + foreach ($this->resourceTrackable as $trackable) { + $trackable->trackResources(null); + } + } + + return new ComponentPlugin($properties, $this->rootComponent); + } +} diff --git a/src/Config/SDK/Configuration/Internal/ComponentPlugin.php b/src/Config/SDK/Configuration/Internal/ComponentPlugin.php new file mode 100644 index 000000000..a3b65e492 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ComponentPlugin.php @@ -0,0 +1,33 @@ + + * + * @internal + */ +final class ComponentPlugin implements \OpenTelemetry\Config\SDK\Configuration\ComponentPlugin +{ + + /** + * @param array $properties resolved properties according to component provider config + * @param ComponentProvider $provider component provider used to create the component + */ + public function __construct( + private readonly array $properties, + private readonly ComponentProvider $provider, + ) { + } + + public function create(Context $context): mixed + { + return $this->provider->createPlugin($this->properties, $context); + } +} diff --git a/src/Config/SDK/Configuration/Internal/ComponentProviderRegistry.php b/src/Config/SDK/Configuration/Internal/ComponentProviderRegistry.php new file mode 100644 index 000000000..472716636 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ComponentProviderRegistry.php @@ -0,0 +1,187 @@ +> */ + private array $providers = []; + /** @var array> */ + private array $recursionProtection = []; + private ?ResourceCollection $resources = null; + + public function register(ComponentProvider $provider): void + { + $name = self::loadName($provider); + $type = self::loadType($provider); + if (isset($this->providers[$type][$name])) { + throw new LogicException(sprintf('Duplicate component provider registered for "%s" "%s"', $type, $name)); + } + + $this->providers[$type][$name] = $provider; + } + + public function trackResources(?ResourceCollection $resources): void + { + $this->resources = $resources; + } + + public function component(string $name, string $type): NodeDefinition + { + if (!$this->getProviders($type)) { + return (new VariableNodeDefinition($name)) + ->info(sprintf('Component "%s"', $type)) + ->defaultNull() + ->validate()->always()->thenInvalid(sprintf('Component "%s" cannot be configured, it does not have any associated provider', $type))->end(); + } + + $node = new ArrayNodeDefaultNullDefinition($name); + $this->applyToArrayNode($node, $type); + + return $node; + } + + public function componentList(string $name, string $type): ArrayNodeDefinition + { + $node = new ArrayNodeDefinition($name); + $this->applyToArrayNode($node->arrayPrototype(), $type); + + return $node; + } + + public function componentNames(string $name, string $type): ArrayNodeDefinition + { + $node = new ArrayNodeDefinition($name); + + $providers = $this->getProviders($type); + foreach ($providers as $providerName => $provider) { + try { + $provider->getConfig(new ComponentProviderRegistry())->getNode(true)->finalize([]); + } catch (InvalidConfigurationException) { + unset($providers[$providerName]); + } + } + if ($providers) { + $node->enumPrototype()->values(array_keys($providers))->end(); + + $node->validate()->always(function (array $value) use ($type): array { + $plugins = []; + foreach ($value as $name) { + $provider = $this->providers[$type][$name]; + $this->resources?->addClassResource($provider); + + $plugins[] = new ComponentPlugin([], $provider); + } + + return $plugins; + }); + } + + return $node; + } + + private function applyToArrayNode(ArrayNodeDefinition $node, string $type): void + { + $node->info(sprintf('Component "%s"', $type)); + $node->performNoDeepMerging(); + + foreach ($this->getProviders($type) as $name => $provider) { + $this->recursionProtection[$type][$name] = true; + + try { + $node->children()->append($provider->getConfig($this)); + } finally { + unset($this->recursionProtection[$type][$name]); + } + } + + $node->validate()->always(function (array $value) use ($type): ComponentPlugin { + if (count($value) !== 1) { + throw new InvalidArgumentException(sprintf( + 'Component "%s" must have exactly one element defined, got %s', + $type, + implode(', ', array_map(json_encode(...), array_keys($value)) ?: ['none']) + )); + } + + $name = array_key_first($value); + $provider = $this->providers[$type][$name]; + $this->resources?->addClassResource($provider); + + return new ComponentPlugin($value[$name], $this->providers[$type][$name]); + }); + } + + /** + * Returns all registered providers for a specific component type. + * + * @param string $type the component type to load providers for + * @return array component providers indexed by their name + */ + private function getProviders(string $type): array + { + return array_diff_key( + $this->providers[$type] ?? [], + $this->recursionProtection[$type] ?? [], + ); + } + + /** + * @psalm-suppress PossiblyNullFunctionCall,InaccessibleProperty + */ + private static function loadName(ComponentProvider $provider): string + { + static $accessor; //@todo inaccessible property $node->name + /** @phpstan-ignore-next-line */ + $accessor ??= (static fn (NodeDefinition $node): ?string => $node->name)->bindTo(null, NodeDefinition::class); + + return $accessor($provider->getConfig(new ComponentProviderRegistry())); + } + + private static function loadType(ComponentProvider $provider): string + { + /** @noinspection PhpUnhandledExceptionInspection */ + if ($returnType = (new ReflectionClass($provider))->getMethod('createPlugin')->getReturnType()) { + return self::typeToString($returnType); + } + + return 'mixed'; + } + + private static function typeToString(ReflectionType $type): string + { + /** @phpstan-ignore-next-line */ + return match ($type::class) { + ReflectionNamedType::class => $type->getName(), + ReflectionUnionType::class => implode('|', array_map(self::typeToString(...), $type->getTypes())), + ReflectionIntersectionType::class => implode('&', array_map(self::typeToString(...), $type->getTypes())), + }; + } +} diff --git a/src/Config/SDK/Configuration/Internal/ComposerPackageResource.php b/src/Config/SDK/Configuration/Internal/ComposerPackageResource.php new file mode 100644 index 000000000..6eaf33b2c --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ComposerPackageResource.php @@ -0,0 +1,44 @@ +packageName = $packageName; + $this->version = self::getVersion($packageName); + } + + public function isFresh(int $timestamp): bool + { + return $this->version === self::getVersion($this->packageName); + } + + public function __toString(): string + { + return 'composer.' . $this->packageName; + } + + /** + * @psalm-suppress NullableReturnStatement,InvalidNullableReturnType + */ + private static function getVersion(string $packageName): string|false + { + return InstalledVersions::isInstalled($packageName) + ? InstalledVersions::getVersion($packageName) + : false; + } +} diff --git a/src/Config/SDK/Configuration/Internal/ConfigurationLoader.php b/src/Config/SDK/Configuration/Internal/ConfigurationLoader.php new file mode 100644 index 000000000..a5b36049d --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ConfigurationLoader.php @@ -0,0 +1,38 @@ +resources = $resources; + } + + public function loadConfiguration(mixed $configuration): void + { + $this->configurations[] = $configuration; + } + + public function addResource(ResourceInterface $resource): void + { + $this->resources?->addResource($resource); + } + + public function getConfigurations(): array + { + return $this->configurations; + } +} diff --git a/src/Config/SDK/Configuration/Internal/EnvSubstitutionNormalization.php b/src/Config/SDK/Configuration/Internal/EnvSubstitutionNormalization.php new file mode 100644 index 000000000..82356e662 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/EnvSubstitutionNormalization.php @@ -0,0 +1,101 @@ +getChildNodeDefinitions() as $childNode) { + $this->doApply($childNode); + } + } + + private function doApply(NodeDefinition $node): void + { + if ($node instanceof ScalarNodeDefinition) { + $filter = match (true) { + $node instanceof BooleanNodeDefinition => FILTER_VALIDATE_BOOLEAN, + $node instanceof IntegerNodeDefinition => FILTER_VALIDATE_INT, + $node instanceof FloatNodeDefinition => FILTER_VALIDATE_FLOAT, + default => FILTER_DEFAULT, + }; + $node->beforeNormalization()->ifString()->then(fn (string $v) => $this->replaceEnvVariables($v, $filter))->end(); + } + if ($node instanceof VariableNodeDefinition) { + $node->beforeNormalization()->always($this->replaceEnvVariablesRecursive(...))->end(); + } + + if ($node instanceof ParentNodeDefinitionInterface) { + foreach ($node->getChildNodeDefinitions() as $childNode) { + $this->doApply($childNode); + } + } + } + + private function replaceEnvVariables(string $value, int $filter = FILTER_DEFAULT): mixed + { + $replaced = preg_replace_callback( + '/\$\{(?[a-zA-Z_]\w*)(?::-(?[^\n]*))?}/', + fn (array $matches): string => $this->envReader->read($matches['ENV_NAME']) ?? $matches['DEFAULT_VALUE'] ?? '', + $value, + -1, + $count, + ); + + if (!$count) { + return $value; + } + if ($replaced === '') { + return null; + } + + return filter_var($replaced, $filter, FILTER_NULL_ON_FAILURE) ?? $replaced; + } + + private function replaceEnvVariablesRecursive(mixed $value): mixed + { + if (is_array($value)) { + foreach ($value as $k => $v) { + if (($r = $this->replaceEnvVariablesRecursive($v)) !== $v) { + $value[$k] = $r; + } + } + } + if (is_string($value)) { + $value = $this->replaceEnvVariables($value); + } + + return $value; + } +} diff --git a/src/Config/SDK/Configuration/Internal/ResourceCollection.php b/src/Config/SDK/Configuration/Internal/ResourceCollection.php new file mode 100644 index 000000000..dc6959032 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ResourceCollection.php @@ -0,0 +1,102 @@ + */ + private array $resources = []; + private readonly ComposerResource $composerResource; + /** @var list */ + private readonly array $vendors; + + /** + * @psalm-suppress PropertyTypeCoercion + */ + public function __construct() + { + $this->composerResource = new ComposerResource(); + $this->vendors = $this->composerResource->getVendors(); + } + + /** + * @psalm-suppress PossiblyInvalidArgument + */ + public function addClassResource(object|string $class): void + { + try { + $reflection = new ReflectionClass($class); + if ($this->isInVendors($reflection->getFileName())) { + return; + } + + $this->addResource(new ReflectionClassResource($reflection, $this->vendors)); + } catch (ReflectionException) { + //@todo $class could be an object here? + $this->addResource(new ClassExistenceResource($class, false)); + } + } + + public function addResource(ResourceInterface $resource): void + { + $path = match (true) { + $resource instanceof FileResource => $resource->getResource(), + $resource instanceof GlobResource => $resource->getPrefix(), + $resource instanceof DirectoryResource => $resource->getResource(), + default => null, + }; + + if ($path !== null && $this->isInVendors($path)) { + return; + } + + $this->resources[(string) $resource] = $resource; + } + + /** + * @return list + */ + public function toArray(): array + { + return array_values($this->resources); + } + + /** + * @see ReflectionClassResource::loadFiles() + */ + private function isInVendors(string $path): bool + { + $path = realpath($path) ?: $path; + + foreach ($this->vendors as $vendor) { + $c = $path[strlen((string) $vendor)] ?? null; + if (str_starts_with($path, (string) $vendor) && ($c === '/' || $c === DIRECTORY_SEPARATOR)) { + $this->addResource($this->composerResource); + + return true; + } + } + + return false; + } +} diff --git a/src/Config/SDK/Configuration/Internal/ResourceTrackable.php b/src/Config/SDK/Configuration/Internal/ResourceTrackable.php new file mode 100644 index 000000000..c6c9f9a54 --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/ResourceTrackable.php @@ -0,0 +1,13 @@ +envReader = $envReader; + } + + public function trackResources(?ResourceCollection $resources): void + { + $this->resources = $resources; + } + + public function read(string $name): ?string + { + $value = $this->envReader->read($name); + $this->resources?->addResource(new EnvResource($name, $value)); + + return $value; + } +} diff --git a/src/Config/SDK/Configuration/Internal/TreatNullAsUnsetNormalization.php b/src/Config/SDK/Configuration/Internal/TreatNullAsUnsetNormalization.php new file mode 100644 index 000000000..97b0f9eef --- /dev/null +++ b/src/Config/SDK/Configuration/Internal/TreatNullAsUnsetNormalization.php @@ -0,0 +1,34 @@ +getChildNodeDefinitions() as $childNode) { + $this->doApply($childNode); + } + } + + private function doApply(NodeDefinition $node): void + { + $node->beforeNormalization()->ifNull()->thenUnset()->end(); + + if ($node instanceof ParentNodeDefinitionInterface) { + foreach ($node->getChildNodeDefinitions() as $childNode) { + $this->doApply($childNode); + } + } + } +} diff --git a/src/Config/SDK/Configuration/Loader/ConfigurationLoader.php b/src/Config/SDK/Configuration/Loader/ConfigurationLoader.php new file mode 100644 index 000000000..8b8973842 --- /dev/null +++ b/src/Config/SDK/Configuration/Loader/ConfigurationLoader.php @@ -0,0 +1,15 @@ +locator->locate($resource); + $this->configuration->addResource(new FileResource($path)); + + if (($content = @\yaml_parse_file($path)) === false) { + throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: %s', $path, error_get_last()['message'] ?? '')); + } + + $this->configuration->loadConfiguration($content); + + return null; + } + + public function supports(mixed $resource, string $type = null): bool + { + return extension_loaded('yaml') + && is_string($resource) + && match ($type ?? pathinfo($resource, PATHINFO_EXTENSION)) { + 'yaml', 'yml' => true, + default => false, + }; + } +} diff --git a/src/Config/SDK/Configuration/Loader/YamlSymfonyFileLoader.php b/src/Config/SDK/Configuration/Loader/YamlSymfonyFileLoader.php new file mode 100644 index 000000000..25d1b02d3 --- /dev/null +++ b/src/Config/SDK/Configuration/Loader/YamlSymfonyFileLoader.php @@ -0,0 +1,55 @@ +locator->locate($resource); + $this->configuration->addResource(new FileResource($path)); + + try { + $content = Yaml::parseFile($resource, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); + } catch (ParseException $e) { + throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: %s', $path, $e->getMessage()), 0, $e); + } + + $this->configuration->loadConfiguration($content); + + return null; + } + + public function supports(mixed $resource, string $type = null): bool + { + return class_exists(Yaml::class) + && is_string($resource) + && match ($type ?? pathinfo($resource, PATHINFO_EXTENSION)) { + 'yaml', 'yml' => true, + default => false, + }; + } +} diff --git a/src/Config/SDK/Configuration/README.md b/src/Config/SDK/Configuration/README.md new file mode 100644 index 000000000..224f2ccaa --- /dev/null +++ b/src/Config/SDK/Configuration/README.md @@ -0,0 +1,70 @@ +# Configuration + +Allows creation of an extensible configuration model according to the +[OTel file configuration specification](https://opentelemetry.io/docs/specs/otel/configuration/file-configuration/). + +## Installation + +```shell +composer require tbachert/otel-sdk-configuration +``` + +Additionally, you will need either `ext-yaml` or `symfony/yaml` to load configuration from yaml config files. + +## Usage + +### Parsing config + +```php +$factory = new ConfigurationFactory( + [ + // all available providers ... + ], + new OpenTelemetryConfiguration(), + new EnvSourceReader([ + new ArrayEnvSource($_SERVER), + new PhpIniEnvSource(), + ]), +); +$configuration = $factory->parseFile(__DIR__ . '/config.yaml'); +$openTelemetry = $configuration->create(new Context()); +``` + +### Defining component providers + +See [examples](./examples) for component provider examples. + +###### Example: BatchSpanProcessor + +```php +final class SpanProcessorBatch implements ComponentProvider { + + /** + * @param array{ + * schedule_delay: int<0, max>, + * 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): SpanProcessor { + // ... + } + + 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', SpanExporter::class)->isRequired()) + ->end() + ; + + return $node; + } +} +``` diff --git a/src/Config/SDK/Configuration/ResourceCollection.php b/src/Config/SDK/Configuration/ResourceCollection.php new file mode 100644 index 000000000..a2742c184 --- /dev/null +++ b/src/Config/SDK/Configuration/ResourceCollection.php @@ -0,0 +1,23 @@ + throw new InvalidArgumentException('must be a valid regex pattern: ' . self::stripPrefix($errstr, 'preg_match(): '), $errno)); + + try { + preg_match($value, ''); + } finally { + restore_error_handler(); + } + + return $value; + }; + } + + private static function stripPrefix(string $string, string $prefix): string + { + if (str_starts_with($string, $prefix)) { + return substr($string, strlen($prefix)); + } + + return $string; + } +} diff --git a/src/Config/SDK/composer.json b/src/Config/SDK/composer.json index 7b6809c3f..75285bb65 100644 --- a/src/Config/SDK/composer.json +++ b/src/Config/SDK/composer.json @@ -18,8 +18,9 @@ ], "require": { "php": "^8.1", + "open-telemetry/context": "^1.0", "open-telemetry/sdk": "^1.0", - "tbachert/otel-sdk-configuration": "^0.1", + "symfony/config": "^5.4 || ^6.4 || ^7.0", "tbachert/spi": "^0.2" }, "autoload": { @@ -27,12 +28,17 @@ "OpenTelemetry\\Config\\SDK\\": "" } }, + "suggest": { + "ext-yaml": "Allows loading config from yaml files", + "symfony/yaml": "Allows loading config from yaml files", + "tbachert/spi": "Allows defining and loading component providers from composer.json extra.spi" + }, "extra": { "branch-alias": { "dev-main": "0.1.x-dev" }, "spi": { - "Nevay\\OTelSDK\\Configuration\\ComponentProvider": [ + "OpenTelemetry\\Config\\SDK\\Configuration\\ComponentProvider": [ "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorB3Multi", "OpenTelemetry\\Config\\SDK\\ComponentProvider\\Propagator\\TextMapPropagatorBaggage", diff --git a/tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php b/tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php new file mode 100644 index 000000000..2cc3af786 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ConfigurationFactoryTest.php @@ -0,0 +1,242 @@ +children() + ->scalarNode('string_key')->end() + ->scalarNode('other_string_key')->end() + ->scalarNode('another_string_key')->end() + ->scalarNode('string_key_with_quoted_hex_value')->end() + ->scalarNode('yet_another_string_key')->end() + ->booleanNode('bool_key')->end() + ->integerNode('int_key')->end() + ->integerNode('int_key_with_unquoted_hex_value')->end() + ->floatNode('float_key')->end() + ->scalarNode('combo_string_key')->end() + ->scalarNode('string_key_with_default')->end() + ->variableNode('undefined_key')->end() + ->variableNode('${STRING_VALUE}')->end() + ->end() + ; + + return $node; + } + }, + new EnvSourceReader([ + new ArrayEnvSource([ + 'STRING_VALUE' => 'value', + 'BOOl_VALUE' => 'true', + 'INT_VALUE' => '1', + 'FLOAT_VALUE' => '1.1', + 'HEX_VALUE' => '0xdeadbeef', + 'INVALID_MAP_VALUE' => "value\nkey:value", + ]), + ]), + ); + + /** @todo int_key_with_unquoted_hex_value is being interpreted as string */ + $parsed = $factory->process([ + Yaml::parse(<<<'YAML' + string_key: ${STRING_VALUE} # Valid reference to STRING_VALUE + other_string_key: "${STRING_VALUE}" # Valid reference to STRING_VALUE inside double quotes + another_string_key: "${BOOl_VALUE}" # Valid reference to BOOl_VALUE inside double quotes + string_key_with_quoted_hex_value: "${HEX_VALUE}" # Valid reference to HEX_VALUE inside double quotes + yet_another_string_key: ${INVALID_MAP_VALUE} # Valid reference to INVALID_MAP_VALUE, but YAML structure from INVALID_MAP_VALUE MUST NOT be injected + bool_key: ${BOOl_VALUE} # Valid reference to BOOl_VALUE + int_key: ${INT_VALUE} # Valid reference to INT_VALUE + #int_key_with_unquoted_hex_value: ${HEX_VALUE} # Valid reference to HEX_VALUE without quotes + float_key: ${FLOAT_VALUE} # Valid reference to FLOAT_VALUE + combo_string_key: foo ${STRING_VALUE} ${FLOAT_VALUE} # Valid reference to STRING_VALUE and FLOAT_VALUE + string_key_with_default: ${UNDEFINED_KEY:-fallback} # UNDEFINED_KEY is not defined but a default value is included + undefined_key: ${UNDEFINED_KEY} # Invalid reference, UNDEFINED_KEY is not defined and is replaced with "" + ${STRING_VALUE}: value # Invalid reference, substitution is not valid in mapping keys and reference is ignored + YAML), + ]); + + $this->assertSame( + Yaml::parse(<<<'YAML' + string_key: value # Interpreted as type string, tag URI tag:yaml.org,2002:str + other_string_key: "value" # Interpreted as type string, tag URI tag:yaml.org,2002:str + another_string_key: "true" # Interpreted as type string, tag URI tag:yaml.org,2002:str + string_key_with_quoted_hex_value: "0xdeadbeef" # Interpreted as type string, tag URI tag:yaml.org,2002:str + yet_another_string_key: "value\nkey:value" # Interpreted as type string, tag URI tag:yaml.org,2002:str + bool_key: true # Interpreted as type bool, tag URI tag:yaml.org,2002:bool + int_key: 1 # Interpreted as type int, tag URI tag:yaml.org,2002:int + #int_key_with_unquoted_hex_value: 3735928559 # Interpreted as type int, tag URI tag:yaml.org,2002:int + float_key: 1.1 # Interpreted as type float, tag URI tag:yaml.org,2002:float + combo_string_key: foo value 1.1 # Interpreted as type string, tag URI tag:yaml.org,2002:str + string_key_with_default: fallback # Interpreted as type string, tag URI tag:yaml.org,2002:str + # undefined_key removed as null is treated as unset + # undefined_key: # Interpreted as type null, tag URI tag:yaml.org,2002:null + ${STRING_VALUE}: value # Interpreted as type string, tag URI tag:yaml.org,2002:str + YAML), + self::getPropertiesFromPlugin($parsed), + ); + } + + #[BackupGlobals(true)] + #[CoversNothing] + public function test_env_substitution_string(): void + { + $_SERVER['OTEL_SERVICE_NAME'] = 'example-service'; + $parsed = self::factory()->process([[ + 'file_format' => '0.1', + 'resource' => [ + 'attributes' => [ + 'service.name' => '${OTEL_SERVICE_NAME}', + ], + ], + ]]); + + $this->assertInstanceOf(ComponentPlugin::class, $parsed); + $this->assertSame('example-service', self::getPropertiesFromPlugin($parsed)['resource']['attributes']['service.name']); + } + + #[BackupGlobals(true)] + public function test_env_substitution_non_string(): void + { + $_SERVER['OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'] = '2048'; + $parsed = self::factory()->process([[ + 'file_format' => '0.1', + 'attribute_limits' => [ + 'attribute_value_length_limit' => '${OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT}', + ], + ]]); + + $this->assertInstanceOf(ComponentPlugin::class, $parsed); + $this->assertSame(2048, self::getPropertiesFromPlugin($parsed)['attribute_limits']['attribute_value_length_limit']); + } + + public function test_treat_null_as_unset(): void + { + $parsed = self::factory()->process([[ + 'file_format' => '0.1', + 'attribute_limits' => [ + 'attribute_count_limit' => null, + ], + ]]); + + $this->assertInstanceOf(ComponentPlugin::class, $parsed); + $this->assertSame(128, self::getPropertiesFromPlugin($parsed)['attribute_limits']['attribute_count_limit']); + } + + /** + * @psalm-suppress UndefinedThisPropertyFetch,PossiblyNullFunctionCall + */ + private function getPropertiesFromPlugin(ComponentPlugin $plugin): array + { + assert($plugin instanceof Internal\ComponentPlugin); + + /** @phpstan-ignore-next-line */ + return (fn () => $this->properties)->bindTo($plugin, Internal\ComponentPlugin::class)(); + } + + public static function openTelemetryConfigurationDataProvider(): iterable + { + yield 'kitchen-sink' => [__DIR__ . '/configurations/kitchen-sink.yaml']; + yield 'anchors' => [__DIR__ . '/configurations/anchors.yaml']; + } + + #[DataProvider('openTelemetryConfigurationDataProvider')] + public function test_open_telemetry_configuration(string $file): void + { + $this->expectNotToPerformAssertions(); + self::factory()->parseFile($file); + } + + private function factory(): ConfigurationFactory + { + return new ConfigurationFactory( + [ + new ComponentProvider\Propagator\TextMapPropagatorB3(), + new ComponentProvider\Propagator\TextMapPropagatorB3Multi(), + new ComponentProvider\Propagator\TextMapPropagatorBaggage(), + new ComponentProvider\Propagator\TextMapPropagatorComposite(), + new ComponentProvider\Propagator\TextMapPropagatorJaeger(), + new ComponentProvider\Propagator\TextMapPropagatorOTTrace(), + new ComponentProvider\Propagator\TextMapPropagatorTraceContext(), + new ComponentProvider\Propagator\TextMapPropagatorXRay(), + + new ComponentProvider\Trace\SamplerAlwaysOff(), + new ComponentProvider\Trace\SamplerAlwaysOn(), + new ComponentProvider\Trace\SamplerParentBased(), + new ComponentProvider\Trace\SamplerTraceIdRatioBased(), + new ComponentProvider\Trace\SpanExporterConsole(), + new ComponentProvider\Trace\SpanExporterOtlp(), + new ComponentProvider\Trace\SpanExporterZipkin(), + new ComponentProvider\Trace\SpanProcessorBatch(), + new ComponentProvider\Trace\SpanProcessorSimple(), + + new ComponentProvider\Metrics\AggregationResolverDefault(), + new ComponentProvider\Metrics\AggregationResolverDrop(), + new ComponentProvider\Metrics\AggregationResolverExplicitBucketHistogram(), + new ComponentProvider\Metrics\AggregationResolverLastValue(), + new ComponentProvider\Metrics\AggregationResolverSum(), + new ComponentProvider\Metrics\MetricExporterConsole(), + new ComponentProvider\Metrics\MetricExporterOtlp(), + new ComponentProvider\Metrics\MetricExporterPrometheus(), + new ComponentProvider\Metrics\MetricReaderPeriodic(), + new ComponentProvider\Metrics\MetricReaderPull(), + + new ComponentProvider\Logs\LogRecordExporterConsole(), + new ComponentProvider\Logs\LogRecordExporterOtlp(), + new ComponentProvider\Logs\LogRecordProcessorBatch(), + new ComponentProvider\Logs\LogRecordProcessorSimple(), + ], + new ComponentProvider\OpenTelemetryConfiguration(), + new EnvSourceReader([ + new ServerEnvSource(), + new PhpIniEnvSource(), + ]), + ); + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php new file mode 100644 index 000000000..df77c1224 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordExporterConsole.php @@ -0,0 +1,29 @@ +, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * } $properties + */ + public function createPlugin(array $properties, Context $context): LogRecordExporter + { + throw new BadMethodCallException('not implemented'); + } + + 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/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php new file mode 100644 index 000000000..1d4a00f91 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorBatch.php @@ -0,0 +1,48 @@ +, + * 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): LogRecordProcessor + { + throw new BadMethodCallException('not implemented'); + } + + 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', LogRecordExporter::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php new file mode 100644 index 000000000..fa728816f --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Logs/LogRecordProcessorSimple.php @@ -0,0 +1,40 @@ +, + * } $properties + */ + public function createPlugin(array $properties, Context $context): LogRecordProcessor + { + throw new BadMethodCallException('not implemented'); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { + $node = new ArrayNodeDefinition('simple'); + $node + ->children() + ->append($registry->component('exporter', LogRecordExporter::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php new file mode 100644 index 000000000..4ccfc034b --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverDefault.php @@ -0,0 +1,29 @@ +, + * record_min_max: bool, + * } $properties + */ + public function createPlugin(array $properties, Context $context): AggregationResolver + { + throw new BadMethodCallException('not implemented'); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { + $node = new ArrayNodeDefinition('explicit_bucket_histogram'); + $node + ->children() + ->arrayNode('boundaries') + ->floatPrototype()->end() + ->validate() + ->ifArray() + ->then(static function (array $boundaries): array { + $last = -INF; + foreach ($boundaries as $boundary) { + if ($boundary <= $last) { + throw new InvalidArgumentException('histogram boundaries must be strictly ascending'); + } + + $last = $boundary; + } + + return $boundaries; + }) + ->end() + ->end() + ->booleanNode('record_min_max')->defaultTrue()->end() + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php new file mode 100644 index 000000000..16dc6a4dd --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/AggregationResolverLastValue.php @@ -0,0 +1,29 @@ +, + * 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): MetricExporter + { + throw new BadMethodCallException('not implemented'); + } + + 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', 'base2_exponential_bucket_histogram']) + ->defaultValue('explicit_bucket_histogram') + ->end() + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php new file mode 100644 index 000000000..beb2873c7 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricExporterPrometheus.php @@ -0,0 +1,47 @@ +children() + ->scalarNode('host')->defaultValue('localhost')->validate()->always(Validation::ensureString())->end()->end() + ->integerNode('port')->defaultValue(9464)->end() + ->booleanNode('without_units')->defaultFalse()->end() + ->booleanNode('without_type_suffix')->defaultFalse()->end() + ->booleanNode('without_scope_info')->defaultFalse()->end() + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php new file mode 100644 index 000000000..932668ea0 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPeriodic.php @@ -0,0 +1,44 @@ +, + * timeout: int<0, max>, + * exporter: ComponentPlugin, + * } $properties + */ + public function createPlugin(array $properties, Context $context): MetricReader + { + throw new BadMethodCallException('not implemented'); + } + + 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', MetricExporter::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php new file mode 100644 index 000000000..c9ce152b2 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Metrics/MetricReaderPull.php @@ -0,0 +1,40 @@ +, + * } $properties + */ + public function createPlugin(array $properties, Context $context): MetricReader + { + throw new BadMethodCallException('not implemented'); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { + $node = new ArrayNodeDefinition('pull'); + $node + ->children() + ->append($registry->component('exporter', MetricExporter::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php new file mode 100644 index 000000000..489f7f5b1 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/OpenTelemetryConfiguration.php @@ -0,0 +1,232 @@ +, + * 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>, + * }, + * meter_provider: array{ + * views: list, + * aggregation: ?ComponentPlugin, + * }, + * selector: array{ + * instrument_type: 'counter'|'gauge'|'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): Configuration + { + throw new BadMethodCallException('not implemented'); + } + + 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)->defaultNull()->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', Sampler::class)) + ->append($registry->componentList('processors', SpanProcessor::class)) + ->end() + ; + + 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', AggregationResolver::class)) + ->end() + ->end() + ->arrayNode('selector') + ->addDefaultsIfNotSet() + ->children() + ->enumNode('instrument_type') + ->values([ + 'counter', + 'gauge', + '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', MetricReader::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', LogRecordProcessor::class)) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php new file mode 100644 index 000000000..6dab69009 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorB3.php @@ -0,0 +1,29 @@ +> $properties + */ + public function createPlugin(array $properties, Context $context): TextMapPropagatorInterface + { + throw new BadMethodCallException('not implemented'); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { + return $registry->componentNames('composite', TextMapPropagatorInterface::class); + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php new file mode 100644 index 000000000..1d6a01da0 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Propagator/TextMapPropagatorJaeger.php @@ -0,0 +1,29 @@ +, + * 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): Sampler + { + throw new BadMethodCallException('not implemented'); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { + $node = new ArrayNodeDefinition('parent_based'); + $node + ->children() + ->append($registry->component('root', Sampler::class)->isRequired()) + ->append($registry->component('remote_parent_sampled', Sampler::class)) + ->append($registry->component('remote_parent_not_sampled', Sampler::class)) + ->append($registry->component('local_parent_sampled', Sampler::class)) + ->append($registry->component('local_parent_not_sampled', Sampler::class)) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php new file mode 100644 index 000000000..eb6e6cb7d --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SamplerTraceIdRatioBased.php @@ -0,0 +1,38 @@ +children() + ->floatNode('ratio')->min(0)->max(1)->isRequired()->end() + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php new file mode 100644 index 000000000..be7627279 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterConsole.php @@ -0,0 +1,29 @@ +, + * compression: 'gzip'|null, + * timeout: int<0, max>, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanExporter + { + throw new BadMethodCallException('not implemented'); + } + + 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/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php new file mode 100644 index 000000000..c0037c901 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanExporterZipkin.php @@ -0,0 +1,41 @@ +, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanExporter + { + throw new BadMethodCallException('not implemented'); + } + + 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/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php new file mode 100644 index 000000000..de2c24026 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorBatch.php @@ -0,0 +1,48 @@ +, + * 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): SpanProcessor + { + throw new BadMethodCallException('not implemented'); + } + + 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', SpanExporter::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php new file mode 100644 index 000000000..b9c3c7b41 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/ExampleSdk/Trace/SpanProcessorSimple.php @@ -0,0 +1,40 @@ +, + * } $properties + */ + public function createPlugin(array $properties, Context $context): SpanProcessor + { + throw new BadMethodCallException('not implemented'); + } + + public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition + { + $node = new ArrayNodeDefinition('simple'); + $node + ->children() + ->append($registry->component('exporter', SpanExporter::class)->isRequired()) + ->end() + ; + + return $node; + } +} diff --git a/tests/Unit/Config/SDK/Configuration/configurations/anchors.yaml b/tests/Unit/Config/SDK/Configuration/configurations/anchors.yaml new file mode 100644 index 000000000..f5c0f1a10 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/configurations/anchors.yaml @@ -0,0 +1,44 @@ +# Copied from https://github.com/open-telemetry/opentelemetry-configuration. License Apache 2.0 + +# 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 + default_histogram_aggregation: base2_exponential_bucket_histogram + +tracer_provider: + processors: + - batch: + exporter: + otlp: + # expand the otlp-exporter anchor + <<: *otlp-exporter \ No newline at end of file diff --git a/tests/Unit/Config/SDK/Configuration/configurations/kitchen-sink.yaml b/tests/Unit/Config/SDK/Configuration/configurations/kitchen-sink.yaml new file mode 100644 index 000000000..8a8a5b800 --- /dev/null +++ b/tests/Unit/Config/SDK/Configuration/configurations/kitchen-sink.yaml @@ -0,0 +1,388 @@ +# Copied from https://github.com/open-telemetry/opentelemetry-configuration. License Apache 2.0 +# Changes: +# - removed "exporter.otlp.insecure" fields + +# 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 pull-based metric reader. + - pull: + # Configure exporter. + # + # Environment variable: OTEL_METRICS_EXPORTER + exporter: + # Configure exporter to be prometheus. + prometheus: + # Configure host. + # + # Environment variable: OTEL_EXPORTER_PROMETHEUS_HOST + host: localhost + # Configure port. + # + # Environment variable: OTEL_EXPORTER_PROMETHEUS_PORT + port: 9464 + # Configure Prometheus Exporter to produce metrics without a unit suffix or UNIT metadata. + without_units: false + # Configure Prometheus Exporter to produce metrics without a type suffix. + without_type_suffix: false + # Configure Prometheus Exporter to produce metrics without a scope info metric. + without_scope_info: false + # 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 default histogram aggregation. + # + # Environment variable: OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION + default_histogram_aggregation: base2_exponential_bucket_histogram + # 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 aggregation to be explicit_bucket_histogram. + explicit_bucket_histogram: + # Configure bucket boundaries. + boundaries: [ 0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 7500.0, 10000.0 ] + # Configure record min and max. + record_min_max: true + # 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, xray, ottrace] + +# 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.16.0 \ No newline at end of file