Skip to content

feat(engine): wire extensions and capabilities into runtime pipeline#2860

Open
gouslu wants to merge 11 commits intoopen-telemetry:mainfrom
gouslu:gouslu/extension-system-p1-pr4
Open

feat(engine): wire extensions and capabilities into runtime pipeline#2860
gouslu wants to merge 11 commits intoopen-telemetry:mainfrom
gouslu:gouslu/extension-system-p1-pr4

Conversation

@gouslu
Copy link
Copy Markdown
Contributor

@gouslu gouslu commented May 6, 2026

Change Summary

Part 4 of the Extension System (P1) series. Wires the previously
landed Capability Registry & Resolver (#2732) into the runtime
pipeline so extensions are actually instantiated, started, and
shut down by the engine, and so consumer nodes can resolve their
capability bindings at build time.

Highlights:

  • Runtime wiring in runtime_pipeline.rs: extension lifecycle
    is invoked before any data-path node is spawned, and Shutdown
    is delivered to extensions only after the data path drains
    ("started first, shut down last"). Active and passive extensions
    are handled separately; failures abort startup cleanly.
  • Local capability ownership aligned with shared via a
    Box-clone factory pattern, removing the prior asymmetry between
    the two trait variants.
  • Two reference test capabilities under
    crates/engine/src/capability/: NoOpStateless and
    NoOpStateful. They exercise every codegen path of the
    #[capability] proc macro (&self × {sync, async}, &mut self
    × {sync, async}, borrowed/owned returns, etc.).
  • Comprehensive end-to-end test suite at
    crates/engine/tests/extension_e2e.rs (26 tests) covering:
    passive/active/background extensions, lifecycle ordering and
    shutdown ordering, fail-fast on extension errors, dual-variant
    pruning, one-shot capability enforcement (all accessor
    combinations), shared mutable state across consumers via
    Arc/Rc for both local and shared trait variants, async
    &mut self invocation through boxed handles, and active
    extensions mutating shared state observed by capability
    consumers.
  • Architecture doc updated with a precise statement of the
    start-first/shut-down-last invariant (it orders lifecycle
    calls, not init completion) and a noted future consideration
    to add an opt-in readiness probe if/when an extension needs an
    init-complete guarantee.
  • URN unification: extension URNs now use the canonical
    4-segment form urn:<namespace>:extension:<id> (mirroring the
    receiver/processor/exporter convention), with a short form
    extension:<id>. The shared parser core lives in a new
    private crates/config/src/urn.rs; node_urn.rs and
    extension_urn.rs delegate to it with disjoint accepted-kind
    sets so the two URN types cannot be confused. As a consequence,
    NodeKind::Extension and the now-unreachable
    Error::ExtensionInNodesSection are removed. Misplacement
    errors include actionable hints (e.g. "declare under
    extensions: instead of nodes:"
    ).
  • All in-tree node factories (receivers, processors, exporters
    in core-nodes and contrib-nodes) updated to accept the new
    &Capabilities parameter; existing factories that don't depend
    on any capability simply ignore it.

What issue does this PR close?

How are these changes tested?

  • New extension_e2e.rs integration test (26 tests) exercises the
    wiring end-to-end against synthetic receivers/processors/
    exporters/extensions.
  • New unit tests in urn.rs cover the shared parser core and the
    misplacement-error hints; existing extension_urn and
    node_urn tests updated to assert the canonical 4-segment form.
  • Pipeline-level regression tests cover rejecting extension URNs
    in the nodes: section and node URNs in the extensions:
    section.
  • cargo xtask check (structure check + fmt + clippy --workspace --all-targets -- -D warnings + cargo test --workspace) passes
    cleanly. No new clippy warnings.

Are there any user-facing changes?

Yes:

  • Extension URN format: extension URNs now use
    urn:<namespace>:extension:<id> (4-segment) instead of the
    pre-existing 3-segment urn:<namespace>:<id>. Short form
    extension:<id> (expands to urn:otel:extension:<id>) is
    available as a developer convenience. Existing 3-segment
    extension URNs in pipeline configs must be updated; the bundled
    configs/fake-with-extension.yaml shows the new shape.
  • New extension authoring surface: Extension trait,
    ExtensionWrapper::builder typestate, the
    extension_capabilities! macro, and the test capabilities
    NoOpStateless / NoOpStateful are now reachable for
    external extension authors. The architecture doc captures the
    lifecycle contract.
  • Node factory signature now includes &Capabilities as a
    parameter; existing custom factories will need to accept (and
    may ignore) this new argument

gouslu and others added 3 commits May 5, 2026 20:15
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extension and node URNs now share one canonical 4-segment shape
`urn:<namespace>:<kind>:<id>` (e.g., `urn:microsoft:extension:azure_identity_auth`),
mirroring the receiver/processor/exporter convention. Short forms
`<kind>:<id>` work for both, expanding to `urn:otel:<kind>:<id>`.

The previous 3-segment extension form (`urn:<ns>:<id>`) is no longer
accepted. Misplacement errors include actionable hints, e.g.
'(declare under `extensions:` instead of `nodes:`)'.

- New private `crates/config/src/urn.rs` factors out the shared
  parser core (`parse_kinded_urn`, `build_canonical_urn`, segment
  validators, misplacement-hint formatter).
- `node_urn.rs` and `extension_urn.rs` now delegate to it; their
  accepted-kind sets are disjoint, so `NodeUrn` can never parse an
  extension URN and vice versa.
- Removed `NodeKind::Extension` from the node enum and all defensive
  match arms in `pipeline.rs`, `controller/lib.rs`,
  `controller/startup.rs`, `engine/lib.rs`.
- Removed `Error::ExtensionInNodesSection` (became unreachable —
  type-rejected at parse).
- Updated YAML fixtures, bundled `configs/fake-with-extension.yaml`,
  and all `extension_e2e.rs` test URN constants to the 4-segment form.
- Added regression tests for misplacement-hint error messages.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the rust Pull requests that update Rust code label May 6, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 86.33194% with 98 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.33%. Comparing base (0f3ffaf) to head (44ca58f).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2860      +/-   ##
==========================================
+ Coverage   86.27%   86.33%   +0.06%     
==========================================
  Files         715      717       +2     
  Lines      272067   272391     +324     
==========================================
+ Hits       234715   235162     +447     
+ Misses      36828    36705     -123     
  Partials      524      524              
Components Coverage Δ
otap-dataflow 87.31% <86.33%> (+0.07%) ⬆️
query_abstraction 80.61% <ø> (ø)
query_engine 90.73% <ø> (ø)
otel-arrow-go 52.45% <ø> (ø)
quiver 92.25% <ø> (ø)
🚀 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.

gouslu and others added 5 commits May 6, 2026 12:58
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@gouslu gouslu marked this pull request as ready for review May 8, 2026 16:48
@gouslu gouslu requested a review from a team as a code owner May 8, 2026 16:48
gouslu and others added 3 commits May 8, 2026 10:12
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… validation

The file contains Jinja placeholders ({{core_start}}, {{core_end}}) but
was missing the .j2 suffix, so the validate-configs CI script picked it
up as a real config and failed YAML parsing. Sibling otlp-otlp.yaml.j2
and otlphttp-otlphttp.yaml.j2 already use the .j2 convention; align
otap-otap with them and update the three suite references.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust Pull requests that update Rust code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant