Skip to content

feat(otlp-exporter-base): add env-free createOtlp*Exporter factory functions - #6990

Open
pacocartones wants to merge 2 commits into
open-telemetry:mainfrom
pacocartones:feat/6959-otlp-exporter-factories
Open

feat(otlp-exporter-base): add env-free createOtlp*Exporter factory functions#6990
pacocartones wants to merge 2 commits into
open-telemetry:mainfrom
pacocartones:feat/6959-otlp-exporter-factories

Conversation

@pacocartones

@pacocartones pacocartones commented Aug 8, 2026

Copy link
Copy Markdown

Which problem is this PR solving?

Closes #6959.

The Declarative Config file handling in sdk-node needs to create OTLP exporters while passing undefined for options and without the exporter packages reading process.env (declarative config rule: the usual OTEL_ 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 exported convertLegacyHttpOptionsWithoutEnv(config, signalResourcePath, requiredHeaders) — same legacy-options conversion as convertLegacyHttpOptions, but with an empty environment fallback, so unset options land on the OTLP specification defaults.
  • @opentelemetry/otlp-grpc-exporter-base: same, convertLegacyOtlpGrpcOptionsWithoutEnv(config).
  • New factory functions, one per OTLP exporter package (also on the browser entry points of the isomorphic packages, for API parity — the browser path never read env anyway):
Package Factory
@opentelemetry/exporter-trace-otlp-http createOtlpHttpSpanExporter(config?)
@opentelemetry/exporter-trace-otlp-proto createOtlpProtoSpanExporter(config?)
@opentelemetry/exporter-trace-otlp-grpc createOtlpGrpcSpanExporter(config?)
@opentelemetry/exporter-metrics-otlp-http createOtlpHttpMetricExporter(config?)
@opentelemetry/exporter-metrics-otlp-proto createOtlpProtoMetricExporter(config?)
@opentelemetry/exporter-metrics-otlp-grpc createOtlpGrpcMetricExporter(config?)
@opentelemetry/exporter-logs-otlp-http createOtlpHttpLogExporter(config?)
@opentelemetry/exporter-logs-otlp-proto createOtlpProtoLogExporter(config?)
@opentelemetry/exporter-logs-otlp-grpc createOtlpGrpcLogExporter(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 unset temporalityPreference resolves to the specification default (cumulative) instead of reading OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE.

  • READMEs of the nine packages document the new factory next to the env-var configuration section.
  • CHANGELOG entry in experimental/CHANGELOG.md.

Notes on the issue's "files to update" list:

  • OTLPMetricExporterBase.ts ended up not needing changes: the metric factories pass an explicit temporalityPreference (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.
  • The *-env-configuration.ts modules are also unchanged on purpose: they keep serving the class constructors; the factory path simply doesn't call them.
  • sdk-node is not switched over in this PR — the factories are the enabler; wiring create-from-config.ts to them is a clean follow-up.

Type of change

  • New feature (non-breaking change which adds functionality)

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 own server.address/server.port self-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 assert selectAggregationTemporality(COUNTER) is CUMULATIVE with OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta set (control: the class returns DELTA).

Red first (tests added on top of main, before the implementation):

  • npm run compileerror TS2724: '"../../../src/configuration/convert-legacy-node-http-options"' has no exported member named 'convertLegacyHttpOptionsWithoutEnv'. Did you mean 'convertLegacyHttpOptions'?
  • After implementing only the base packages, the package-level tests failed as expected, e.g. 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:

# cd ~/repos/otel-js && npm run compile        (tsc -b, also type-checks the tests)
FINAL_COMPILE_EXIT=0

# per package: TS_NODE_TRANSPILE_ONLY=1 npx mocha --require ts-node/register 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'
# (npm test also works; on Windows I invoked mocha directly because npm's cmd.exe
#  passes the quoted glob to mocha literally)
otlp-exporter-base                     156 passing
otlp-grpc-exporter-base                 79 passing (1 pre-existing pending)
exporter-trace-otlp-http                 3 passing
exporter-trace-otlp-proto                3 passing
exporter-trace-otlp-grpc                 2 passing   (spins up a real in-process gRPC server)
exporter-metrics-otlp-http               8 passing
exporter-metrics-otlp-proto              3 passing
exporter-metrics-otlp-grpc               4 passing   (idem)
exporter-logs-otlp-http                  3 passing
exporter-logs-otlp-proto                 3 passing
exporter-logs-otlp-grpc                  2 passing   (idem)

# per isomorphic package: npx karma start --single-run  (Chrome Headless 151)
exporter-trace-otlp-http       2/2 SUCCESS
exporter-trace-otlp-proto      2/2 SUCCESS
exporter-metrics-otlp-http     7/7 SUCCESS
exporter-metrics-otlp-proto    2/2 SUCCESS
exporter-logs-otlp-http        2/2 SUCCESS
exporter-logs-otlp-proto       2/2 SUCCESS

# lint
npm run lint            # per touched package: 11/11 clean (one pre-existing no-shadow
                        # warning in an untouched file of otlp-exporter-base)
npm run lint:markdown   # clean

Not verified locally (CI covers these): the Node 18–26 test matrix and the Windows job, test:webworker, bundler-tests, e2e/w3c integration tests, and npm 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:

  • Followed the style guidelines of this project (eslint + prettier clean, lint:fix applied)
  • Unit tests have been added (and fail without the change — see above)
  • Documentation has been updated (READMEs of all nine packages + experimental/CHANGELOG.md)

Review follow-up (2026-08-11)

The two points from the initial maintainer review are addressed in 20b64b5:

  • @opentelemetry/sdk-metrics 2.10.0 is now a runtime dependency of the gRPC and proto metric exporter packages, with the workspace lockfile updated consistently.
  • The four new Node HTTP/proto log and trace suites stub node:http.request, restore the built-in binding between tests, and await LoggerProvider.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 passes 3/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.

…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
@pacocartones
pacocartones requested review from a team as code owners August 8, 2026 23:10
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

Welcome, contributor! Thank you for your contribution to opentelemetry-js.

Important reminders:

@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Aug 8, 2026

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-09-02 16:39 UTC

Review the latest changes.

Also blocked by: Merge conflicts.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

@JacksonWeber

Copy link
Copy Markdown
Contributor

Couple of problems after taking an initial look:

  • The new metric factory return types expose @opentelemetry/sdk-metrics, but the gRPC/proto packages list it only as a dev dependency. Could this be moved to dependencies?

  • Several new Node tests make real HTTP requests without shutting down the tracer/logger provider. Please stub the requests and clean up the providers to avoid leaked sockets or flaky tests.

Signed-off-by: pacocartones <manusanchezhl@gmail.com>
@pacocartones

Copy link
Copy Markdown
Author

@JacksonWeber Thanks for the review. I addressed both points in 20b64b5:

  • moved @opentelemetry/sdk-metrics 2.10.0 from devDependencies to dependencies in the gRPC and proto metric exporter packages, with the workspace lockfile updated consistently;
  • stubbed node:http.request in the four new Node HTTP/proto log and trace suites, restored the built-in binding between tests, and awaited logger/tracer provider shutdown.

Fresh verification on the pushed head passes the four suites (12/12), the dependency probe (3/3), ESLint, and Prettier.

AI-assisted: this follow-up was drafted with AI assistance. I reviewed the complete diff and fresh verification output, and I own the change.

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.

[otlp exporters] remove envvar config by default

2 participants