Skip to content

otel: create migration mechanism to semantic convention attribute names#45184

Open
fcfort wants to merge 10 commits into
envoyproxy:mainfrom
fcfort:semconv
Open

otel: create migration mechanism to semantic convention attribute names#45184
fcfort wants to merge 10 commits into
envoyproxy:mainfrom
fcfort:semconv

Conversation

@fcfort

@fcfort fcfort commented May 20, 2026

Copy link
Copy Markdown
Contributor

Commit Message: otel: create migration mechanism to semantic convention attribute names

Additional Description:

This change implements the ability to bring Envoy’s OpenTelemetry tracer in alignment with the stable OpenTelemetry HTTP Semantic Conventions.

The architecture avoids adding additional string comparisons at core call sites by utilizing C++ overload resolution within the tracing driver APIs (setTag overload for typed Tracing::Tag).

Stability Opt-In Levels:

  • UNKNOWN: Defaults to legacy tags only (backward-compatible default behavior).
  • LEGACY: Emits only the legacy Envoy attributes.
  • LEGACY_AND_SEMCONV: Emits BOTH stable OTel and legacy Envoy attributes simultaneously.
  • SEMCONV: Emits only the stable OpenTelemetry HTTP/Network semantic convention attributes.

This was loosely inspired by the approach outlined in https://opentelemetry.io/docs/specs/semconv/http/ regarding OTEL_SEMCONV_STABILITY_OPT_IN.

Tag Migration Mapping:

The following table defines the exact mapping of span tags that will be migrated from the legacy Envoy naming conventions to the stable OpenTelemetry HTTP and Network semantic conventions under the respective opt-in levels:

Legacy Envoy Tag Name Stable OpenTelemetry Semantic Convention Tag Name
http.method http.request.method
http.status_code http.response.status_code
http.url url.full
peer.address network.peer.address
request_size http.request.body.size
response_size http.response.body.size
retry.count http.request.resend_count
user_agent user_agent.original

Note: http.protocol is deliberately NOT migrated to url.scheme or any other semantic convention name because its semantics differ. It is unaffected by the opt-in levels and continues to emit only as http.protocol.

Risk Level: Low (Adds standardized stability opt-in tags, defaults to backward-compatible legacy behavior).

Testing:

  • Enhanced opentelemetry_tracer_impl_test.cc with the new ExportOTLPSpanWithLegacyOptIn unit test to validate the LEGACY configuration behavior.
  • Re-ran and verified existing OpenTelemetry tests (//test/extensions/tracers/opentelemetry:opentelemetry_test) and affected core tracing and routing tests (//test/common/http:async_client_impl_test and //test/common/router:router_test).

Docs Changes: None.
Release Notes: Added otel_semconv_stability_opt_in configuration to support stable HTTP semantic convention attribute names in the OpenTelemetry tracer.
Platform Specific Features: None.
Fixes #30821.

[Disclosed usage of generative AI: Yes, used to assist in code modifications.]

@repokitteh-read-only

Copy link
Copy Markdown

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to (api/envoy/|docs/root/api-docs/).
envoyproxy/api-shepherds assignee is @adisuissa
CC @envoyproxy/api-watchers: FYI only for changes made to (api/envoy/|docs/root/api-docs/).

🐱

Caused by: #45184 was opened by fcfort.

see: more, trace.

Comment thread api/envoy/config/trace/v3/opentelemetry.proto Outdated
Comment thread api/envoy/config/trace/v3/opentelemetry.proto Outdated
Comment thread api/envoy/config/trace/v3/opentelemetry.proto Outdated
Comment thread api/envoy/config/trace/v3/opentelemetry.proto Outdated

@adisuissa adisuissa 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.

Thanks!
LEft a couple of minor API comments.

Comment thread api/envoy/config/trace/v3/opentelemetry.proto Outdated
Comment thread api/envoy/config/trace/v3/opentelemetry.proto Outdated
fcfort added 9 commits May 27, 2026 22:23
Signed-off-by: Frank Fort <ffort@google.com>
Signed-off-by: Frank Fort <ffort@google.com>
Signed-off-by: Frank Fort <ffort@google.com>
Signed-off-by: Frank Fort <ffort@google.com>
Signed-off-by: Frank Fort <ffort@google.com>
Signed-off-by: Frank Fort <ffort@google.com>
Signed-off-by: Frank Fort <ffort@google.com>
Signed-off-by: Frank Fort <ffort@google.com>
@fcfort

fcfort commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

/retest for failed TSAN timeout in //test/integration:quic_http_integration_test

@adisuissa adisuissa 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.

Thanks. Left a couple of minor API comments.
Assigning @wbpcode who has a better understanding of tracing.

Comment thread api/envoy/config/trace/v3/opentelemetry.proto Outdated
// Configures usage of Semantic Conventions standard tag names. Specifying both options will
// emit both legacy and semantic convention tags. If neither are specified, only legacy Envoy
// tags are emitted.
message OtelSemconvStabilityOptIn {

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.

BTW: Why is it called "OptIn" and not just "OtelSemconvStability"?
Can you please also add a link to where this is defined.

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.

Mostly to match the pattern from the OTEL_SEMCONV_STABILITY_OPT_IN environment variable from https://opentelemetry.io/docs/specs/semconv/http/. I added a comment with a link to this regard.

@adisuissa

Copy link
Copy Markdown
Contributor

/assign @wbpcode

Signed-off-by: Frank Fort <ffort@google.com>

@wbpcode wbpcode left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for this contribution. It's a good idea to use a enum to represent specific attributes.

But I guess the semantic convention should part of opentelmetry extension rather then the core of Envoy. But it's good idea to use an enum to represent well known attributes.

/wait

Comment thread envoy/tracing/trace_tag.h
/**
* Standardized tracing tag identifiers.
*/
enum class TagName {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
enum class TagName {
enum class WellKnownTagName {

virtual void setTag(const Tag& tag, absl::string_view value) {
// Default implementation delegates to string-based name
setTag(tag.name(), value);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rather than to use the Tag as input parameter, I prefer to use only the enum:

virtual void setTag(WellKnownTagName tag, absl::string_view value) PURE;

And rather than to update every span implementation to add using Tracing::Span::setTag;, we would prefer to add an implementation for every span implementation like:

void setTag(WellKnownTagName tag, absl::string_view value) {
  setTag(Tracing::fromWellKnownTagName(tag), value);
}

The fromWellKnownTagName() could be a common helper that shared by every span implementation.

And the opentelemetry could override this new setTag to convert enum to semantic convention attribute name based on the configuration.

Comment thread envoy/tracing/trace_tag.h
Comment on lines +58 to +81
class Tag {
public:
Tag(absl::string_view name, TagName id, absl::string_view sem_conv_name = "")
: name_(name), id_(id), sem_conv_name_(sem_conv_name.empty() ? name : sem_conv_name) {}

absl::string_view name() const { return name_; }
TagName id() const { return id_; }
absl::string_view semConvName() const { return sem_conv_name_; }

/**
* Implicit conversion to string_view enables transparent use at legacy call sites
* that expect string names.
*/
operator absl::string_view() const { return name_; }

bool operator==(const Tag& other) const {
return id_ == other.id_ && name_ == other.name_ && sem_conv_name_ == other.sem_conv_name_;
}

private:
const std::string name_;
const TagName id_;
const std::string sem_conv_name_;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

If we change the setTag method from setTag(Tag) to setTag(WellKnownTagName) then we can't define an absl:string_view() operator on the enum and thus will be forced to change all existing setTag call-sites to take this new WellKnownTagName enum. This would be a breaking API change no? I don't see how we can do what you're suggesting.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I may didn't make it clear. Note, the previous virtual void setTag(absl::string_view name, absl::string_view value) PURE; should still be kept along with the new virtual void setTag(WellKnonwTagname name, absl::string_view) PURE;.

And we can provide an implementation for new method like my comment at #45184 (comment). I don't think we need to change every call sites but only the call sites that will use the well tag known names?

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.

But that won't let us accomplish a migration. What we want is a way for users of the OTel tracer to be able to opt-in to using a different tag name for the same concept (i.e. the request method or response code). We need the existing call sites to call into the new method which we can accomplish using the technique I outlined in #30821. Having a new API that isn't backwards compatible will force us to change existing call sites in order to add new behavior.

@wbpcode wbpcode Jun 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think change existing call sites is unacceptable for these well known tags names.

If you do want to avoid that or want to try your best to avoid call sites change, you could update the class TracingTagValues's member type be the WellKnonwTagName (just like you current PR have updated it to new Tag type), then we needn't to change call sites. And the previous string values could be stored in constexpr string_view array and a helper could be used to convert the name to default string.

constexpr absl::string_view WellKnonwTagNameViews [] = {...}

absl::string_view wellKnonwTagnameToView(WellKnonwTagName name) {
  return WellKnonwTagNameViews[static_cast<size_t>(name)];
}

For every span implementation (except Otel), you could add a default new setTag(WellKnonwTagName):

void setTag(WellKnonwTagName name, absl::string_view value) {
  setTag(Tracing::wellKnonwTagnameToView(name), value);
}

From API's perspective, I don't think the sem_conv_name_ make sense. It should be part of implementation detail rather than part of abstract API. That's why I stick with we should only use the WellKnonwTagName only in the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenTelemetry tracer - Align attributes with OTel HTTP semantic conventions

3 participants