From 1c704e51df79c1112ed01e83e3f32751e591ad23 Mon Sep 17 00:00:00 2001 From: Brian Marks Date: Mon, 22 Jun 2026 13:50:50 -0400 Subject: [PATCH] feat(otel): capture OTEL_CONFIG_WHITELIST vars with SDK-accurate type/default The supported-configurations.json generator only scraped OTEL env vars that the C extension reads via ZAI_STRL(), so SDK-owned configs such as OTEL_EXPORTER_OTLP_HEADERS were never published. Scrape the OTEL_CONFIG_WHITELIST array in src/DDTrace/OpenTelemetry/Configuration.php as an additional source (scoped to the array literal so unrelated OTEL_ mentions can't leak in) and add that file to the input manifest. These OTEL vars are resolved by the open-telemetry/sdk PHP package rather than the extension, so publishing them all as string/"" was inaccurate. Add a static type/default table sourced from open-telemetry/sdk 1.x (Common/Configuration/ValueTypes.php and Defaults.php) so timeouts/intervals/ sizes are int, headers/resource attrs are map, exporters/propagators are array, and protocols/endpoints/samplers carry their real SDK defaults. The table is authoritative for OTEL vars, so SDK defaults are published even where the extension also defines the config (e.g. OTEL_EXPORTER_OTLP_METRICS_ENDPOINT). Existing implementation labels are preserved. Note: defaults reflect SDK values; DatadogResolver overrides some at runtime (e.g. metrics temporality -> delta). Co-Authored-By: Claude Opus 4.8 (1M context) --- metadata/supported-configurations.json | 162 ++++++++++++++++--- tooling/generate-supported-configurations.sh | 79 ++++++++- 2 files changed, 218 insertions(+), 23 deletions(-) diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 1cf6ad217f..a2eb6e8c36 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -2654,45 +2654,171 @@ "default": "" } ], + "OTEL_BLRP_EXPORT_TIMEOUT": [ + { + "implementation": "A", + "type": "int", + "default": "30000" + } + ], + "OTEL_BLRP_MAX_EXPORT_BATCH_SIZE": [ + { + "implementation": "A", + "type": "int", + "default": "512" + } + ], + "OTEL_BLRP_MAX_QUEUE_SIZE": [ + { + "implementation": "A", + "type": "int", + "default": "2048" + } + ], + "OTEL_BLRP_SCHEDULE_DELAY": [ + { + "implementation": "A", + "type": "int", + "default": "1000" + } + ], "OTEL_EXPORTER_OTLP_ENDPOINT": [ { - "implementation": "D", + "implementation": "B", "type": "string", - "default": "" + "default": "http://localhost:4318" } ], - "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": [ + "OTEL_EXPORTER_OTLP_HEADERS": [ { - "implementation": "D", - "type": "string", + "implementation": "A", + "type": "map", "default": "" } ], - "OTEL_LOG_LEVEL": [ + "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": [ { - "implementation": "E", + "implementation": "C", "type": "string", - "default": "" + "default": "http://localhost:4318" } ], - "OTEL_METRICS_EXPORTER": [ + "OTEL_EXPORTER_OTLP_LOGS_HEADERS": [ + { + "implementation": "B", + "type": "map", + "default": null + } + ], + "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": [ { "implementation": "D", "type": "string", - "default": "" + "default": "http/protobuf" } ], - "OTEL_PROPAGATORS": [ + "OTEL_EXPORTER_OTLP_LOGS_TIMEOUT": [ + { + "implementation": "A", + "type": "int", + "default": "10000" + } + ], + "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": [ { "implementation": "B", "type": "string", - "default": "" + "default": "http://localhost:4318" } ], - "OTEL_RESOURCE_ATTRIBUTES": [ + "OTEL_EXPORTER_OTLP_METRICS_HEADERS": [ + { + "implementation": "A", + "type": "map", + "default": null + } + ], + "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": [ { "implementation": "B", "type": "string", + "default": "http/protobuf" + } + ], + "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": [ + { + "implementation": "C", + "type": "string", + "default": "cumulative" + } + ], + "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": [ + { + "implementation": "B", + "type": "int", + "default": "10000" + } + ], + "OTEL_EXPORTER_OTLP_PROTOCOL": [ + { + "implementation": "A", + "type": "string", + "default": "http/protobuf" + } + ], + "OTEL_EXPORTER_OTLP_TIMEOUT": [ + { + "implementation": "A", + "type": "int", + "default": "10000" + } + ], + "OTEL_LOGS_EXPORTER": [ + { + "implementation": "C", + "type": "array", + "default": "otlp" + } + ], + "OTEL_LOG_LEVEL": [ + { + "implementation": "F", + "type": "string", + "default": "info" + } + ], + "OTEL_METRICS_EXPORTER": [ + { + "implementation": "E", + "type": "array", + "default": "otlp" + } + ], + "OTEL_METRIC_EXPORT_INTERVAL": [ + { + "implementation": "B", + "type": "int", + "default": "60000" + } + ], + "OTEL_METRIC_EXPORT_TIMEOUT": [ + { + "implementation": "B", + "type": "int", + "default": "30000" + } + ], + "OTEL_PROPAGATORS": [ + { + "implementation": "C", + "type": "array", + "default": "tracecontext,baggage" + } + ], + "OTEL_RESOURCE_ATTRIBUTES": [ + { + "implementation": "A", + "type": "map", "default": "" } ], @@ -2705,16 +2831,16 @@ ], "OTEL_TRACES_EXPORTER": [ { - "implementation": "E", - "type": "string", - "default": "" + "implementation": "I", + "type": "array", + "default": "otlp" } ], "OTEL_TRACES_SAMPLER": [ { - "implementation": "D", + "implementation": "E", "type": "string", - "default": "" + "default": "parentbased_always_on" } ], "OTEL_TRACES_SAMPLER_ARG": [ diff --git a/tooling/generate-supported-configurations.sh b/tooling/generate-supported-configurations.sh index 3f0c5296b1..44159f2ff0 100755 --- a/tooling/generate-supported-configurations.sh +++ b/tooling/generate-supported-configurations.sh @@ -12,6 +12,7 @@ readonly CONFIG_HEADER_FILES=( readonly OTEL_CONFIG_FILES=( "ext/otel_config.c" "tracer/tracer_otel_config.c" + "src/DDTrace/OpenTelemetry/Configuration.php" ) readonly PROFILING_CONFIG_FILE="profiling/src/config.rs" readonly GENERATOR_SCRIPT_FILE="tooling/generate-supported-configurations.sh" @@ -120,6 +121,24 @@ function add_supported_entry(&$supported, $name, $entry) { } } +function add_otel_entries(&$supported, $names, $metadata) { + $names = array_unique($names); + sort($names); + foreach ($names as $name) { + if (isset($metadata[$name])) { + // The SDK metadata table is authoritative for OTEL vars: overwrite any + // entry derived from an extension CONFIG of the same name (e.g. + // OTEL_EXPORTER_OTLP_METRICS_ENDPOINT) so the published default is the + // SDK's rather than the extension's runtime resolution. + [$type, $default] = $metadata[$name]; + $supported[$name] = [["implementation" => "A", "type" => $type, "default" => $default]]; + } else { + // Not in the table: an OTEL var resolved by the SDK that we don't model. + add_supported_entry($supported, $name, ["implementation" => "A", "type" => "string", "default" => ""]); + } + } +} + // temporary solution until we merge configs function map_rust_type($rawType, $parser) { $map = [ @@ -273,18 +292,68 @@ foreach (explode("|NEXT_CONFIG|", file_get_contents("php://stdin")) as $configLi add_supported_entry($supported, $name, $entry); } +// Type and default for OTEL configs, sourced from the open-telemetry/sdk PHP +// package (Common/Configuration/ValueTypes.php and Defaults.php, v1.x), since +// these vars are resolved by the SDK rather than the extension. SDK enum/mixed +// types map to the schema's "string", list -> "array", map -> "map", and +// integer -> "int"; per the schema every default is a string and map/array +// defaults are "". The *_LOGS_* vars are undefined in the SDK's ValueTypes and +// mirror their generic OTLP counterparts. The metrics temporality default is the +// SDK value "cumulative"; DatadogResolver overrides it to "delta" at runtime. +// These SDK defaults are authoritative even where the extension also defines the +// config (e.g. OTEL_EXPORTER_OTLP_METRICS_ENDPOINT), so the published default +// reflects the OTel spec, not the extension's runtime resolution. +$otelMetadata = [ + "OTEL_BLRP_EXPORT_TIMEOUT" => ["int", "30000"], + "OTEL_BLRP_MAX_EXPORT_BATCH_SIZE" => ["int", "512"], + "OTEL_BLRP_MAX_QUEUE_SIZE" => ["int", "2048"], + "OTEL_BLRP_SCHEDULE_DELAY" => ["int", "1000"], + "OTEL_EXPORTER_OTLP_ENDPOINT" => ["string", "http://localhost:4318"], + "OTEL_EXPORTER_OTLP_HEADERS" => ["map", ""], + "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT" => ["string", "http://localhost:4318"], + "OTEL_EXPORTER_OTLP_LOGS_HEADERS" => ["map", null], + "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL" => ["string", "http/protobuf"], + "OTEL_EXPORTER_OTLP_LOGS_TIMEOUT" => ["int", "10000"], + "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT" => ["string", "http://localhost:4318"], + "OTEL_EXPORTER_OTLP_METRICS_HEADERS" => ["map", null], + "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL" => ["string", "http/protobuf"], + "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE" => ["string", "cumulative"], + "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT" => ["int", "10000"], + "OTEL_EXPORTER_OTLP_PROTOCOL" => ["string", "http/protobuf"], + "OTEL_EXPORTER_OTLP_TIMEOUT" => ["int", "10000"], + "OTEL_LOG_LEVEL" => ["string", "info"], + "OTEL_LOGS_EXPORTER" => ["array", "otlp"], + "OTEL_METRICS_EXPORTER" => ["array", "otlp"], + "OTEL_METRIC_EXPORT_INTERVAL" => ["int", "60000"], + "OTEL_METRIC_EXPORT_TIMEOUT" => ["int", "30000"], + "OTEL_PROPAGATORS" => ["array", "tracecontext,baggage"], + "OTEL_RESOURCE_ATTRIBUTES" => ["map", ""], + "OTEL_SERVICE_NAME" => ["string", ""], + "OTEL_TRACES_EXPORTER" => ["array", "otlp"], + "OTEL_TRACES_SAMPLER" => ["string", "parentbased_always_on"], + "OTEL_TRACES_SAMPLER_ARG" => ["string", ""], +]; + +// OTEL env vars the C extension reads directly via ZAI_STRL("OTEL_..."). $otelPaths = ["../ext/otel_config.c", "../tracer/tracer_otel_config.c"]; foreach ($otelPaths as $otelPath) { if (file_exists($otelPath)) { preg_match_all('/ZAI_STRL\("(OTEL_[A-Z0-9_]+)"\)/', file_get_contents($otelPath), $m); - $otelVars = array_unique($m[1]); - sort($otelVars); - foreach ($otelVars as $v) { - add_supported_entry($supported, $v, ["implementation" => "A", "type" => "string", "default" => ""]); - } + add_otel_entries($supported, $m[1], $otelMetadata); } } +// OTEL configs read by the OpenTelemetry SDK rather than the extension (e.g. +// OTEL_EXPORTER_OTLP_HEADERS), enumerated in the PHP telemetry whitelist. +// Scope to the OTEL_CONFIG_WHITELIST array literal so unrelated OTEL_ mentions +// elsewhere in the file (comments, error strings) can't be published. +$otelWhitelistPath = "../src/DDTrace/OpenTelemetry/Configuration.php"; +if (file_exists($otelWhitelistPath) + && preg_match('/OTEL_CONFIG_WHITELIST\s*=\s*\[(.*?)\]/s', file_get_contents($otelWhitelistPath), $whitelistMatch)) { + preg_match_all('/\'(OTEL_[A-Z0-9_]+)\'/', $whitelistMatch[1], $m); + add_otel_entries($supported, $m[1], $otelMetadata); +} + $profilingPath = "../profiling/src/config.rs"; add_rust_profiling_configurations($supported, $profilingPath);