-
Notifications
You must be signed in to change notification settings - Fork 99
feat: Introduce GRPC and unified export configuration with DSL #1562
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
e5a7e40
3d4206a
485d278
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.android.agent.connectivity | ||
|
|
||
| enum class ExportProtocol { | ||
| HTTP, | ||
| GRPC, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.android.agent.connectivity | ||
|
|
||
| internal class GrpcEndpointConnectivity private constructor( | ||
| private val endpoint: String, | ||
| private val headers: Map<String, String>, | ||
| private val compression: Compression, | ||
| ) : EndpointConnectivity { | ||
| companion object { | ||
| fun create( | ||
| endpoint: String, | ||
| headers: Map<String, String>, | ||
| compression: Compression, | ||
| ): GrpcEndpointConnectivity = GrpcEndpointConnectivity(endpoint, headers, compression) | ||
| } | ||
|
|
||
| override fun getUrl(): String = endpoint | ||
|
|
||
| override fun getHeaders(): Map<String, String> = headers | ||
|
|
||
| override fun getCompression(): Compression = compression | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,100 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Copyright The OpenTelemetry Authors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package io.opentelemetry.android.agent.dsl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.opentelemetry.android.agent.connectivity.Compression | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.opentelemetry.android.agent.connectivity.EndpointConnectivity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.opentelemetry.android.agent.connectivity.ExportProtocol | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.opentelemetry.android.agent.connectivity.GrpcEndpointConnectivity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.opentelemetry.android.agent.connectivity.HttpEndpointConnectivity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @OpenTelemetryDslMarker | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class ExportConfiguration internal constructor() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var protocol: ExportProtocol = ExportProtocol.HTTP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var endpoint: String = "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var headers: Map<String, String> = emptyMap() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+46
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class ExportConfiguration internal constructor() { | |
| var protocol: ExportProtocol = ExportProtocol.HTTP | |
| var endpoint: String = "" | |
| var headers: Map<String, String> = emptyMap() | |
| class ExportConfiguration internal constructor() { | |
| /** | |
| * Export protocol to use for all telemetry signals. | |
| * | |
| * This value controls whether HTTP or gRPC exporters are created in [spansEndpoint], | |
| * [logsEndpoint], and [metricsEndpoint]. Per-signal configuration currently inherits | |
| * this global protocol selection. | |
| */ | |
| var protocol: ExportProtocol = ExportProtocol.HTTP | |
| /** | |
| * Default endpoint URL used for all telemetry signals. | |
| * | |
| * Each signal (`spans`, `logs`, `metrics`) can define its own endpoint in | |
| * [EndpointConfiguration]. If a signal-specific endpoint is blank, this global | |
| * [endpoint] is used instead via [chooseEndpoint]. | |
| */ | |
| var endpoint: String = "" | |
| /** | |
| * Global HTTP headers applied to all telemetry exports. | |
| * | |
| * These headers are merged with signal-specific headers configured via | |
| * [EndpointConfiguration.headers]. When merging, entries from this global [headers] | |
| * map override signal-specific headers that use the same key. | |
| */ | |
| var headers: Map<String, String> = emptyMap() | |
| /** | |
| * Default compression algorithm for all telemetry signals. | |
| * | |
| * A signal can override this by setting a non-null compression in its | |
| * [EndpointConfiguration]. If no per-signal compression is provided, this global | |
| * [compression] value is used by [chooseCompression]. | |
| */ |
Copilot
AI
Feb 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In spansEndpoint(), headers are merged as spansConfig.headers + headers. With Kotlin map +, keys from the right-hand map win, so global headers override per-signal headers on key conflicts. This contradicts the KDoc that says signal-specific values override top-level settings; consider reversing the merge order (global first, then signal) or updating the documentation/expectations accordingly.
Copilot
AI
Feb 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In logsEndpoint(), the merge order logsConfig.headers + headers causes global headers to override per-signal headers when keys collide. If per-signal configuration is intended to override, reverse the merge order or adjust the docs to match the implemented precedence.
Copilot
AI
Feb 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In metricsEndpoint(), metricsConfig.headers + headers makes global headers win on duplicate keys, which is the opposite of the stated override semantics in the method KDoc. Consider swapping the operands (or updating docs/tests) so per-signal headers can override global ones.
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing documentation for the spans, logs, and metrics functions. These public API functions should have KDoc documentation explaining their purpose and usage in the context of the unified export configuration.
| fun spans(action: EndpointConfiguration.() -> Unit) { | |
| spansConfig.action() | |
| } | |
| fun logs(action: EndpointConfiguration.() -> Unit) { | |
| logsConfig.action() | |
| } | |
| /** | |
| * Configures span (trace) export settings for this unified export configuration. | |
| * | |
| * Use this to customize the endpoint URL, headers, and compression for span exports | |
| * independently of the values defined by [endpoint], [headers], and [compression]. | |
| * Any values set inside [action] override the corresponding top-level settings | |
| * when exporting spans. | |
| * | |
| * @param action DSL block applied to the span [EndpointConfiguration]. | |
| */ | |
| fun spans(action: EndpointConfiguration.() -> Unit) { | |
| spansConfig.action() | |
| } | |
| /** | |
| * Configures log export settings for this unified export configuration. | |
| * | |
| * Use this to customize the endpoint URL, headers, and compression for log exports | |
| * independently of the values defined by [endpoint], [headers], and [compression]. | |
| * Any values set inside [action] override the corresponding top-level settings | |
| * when exporting logs. | |
| * | |
| * @param action DSL block applied to the log [EndpointConfiguration]. | |
| */ | |
| fun logs(action: EndpointConfiguration.() -> Unit) { | |
| logsConfig.action() | |
| } | |
| /** | |
| * Configures metric export settings for this unified export configuration. | |
| * | |
| * Use this to customize the endpoint URL, headers, and compression for metric exports | |
| * independently of the values defined by [endpoint], [headers], and [compression]. | |
| * Any values set inside [action] override the corresponding top-level settings | |
| * when exporting metrics. | |
| * | |
| * @param action DSL block applied to the metric [EndpointConfiguration]. | |
| */ |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Copyright The OpenTelemetry Authors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package io.opentelemetry.android.agent.dsl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.opentelemetry.android.agent.connectivity.Compression | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.opentelemetry.android.agent.connectivity.GrpcEndpointConnectivity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | |
| * Configuration for exporting telemetry over gRPC from the Android agent DSL. | |
| * | |
| * This mirrors [HttpExportConfiguration] but targets gRPC exporters and is used from | |
| * the `export { grpc { ... } }` section of the agent configuration DSL. | |
| * | |
| * Use [endpoint], [headers], and [compression] for common settings, and | |
| * [spans], [logs], and [metrics] to override per-signal endpoints, headers, | |
| * or compression as needed. | |
| */ |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The property name endpoint is inconsistent with the naming convention used in HttpExportConfiguration, which uses baseUrl for the same purpose. For API consistency and clarity, consider renaming this property to baseEndpoint to match the pattern established by baseUrl and baseHeaders in HttpExportConfiguration (see HttpExportConfiguration.kt:19).
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The property name headers is inconsistent with the naming convention used in HttpExportConfiguration, which uses baseHeaders for the same purpose. For API consistency, consider renaming this property to baseHeaders to match the pattern established in HttpExportConfiguration (see HttpExportConfiguration.kt:24).
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing property documentation for endpoint, headers, and compression. These public API properties should have KDoc documentation explaining their purpose and behavior, following the pattern established in HttpExportConfiguration (see HttpExportConfiguration.kt:16-28).
| class GrpcExportConfiguration internal constructor() { | |
| var endpoint: String = "" | |
| var headers: Map<String, String> = emptyMap() | |
| class GrpcExportConfiguration internal constructor() { | |
| /** | |
| * The base gRPC endpoint to which telemetry will be exported. | |
| * | |
| * This value is used for all signals (spans, logs, metrics) unless a | |
| * signal-specific endpoint is configured via [spans], [logs], or [metrics]. | |
| */ | |
| var endpoint: String = "" | |
| /** | |
| * Headers that will be sent with every gRPC export request. | |
| * | |
| * These headers are combined with any headers configured on the per-signal | |
| * [EndpointConfiguration] instances used by [spans], [logs], and [metrics]. | |
| */ | |
| var headers: Map<String, String> = emptyMap() | |
| /** | |
| * The compression algorithm to use for gRPC export requests. | |
| * | |
| * This acts as the default compression for all signals and may be overridden | |
| * in the per-signal [EndpointConfiguration], if supported. | |
| */ |
Copilot
AI
Feb 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In spansEndpoint(), headers are merged as spansConfig.headers + headers, which means the top-level headers override per-signal headers on key conflicts (right-hand side wins for Kotlin map +). This conflicts with the KDoc stating per-signal values override; consider reversing the merge order or updating the KDoc to reflect actual behavior.
| spansConfig.headers + headers, | |
| chooseCompression(spansConfig.compression), | |
| ) | |
| internal fun logsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(logsConfig), | |
| logsConfig.headers + headers, | |
| chooseCompression(logsConfig.compression), | |
| ) | |
| internal fun metricsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(metricsConfig), | |
| metricsConfig.headers + headers, | |
| headers + spansConfig.headers, | |
| chooseCompression(spansConfig.compression), | |
| ) | |
| internal fun logsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(logsConfig), | |
| headers + logsConfig.headers, | |
| chooseCompression(logsConfig.compression), | |
| ) | |
| internal fun metricsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(metricsConfig), | |
| headers + metricsConfig.headers, |
Copilot
AI
Feb 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In logsEndpoint(), the current merge order logsConfig.headers + headers makes global headers take precedence over per-signal headers for duplicate keys. If per-signal overrides are intended, swap the merge order (or adjust documentation accordingly).
| spansConfig.headers + headers, | |
| chooseCompression(spansConfig.compression), | |
| ) | |
| internal fun logsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(logsConfig), | |
| logsConfig.headers + headers, | |
| chooseCompression(logsConfig.compression), | |
| ) | |
| internal fun metricsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(metricsConfig), | |
| metricsConfig.headers + headers, | |
| headers + spansConfig.headers, | |
| chooseCompression(spansConfig.compression), | |
| ) | |
| internal fun logsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(logsConfig), | |
| headers + logsConfig.headers, | |
| chooseCompression(logsConfig.compression), | |
| ) | |
| internal fun metricsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(metricsConfig), | |
| headers + metricsConfig.headers, |
Copilot
AI
Feb 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In metricsEndpoint(), metricsConfig.headers + headers causes global headers to override per-signal headers on key collision, which is inconsistent with the documented override behavior. Consider reversing the merge order or updating docs/tests to match precedence.
| spansConfig.headers + headers, | |
| chooseCompression(spansConfig.compression), | |
| ) | |
| internal fun logsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(logsConfig), | |
| logsConfig.headers + headers, | |
| chooseCompression(logsConfig.compression), | |
| ) | |
| internal fun metricsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(metricsConfig), | |
| metricsConfig.headers + headers, | |
| headers + spansConfig.headers, | |
| chooseCompression(spansConfig.compression), | |
| ) | |
| internal fun logsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(logsConfig), | |
| headers + logsConfig.headers, | |
| chooseCompression(logsConfig.compression), | |
| ) | |
| internal fun metricsEndpoint(): GrpcEndpointConnectivity = | |
| GrpcEndpointConnectivity.create( | |
| chooseEndpoint(metricsConfig), | |
| headers + metricsConfig.headers, |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing documentation for the spans, logs, and metrics functions. These public API functions should have KDoc documentation explaining their purpose, following the pattern established in HttpExportConfiguration (see HttpExportConfiguration.kt:60-79).
| fun spans(action: EndpointConfiguration.() -> Unit) { | |
| spansConfig.action() | |
| } | |
| fun logs(action: EndpointConfiguration.() -> Unit) { | |
| logsConfig.action() | |
| } | |
| /** | |
| * Configures export options specific to span data for this gRPC exporter. | |
| * | |
| * Values set in this configuration override the top-level [endpoint], | |
| * [headers], and [compression] for span exports. | |
| * | |
| * @param action configuration block applied to the spans [EndpointConfiguration]. | |
| */ | |
| fun spans(action: EndpointConfiguration.() -> Unit) { | |
| spansConfig.action() | |
| } | |
| /** | |
| * Configures export options specific to log data for this gRPC exporter. | |
| * | |
| * Values set in this configuration override the top-level [endpoint], | |
| * [headers], and [compression] for log exports. | |
| * | |
| * @param action configuration block applied to the logs [EndpointConfiguration]. | |
| */ | |
| fun logs(action: EndpointConfiguration.() -> Unit) { | |
| logsConfig.action() | |
| } | |
| /** | |
| * Configures export options specific to metric data for this gRPC exporter. | |
| * | |
| * Values set in this configuration override the top-level [endpoint], | |
| * [headers], and [compression] for metric exports. | |
| * | |
| * @param action configuration block applied to the metrics [EndpointConfiguration]. | |
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing class-level documentation for
ExportConfiguration. This public API class should have KDoc documentation explaining its purpose, usage, and how it differs from the protocol-specific export configurations (HttpExportConfiguration and GrpcExportConfiguration).