Skip to content

feat(sdk-node,instrumentation,instrumentation-http): add declarative config support for instrumentation/development#6864

Closed
mwear wants to merge 16 commits into
open-telemetry:mainfrom
mwear:inst-config-readers
Closed

feat(sdk-node,instrumentation,instrumentation-http): add declarative config support for instrumentation/development#6864
mwear wants to merge 16 commits into
open-telemetry:mainfrom
mwear:inst-config-readers

Conversation

@mwear

@mwear mwear commented Jun 30, 2026

Copy link
Copy Markdown
Member

Which problem is this PR solving?

This PR adds support for the instrumentation/development section of declarative config. It enables instrumentations to read and apply config from that section and updates the http instrumentation to use it as an example.

The approach is opt-in typed readers rather than a generic passthrough: each instrumentation maps the snake_case keys it supports onto its config fields. Invalid types and keys are detected and logged as warnings. The implementation is tolerant of instrumentations that have yet to implement support for declarative config or that have been built against an older @opentelemetry/instrumentation base.

The general section (shared semconv config) is intentionally left for a follow-up; the reader signature already accepts it.

Fixes #6854

Short description of the changes

@opentelemetry/instrumentation:

  • Add applyDeclarativeConfig(block, general?) to InstrumentationBase and an overridable readDeclarativeConfig(). The default reads enabled; an instrumentation overrides the reader to map its own keys.
  • Add declarativeConfigProperties(), a null-safe typed accessor over a config block (getBoolean/getString/getNumber/getStringArray/getStructured).

@opentelemetry/sdk-node:

  • startNodeSDK() matches each instrumentation to its instrumentation/development.js block by package name and applies it, gating registration on enabled.
  • Tolerate instrumentations built against an older @opentelemetry/instrumentation base (no applyDeclarativeConfig): honor enabled directly and warn that field config needs an update.

@opentelemetry/instrumentation-http:

  • Read the config fields it supports from declarative config. headersToSpanAttributes is deferred with general, since it is the same concept as general.http.*.captured_headers.

An example config file:

file_format: "1.0"

tracer_provider:
  processors:
    - simple:
        exporter:
          console: {}

instrumentation/development:
  js:
    # Goes through the instrumentation's reader (snake_case keys).
    "@opentelemetry/instrumentation-http":
      require_parent_for_outgoing_spans: true
      server_name: my-server
      redacted_query_params:
        - sig
        - token

    # `enabled` works for every instrumentation, reader or not.
    "@opentelemetry/instrumentation-express":
      enabled: false

A note on validation: unknown keys in an instrumentation block are warned about and ignored, not rejected. The schema-validated sections (tracer_provider, etc.) are strict via the config model, but the per-instrumentation block is an open map in the schema, so the reader is the only validator. Java, the only existing implementation, behaves the same way, so this keeps us consistent while keeping a config typo from breaking startup.

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • units, integration, manual

Checklist:

  • Followed the style guidelines of this project
  • Unit tests have been added
  • Documentation has been updated

@mwear
mwear requested a review from a team as a code owner June 30, 2026 22:03
@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.16%. Comparing base (dddbc0e) to head (d8cf74a).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6864      +/-   ##
==========================================
- Coverage   95.58%   95.16%   -0.42%     
==========================================
  Files         388      398      +10     
  Lines       13152    14340    +1188     
  Branches     3001     3318     +317     
==========================================
+ Hits        12571    13647    +1076     
- Misses        581      693     +112     
Files with missing lines Coverage Δ
...ges/opentelemetry-instrumentation-http/src/http.ts 93.78% <100.00%> (ø)
...instrumentation/src/declarativeConfigProperties.ts 100.00% <100.00%> (ø)
...entelemetry-instrumentation/src/instrumentation.ts 91.30% <100.00%> (+3.80%) ⬆️
...ental/packages/opentelemetry-sdk-node/src/start.ts 97.08% <100.00%> (+0.05%) ⬆️
...ental/packages/opentelemetry-sdk-node/src/utils.ts 96.51% <100.00%> (+0.03%) ⬆️

... and 10 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment on lines +12 to +15
"test:cjs": "nyc --silent mocha test/**/*.test.ts",
"test:esm": "nyc --silent --no-clean node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ../../../node_modules/mocha/bin/mocha 'test/**/*.test.mjs'",
"test:double-instr": "nyc --silent --no-clean node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ../../../node_modules/mocha/bin/mocha 'test/integrations/double-instr.test.cjs'",
"test": "npm run test:cjs && npm run test:esm && npm run test:double-instr && nyc report",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The package.json test-script changes in instrumentation and instrumentation-http fix Codecov under-reporting. In a chain like npm run test:cjs && npm run test:esm && npm run test:double-instr, each subsequent nyc run clobbers the previous run's coverage (nyc wipes .nyc_output before each run), so only the last run's coverage gets uploaded. The fix accumulates coverage across runs and emits one merged report. This should probably be split into its own PR. I included it here to get this PR green. Here is what codecov looked like without these changes:

Image

@opentelemetry-pr-dashboard

Copy link
Copy Markdown

This PR has review comments. Review suggestions, whether from maintainers or automated reviewers, aren't always correct or required. Please evaluate each comment on its merits, then make sure each thread has a clear outcome.

For example, link to the commit if you applied a suggestion, explain why it wasn't applied, or ask a follow-up question.

Automation flags a PR for human review once every review thread has a reply or is marked as resolved.

Status across open PRs is visible on the pull request dashboard.

@trentm

trentm commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Thanks, Matt.

My understanding of the intent of the spec (https://opentelemetry.io/docs/specs/otel/configuration/api/) was that we would add a ConfigProvider to @opentelemetry/api -- alongside TracerProvider, etc. Instrumentations would then:

import { config } from '@opentelemetry/api';
const conf = config.getConfigProvider().getInstrumentationConfig();

or something like that, and then use settings on that conf of type ConfigProperties as relevant for the instrumentation.

(E.g. in Java: https://github.com/open-telemetry/opentelemetry-java/blob/main/api/incubator/src/main/java/io/opentelemetry/api/incubator/config/ConfigProvider.java#L20-L29 and a usage example https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/3118b49eade43b82bac593a980cb83db1ee540b1/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java#L400-L418)

This would require some sequencing. startNodeSDK() would need to set the global ConfigProvider before instrumentations are enabled. Instrumentations would need to know to only use the ConfigProvider during or after being .enable()'d.

I think, then, we'd be able to get away from having to add methods to the InstrumentationBase class.

This is all vapourware, however.
I'd done a little thinking about this, but haven't written any PoC to know if what I'm thinking would be awkward in code.

@mwear

mwear commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

@trentm, Thanks for the overview of how things should work. I somehow missed that. I'll rework this to follow the ConfigProvider approach and see how it works out.

@mwear
mwear marked this pull request as draft July 1, 2026 14:22
@mwear

mwear commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

I've looked things over and the good news is that most of this is reusable. The ConfigProvider approach is a pull model, whereas the readers approach is push model from the instrumentation perspective. The biggest change is introducing a ConfigProvider API to pull from. I'll close this PR and open a new one when I have that working.

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.

Support instrumentation config in declarative configuration

2 participants