Define dedicated file configuration SPI ComponentProvider#6457
Define dedicated file configuration SPI ComponentProvider#6457jack-berg merged 10 commits intoopen-telemetry:mainfrom
Conversation
| * <p>This class is internal and is hence not for public use. Its APIs are unstable and can change | ||
| * at any time. | ||
| */ | ||
| public class PrometheusComponentProvider implements ComponentProvider<MetricReader> { |
There was a problem hiding this comment.
A demonstration ComponentProvider. Notice how config properties are accessed without dot notation since the YAML node is presented directly as the StructuredConfigProperties.
| * @throws ConfigurationException if the property is not a sequence of mappings | ||
| */ | ||
| @Nullable | ||
| List<StructuredConfigProperties> getStructuredList(String name); |
There was a problem hiding this comment.
getStructured and getStructuredList are the key bits which allow reading complex data.
| * @see #getConfig() | ||
| */ | ||
| @Nullable | ||
| abstract StructuredConfigProperties getStructuredConfig(); |
There was a problem hiding this comment.
This new method allows callers to determine if autoconfiguration was driven by file configuration or by env vars / system properties. Either this or getConfig will return null. The other will be non-null.
If file configuration is used, getStructuredConfig represents the full YAML config file.
There was a problem hiding this comment.
This is kinda the only unfortunate downside of this approach that I can find thus far. It's a small drag that users of the autoconfigured sdk now have to be aware or otherwise check which config was used to get the data they need.
It feels like there is room to flatten the structured config into ConfigProperties and also to objectify the ConfigProperties into a structured thing...but we can have that conversation another time.
There was a problem hiding this comment.
It's a small drag that users of the autoconfigured sdk now have to be aware or otherwise check which config was used to get the data they need.
I would characterize it slightly differently: Providers of custom components like exporters and samplers need to be aware that somebody can use file based config or flat system property / env var based config, and provide different SPI implementations for each. This is frustrating, but seems to be the inevitable result of otel getting as far as it did without a proper configuration story. As I mentioned in the PR description, I started with the opposite approach and tried to have a single unified ConfigProperties for both configuration routes. I've concluded while this is simpler from an API standpoint, its more confusing and brittle for users, since even though we can do some gymnastics to make ConfigProperties work for both cases, the data presented to SPI implementers will be different (i.e. the property names and structure and semantics will be different for flat env vars than in structured config). So there appears to be no getting around confronting the user with this difference. Might as well make it as explicit and obvious as possible.
| assertThat(otherProps.getString("str_key")).isEqualTo("str_value"); | ||
| StructuredConfigProperties otherMapKeyProps = otherProps.getStructured("map_key"); | ||
| assertThat(otherMapKeyProps).isNotNull(); | ||
| assertThat(otherMapKeyProps.getString("str_key1")).isEqualTo("str_value1"); |
There was a problem hiding this comment.
This test demonstrates how a consumers like the otel java agent could access complex config data which is not part of the core file configuration schema. The other key and the structure it encloses is not part of the core schema yet its contents are accessible.
This will be important for configuring java agent specific options, like content for the JMX integration.
| MetricReader metricReader = | ||
| FileConfigUtil.loadComponent( | ||
| spiHelper, MetricReader.class, "prometheus", prometheusModel); | ||
| return FileConfigUtil.addAndReturn(closeables, metricReader); |
There was a problem hiding this comment.
Here's what it looks like to load a component in the file configuration implementation. We state that we want ComponentProvider which provides instances of MetricReader.class named prometheus, and we pass the prometheusModel to it (which is translated to StructuredConfigProperties).
Nice and easy.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6457 +/- ##
============================================
- Coverage 90.86% 90.72% -0.14%
- Complexity 6155 6214 +59
============================================
Files 675 678 +3
Lines 18461 18621 +160
Branches 1813 1828 +15
============================================
+ Hits 16774 16894 +120
- Misses 1151 1180 +29
- Partials 536 547 +11 ☔ View full report in Codecov by Sentry. |
breedx-splk
left a comment
There was a problem hiding this comment.
@jack-berg this is a fantastic step forward on the config front!
...ure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ComponentProvider.java
Show resolved
Hide resolved
...rc/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/StructuredConfigProperties.java
Outdated
Show resolved
Hide resolved
...java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java
Outdated
Show resolved
Hide resolved
...java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java
Show resolved
Hide resolved
| * @see #getConfig() | ||
| */ | ||
| @Nullable | ||
| abstract StructuredConfigProperties getStructuredConfig(); |
There was a problem hiding this comment.
This is kinda the only unfortunate downside of this approach that I can find thus far. It's a small drag that users of the autoconfigured sdk now have to be aware or otherwise check which config was used to get the data they need.
It feels like there is room to flatten the structured config into ConfigProperties and also to objectify the ConfigProperties into a structured thing...but we can have that conversation another time.
...ubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfigUtil.java
Show resolved
Hide resolved
|
@breedx-splk I would greatly appreciate another look when you have a chance 🙂 |
|
@open-telemetry/java-approvers will merge tomorrow if there are no additional comments. |
A while ago I opened PR #5912, which introduced ExtendedConfigProperties. The idea was to have an extended version of the ConfigProperties interface which included new accessors for reading structured data in addition to the simple types already exposed by ConfigProperties. Then, when file configuration needed to load a custom SDK extension component like SpanExporter, it would construct a ExtendedConfigProperties from the YAML contents and pass it to the SPI (i.e. ConfigurableSpanExporterProvider.
This approach is problematic because it requires SPI implementations to understand whether they're working on a file configuration context or not based on whether the ConfigProperties is actually an instance of ExtendedConfigProperties. The shape of data and the access patterns is quite different for file configuration vs env var / system property based configuration, so this whole thing is error prone and rather confusing.
In this PR, I propose a different direction which embraces the spec decision that file configuration should be thought of as the v2 of configuration, rather than something that is an extension of the existing env var / system property mechanism. Here's how I'm thinking about it:
otel.experimental.config.fileyou're opting into this separate path. If you don't, all the existing SPIs and config mechanism works.ComponentProvider#create(StructuredConfigProperties).For demonstration purposes and to make this PR as simple as possible, I've implemented a single ComponentProvider in the
opentelemetry-exporters-prometheusartifact. If this PR is merged, I will followup by implementing ComponentProvider for the other built in components.