Skip to content

Commit 4cb73bd

Browse files
bm1549claude
andcommitted
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) <noreply@anthropic.com>
1 parent 8499f59 commit 4cb73bd

2 files changed

Lines changed: 213 additions & 18 deletions

File tree

metadata/supported-configurations.json

Lines changed: 139 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,45 +2654,171 @@
26542654
"default": ""
26552655
}
26562656
],
2657+
"OTEL_BLRP_EXPORT_TIMEOUT": [
2658+
{
2659+
"implementation": "A",
2660+
"type": "int",
2661+
"default": "30000"
2662+
}
2663+
],
2664+
"OTEL_BLRP_MAX_EXPORT_BATCH_SIZE": [
2665+
{
2666+
"implementation": "A",
2667+
"type": "int",
2668+
"default": "512"
2669+
}
2670+
],
2671+
"OTEL_BLRP_MAX_QUEUE_SIZE": [
2672+
{
2673+
"implementation": "A",
2674+
"type": "int",
2675+
"default": "2048"
2676+
}
2677+
],
2678+
"OTEL_BLRP_SCHEDULE_DELAY": [
2679+
{
2680+
"implementation": "A",
2681+
"type": "int",
2682+
"default": "1000"
2683+
}
2684+
],
26572685
"OTEL_EXPORTER_OTLP_ENDPOINT": [
26582686
{
2659-
"implementation": "D",
2687+
"implementation": "B",
26602688
"type": "string",
2689+
"default": "http://localhost:4318"
2690+
}
2691+
],
2692+
"OTEL_EXPORTER_OTLP_HEADERS": [
2693+
{
2694+
"implementation": "A",
2695+
"type": "map",
26612696
"default": ""
26622697
}
26632698
],
2664-
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": [
2699+
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": [
2700+
{
2701+
"implementation": "A",
2702+
"type": "string",
2703+
"default": "http://localhost:4318"
2704+
}
2705+
],
2706+
"OTEL_EXPORTER_OTLP_LOGS_HEADERS": [
2707+
{
2708+
"implementation": "A",
2709+
"type": "map",
2710+
"default": ""
2711+
}
2712+
],
2713+
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": [
26652714
{
26662715
"implementation": "D",
26672716
"type": "string",
2717+
"default": "http/protobuf"
2718+
}
2719+
],
2720+
"OTEL_EXPORTER_OTLP_LOGS_TIMEOUT": [
2721+
{
2722+
"implementation": "A",
2723+
"type": "int",
2724+
"default": "10000"
2725+
}
2726+
],
2727+
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": [
2728+
{
2729+
"implementation": "B",
2730+
"type": "string",
2731+
"default": "http://localhost:4318"
2732+
}
2733+
],
2734+
"OTEL_EXPORTER_OTLP_METRICS_HEADERS": [
2735+
{
2736+
"implementation": "A",
2737+
"type": "map",
26682738
"default": ""
26692739
}
26702740
],
2741+
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": [
2742+
{
2743+
"implementation": "B",
2744+
"type": "string",
2745+
"default": "http/protobuf"
2746+
}
2747+
],
2748+
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": [
2749+
{
2750+
"implementation": "A",
2751+
"type": "string",
2752+
"default": "cumulative"
2753+
}
2754+
],
2755+
"OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": [
2756+
{
2757+
"implementation": "B",
2758+
"type": "int",
2759+
"default": "10000"
2760+
}
2761+
],
2762+
"OTEL_EXPORTER_OTLP_PROTOCOL": [
2763+
{
2764+
"implementation": "A",
2765+
"type": "string",
2766+
"default": "http/protobuf"
2767+
}
2768+
],
2769+
"OTEL_EXPORTER_OTLP_TIMEOUT": [
2770+
{
2771+
"implementation": "A",
2772+
"type": "int",
2773+
"default": "10000"
2774+
}
2775+
],
2776+
"OTEL_LOGS_EXPORTER": [
2777+
{
2778+
"implementation": "A",
2779+
"type": "array",
2780+
"default": "otlp"
2781+
}
2782+
],
26712783
"OTEL_LOG_LEVEL": [
26722784
{
26732785
"implementation": "E",
26742786
"type": "string",
2675-
"default": ""
2787+
"default": "info"
26762788
}
26772789
],
26782790
"OTEL_METRICS_EXPORTER": [
26792791
{
26802792
"implementation": "D",
2681-
"type": "string",
2682-
"default": ""
2793+
"type": "array",
2794+
"default": "otlp"
2795+
}
2796+
],
2797+
"OTEL_METRIC_EXPORT_INTERVAL": [
2798+
{
2799+
"implementation": "A",
2800+
"type": "int",
2801+
"default": "60000"
2802+
}
2803+
],
2804+
"OTEL_METRIC_EXPORT_TIMEOUT": [
2805+
{
2806+
"implementation": "A",
2807+
"type": "int",
2808+
"default": "30000"
26832809
}
26842810
],
26852811
"OTEL_PROPAGATORS": [
26862812
{
26872813
"implementation": "B",
2688-
"type": "string",
2689-
"default": ""
2814+
"type": "array",
2815+
"default": "tracecontext,baggage"
26902816
}
26912817
],
26922818
"OTEL_RESOURCE_ATTRIBUTES": [
26932819
{
2694-
"implementation": "B",
2695-
"type": "string",
2820+
"implementation": "A",
2821+
"type": "map",
26962822
"default": ""
26972823
}
26982824
],
@@ -2706,15 +2832,15 @@
27062832
"OTEL_TRACES_EXPORTER": [
27072833
{
27082834
"implementation": "E",
2709-
"type": "string",
2710-
"default": ""
2835+
"type": "array",
2836+
"default": "otlp"
27112837
}
27122838
],
27132839
"OTEL_TRACES_SAMPLER": [
27142840
{
2715-
"implementation": "D",
2841+
"implementation": "E",
27162842
"type": "string",
2717-
"default": ""
2843+
"default": "parentbased_always_on"
27182844
}
27192845
],
27202846
"OTEL_TRACES_SAMPLER_ARG": [

tooling/generate-supported-configurations.sh

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ readonly CONFIG_HEADER_FILES=(
1212
readonly OTEL_CONFIG_FILES=(
1313
"ext/otel_config.c"
1414
"tracer/tracer_otel_config.c"
15+
"src/DDTrace/OpenTelemetry/Configuration.php"
1516
)
1617
readonly PROFILING_CONFIG_FILE="profiling/src/config.rs"
1718
readonly GENERATOR_SCRIPT_FILE="tooling/generate-supported-configurations.sh"
@@ -120,6 +121,24 @@ function add_supported_entry(&$supported, $name, $entry) {
120121
}
121122
}
122123
124+
function add_otel_entries(&$supported, $names, $metadata) {
125+
$names = array_unique($names);
126+
sort($names);
127+
foreach ($names as $name) {
128+
if (isset($metadata[$name])) {
129+
// The SDK metadata table is authoritative for OTEL vars: overwrite any
130+
// entry derived from an extension CONFIG of the same name (e.g.
131+
// OTEL_EXPORTER_OTLP_METRICS_ENDPOINT) so the published default is the
132+
// SDK's rather than the extension's runtime resolution.
133+
[$type, $default] = $metadata[$name];
134+
$supported[$name] = [["implementation" => "A", "type" => $type, "default" => $default]];
135+
} else {
136+
// Not in the table: an OTEL var resolved by the SDK that we don't model.
137+
add_supported_entry($supported, $name, ["implementation" => "A", "type" => "string", "default" => ""]);
138+
}
139+
}
140+
}
141+
123142
// temporary solution until we merge configs
124143
function map_rust_type($rawType, $parser) {
125144
$map = [
@@ -273,18 +292,68 @@ foreach (explode("|NEXT_CONFIG|", file_get_contents("php://stdin")) as $configLi
273292
add_supported_entry($supported, $name, $entry);
274293
}
275294
295+
// Type and default for OTEL configs, sourced from the open-telemetry/sdk PHP
296+
// package (Common/Configuration/ValueTypes.php and Defaults.php, v1.x), since
297+
// these vars are resolved by the SDK rather than the extension. SDK enum/mixed
298+
// types map to the schema's "string", list -> "array", map -> "map", and
299+
// integer -> "int"; per the schema every default is a string and map/array
300+
// defaults are "". The *_LOGS_* vars are undefined in the SDK's ValueTypes and
301+
// mirror their generic OTLP counterparts. The metrics temporality default is the
302+
// SDK value "cumulative"; DatadogResolver overrides it to "delta" at runtime.
303+
// These SDK defaults are authoritative even where the extension also defines the
304+
// config (e.g. OTEL_EXPORTER_OTLP_METRICS_ENDPOINT), so the published default
305+
// reflects the OTel spec, not the extension's runtime resolution.
306+
$otelMetadata = [
307+
"OTEL_BLRP_EXPORT_TIMEOUT" => ["int", "30000"],
308+
"OTEL_BLRP_MAX_EXPORT_BATCH_SIZE" => ["int", "512"],
309+
"OTEL_BLRP_MAX_QUEUE_SIZE" => ["int", "2048"],
310+
"OTEL_BLRP_SCHEDULE_DELAY" => ["int", "1000"],
311+
"OTEL_EXPORTER_OTLP_ENDPOINT" => ["string", "http://localhost:4318"],
312+
"OTEL_EXPORTER_OTLP_HEADERS" => ["map", ""],
313+
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT" => ["string", "http://localhost:4318"],
314+
"OTEL_EXPORTER_OTLP_LOGS_HEADERS" => ["map", ""],
315+
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL" => ["string", "http/protobuf"],
316+
"OTEL_EXPORTER_OTLP_LOGS_TIMEOUT" => ["int", "10000"],
317+
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT" => ["string", "http://localhost:4318"],
318+
"OTEL_EXPORTER_OTLP_METRICS_HEADERS" => ["map", ""],
319+
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL" => ["string", "http/protobuf"],
320+
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE" => ["string", "cumulative"],
321+
"OTEL_EXPORTER_OTLP_METRICS_TIMEOUT" => ["int", "10000"],
322+
"OTEL_EXPORTER_OTLP_PROTOCOL" => ["string", "http/protobuf"],
323+
"OTEL_EXPORTER_OTLP_TIMEOUT" => ["int", "10000"],
324+
"OTEL_LOG_LEVEL" => ["string", "info"],
325+
"OTEL_LOGS_EXPORTER" => ["array", "otlp"],
326+
"OTEL_METRICS_EXPORTER" => ["array", "otlp"],
327+
"OTEL_METRIC_EXPORT_INTERVAL" => ["int", "60000"],
328+
"OTEL_METRIC_EXPORT_TIMEOUT" => ["int", "30000"],
329+
"OTEL_PROPAGATORS" => ["array", "tracecontext,baggage"],
330+
"OTEL_RESOURCE_ATTRIBUTES" => ["map", ""],
331+
"OTEL_SERVICE_NAME" => ["string", ""],
332+
"OTEL_TRACES_EXPORTER" => ["array", "otlp"],
333+
"OTEL_TRACES_SAMPLER" => ["string", "parentbased_always_on"],
334+
"OTEL_TRACES_SAMPLER_ARG" => ["string", ""],
335+
];
336+
337+
// OTEL env vars the C extension reads directly via ZAI_STRL("OTEL_...").
276338
$otelPaths = ["../ext/otel_config.c", "../tracer/tracer_otel_config.c"];
277339
foreach ($otelPaths as $otelPath) {
278340
if (file_exists($otelPath)) {
279341
preg_match_all('/ZAI_STRL\("(OTEL_[A-Z0-9_]+)"\)/', file_get_contents($otelPath), $m);
280-
$otelVars = array_unique($m[1]);
281-
sort($otelVars);
282-
foreach ($otelVars as $v) {
283-
add_supported_entry($supported, $v, ["implementation" => "A", "type" => "string", "default" => ""]);
284-
}
342+
add_otel_entries($supported, $m[1], $otelMetadata);
285343
}
286344
}
287345
346+
// OTEL configs read by the OpenTelemetry SDK rather than the extension (e.g.
347+
// OTEL_EXPORTER_OTLP_HEADERS), enumerated in the PHP telemetry whitelist.
348+
// Scope to the OTEL_CONFIG_WHITELIST array literal so unrelated OTEL_ mentions
349+
// elsewhere in the file (comments, error strings) can't be published.
350+
$otelWhitelistPath = "../src/DDTrace/OpenTelemetry/Configuration.php";
351+
if (file_exists($otelWhitelistPath)
352+
&& preg_match('/OTEL_CONFIG_WHITELIST\s*=\s*\[(.*?)\]/s', file_get_contents($otelWhitelistPath), $whitelistMatch)) {
353+
preg_match_all('/\'(OTEL_[A-Z0-9_]+)\'/', $whitelistMatch[1], $m);
354+
add_otel_entries($supported, $m[1], $otelMetadata);
355+
}
356+
288357
$profilingPath = "../profiling/src/config.rs";
289358
add_rust_profiling_configurations($supported, $profilingPath);
290359

0 commit comments

Comments
 (0)