Skip to content

Commit 6e6f910

Browse files
authored
Define sdk extension component support in file configuration (open-telemetry#3802)
Part of incorporating [OTEP open-telemetry#225](open-telemetry/oteps#225) into the specification. Followup to open-telemetry#3744. This defines how file configuration works with custom SDK extension components (Samplers, Exporters, etc). It defines the concept of a Component Provider: - Component providers are registered with the type of extension component they provide and a name. Component providers are registered automatically or manually based on what is idiomatic in the language. - Component providers have a Create Plugin method, which passes configuration properties as a parameter and returns the configured component - When Create is called to interpret a file configuration model, and it comes across a reference to a extension component which is not built-in, it invokes Create Plugin on the corresponding component provider. If no corresponding component provider exists, or if Create Plugin returns an Error, Create returns an error. Prototype implementation in java here: open-telemetry/opentelemetry-java-examples#227 cc @open-telemetry/configuration-maintainers
1 parent d0ccbc1 commit 6e6f910

File tree

3 files changed

+155
-26
lines changed

3 files changed

+155
-26
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ release.
2828

2929
- Add file configuration section to spec compliance matrix.
3030
([#3804](https://github.com/open-telemetry/opentelemetry-specification/pull/3804))
31+
- Define mechanism for SDK extension components.
32+
([#3802](https://github.com/open-telemetry/opentelemetry-specification/pull/3802))
3133

3234
### Common
3335

spec-compliance-matrix.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,18 +313,21 @@ Note: Support for environment variables is optional.
313313
See [File Configuration](./specification/configuration/file-configuration.md)
314314
for details.
315315

316-
| Feature | Go | Java | JS | Python | Ruby | Erlang | PHP | Rust | C++ | .NET | Swift |
317-
|------------------------------------------------------------------|----|------|----|--------|------|--------|-----|------|-----|------|-------|
318-
| `Parse` a configuration file | | | | | | | | | | | |
319-
| The `Parse` operation accepts the configuration YAML file format | | | | | | | | | | | |
320-
| The `Parse` operation performs environment variable substitution | | | | | | | | | | | |
321-
| The `Parse` operation returns configuration model | | | | | | | | | | | |
322-
| `Create` SDK components | | | | | | | | | | | |
323-
| The `Create` operation accepts configuration model | | | | | | | | | | | |
324-
| The `Create` operation returns `TracerProvider` | | | | | | | | | | | |
325-
| The `Create` operation returns `MeterProvider` | | | | | | | | | | | |
326-
| The `Create` operation returns `LoggerProvider` | | | | | | | | | | | |
327-
| The `Create` operation returns `Propagators` | | | | | | | | | | | |
316+
| Feature | Go | Java | JS | Python | Ruby | Erlang | PHP | Rust | C++ | .NET | Swift |
317+
|-------------------------------------------------------------------------------------------------------------------------|----|------|----|--------|------|--------|-----|------|-----|------|-------|
318+
| `Parse` a configuration file | | | | | | | | | | | |
319+
| The `Parse` operation accepts the configuration YAML file format | | | | | | | | | | | |
320+
| The `Parse` operation performs environment variable substitution | | | | | | | | | | | |
321+
| The `Parse` operation returns configuration model | | | | | | | | | | | |
322+
| The `Parse` operation resolves extension component configuration to `properties` | | | | | | | | | | | |
323+
| `Create` SDK components | | | | | | | | | | | |
324+
| The `Create` operation accepts configuration model | | | | | | | | | | | |
325+
| The `Create` operation returns `TracerProvider` | | | | | | | | | | | |
326+
| The `Create` operation returns `MeterProvider` | | | | | | | | | | | |
327+
| The `Create` operation returns `LoggerProvider` | | | | | | | | | | | |
328+
| The `Create` operation returns `Propagators` | | | | | | | | | | | |
329+
| The `Create` operation calls `CreatePlugin` of corresponding `ComponentProvider` when encountering extension components | | | | | | | | | | | |
330+
| Register a `ComponentProvider` | | | | | | | | | | | |
328331

329332
## Exporters
330333

specification/configuration/file-configuration.md

Lines changed: 138 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@ linkTitle: File
1616
* [Environment variable substitution](#environment-variable-substitution)
1717
- [SDK Configuration](#sdk-configuration)
1818
* [In-Memory Configuration Model](#in-memory-configuration-model)
19+
* [SDK Extension Components](#sdk-extension-components)
20+
+ [Component Provider](#component-provider)
21+
+ [Create Plugin](#create-plugin)
1922
* [Operations](#operations)
2023
+ [Parse](#parse)
2124
+ [Create](#create)
25+
+ [Register Component Provider](#register-component-provider)
2226
- [References](#references)
2327

2428
<!-- tocstop -->
@@ -142,6 +146,93 @@ to provide this in-memory representation in a manner that is idiomatic for their
142146
language. If an SDK needs to expose a class or interface, the
143147
name `Configuration` is RECOMMENDED.
144148

149+
### SDK Extension Components
150+
151+
The SDK supports a variety of
152+
extension [plugin interfaces](../glossary.md#sdk-plugins), allowing users and
153+
libraries to customize behaviors including the sampling, processing, and
154+
exporting of data. In general, the [configuration model](#configuration-model)
155+
defines specific types for built-in implementations of these plugin interfaces.
156+
For example,
157+
the [BatchSpanProcessor](https://github.com/open-telemetry/opentelemetry-configuration/blob/f38ac7c3a499ae5f81924ef9c455c27a56130562/schema/tracer_provider.json#L22)
158+
type refers to the
159+
built-in [Batching span processor](../trace/sdk.md#batching-processor). The
160+
schema SHOULD also support the ability to specify custom implementations of
161+
plugin interfaces defined by libraries or users.
162+
163+
For example, a custom [span exporter](../trace/sdk.md#span-exporter) might be configured as follows:
164+
165+
```yaml
166+
tracer_provider:
167+
processors:
168+
- batch:
169+
exporter:
170+
my-exporter:
171+
config-parameter: value
172+
```
173+
174+
Here we specify that the tracer provider has a batch span processor
175+
paired with a custom span exporter named `my-exporter`, which is configured
176+
with `config-parameter: value`. For this configuration to succeed,
177+
a [component provider](#component-provider) must
178+
be [registered](#register-component-provider) with `type: SpanExporter`,
179+
and `name: my-exporter`. When [parse](#parse) is called, the implementation will
180+
encounter `my-exporter` and translate the corresponding configuration to an
181+
equivalent generic `properties` representation (
182+
i.e. `properties: {config-parameter: value}`). When [create](#create) is called,
183+
the implementation will encounter `my-exporter` and
184+
invoke [create plugin](#create-plugin) on the registered component provider
185+
with the configuration `properties` determined during `parse`.
186+
187+
Given the inherent differences across languages, the details of extension
188+
component mechanisms are likely to vary to a greater degree than is the case
189+
with other APIs defined by OpenTelemetry. This is to be expected and is
190+
acceptable so long as the implementation results in the defined behaviors.
191+
192+
#### Component Provider
193+
194+
A component provider is responsible for interpreting configuration and returning
195+
an implementation of a particular type of SDK extension plugin interface.
196+
197+
Component providers are registered with an SDK implementation of configuration
198+
via [register](#register-component-provider). This MAY be done automatically or
199+
require manual intervention by the user based on what is possible and idiomatic
200+
in the language ecosystem. For example in Java, component providers might be
201+
registered automatically using
202+
the [service provider interface (SPI)](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html)
203+
mechanism.
204+
205+
See [create](#create), which details component provider usage in file
206+
configuration interpretation.
207+
208+
#### Create Plugin
209+
210+
Interpret configuration to create a instance of a SDK extension plugin
211+
interface.
212+
213+
**Parameters:**
214+
215+
* `properties` - The configuration properties. Properties MUST fully represent
216+
the configuration as specified in
217+
the [configuration file](#configuration-file), including the ability to access
218+
scalars, mappings, and sequences (of scalars and other structures). It MUST be
219+
possible to determine if a particular property is present. It SHOULD be
220+
possible to access properties in a type safe manner, based on what is idiomatic
221+
in the language.
222+
223+
**Returns:** A configured SDK extension plugin interface implementation.
224+
225+
The plugin interface MAY have properties which are optional or required, and
226+
have specific requirements around type or format. The set of properties a
227+
component provider accepts, along with their requirement level and expected
228+
type, comprise a configuration schema. A component provider SHOULD document its
229+
configuration schema.
230+
231+
When Create Plugin is invoked, the component provider interprets `properties`
232+
and attempts to extract data according to its configuration schema. If this
233+
fails (e.g. a required property is not present, a type is mismatches, etc.),
234+
Create Plugin SHOULD return an error.
235+
145236
### Operations
146237

147238
SDK implementations of configuration MUST provide the following operations.
@@ -157,10 +248,6 @@ with OpAmp
157248

158249
Parse and validate a [configuration file](#configuration-file).
159250

160-
Parse MUST perform [environment variable substitution](#environment-variable-substitution).
161-
162-
Parse MUST interpret null as equivalent to unset.
163-
164251
**Parameters:**
165252

166253
* `file`: The [configuration file](#configuration-file) to parse. This MAY be a
@@ -173,7 +260,17 @@ Parse MUST interpret null as equivalent to unset.
173260

174261
**Returns:** [configuration model](#in-memory-configuration-model)
175262

176-
This SHOULD return an error if:
263+
Parse MUST perform [environment variable substitution](#environment-variable-substitution).
264+
265+
Parse MUST interpret null as equivalent to unset.
266+
267+
When encountering a reference to
268+
a [SDK extension component](#sdk-extension-components) which is not built in to
269+
the SDK, Parse MUST resolve corresponding configuration to a
270+
generic `properties` representation as described
271+
in [Create Plugin](#create-plugin).
272+
273+
Parse SHOULD return an error if:
177274

178275
* The `file` doesn't exist or is invalid
179276
* The parsed `file` content does not conform to
@@ -183,15 +280,6 @@ This SHOULD return an error if:
183280

184281
Interpret [configuration model](#in-memory-configuration-model) and return SDK components.
185282

186-
If a field is null or unset and a default value is defined, Create MUST ensure
187-
the SDK component is configured with the default value. If a field is null or
188-
unset and no default value is defined, Create SHOULD return an error. For
189-
example, if configuring
190-
the [span batching processor](../trace/sdk.md#batching-processor) and
191-
the `scheduleDelayMillis` field is null or unset, the component is configured
192-
with the default value of `5000`. However, if the `exporter` field is null or
193-
unset, Create fails fast since there is no default value for `exporter`.
194-
195283
**Parameters:**
196284

197285
* `configuration` - The configuration model.
@@ -206,12 +294,48 @@ unset, Create fails fast since there is no default value for `exporter`.
206294
The multiple responses MAY be returned using a tuple, or some other data
207295
structure encapsulating the components.
208296

297+
If a field is null or unset and a default value is defined, Create MUST ensure
298+
the SDK component is configured with the default value. If a field is null or
299+
unset and no default value is defined, Create SHOULD return an error. For
300+
example, if configuring
301+
the [span batching processor](../trace/sdk.md#batching-processor) and
302+
the `scheduleDelayMillis` field is null or unset, the component is configured
303+
with the default value of `5000`. However, if the `exporter` field is null or
304+
unset, Create fails fast since there is no default value for `exporter`.
305+
306+
When encountering a reference to
307+
a [SDK extension component](#sdk-extension-components) which is not built in to
308+
the SDK, Create MUST resolve the component using [Create Plugin](#create-plugin)
309+
of the [component provider](#component-provider) of the corresponding `type`
310+
and `name` used to [register](#register-component-provider), including the
311+
configuration `properties` as an argument. If no component provider is
312+
registered with the `type` and `name`, Create SHOULD return an error.
313+
If [Create Plugin](#create-plugin) returns an error, Create SHOULD propagate the
314+
error.
315+
209316
This SHOULD return an error if it encounters an error in `configuration` (i.e.
210317
fail fast) in accordance with
211318
initialization [error handling principles](../error-handling.md#basic-error-handling-principles).
212319

213320
TODO: define behavior if some portion of configuration model is not supported
214321

322+
#### Register Component Provider
323+
324+
The file configuration implementation MUST provide a mechanism to
325+
register [component providers](#component-provider).
326+
327+
**Parameters:**
328+
329+
* `component_provider` - The [component provider](#component-provider).
330+
* `type` - The type of plugin interface it provides (e.g. SpanExporter, Sampler,
331+
etc).
332+
* `name` - The name used to identify the type of component. This is used
333+
in [configuration files](#configuration-file) to specify that the
334+
corresponding `component_provider` is to provide the component.
335+
336+
The `type` and `name` comprise a unique key. Register MUST return an error if it
337+
is called multiple times with the same `type` and `name` combination.
338+
215339
## References
216340

217341
* Configuration

0 commit comments

Comments
 (0)