feat(otlp-exporter-base): add env-free createOtlp*Exporter factory functions - #6990
feat(otlp-exporter-base): add env-free createOtlp*Exporter factory functions#6990pacocartones wants to merge 2 commits into
Conversation
…nctions
Add createOtlp{Http,Proto,Grpc}{Span,Metric,Log}Exporter() factories to
the nine OTLP exporter packages. They resolve caller options over the
OTLP specification defaults without reading process.env, so declarative
config in sdk-node can construct exporters with undefined options
without the environment leaking in. The exporter classes keep reading
the env unchanged (no deprecation yet).
Closes open-telemetry#6959
|
Welcome, contributor! Thank you for your contribution to opentelemetry-js. Important reminders:
|
Pull request dashboard statusWaiting on reviewers · refreshed 2026-09-02 16:39 UTC Review the latest changes. Also blocked by: Merge conflicts. Status above doesn't look right?
|
|
Couple of problems after taking an initial look:
|
Signed-off-by: pacocartones <manusanchezhl@gmail.com>
|
@JacksonWeber Thanks for the review. I addressed both points in
Fresh verification on the pushed head passes the four suites ( AI-assisted: this follow-up was drafted with AI assistance. I reviewed the complete diff and fresh verification output, and I own the change. |
Which problem is this PR solving?
Closes #6959.
The Declarative Config file handling in
sdk-nodeneeds to create OTLP exporters while passingundefinedfor options and without the exporter packages readingprocess.env(declarative config rule: the usualOTEL_SDK env vars must not be used). Today every OTLP exporter class merges configuration from the environment as a fallback between the user-provided options and the specification defaults, so there is no way to construct an exporter that ignores the environment.Short description of the changes
Following the approach sketched in the issue, this PR adds
create...Exporter()factory functions that never touch the environment, and leaves the exporter classes fully compatible (they still read the env; they are not deprecated yet — that can be a follow-up):@opentelemetry/otlp-exporter-base/node-http: new exportedconvertLegacyHttpOptionsWithoutEnv(config, signalResourcePath, requiredHeaders)— same legacy-options conversion asconvertLegacyHttpOptions, but with an empty environment fallback, so unset options land on the OTLP specification defaults.@opentelemetry/otlp-grpc-exporter-base: same,convertLegacyOtlpGrpcOptionsWithoutEnv(config).@opentelemetry/exporter-trace-otlp-httpcreateOtlpHttpSpanExporter(config?)@opentelemetry/exporter-trace-otlp-protocreateOtlpProtoSpanExporter(config?)@opentelemetry/exporter-trace-otlp-grpccreateOtlpGrpcSpanExporter(config?)@opentelemetry/exporter-metrics-otlp-httpcreateOtlpHttpMetricExporter(config?)@opentelemetry/exporter-metrics-otlp-protocreateOtlpProtoMetricExporter(config?)@opentelemetry/exporter-metrics-otlp-grpccreateOtlpGrpcMetricExporter(config?)@opentelemetry/exporter-logs-otlp-httpcreateOtlpHttpLogExporter(config?)@opentelemetry/exporter-logs-otlp-protocreateOtlpProtoLogExporter(config?)@opentelemetry/exporter-logs-otlp-grpccreateOtlpGrpcLogExporter(config?)Each factory accepts the same (fully optional) options bag as the matching class and returns the SDK interface (
SpanExporter/PushMetricExporter/LogRecordExporter). For metric exporters, an unsettemporalityPreferenceresolves to the specification default (cumulative) instead of readingOTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE.experimental/CHANGELOG.md.Notes on the issue's "files to update" list:
OTLPMetricExporterBase.tsended up not needing changes: the metric factories pass an explicittemporalityPreference(caller value or the spec default), so the env-reading branch in the base class is never reached from the factory path. Happy to restructure if you'd rather have an explicit env-free mode in the base class.*-env-configuration.tsmodules are also unchanged on purpose: they keep serving the class constructors; the factory path simply doesn't call them.sdk-nodeis not switched over in this PR — the factories are the enabler; wiringcreate-from-config.tsto them is a clean follow-up.Type of change
How Has This Been Tested?
New tests per package, co-located with the existing ones. The key assertion: with
OTEL_EXPORTER_OTLP_*variables set, a factory-created exporter resolves the specification defaults (asserted via the exporter's ownserver.address/server.portself-observability metrics for the HTTP packages, and via the resolved config object in the base packages), while a control in the same file proves the class-based exporter still picks up the same env vars. Metric packages assertselectAggregationTemporality(COUNTER)isCUMULATIVEwithOTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=deltaset (control: the class returnsDELTA).Red first (tests added on top of
main, before the implementation):npm run compile→error TS2724: '"../../../src/configuration/convert-legacy-node-http-options"' has no exported member named 'convertLegacyHttpOptionsWithoutEnv'. Did you mean 'convertLegacyHttpOptions'?exporter-trace-otlp-http:1 passing, 2 failing — TypeError: (0 , node_1.createOtlpHttpSpanExporter) is not a function(same shape for the metric and gRPC packages).Green (after the full change), all run locally on Windows with Node v24.14.1:
Not verified locally (CI covers these): the Node 18–26 test matrix and the Windows job,
test:webworker,bundler-tests, e2e/w3c integration tests, andnpm run docs/docs:test(typedoc + linkinator, part of the CI lint job). None of the touched packages require external services; the gRPC tests start an in-process server.Checklist:
eslint+prettierclean,lint:fixapplied)experimental/CHANGELOG.md)Review follow-up (2026-08-11)
The two points from the initial maintainer review are addressed in
20b64b5:@opentelemetry/sdk-metrics2.10.0is now a runtime dependency of the gRPC and proto metric exporter packages, with the workspace lockfile updated consistently.node:http.request, restore the built-in binding between tests, and awaitLoggerProvider.shutdown()/TracerProvider.shutdown()before assertions, so they do not leave real requests or providers running.Fresh focused verification on the published commit: the four Node suites pass
12/12; the gRPC/HTTP/proto dependency classification probe passes3/3; ESLint and Prettier pass on all seven follow-up files.AI-assisted: this change was drafted with AI assistance. I reviewed the complete diff, ran the red→green and the gates shown above on my own machine, and I own the change — happy to walk through every line and adjust naming/scope as you prefer.