Skip to content

Enable standalone Config v2 runtime loading#2682

Open
MrAlias wants to merge 20 commits into
open-telemetry:mainfrom
MrAlias:agent/config-v2-standalone-runtime
Open

Enable standalone Config v2 runtime loading#2682
MrAlias wants to merge 20 commits into
open-telemetry:mainfrom
MrAlias:agent/config-v2-standalone-runtime

Conversation

@MrAlias

@MrAlias MrAlias commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • detect Config v2 during standalone OBI startup and convert the full declarative document through the internal schema and runtime conversion packages
  • fall back to the legacy v1 loader only when v2 detection returns an explicit NotV2Error, while preserving the original input for v1 environment handling and defaults
  • reject malformed and unsupported v2 documents without attempting v1 parsing, and emit a version-only startup diagnostic after logging is configured
  • cover representative standalone sections, top-level document conversion, v1 compatibility, environment substitution, defaults, and v2 failure modes

Why

Standalone OBI currently routes every configuration document through the legacy v1 loader. That prevents valid v2 documents from reaching the existing schema and conversion path, and an unconditional fallback could hide invalid v2 configuration by interpreting it as v1.

This change makes version detection authoritative: valid v2 documents use the complete v2 conversion path, explicit non-v2 input retains the established v1 behavior, and recognized but invalid v2 input fails startup with its v2 diagnostic.

Runtime impact

Existing v1 configuration remains supported, including legacy environment-variable precedence and escaping. V2 defaulting and environment substitution run once, standalone-only sections are accepted, and startup logs identify only the selected configuration version without printing configuration values.

Verification

  • go test -race ./cmd/obi ./internal/config/schema ./internal/config/convert
  • go vet ./cmd/obi
  • golangci-lint run ./cmd/obi --timeout=6m
  • make check-config-v2-artifacts
  • make license-header-check
  • make compile

This is part of the Config v2 release gate and should ship together with the Collector receiver work, migration documentation, and published v2 artifacts tracked from #2251.

Closes #2535

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.89931% with 333 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.04%. Comparing base (27fbfa6) to head (d22f992).

Files with missing lines Patch % Lines
internal/config/convert/import_document.go 46.63% 162 Missing and 52 partials ⚠️
internal/config/convert/import.go 81.22% 41 Missing and 14 partials ⚠️
internal/config/schema/schema.go 59.59% 27 Missing and 13 partials ⚠️
cmd/obi/main.go 68.08% 12 Missing and 3 partials ⚠️
internal/config/schema/instrumentation.go 56.25% 5 Missing and 2 partials ⚠️
internal/config/convert/import_enrich.go 88.88% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2682      +/-   ##
==========================================
- Coverage   69.88%   69.04%   -0.85%     
==========================================
  Files         359      361       +2     
  Lines       51142    52269    +1127     
==========================================
+ Hits        35739    36087     +348     
- Misses      13172    13873     +701     
- Partials     2231     2309      +78     
Flag Coverage Δ
integration-test 46.09% <2.95%> (-4.35%) ⬇️
integration-test-arm 25.32% <2.63%> (-0.79%) ⬇️
integration-test-vm-5.15-lts 24.70% <2.95%> (-1.99%) ⬇️
integration-test-vm-6.18-lts 24.76% <2.95%> (-2.10%) ⬇️
k8s-integration-test 31.30% <2.95%> (-2.96%) ⬇️
oats-test 32.08% <2.95%> (-2.50%) ⬇️
unittests 67.77% <72.21%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 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.

@MrAlias

MrAlias commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Blocked by #2700

MrAlias and others added 15 commits July 20, 2026 15:16
Load standalone configuration through the v2 schema and full-document
runtime converter before considering the legacy parser. Fall back only
when detection explicitly reports that the input is not v2, so malformed
or unsupported v2 documents fail startup instead of being misread as v1.

Keep untouched input bytes for the v1 path to preserve its existing
environment-substitution and defaulting behavior. Report the selected
version and cover both paths, standalone-only sections, defaults, and
failure modes in startup tests.
Copy the internal Config v2 schema and conversion packages into the
production Docker builder so the standalone binary can compile in release
images. The startup path now imports these packages directly, while the
previous narrow build context omitted them.

Update the converter documentation to reflect that it now participates in
standalone runtime loading.
Copy the internal Config v2 packages into each Docker build context that
compiles the OBI binary. This keeps debug and integration images aligned
with the production image and prevents missing-package build failures.
Launch the integration image with a representative Config v2 document and
verify that OBI detects v2, instruments the selected process, and exposes
HTTP telemetry through its configured Prometheus reader.

This closes the runtime coverage gap where only configuration conversion
was exercised without starting standalone OBI.
Parsed Config v2 documents must distinguish omitted fields from explicit
false and zero values. Without that distinction, partial documents
cannot disable default-on features or request zero-valued limits.

Retain each parsed extension source and overlay it onto the canonical
Config v2 defaults before conversion. Programmatically constructed
partial schemas keep their existing compatibility behavior.
The published Config v2 schema disallows extra properties, but the YAML
decoder silently ignored misspelled OBI settings. A typo could therefore
leave a default active without any configuration error.

Decode OBI-owned sections with known-field checks while leaving the wider
OpenTelemetry declarative document extensible. Apply the same validation
to standalone extensions and receiver-embedded configuration.
Runtime and log annotation filters are published, but no equivalent
selection mechanism exists in the current runtime configuration.
Accepting non-empty filters would broaden injection or log mutation
beyond the requested scope.

Fail closed with a field-specific error until those mappings exist.
Continue accepting empty filter objects used by the documented
default configuration.
Parsed Config v2 documents are overlaid on generated runtime defaults.
A shallow copy left nested maps shared with obi.DefaultConfig, allowing
one conversion to alter defaults observed by later configurations.

Deep-copy the extension before decoding the source overlay. Preserve
the existing merge behavior and verify that merged resource labels do
not mutate their source defaults.
Strict known-field decoding serializes extracted YAML nodes before
decoding them again. Aliases that referenced top-level anchors lost
their definitions when only the OBI subtree was serialized.

Expand aliases into cloned nodes before serialization while retaining
cycle and unresolved-alias errors. Valid declarative documents can now
share anchored values with the OBI extension.
Honor default inclusion with a catch-all selector and accept rule orders
only when they preserve the runtime's exclusion-first behavior.

Reject selector combinations and rule shapes that the legacy matcher cannot
represent so Config v2 loading never silently drops capture intent.
Fail Config v2 loading when extensible enrichment objects contain fields
that the runtime converter cannot apply. This prevents accepted DNS and
rule-based enrichment settings from becoming silent no-ops.

Keep the published default example limited to supported service-name and
attribute controls so its documented behavior matches runtime behavior.
Honor capture match order when multiple include rules refine exports
or HTTP routes. Validate OTLP exporter ports before mapping them into
runtime discovery settings.
Require protocol and signal filters to agree when they map to one
runtime filter. Divergent application, network, and stats filters
now fail with their source path instead of being ignored or widened.
Fail conversion when extensible network capture or stats objects
contain properties without a runtime representation. This prevents
accepted Config v2 settings from becoming silent no-ops.
Validate every declarative SDK and exporter field before conversion so
standalone startup cannot silently substitute runtime defaults for the
requested behavior.

Import OTLP/HTTP, headers, transport selection, resource identity, and
declarative exporter defaults where OBI has equivalent runtime settings.
Return path-specific errors for unsupported provider, processor, and TLS
options.
@MrAlias
MrAlias force-pushed the agent/config-v2-standalone-runtime branch from f85a4f7 to 4b1ccba Compare July 20, 2026 15:33

@grcevski grcevski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks great generally, I left a few comments/questions.

if encoding == nil || *encoding == otelconfx.OTLPHttpEncodingProtobuf {
return otelcfg.ProtocolHTTPProtobuf, nil
}
if *encoding == otelconfx.OTLPHttpEncodingJson {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this may not work, since we rely on the env variable to be picked up by the OTel exporters, we don't explicitly set the protocol in traces.go and exporter.go.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The conversion assigns the runtime protocol directly for both signal paths: TracesProtocol is set for OTLP/gRPC and OTLP/HTTP, and MetricsProtocol is set the same way. TestDocumentToRuntimeImportsOTLPHTTPExporters covers JSON traces and protobuf metrics, while the default exporter test covers gRPC, so this path does not rely on the exporter environment lookup.

Comment thread internal/config/convert/import_document.go Outdated
MrAlias added 4 commits July 22, 2026 18:35
Parse declarative OTLP header lists with the OpenTelemetry baggage
parser so escaped values and invalid input follow the published schema.

Make the receiver selection test explicit about excluding unmatched
processes and restore gofumpt formatting required by CI.
Expect the declarative include-by-default policy to add its catch-all
selector alongside the explicit open-port selector.

This keeps the branch test consistent with current main and prevents the
synthetic PR merge from asserting contradictory policy behavior.
Compose cleanup previously removed only services that had already stopped.
A hung OBI container could abort shutdown and leave the rest of the stack
running, causing later integration tests to collide on ports.

Request that Compose stop services during removal so cleanup deletes every
service in the test stack.
Unit shard 0 failed twice in GitHub Actions while the exact synthetic
merge passed all 1,975 shard tests locally with race detection and
coverage.

Create a new head SHA so GitHub reruns the check suite after the validated
Compose cleanup change.
@MrAlias
MrAlias marked this pull request as ready for review July 23, 2026 00:12
@MrAlias
MrAlias requested a review from a team as a code owner July 23, 2026 00:12
Bring this pull request up to date with the latest base branch changes so it can be tested and reviewed against the current codebase.
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.

Enable Config v2 standalone runtime loading

2 participants