Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add sdk-config 0.3 support for key/value headers and attributes #1428

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/load_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ file_format: '0.3'

resource:
attributes:
service.name: opentelemetry-demo
- name: service.name
value: opentelemetry-demo
attributes_list: service.name=unused,example.foo=foo_value,example.bar=bar_value

propagators:
composite: [ tracecontext, baggage ]
Expand Down
3 changes: 2 additions & 1 deletion examples/load_config_env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ disabled: ${OTEL_SDK_DISABLED}

resource:
attributes:
service.name: ${OTEL_SERVICE_NAME}
- name: service.name
value: ${OTEL_SERVICE_NAME}

propagators:
composite: [ tracecontext, baggage ]
Expand Down
16 changes: 13 additions & 3 deletions src/Config/SDK/ComponentProvider/Logs/LogRecordExporterOtlp.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ final class LogRecordExporterOtlp implements ComponentProvider
* certificate: ?string,
* client_key: ?string,
* client_certificate: ?string,
* headers: array<string, string>,
* headers: array,
brettmc marked this conversation as resolved.
Show resolved Hide resolved
* headers_list: ?string,
* compression: 'gzip'|null,
* timeout: int<0, max>,
* } $properties
Expand All @@ -40,10 +41,13 @@ public function createPlugin(array $properties, Context $context): LogRecordExpo
{
$protocol = $properties['protocol'];

$headers_list = array_column(array_map(fn ($item) => explode('=', $item), explode(',', $properties['headers_list'] ?? '')), 1, 0);
$headers = array_column($properties['headers'], 'value', 'name') + $headers_list;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be moved into a utility class? It looks to be used in several places 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had an existing class which already does this, so I've updated to use MapParser


return new LogsExporter(Registry::transportFactory($protocol)->create(
endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::LOGS, $protocol),
contentType: Protocols::contentType($protocol),
headers: $properties['headers'],
headers: $headers,
compression: $properties['compression'],
timeout: $properties['timeout'],
cacert: $properties['certificate'],
Expand All @@ -63,8 +67,14 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit
->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->arrayNode('headers')
->scalarPrototype()->end()
->arrayPrototype()
->children()
->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->end()
->end()
->end()
->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->enumNode('compression')->values(['gzip'])->defaultNull()->end()
->integerNode('timeout')->min(0)->defaultValue(10)->end()
->end()
Expand Down
16 changes: 13 additions & 3 deletions src/Config/SDK/ComponentProvider/Metrics/MetricExporterOtlp.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ final class MetricExporterOtlp implements ComponentProvider
* certificate: ?string,
* client_key: ?string,
* client_certificate: ?string,
* headers: array<string, string>,
* headers: array,
* headers_list: ?string,
* compression: 'gzip'|null,
* timeout: int<0, max>,
* temporality_preference: 'cumulative'|'delta'|'lowmemory',
Expand All @@ -43,6 +44,9 @@ public function createPlugin(array $properties, Context $context): MetricExporte
{
$protocol = $properties['protocol'];

$headers_list = array_column(array_map(fn ($item) => explode('=', $item), explode(',', $properties['headers_list'] ?? '')), 1, 0);
$headers = array_column($properties['headers'], 'value', 'name') + $headers_list;

$temporality = match ($properties['temporality_preference']) {
'cumulative' => Temporality::CUMULATIVE,
'delta' => Temporality::DELTA,
Expand All @@ -52,7 +56,7 @@ public function createPlugin(array $properties, Context $context): MetricExporte
return new MetricExporter(Registry::transportFactory($protocol)->create(
endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::METRICS, $protocol),
contentType: Protocols::contentType($protocol),
headers: $properties['headers'],
headers: $headers,
compression: $properties['compression'],
timeout: $properties['timeout'],
cacert: $properties['certificate'],
Expand All @@ -72,8 +76,14 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit
->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->arrayNode('headers')
->scalarPrototype()->end()
->arrayPrototype()
->children()
->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->end()
->end()
->end()
->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->enumNode('compression')->values(['gzip'])->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->integerNode('timeout')->min(0)->defaultValue(10)->end()
->enumNode('temporality_preference')
Expand Down
19 changes: 16 additions & 3 deletions src/Config/SDK/ComponentProvider/OpenTelemetrySdk.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ final class OpenTelemetrySdk implements ComponentProvider
* disabled: bool,
* resource: array{
* attributes: array,
* attributes_list: ?string,
* schema_url: ?string,
* },
* attribute_limits: array{
Expand Down Expand Up @@ -113,10 +114,12 @@ public function createPlugin(array $properties, Context $context): SdkBuilder
if ($properties['disabled']) {
return $sdkBuilder;
}

$attributes_list = array_column(array_map(fn ($item) => explode('=', $item), explode(',', $properties['resource']['attributes_list'] ?? '')), 1, 0);
$attributes = array_column($properties['resource']['attributes'], 'value', 'name') + $attributes_list;
//todo merge with attributes_list
$resource = ResourceInfoFactory::defaultResource()
->merge(ResourceInfo::create(
attributes: Attributes::create($properties['resource']['attributes']),
attributes: Attributes::create($attributes),
schemaUrl: $properties['resource']['schema_url'],
));

Expand Down Expand Up @@ -284,8 +287,18 @@ private function getResourceConfig(): ArrayNodeDefinition
->addDefaultsIfNotSet()
->children()
->arrayNode('attributes')
->variablePrototype()->end()
->arrayPrototype()
->children()
->scalarNode('name')->isRequired()->end()
->variableNode('value')->isRequired()->end()
// @todo use type to validate and/or cast attributes
->enumNode('type')->defaultNull()
->values(['string', 'bool', 'int', 'double', 'string_array', 'bool_array', 'int_array', 'double_array'])
->end()
->end()
->end()
->end()
->scalarNode('attributes_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->scalarNode('schema_url')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->end();

Expand Down
16 changes: 13 additions & 3 deletions src/Config/SDK/ComponentProvider/Trace/SpanExporterOtlp.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ final class SpanExporterOtlp implements ComponentProvider
* certificate: ?string,
* client_key: ?string,
* client_certificate: ?string,
* headers: array<string, string>,
* headers: array,
* headers_list: ?string,
* compression: 'gzip'|null,
* timeout: int<0, max>,
* } $properties
Expand All @@ -40,10 +41,13 @@ public function createPlugin(array $properties, Context $context): SpanExporterI
{
$protocol = $properties['protocol'];

$headers_list = array_column(array_map(fn ($item) => explode('=', $item), explode(',', $properties['headers_list'] ?? '')), 1, 0);
$headers = array_column($properties['headers'], 'value', 'name') + $headers_list;

return new SpanExporter(Registry::transportFactory($protocol)->create(
endpoint: $properties['endpoint'] . OtlpUtil::path(Signals::TRACE, $protocol),
contentType: Protocols::contentType($protocol),
headers: $properties['headers'],
headers: $headers,
compression: $properties['compression'],
timeout: $properties['timeout'],
cacert: $properties['certificate'],
Expand All @@ -63,8 +67,14 @@ public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinit
->scalarNode('client_key')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->scalarNode('client_certificate')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->arrayNode('headers')
->scalarPrototype()->end()
->arrayPrototype()
->children()
->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
->scalarNode('value')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->end()
->end()
->end()
->scalarNode('headers_list')->defaultNull()->validate()->always(Validation::ensureString())->end()->end()
->enumNode('compression')->values(['gzip'])->defaultNull()->end()
->integerNode('timeout')->min(0)->defaultValue(10)->end()
->end()
Expand Down
3 changes: 2 additions & 1 deletion tests/Integration/Config/configurations/anchors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ exporters:
client_key: /app/cert.pem
client_certificate: /app/cert.pem
headers:
api-key: !!str 1234
- name: api-key
value: "str 1234"
compression: gzip
timeout: 10000

Expand Down
68 changes: 49 additions & 19 deletions tests/Integration/Config/configurations/kitchen-sink.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ logger_provider:
#
# 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
# Configure headers. Entries have higher priority than entries from .headers_list.
headers:
api-key: "1234"
- name: api-key
value: "1234"
# Configure headers. Entries have lower priority than entries from .headers.
# The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details.
headers_list: "api-key=1234"
# Configure compression.
#
# Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_LOGS_COMPRESSION
Expand Down Expand Up @@ -138,11 +140,13 @@ meter_provider:
#
# 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
# Configure headers. Entries have higher priority than entries from .headers_list.
headers:
api-key: !!str 1234
- name: api-key
value: "1234"
# Configure headers. Entries have lower priority than entries from .headers.
# The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details.
headers_list: "api-key=1234"
# Configure compression.
#
# Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_METRICS_COMPRESSION
Expand Down Expand Up @@ -244,11 +248,13 @@ tracer_provider:
#
# 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
# Configure headers. Entries have higher priority than entries from .headers_list.
headers:
api-key: !!str 1234
- name: api-key
value: "1234"
# Configure headers. Entries have lower priority than entries from .headers.
# The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details.
headers_list: "api-key=1234"
# Configure compression.
#
# Environment variable: OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_TRACES_COMPRESSION
Expand Down Expand Up @@ -340,14 +346,38 @@ tracer_provider:

# Configure resource for all signals.
resource:
# Configure resource attributes.
#
# Environment variable: OTEL_RESOURCE_ATTRIBUTES
# Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list.
# 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.
attributes:
# Configure `service.name` resource attribute
#
# Environment variable: OTEL_SERVICE_NAME
service.name: !!str "unknown_service"
- name: service.name
value: unknown_service
- name: string_key
value: value
type: string
- name: bool_key
value: true
type: bool
- name: int_key
value: 1
type: int
- name: double_key
value: 1.1
type: double
- name: string_array_key
value: [ "value1", "value2" ]
type: string_array
- name: bool_array_key
value: [ true, false ]
type: bool_array
- name: int_array_key
value: [ 1, 2 ]
type: int_array
- name: double_array_key
value: [ 1.1, 2.2 ]
type: double_array
# Configure resource attributes. Entries have lower priority than entries from .resource.attributes.
# 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.
attributes_list: "service.namespace=my-namespace,service.version=1.0.0"
# Configure the resource schema URL.
schema_url: https://opentelemetry.io/schemas/1.27.0

Expand Down