Improve the OpenTelemetry bridge - #2807
Merged
Merged
Conversation
🤖 GitHub commentsJust comment with:
|
🔍 Preview links for changed docs |
✅ Elastic Docs Style Checker (Vale)No issues found on modified lines! The Vale linter checks documentation changes against the Elastic Docs style guide. To use Vale locally or report issues, refer to Elastic style guide for Vale. |
stevejgordon
force-pushed
the
otel-bridge-options
branch
from
September 11, 2026 13:15
eb4158c to
ca29448
Compare
stevejgordon
marked this pull request as ready for review
September 11, 2026 13:51
LikeTheSalad
approved these changes
Sep 14, 2026
intuibase
approved these changes
Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A batch of related OpenTelemetry bridge work. The theme is that an application using the core package plus OpenTelemetry instrumentation, with no Elastic integration packages, should produce a sensible trace out of the box and that the bridge should not turn on telemetry the application did not ask for.
Incoming ASP.NET Core requests
Microsoft.AspNetCore.Hosting.HttpRequestInwas inKnownListeners.SkippedActivityNamesSet, so in an application withoutElastic.Apm.AspNetCorethere was no transaction for a request and every activity started while handling it became a root transaction of its own trace.It is now skipped only while
Elastic.Apm.AspNetCoreorElastic.Apm.Azure.Functionsis loaded. Both create the request transaction from the hosting layer's diagnostic events, and the Azure Functions integration does so without referencing the AspNetCore assembly, so detecting only the latter would duplicate transactions for Functions users.Aligns span naming with the ASP.NET Core instrumentation when possible and ensures that custom names or names set after the Activity starts are preserved.
The transaction also records
context.requestmethod and URL, under both the current (url.scheme,url.path,url.query,server.address,server.port) and older (http.scheme,http.target,http.host) conventions. APM Server rebuilds those fields for the transaction itself fromotel.attributes, but an error copies the transaction's context as it stands when it is captured and carries no attributes of its own, so this is what gives errors in a bridge-only application a URL.Activity source filtering
ShouldListenTowas_ => true. Two new options narrow it:OpenTelemetryBridgeAllowedActivitySources(default*) andOpenTelemetryBridgeDeniedActivitySources(default empty). Allow is a gate, deny is a veto. Filtering is applied at subscription, so an excluded source is never observed and a source which only emits while a listener is attached is never created which also means these are read once at startup and are not centrally configurable.On .NET 9 and later the runtime's
Experimental.System.Net.*sources (DNS resolution, socket connect, TLS handshake, HTTP connection setup) are dormant until something subscribes but the catch-all subscription was what activated them. Transactions which opened a new connection therefore containedDNS lookup,socket connect,TLS client handshake,HTTP connection_setupandHTTP wait_for_connectionspans.The bridge no longer subscribes to
Experimental.*by default. SetELASTIC_APM_OPENTELEMETRY_BRIDGE_EXPERIMENTAL_SOURCES_ENABLED=trueto restore it. .NET 8 and earlier are unaffected. When enabled, connection level activities are captured as spans within an existing trace and are never promoted to transactions:ConnectionSetupis deliberately the root of its own trace because a connection outlives the requests that share it, so promoting it produced top level transactions for application startup, background work and the agent's own transport.Trace topology and naming
ShouldSkipActivity, or excluded by the source filter), the walk continues up to the top-most such ancestor and the trace is continued from itsParentIdandTraceStateString. An upstream sampling decision is honoured, instead of the activity starting a fresh trace.HasCustomName(already onTransaction, added toSpan) replaces thename == OperationNameheuristic, so aDisplayNameset when the activity stops is adopted while a name set through the Elastic API always wins.Attribute mapping
Current and legacy keys are read side by side for method (
_OTHERresolved throughhttp.request.method_original), scheme, path, query, host and port;InferTransactionTyperecognises modern server spans, which previously came outunknown;url.schemeclassifies an HTTP client span the wayhttp.schemealready did; andspan.context.service.targetis only emitted when it has a type or a name, which APM Server otherwise rejects.Supporting changes
AbstractConfigurationReader: the near-duplicate wildcard list parsers are oneParseWildcardMatchers(...)helper, withblankIsDefaultpreserving each option's existing empty-value meaning.HostBuilderExtensions: the framework version is read by loadingMicrosoft.AspNetCoreby name, rather than the first loaded assembly with that prefix, which could be an out of band package such asMicrosoft.AspNetCore.Mvc.Testingand made the reported version depend on load order.