Skip to content

Commit f1c9827

Browse files
authored
add sdk-config 0.3 support for key/value headers and attributes (#1428)
- headers and attributes are now arrays with `key` and `value` elements - headers can optionally contain a `headers_list` element which supports a lower-priority CSV of key/value entries - attributes can optionally contain an `attributes_list` element which supports a lower-priority CSV of key/value/data-type entries
1 parent 8857b0c commit f1c9827

File tree

8 files changed

+110
-34
lines changed

8 files changed

+110
-34
lines changed

examples/load_config.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ file_format: '0.3'
22

33
resource:
44
attributes:
5-
service.name: opentelemetry-demo
5+
- name: service.name
6+
value: opentelemetry-demo
7+
attributes_list: service.name=unused,example.foo=foo_value,example.bar=bar_value
68

79
propagators:
810
composite: [ tracecontext, baggage ]

examples/load_config_env.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ disabled: ${OTEL_SDK_DISABLED}
44

55
resource:
66
attributes:
7-
service.name: ${OTEL_SERVICE_NAME}
7+
- name: service.name
8+
value: ${OTEL_SERVICE_NAME}
89

910
propagators:
1011
composite: [ tracecontext, baggage ]

src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OpenTelemetry\Contrib\Otlp\LogsExporter;
1414
use OpenTelemetry\Contrib\Otlp\OtlpUtil;
1515
use OpenTelemetry\Contrib\Otlp\Protocols;
16+
use OpenTelemetry\SDK\Common\Configuration\Parser\MapParser;
1617
use OpenTelemetry\SDK\Logs\LogRecordExporterInterface;
1718
use OpenTelemetry\SDK\Registry;
1819
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
@@ -31,7 +32,8 @@ final class LogRecordExporterOtlp implements ComponentProvider
3132
* certificate: ?string,
3233
* client_key: ?string,
3334
* client_certificate: ?string,
34-
* headers: array<string, string>,
35+
* headers: list<array{name: string, value: string}>,
36+
* headers_list: ?string,
3537
* compression: 'gzip'|null,
3638
* timeout: int<0, max>,
3739
* } $properties
@@ -40,10 +42,12 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo
4042
{
4143
$protocol = $properties['protocol'];
4244

45+
$headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']);
46+
4347
return new LogsExporter(Registry::transportFactory($protocol)->create(
4448
endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::LOGS, $protocol),
4549
contentType: Protocols::contentType($protocol),
46-
headers: $properties['headers'],
50+
headers: $headers,
4751
compression: $properties['compression'],
4852
timeout: $properties['timeout'],
4953
cacert: $properties['certificate'],
@@ -63,8 +67,14 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit
6367
->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
6468
->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
6569
->arrayNode('headers')
66-
->scalarPrototype()->end()
70+
->arrayPrototype()
71+
->children()
72+
->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
73+
->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
74+
->end()
75+
->end()
6776
->end()
77+
->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
6878
->enumNode('compression')->values(['gzip'])->defaultNull()->end()
6979
->integerNode('timeout')->min(0)->defaultValue(10)->end()
7080
->end()

src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OpenTelemetry\Contrib\Otlp\MetricExporter;
1414
use OpenTelemetry\Contrib\Otlp\OtlpUtil;
1515
use OpenTelemetry\Contrib\Otlp\Protocols;
16+
use OpenTelemetry\SDK\Common\Configuration\Parser\MapParser;
1617
use OpenTelemetry\SDK\Metrics\Data\Temporality;
1718
use OpenTelemetry\SDK\Metrics\MetricExporterInterface;
1819
use OpenTelemetry\SDK\Registry;
@@ -32,7 +33,8 @@ final class MetricExporterOtlp implements ComponentProvider
3233
* certificate: ?string,
3334
* client_key: ?string,
3435
* client_certificate: ?string,
35-
* headers: array<string, string>,
36+
* headers: list<array{name: string, value: string}>,
37+
* headers_list: ?string,
3638
* compression: 'gzip'|null,
3739
* timeout: int<0, max>,
3840
* temporality_preference: 'cumulative'|'delta'|'lowmemory',
@@ -43,6 +45,8 @@ public function createPlugin(array $properties, Context $context): MetricExporte
4345
{
4446
$protocol = $properties['protocol'];
4547

48+
$headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']);
49+
4650
$temporality = match ($properties['temporality_preference']) {
4751
'cumulative' => Temporality::CUMULATIVE,
4852
'delta' => Temporality::DELTA,
@@ -52,7 +56,7 @@ public function createPlugin(array $properties, Context $context): MetricExporte
5256
return new MetricExporter(Registry::transportFactory($protocol)->create(
5357
endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::METRICS, $protocol),
5458
contentType: Protocols::contentType($protocol),
55-
headers: $properties['headers'],
59+
headers: $headers,
5660
compression: $properties['compression'],
5761
timeout: $properties['timeout'],
5862
cacert: $properties['certificate'],
@@ -72,8 +76,14 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit
7276
->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
7377
->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
7478
->arrayNode('headers')
75-
->scalarPrototype()->end()
79+
->arrayPrototype()
80+
->children()
81+
->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
82+
->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
83+
->end()
84+
->end()
7685
->end()
86+
->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
7787
->enumNode('compression')->values(['gzip'])->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
7888
->integerNode('timeout')->min(0)->defaultValue(10)->end()
7989
->enumNode('temporality_preference')

src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator;
1414
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
1515
use OpenTelemetry\SDK\Common\Attribute\Attributes;
16+
use OpenTelemetry\SDK\Common\Configuration\Parser\MapParser;
1617
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
1718
use OpenTelemetry\SDK\Logs\EventLoggerProvider;
1819
use OpenTelemetry\SDK\Logs\LoggerProvider;
@@ -56,6 +57,7 @@ final class OpenTelemetrySdk implements ComponentProvider
5657
* disabled: bool,
5758
* resource: array{
5859
* attributes: array,
60+
* attributes_list: ?string,
5961
* schema_url: ?string,
6062
* },
6163
* attribute_limits: array{
@@ -113,10 +115,10 @@ public function createPlugin(array $properties, Context $context): SdkBuilder
113115
if ($properties['disabled']) {
114116
return $sdkBuilder;
115117
}
116-
118+
$attributes = array_column($properties['resource']['attributes'], 'value', 'name') + MapParser::parse($properties['resource']['attributes_list']);
117119
$resource = ResourceInfoFactory::defaultResource()
118120
->merge(ResourceInfo::create(
119-
attributes: Attributes::create($properties['resource']['attributes']),
121+
attributes: Attributes::create($attributes),
120122
schemaUrl: $properties['resource']['schema_url'],
121123
));
122124

@@ -284,8 +286,18 @@ private function getResourceConfig(): ArrayNodeDefinition
284286
->addDefaultsIfNotSet()
285287
->children()
286288
->arrayNode('attributes')
287-
->variablePrototype()->end()
289+
->arrayPrototype()
290+
->children()
291+
->scalarNode('name')->isRequired()->end()
292+
->variableNode('value')->isRequired()->end()
293+
// @todo use type to validate and/or cast attributes
294+
->enumNode('type')->defaultNull()
295+
->values(['string', 'bool', 'int', 'double', 'string_array', 'bool_array', 'int_array', 'double_array'])
296+
->end()
297+
->end()
298+
->end()
288299
->end()
300+
->scalarNode('attributes_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
289301
->scalarNode('schema_url')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
290302
->end();
291303

src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OpenTelemetry\Contrib\Otlp\OtlpUtil;
1414
use OpenTelemetry\Contrib\Otlp\Protocols;
1515
use OpenTelemetry\Contrib\Otlp\SpanExporter;
16+
use OpenTelemetry\SDK\Common\Configuration\Parser\MapParser;
1617
use OpenTelemetry\SDK\Registry;
1718
use OpenTelemetry\SDK\Trace\SpanExporterInterface;
1819
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
@@ -31,7 +32,8 @@ final class SpanExporterOtlp implements ComponentProvider
3132
* certificate: ?string,
3233
* client_key: ?string,
3334
* client_certificate: ?string,
34-
* headers: array<string, string>,
35+
* headers: list<array{name: string, value: string}>,
36+
* headers_list: ?string,
3537
* compression: 'gzip'|null,
3638
* timeout: int<0, max>,
3739
* } $properties
@@ -40,10 +42,12 @@ public function createPlugin(array $properties, Context $context): SpanExporterI
4042
{
4143
$protocol = $properties['protocol'];
4244

45+
$headers = array_column($properties['headers'], 'value', 'name') + MapParser::parse($properties['headers_list']);
46+
4347
return new SpanExporter(Registry::transportFactory($protocol)->create(
4448
endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::TRACE, $protocol),
4549
contentType: Protocols::contentType($protocol),
46-
headers: $properties['headers'],
50+
headers: $headers,
4751
compression: $properties['compression'],
4852
timeout: $properties['timeout'],
4953
cacert: $properties['certificate'],
@@ -63,8 +67,14 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit
6367
->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
6468
->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
6569
->arrayNode('headers')
66-
->scalarPrototype()->end()
70+
->arrayPrototype()
71+
->children()
72+
->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
73+
->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
74+
->end()
75+
->end()
6776
->end()
77+
->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
6878
->enumNode('compression')->values(['gzip'])->defaultNull()->end()
6979
->integerNode('timeout')->min(0)->defaultValue(10)->end()
7080
->end()

tests/Integration/Config/configurations/anchors.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ exporters:
99
client_key: /app/cert.pem
1010
client_certificate: /app/cert.pem
1111
headers:
12-
api-key: !!str 1234
12+
- name: api-key
13+
value: "str 1234"
1314
compression: gzip
1415
timeout: 10000
1516

tests/Integration/Config/configurations/kitchen-sink.yaml

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,13 @@ logger_provider:
7474
#
7575
# Environment variable: OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE
7676
client_certificate: /app/cert.pem
77-
# Configure headers.
78-
#
79-
# Environment variable: OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_LOGS_HEADERS
77+
# Configure headers. Entries have higher priority than entries from .headers_list.
8078
headers:
81-
api-key: "1234"
79+
- name: api-key
80+
value: "1234"
81+
# Configure headers. Entries have lower priority than entries from .headers.
82+
# The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details.
83+
headers_list: "api-key=1234"
8284
# Configure compression.
8385
#
8486
# Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_LOGS_COMPRESSION
@@ -138,11 +140,13 @@ meter_provider:
138140
#
139141
# Environment variable: OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE
140142
client_certificate: /app/cert.pem
141-
# Configure headers.
142-
#
143-
# Environment variable: OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_METRICS_HEADERS
143+
# Configure headers. Entries have higher priority than entries from .headers_list.
144144
headers:
145-
api-key: !!str 1234
145+
- name: api-key
146+
value: "1234"
147+
# Configure headers. Entries have lower priority than entries from .headers.
148+
# The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details.
149+
headers_list: "api-key=1234"
146150
# Configure compression.
147151
#
148152
# Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_METRICS_COMPRESSION
@@ -244,11 +248,13 @@ tracer_provider:
244248
#
245249
# Environment variable: OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE
246250
client_certificate: /app/cert.pem
247-
# Configure headers.
248-
#
249-
# Environment variable: OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS
251+
# Configure headers. Entries have higher priority than entries from .headers_list.
250252
headers:
251-
api-key: !!str 1234
253+
- name: api-key
254+
value: "1234"
255+
# Configure headers. Entries have lower priority than entries from .headers.
256+
# The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details.
257+
headers_list: "api-key=1234"
252258
# Configure compression.
253259
#
254260
# Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_TRACES_COMPRESSION
@@ -340,14 +346,38 @@ tracer_provider:
340346

341347
# Configure resource for all signals.
342348
resource:
343-
# Configure resource attributes.
344-
#
345-
# Environment variable: OTEL_RESOURCE_ATTRIBUTES
349+
# Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list.
350+
# Entries must contain .name nand .value, and may optionally include .type, which defaults ot "string" if not set. The value must match the type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array.
346351
attributes:
347-
# Configure `service.name` resource attribute
348-
#
349-
# Environment variable: OTEL_SERVICE_NAME
350-
service.name: !!str "unknown_service"
352+
- name: service.name
353+
value: unknown_service
354+
- name: string_key
355+
value: value
356+
type: string
357+
- name: bool_key
358+
value: true
359+
type: bool
360+
- name: int_key
361+
value: 1
362+
type: int
363+
- name: double_key
364+
value: 1.1
365+
type: double
366+
- name: string_array_key
367+
value: [ "value1", "value2" ]
368+
type: string_array
369+
- name: bool_array_key
370+
value: [ true, false ]
371+
type: bool_array
372+
- name: int_array_key
373+
value: [ 1, 2 ]
374+
type: int_array
375+
- name: double_array_key
376+
value: [ 1.1, 2.2 ]
377+
type: double_array
378+
# Configure resource attributes. Entries have lower priority than entries from .resource.attributes.
379+
# The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration for details.
380+
attributes_list: "service.namespace=my-namespace,service.version=1.0.0"
351381
# Configure the resource schema URL.
352382
schema_url: https://opentelemetry.io/schemas/1.27.0
353383

0 commit comments

Comments
 (0)