Skip to content

feat(config): Add exporter customizers for declarative config (#6576)#8081

Open
MikeGoldsmith wants to merge 3 commits intoopen-telemetry:mainfrom
honeycombio:mike/exporter-customizers-clean
Open

feat(config): Add exporter customizers for declarative config (#6576)#8081
MikeGoldsmith wants to merge 3 commits intoopen-telemetry:mainfrom
honeycombio:mike/exporter-customizers-clean

Conversation

@MikeGoldsmith
Copy link
Member

Summary

Adds exporter customizers to DeclarativeConfigurationCustomizer for programmatic customization of SpanExporter, MetricExporter, and LogRecordExporter instances created from declarative configuration.

Fixes #6576

Changes

  • Added addSpanExporterCustomizer(), addMetricExporterCustomizer(), addLogRecordExporterCustomizer() to DeclarativeConfigurationCustomizer
  • Customizers compose in SPI registration order via mergeBiFunctionCustomizer() in DeclarativeConfigurationBuilder
  • Factories apply customizers after component creation with fail-fast null checks
  • Comprehensive tests: builder composition, factory application, integration end-to-end

- Add SpanExporter/MetricExporter/LogRecordExporter customizers to DeclarativeConfigurationCustomizer
- Customizers compose in SPI registration order
- Apply in factories after component creation, before return
- Null returns throw DeclarativeConfigException
- Tests: factory unit tests, builder composition tests, integration tests
@MikeGoldsmith MikeGoldsmith requested a review from a team as a code owner February 13, 2026 14:49
@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.22%. Comparing base (7ce6c5c) to head (52c4f98).

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8081      +/-   ##
============================================
+ Coverage     90.20%   90.22%   +0.02%     
- Complexity     7595     7618      +23     
============================================
  Files           841      841              
  Lines         22919    22973      +54     
  Branches       2291     2294       +3     
============================================
+ Hits          20674    20728      +54     
  Misses         1529     1529              
  Partials        716      716              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

I'm supportive of these customizers because even though we want to encourage modeling all properties that matter in the opentelemetry-configuration schema, it will never be possible to cover all cases (e.g. think the executor service used to eval async requests), and we'll want an escape hatch to leverage when a a property hasn't yet been modeled in declarative config but will be.

The exporters are a good place to start because there are known gaps in the what can be expressed in declarative config (i.e. authenticators).

Let's hold off modeling additional customizers (e.g. span processors, propagators, etc) until there are concrete requests by end users or distributions which require them.

}

// Pass exporter customizers to context
context.setSpanExporterCustomizer(builder.getSpanExporterCustomizer());
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we can just pass the builder to DeclarativeConfigContext to avoid the noise of extra getters / setter for each customizer?

*
* @param customizer function receiving (exporterName, exporter) and returning customized exporter
*/
void addSpanExporterCustomizer(BiFunction<String, SpanExporter, SpanExporter> customizer);
Copy link
Member

Choose a reason for hiding this comment

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

This contract is different than the env var / system prop equivalent:

AutoConfigurationCustomizer addSpanExporterCustomizer(BiFunction<SpanExporter, ConfigProperties, SpanExporter>)

Comments:

  • There are mechanisms for a customizer to identify the exporter and decide whether to participate: the exporterName and the class type of the exporter. We don't technically need both. What's the advantage (if any) of the exporter name in addition to the type?
  • The customizer doesn't have access to the DeclarativeConfigProperties for the exporter. We need to add this.
  • One annoying part about this and the existing AutoConfigurationCustomizer pattern is that the customizer implementation has to filter all span exporter and only operate on the instances they care about. I wonder if we could improve on this by decomposing it into a predicate and a customizer: addSpanExporterCustomizer(Predicate<SpanExporter>, BiFunction<SpanExporter, DeclarativeConfigProperties, SpanExporter>, or even something like: <T extends SpanExporter> addSpanExporterCustomizer(Class<T>, BiFunction<T, DeclarativeConfigProperties, T>) to remove the need to do this filtering and type casting entirely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

How should AutoConfigurationCustomizer work when file configuration is used

2 participants