Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion api/envoy/config/trace/v3/opentelemetry.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;

// Configuration for the OpenTelemetry tracer.
// [#extension: envoy.tracers.opentelemetry]
// [#next-free-field: 9]
// [#next-free-field: 10]
message OpenTelemetryConfig {
// The upstream gRPC cluster that will receive OTLP traces.
// Note that the tracer drops traces if the server does not read data fast enough.
Expand Down Expand Up @@ -76,4 +76,15 @@ message OpenTelemetryConfig {
// Specifies whether to set the ``service.name`` resource attribute.
// If not specified, the default is to set this attribute.
google.protobuf.BoolValue set_service_name_resource_attribute = 8;

// Configures usage of Semantic Conventions standard tag names. Specifying both options will emit both legacy and semantic convention tags. If not specified, only legacy Envoy tags are emitted.
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.

The If not specified, only legacy Envoy tags are emitted. should probably be added to the otel_semconv_stability_opt_in field description.

message OtelSemconvStabilityOptIn {
// Emit legacy Envoy attributes.
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.

Please describe what is the default value of each of the BoolValue fields.

google.protobuf.BoolValue emit_legacy_tags = 1;
// Emit the new stable semantic convention tags.
google.protobuf.BoolValue emit_semantic_convention_tags = 2;
}

// Configures which OpenTelemetry semantic convention stability levels to opt-in to.
OtelSemconvStabilityOptIn otel_semconv_stability_opt_in = 9;
}
7 changes: 7 additions & 0 deletions envoy/tracing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,18 @@ envoy_cc_library(
hdrs = ["trace_reason.h"],
)

envoy_cc_library(
name = "trace_tag_interface",
hdrs = ["trace_tag.h"],
deps = ["@abseil-cpp//absl/strings"],
)

envoy_cc_library(
name = "trace_driver_interface",
hdrs = ["trace_driver.h"],
deps = [
":trace_config_interface",
":trace_tag_interface",
"//envoy/stream_info:stream_info_interface",
],
)
Expand Down
12 changes: 12 additions & 0 deletions envoy/tracing/trace_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "envoy/common/pure.h"
#include "envoy/stream_info/stream_info.h"
#include "envoy/tracing/trace_config.h"
#include "envoy/tracing/trace_tag.h"

namespace Envoy {
namespace Tracing {
Expand Down Expand Up @@ -75,6 +76,17 @@ class Span {
*/
virtual void setTag(absl::string_view name, absl::string_view value) PURE;

/**
* Attach metadata to a Span using a structured Tag definition.
* Implementations can override this to specialize tag naming based on ID (e.g. OTel).
* @param tag the tag metadata object
* @param value the value to associate with the tag
*/
virtual void setTag(const Tag& tag, absl::string_view value) {
// Default implementation delegates to string-based name
setTag(tag.name(), value);
}

/**
* Record an event associated with a span, to be handled in an implementation-dependent fashion.
* @param timestamp the time of the event.
Expand Down
84 changes: 84 additions & 0 deletions envoy/tracing/trace_tag.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#pragma once

#include <string>

#include "absl/strings/string_view.h"

namespace Envoy {
namespace Tracing {

/**
* Standardized tracing tag identifiers.
*/
enum class TagName {
Component,
DbInstance,
DbStatement,
DbUser,
DbType,
Error,
HttpMethod,
HttpStatusCode,
HttpUrl,
MessageBusDestination,
PeerAddress,
PeerHostname,
PeerIpv4,
PeerIpv6,
PeerPort,
PeerService,
SpanKind,
DownstreamCluster,
ErrorReason,
GrpcAuthority,
GrpcContentType,
GrpcMessage,
GrpcPath,
GrpcStatusCode,
GrpcTimeout,
GuidXClientTraceId,
GuidXRequestId,
HttpProtocol,
NodeId,
RequestSize,
ResponseFlags,
ResponseSize,
RetryCount,
Status,
UpstreamAddress,
UpstreamCluster,
UpstreamClusterName,
UserAgent,
Zone
};

/**
* Encapsulates a tracing tag default name and its semantic enum identifier.
*/
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_;
};

} // namespace Tracing
} // namespace Envoy
1 change: 1 addition & 0 deletions source/common/tracing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ envoy_cc_library(
"common_values.h",
],
deps = [
"//envoy/tracing:trace_tag_interface",
"//source/common/singleton:const_singleton",
],
)
Expand Down
116 changes: 75 additions & 41 deletions source/common/tracing/common_values.h
Original file line number Diff line number Diff line change
@@ -1,61 +1,95 @@
#pragma once

#include <string>
#include "envoy/tracing/trace_tag.h"

#include "source/common/singleton/const_singleton.h"

namespace Envoy {
namespace Tracing {

/**
* OpenTelemetry standard HTTP/Network semantic convention tag names.
* Follows: https://opentelemetry.io/docs/specs/semconv/http/http-spans/
*/
class SemanticConventionTagValues {
public:
const std::string HttpRequestMethod = "http.request.method";
const std::string HttpResponseStatusCode = "http.response.status_code";
const std::string ErrorType = "error.type";
const std::string UrlFull = "url.full";
const std::string UrlPath = "url.path";
const std::string UrlScheme = "url.scheme";
const std::string HttpRequestResendCount = "http.request.resend_count";
const std::string HttpRequestSize = "http.request.body.size";
const std::string HttpResponseSize = "http.response.body.size";
const std::string ClientAddress = "client.address";
const std::string ClientPort = "client.port";
const std::string ServerAddress = "server.address";
const std::string ServerPort = "server.port";
const std::string NetworkProtocolName = "network.protocol.name";
const std::string NetworkPeerAddress = "network.peer.address";
const std::string NetworkPeerPort = "network.peer.port";
const std::string NetworkProtocolVersion = "network.protocol.version";
const std::string UserAgentOriginal = "user_agent.original";
};

using SemanticConventionTags = ConstSingleton<SemanticConventionTagValues>;

/**
* Tracing tag names.
*/
class TracingTagValues {
public:
// OpenTracing standard tag names.
const std::string Component = "component";
const std::string DbInstance = "db.instance";
const std::string DbStatement = "db.statement";
const std::string DbUser = "db.user";
const std::string DbType = "db.type";
const std::string Error = "error";
const std::string HttpMethod = "http.method";
const std::string HttpStatusCode = "http.status_code";
const std::string HttpUrl = "http.url";
const std::string MessageBusDestination = "message_bus.destination";
const Tag Component{"component", TagName::Component};
const Tag DbInstance{"db.instance", TagName::DbInstance};
const Tag DbStatement{"db.statement", TagName::DbStatement};
const Tag DbUser{"db.user", TagName::DbUser};
const Tag DbType{"db.type", TagName::DbType};
const Tag Error{"error", TagName::Error};
const Tag HttpMethod{"http.method", TagName::HttpMethod,
SemanticConventionTags::get().HttpRequestMethod};
const Tag HttpStatusCode{"http.status_code", TagName::HttpStatusCode,
SemanticConventionTags::get().HttpResponseStatusCode};
const Tag HttpUrl{"http.url", TagName::HttpUrl, SemanticConventionTags::get().UrlFull};
const Tag MessageBusDestination{"message_bus.destination", TagName::MessageBusDestination};
// Downstream remote address for the downstream span and upstream remote address for the upstream
// span.
const std::string PeerAddress = "peer.address";
const std::string PeerHostname = "peer.hostname";
const std::string PeerIpv4 = "peer.ipv4";
const std::string PeerIpv6 = "peer.ipv6";
const std::string PeerPort = "peer.port";
const std::string PeerService = "peer.service";
const std::string SpanKind = "span.kind";
const Tag PeerAddress{"peer.address", TagName::PeerAddress,
SemanticConventionTags::get().NetworkPeerAddress};
const Tag PeerHostname{"peer.hostname", TagName::PeerHostname};
const Tag PeerIpv4{"peer.ipv4", TagName::PeerIpv4};
const Tag PeerIpv6{"peer.ipv6", TagName::PeerIpv6};
const Tag PeerPort{"peer.port", TagName::PeerPort};
const Tag PeerService{"peer.service", TagName::PeerService};
const Tag SpanKind{"span.kind", TagName::SpanKind};

// Non-standard tag names.
const std::string DownstreamCluster = "downstream_cluster";
const std::string ErrorReason = "error.reason";
const std::string GrpcAuthority = "grpc.authority";
const std::string GrpcContentType = "grpc.content_type";
const std::string GrpcMessage = "grpc.message";
const std::string GrpcPath = "grpc.path";
const std::string GrpcStatusCode = "grpc.status_code";
const std::string GrpcTimeout = "grpc.timeout";
const std::string GuidXClientTraceId = "guid:x-client-trace-id";
const std::string GuidXRequestId = "guid:x-request-id";
const std::string HttpProtocol = "http.protocol";
const std::string NodeId = "node_id";
const std::string RequestSize = "request_size";
const std::string ResponseFlags = "response_flags";
const std::string ResponseSize = "response_size";
const std::string RetryCount = "retry.count";
const std::string Status = "status";
const std::string UpstreamAddress = "upstream_address";
const std::string UpstreamCluster = "upstream_cluster";
const std::string UpstreamClusterName = "upstream_cluster.name";
const std::string UserAgent = "user_agent";
const std::string Zone = "zone";
const Tag DownstreamCluster{"downstream_cluster", TagName::DownstreamCluster};
const Tag ErrorReason{"error.reason", TagName::ErrorReason};
const Tag GrpcAuthority{"grpc.authority", TagName::GrpcAuthority};
const Tag GrpcContentType{"grpc.content_type", TagName::GrpcContentType};
const Tag GrpcMessage{"grpc.message", TagName::GrpcMessage};
const Tag GrpcPath{"grpc.path", TagName::GrpcPath};
const Tag GrpcStatusCode{"grpc.status_code", TagName::GrpcStatusCode};
const Tag GrpcTimeout{"grpc.timeout", TagName::GrpcTimeout};
const Tag GuidXClientTraceId{"guid:x-client-trace-id", TagName::GuidXClientTraceId};
const Tag GuidXRequestId{"guid:x-request-id", TagName::GuidXRequestId};
const Tag HttpProtocol{"http.protocol", TagName::HttpProtocol};
const Tag NodeId{"node_id", TagName::NodeId};
const Tag RequestSize{"request_size", TagName::RequestSize,
SemanticConventionTags::get().HttpRequestSize};
const Tag ResponseFlags{"response_flags", TagName::ResponseFlags};
const Tag ResponseSize{"response_size", TagName::ResponseSize,
SemanticConventionTags::get().HttpResponseSize};
const Tag RetryCount{"retry.count", TagName::RetryCount,
SemanticConventionTags::get().HttpRequestResendCount};
const Tag Status{"status", TagName::Status};
const Tag UpstreamAddress{"upstream_address", TagName::UpstreamAddress};
const Tag UpstreamCluster{"upstream_cluster", TagName::UpstreamCluster};
const Tag UpstreamClusterName{"upstream_cluster.name", TagName::UpstreamClusterName};
const Tag UserAgent{"user_agent", TagName::UserAgent,
SemanticConventionTags::get().UserAgentOriginal};
const Tag Zone{"zone", TagName::Zone};

// Tag values.
const std::string Canceled = "canceled";
Expand Down
2 changes: 1 addition & 1 deletion source/common/tracing/http_tracer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static absl::string_view valueOrDefault(const Http::HeaderEntry* header,
return (header != nullptr) ? header->value().getStringView() : default_value;
}

static void addTagIfNotNull(Span& span, absl::string_view tag, const Http::HeaderEntry* entry) {
static void addTagIfNotNull(Span& span, const Tag& tag, const Http::HeaderEntry* entry) {
if (entry != nullptr) {
span.setTag(tag, entry->value().getStringView());
}
Expand Down
1 change: 1 addition & 0 deletions source/common/tracing/null_span_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class NullSpan : public Span {
}

// Tracing::Span
using Span::setTag;
void setOperation(absl::string_view) override {}
void setTag(absl::string_view, absl::string_view) override {}
void log(SystemTime, const std::string&) override {}
Expand Down
1 change: 1 addition & 0 deletions source/extensions/tracers/datadog/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Span : public Tracing::Span {
const datadog::tracing::Optional<datadog::tracing::Span>& impl() const;

// Envoy::Tracing::Span
using Tracing::Span::setTag;
void setOperation(absl::string_view operation) override;
void setTag(absl::string_view name, absl::string_view value) override;
void log(SystemTime, const std::string&) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ class DynamicModuleSpan : public Tracing::Span {
~DynamicModuleSpan() override;

// Tracing::Span interface.
using Tracing::Span::setTag;
void setOperation(absl::string_view operation) override;
void setTag(absl::string_view name, absl::string_view value) override;
void log(SystemTime timestamp, const std::string& event) override;
Expand Down
1 change: 1 addition & 0 deletions source/extensions/tracers/fluentd/fluentd_tracer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ class Span : public Tracing::Span {
SpanContext&& span_context, TimeSource& time_source, bool use_local_decision);

// Tracing::Span
using Tracing::Span::setTag;
void setOperation(absl::string_view operation) override;
void setTag(absl::string_view name, absl::string_view value) override;
void log(SystemTime timestamp, const std::string& event) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ Driver::Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetr
// Get the max cache size from config
uint64_t max_cache_size = PROTOBUF_GET_WRAPPED_OR_DEFAULT(opentelemetry_config, max_cache_size,
DEFAULT_MAX_CACHE_SIZE);
TracerPtr tracer =
std::make_unique<Tracer>(std::move(exporter), factory_context.timeSource(),
factory_context.api().randomGenerator(), factory_context.runtime(),
dispatcher, tracing_stats_, resource_ptr, sampler, max_cache_size);
TracerPtr tracer = std::make_unique<Tracer>(
std::move(exporter), factory_context.timeSource(), factory_context.api().randomGenerator(),
factory_context.runtime(), dispatcher, tracing_stats_, resource_ptr, sampler,
max_cache_size, opentelemetry_config.otel_semconv_stability_opt_in());
return std::make_shared<TlsTracer>(std::move(tracer));
});
}
Expand Down
Loading
Loading