diff --git a/include/envoy/common/BUILD b/include/envoy/common/BUILD index f831dcd62708b..bcb9668dcb5cd 100644 --- a/include/envoy/common/BUILD +++ b/include/envoy/common/BUILD @@ -91,3 +91,12 @@ envoy_cc_library( name = "scope_tracker_interface", hdrs = ["scope_tracker.h"], ) + +envoy_cc_library( + name = "lower_case_string", + hdrs = ["lower_case_string.h"], + deps = [ + "//include/envoy/http:valid_header", + "//source/common/common:assert_lib", + ], +) diff --git a/include/envoy/common/lower_case_string.h b/include/envoy/common/lower_case_string.h new file mode 100644 index 0000000000000..a3e103feaf3e6 --- /dev/null +++ b/include/envoy/common/lower_case_string.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +#include "envoy/http/valid_header.h" + +#include "common/common/assert.h" + +#include "absl/strings/ascii.h" +#include "absl/strings/string_view.h" + +namespace Envoy { + +/* + * Simple function pointer to validate lower case string. There is currently no need to use + * std::function. + */ +using LowerCaseStringValidator = bool (*)(absl::string_view); + +/** + * Wrapper for a lower case string used in header operations to generally avoid needless case + * insensitive compares. + */ +class LowerCaseString { +public: + LowerCaseString(LowerCaseString&& rhs, + LowerCaseStringValidator valid = Http::validHeaderString) noexcept + : string_(std::move(rhs.string_)) { + ASSERT(valid != nullptr ? valid(string_) : true); + } + LowerCaseString& operator=(LowerCaseString&& rhs) noexcept { + string_ = std::move(rhs.string_); + return *this; + } + + LowerCaseString(const LowerCaseString& rhs, + LowerCaseStringValidator valid = Http::validHeaderString) + : string_(rhs.string_) { + ASSERT(valid != nullptr ? valid(string_) : true); + } + LowerCaseString& operator=(const LowerCaseString& rhs) { + string_ = rhs.string_; + return *this; + } + + explicit LowerCaseString(absl::string_view new_string, + LowerCaseStringValidator valid = Http::validHeaderString) + : string_(new_string) { + ASSERT(valid != nullptr ? valid(string_) : true); + lower(); + } + + const std::string& get() const { return string_; } + bool operator==(const LowerCaseString& rhs) const { return string_ == rhs.string_; } + bool operator!=(const LowerCaseString& rhs) const { return string_ != rhs.string_; } + bool operator<(const LowerCaseString& rhs) const { return string_.compare(rhs.string_) < 0; } + + friend std::ostream& operator<<(std::ostream& os, const LowerCaseString& lower_case_string) { + return os << lower_case_string.string_; + } + +private: + void lower() { + std::transform(string_.begin(), string_.end(), string_.begin(), absl::ascii_tolower); + } + + std::string string_; +}; + +/** + * Convenient type for a vector of lower case string and string pair. + */ +using LowerCaseStrPairVector = std::vector>; + +} // namespace Envoy diff --git a/include/envoy/http/BUILD b/include/envoy/http/BUILD index 0e41b02ffd76f..657f2289d2017 100644 --- a/include/envoy/http/BUILD +++ b/include/envoy/http/BUILD @@ -105,6 +105,9 @@ envoy_cc_library( ], deps = [ ":header_formatter_interface", + ":valid_header", + "//include/envoy/common:lower_case_string", + "//include/envoy/tracing:trace_context_interface", "//source/common/common:assert_lib", "//source/common/common:hash_lib", ], @@ -151,3 +154,8 @@ envoy_cc_library( "//include/envoy/config:typed_config_interface", ], ) + +envoy_cc_library( + name = "valid_header", + hdrs = ["valid_header.h"], +) diff --git a/include/envoy/http/header_map.h b/include/envoy/http/header_map.h index 2567a95b6935f..a3d0fc1e908b2 100644 --- a/include/envoy/http/header_map.h +++ b/include/envoy/http/header_map.h @@ -8,9 +8,12 @@ #include #include +#include "envoy/common/lower_case_string.h" #include "envoy/common/optref.h" #include "envoy/common/pure.h" #include "envoy/http/header_formatter.h" +#include "envoy/http/valid_header.h" +#include "envoy/tracing/trace_context.h" #include "common/common/assert.h" #include "common/common/hash.h" @@ -22,76 +25,8 @@ namespace Envoy { namespace Http { -// Used by ASSERTs to validate internal consistency. E.g. valid HTTP header keys/values should -// never contain embedded NULLs. -static inline bool validHeaderString(absl::string_view s) { - // If you modify this list of illegal embedded characters you will probably - // want to change header_map_fuzz_impl_test at the same time. - for (const char c : s) { - switch (c) { - case '\0': - FALLTHRU; - case '\r': - FALLTHRU; - case '\n': - return false; - default: - continue; - } - } - return true; -} - -/** - * Wrapper for a lower case string used in header operations to generally avoid needless case - * insensitive compares. - */ -class LowerCaseString { -public: - LowerCaseString(LowerCaseString&& rhs) noexcept : string_(std::move(rhs.string_)) { - ASSERT(valid()); - } - LowerCaseString& operator=(LowerCaseString&& rhs) noexcept { - string_ = std::move(rhs.string_); - ASSERT(valid()); - return *this; - } - - LowerCaseString(const LowerCaseString& rhs) : string_(rhs.string_) { ASSERT(valid()); } - LowerCaseString& operator=(const LowerCaseString& rhs) { - string_ = std::move(rhs.string_); - ASSERT(valid()); - return *this; - } - - explicit LowerCaseString(const std::string& new_string) : string_(new_string) { - ASSERT(valid()); - lower(); - } - - const std::string& get() const { return string_; } - bool operator==(const LowerCaseString& rhs) const { return string_ == rhs.string_; } - bool operator!=(const LowerCaseString& rhs) const { return string_ != rhs.string_; } - bool operator<(const LowerCaseString& rhs) const { return string_.compare(rhs.string_) < 0; } - - friend std::ostream& operator<<(std::ostream& os, const LowerCaseString& lower_case_string) { - return os << lower_case_string.string_; - } - -private: - void lower() { - std::transform(string_.begin(), string_.end(), string_.begin(), absl::ascii_tolower); - } - bool valid() const { return validHeaderString(string_); } - - std::string string_; -}; - -/** - * Convenient type for a vector of lower case string and string pair. - */ -using LowerCaseStrPairVector = - std::vector>; +using LowerCaseString = Envoy::LowerCaseString; +using LowerCaseStrPairVector = Envoy::LowerCaseStrPairVector; /** * Convenient type for an inline vector that will be used by HeaderString. @@ -817,7 +752,8 @@ class RequestOrResponseHeaderMap : public HeaderMap { // Request headers. class RequestHeaderMap : public RequestOrResponseHeaderMap, - public CustomInlineHeaderBase { + public CustomInlineHeaderBase, + public Tracing::TraceContext { public: INLINE_REQ_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER) INLINE_REQ_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER) diff --git a/include/envoy/http/valid_header.h b/include/envoy/http/valid_header.h new file mode 100644 index 0000000000000..898f8c8298585 --- /dev/null +++ b/include/envoy/http/valid_header.h @@ -0,0 +1,31 @@ +#pragma once + +#include "common/common/macros.h" + +#include "absl/strings/string_view.h" + +namespace Envoy { +namespace Http { + +// Used by ASSERTs to validate internal consistency. E.g. valid HTTP header keys/values should +// never contain embedded NULLs. +static inline bool validHeaderString(absl::string_view s) { + // If you modify this list of illegal embedded characters you will probably + // want to change header_map_fuzz_impl_test at the same time. + for (const char c : s) { + switch (c) { + case '\0': + FALLTHRU; + case '\r': + FALLTHRU; + case '\n': + return false; + default: + continue; + } + } + return true; +} + +} // namespace Http +} // namespace Envoy diff --git a/include/envoy/server/tracer_config.h b/include/envoy/server/tracer_config.h index 25f8b664d9491..4af4caf45bc9a 100644 --- a/include/envoy/server/tracer_config.h +++ b/include/envoy/server/tracer_config.h @@ -41,13 +41,13 @@ class TracerFactory : public Config::TypedFactory { ~TracerFactory() override = default; /** - * Create a particular HttpTracer implementation. If the implementation is unable to produce an - * HttpTracer with the provided parameters, it should throw an EnvoyException in the case of - * general error or a Json::Exception if the json configuration is erroneous. The returned + * Create a particular trace driver implementation. If the implementation is unable to produce + * a trace driver with the provided parameters, it should throw an EnvoyException in the case + * of general error or a Json::Exception if the json configuration is erroneous. The returned * pointer should always be valid. * * NOTE: Due to the corner case of OpenCensus, who can only support a single tracing - * configuration per entire process, the returned HttpTracer instance is not guaranteed + * configuration per entire process, the returned Driver instance is not guaranteed * to be unique. * That is why the return type has been changed to std::shared_ptr<> instead of a more * idiomatic std::unique_ptr<>. @@ -55,8 +55,8 @@ class TracerFactory : public Config::TypedFactory { * @param config supplies the proto configuration for the HttpTracer * @param context supplies the factory context */ - virtual Tracing::HttpTracerSharedPtr createHttpTracer(const Protobuf::Message& config, - TracerFactoryContext& context) PURE; + virtual Tracing::DriverSharedPtr createTracerDriver(const Protobuf::Message& config, + TracerFactoryContext& context) PURE; std::string category() const override { return "envoy.tracers"; } }; diff --git a/include/envoy/tracing/BUILD b/include/envoy/tracing/BUILD index cd539650e0ea2..8f14b0b428342 100644 --- a/include/envoy/tracing/BUILD +++ b/include/envoy/tracing/BUILD @@ -8,12 +8,26 @@ licenses(["notice"]) # Apache 2 envoy_package() +envoy_cc_library( + name = "trace_context_interface", + hdrs = ["trace_context.h"], +) + +envoy_cc_library( + name = "trace_driver_interface", + hdrs = ["trace_driver.h"], + deps = [ + ":trace_context_interface", + ":trace_reason_interface", + "//include/envoy/stream_info:stream_info_interface", + ], +) + envoy_cc_library( name = "http_tracer_interface", hdrs = ["http_tracer.h"], deps = [ - ":trace_reason_interface", - "//include/envoy/access_log:access_log_interface", + ":trace_driver_interface", "//include/envoy/http:header_map_interface", ], ) diff --git a/include/envoy/tracing/http_tracer.h b/include/envoy/tracing/http_tracer.h index bfc29d370291f..052c53cbe0df6 100644 --- a/include/envoy/tracing/http_tracer.h +++ b/include/envoy/tracing/http_tracer.h @@ -4,180 +4,12 @@ #include #include -#include "envoy/access_log/access_log.h" -#include "envoy/common/pure.h" #include "envoy/http/header_map.h" -#include "envoy/tracing/trace_reason.h" +#include "envoy/tracing/trace_driver.h" namespace Envoy { namespace Tracing { -class Span; -using SpanPtr = std::unique_ptr; - -constexpr uint32_t DefaultMaxPathTagLength = 256; - -enum class OperationName { Ingress, Egress }; - -/** - * The context for the custom tag to obtain the tag value. - */ -struct CustomTagContext { - const Http::RequestHeaderMap* request_headers; - const StreamInfo::StreamInfo& stream_info; -}; - -/** - * Tracing custom tag, with tag name and how it would be applied to the span. - */ -class CustomTag { -public: - virtual ~CustomTag() = default; - - /** - * @return the tag name view. - */ - virtual absl::string_view tag() const PURE; - - /** - * The way how to apply the custom tag to the span, - * generally obtain the tag value from the context and attached it to the span. - * @param span the active span. - * @param ctx the custom tag context. - */ - virtual void apply(Span& span, const CustomTagContext& ctx) const PURE; -}; - -using CustomTagConstSharedPtr = std::shared_ptr; -using CustomTagMap = absl::flat_hash_map; - -/** - * Tracing configuration, it carries additional data needed to populate the span. - */ -class Config { -public: - virtual ~Config() = default; - - /** - * @return operation name for tracing, e.g., ingress. - */ - virtual OperationName operationName() const PURE; - - /** - * @return custom tags to be attached to the active span. - */ - virtual const CustomTagMap* customTags() const PURE; - - /** - * @return true if spans should be annotated with more detailed information. - */ - virtual bool verbose() const PURE; - - /** - * @return the maximum length allowed for paths in the extracted HttpUrl tag. - */ - virtual uint32_t maxPathTagLength() const PURE; -}; - -/** - * Basic abstraction for span. - */ -class Span { -public: - virtual ~Span() = default; - - /** - * Set the operation name. - * @param operation the operation name - */ - virtual void setOperation(absl::string_view operation) PURE; - - /** - * Attach metadata to a Span, to be handled in an implementation-dependent fashion. - * @param name the name of the tag - * @param value the value to associate with the tag - */ - virtual void setTag(absl::string_view name, absl::string_view value) PURE; - - /** - * Record an event associated with a span, to be handled in an implementation-dependent fashion. - * @param timestamp the time of the event. - * @param event the name of the event. - */ - virtual void log(SystemTime timestamp, const std::string& event) PURE; - - /** - * Capture the final duration for this Span and carry out any work necessary to complete it. - * Once this method is called, the Span may be safely discarded. - */ - virtual void finishSpan() PURE; - - /** - * Mutate the provided headers with the context necessary to propagate this - * (implementation-specific) trace. - * @param request_headers the headers to which propagation context will be added - */ - virtual void injectContext(Http::RequestHeaderMap& request_headers) PURE; - - /** - * Create and start a child Span, with this Span as its parent in the trace. - * @param config the tracing configuration - * @param name operation name captured by the spawned child - * @param start_time initial start time for the operation captured by the child - */ - virtual SpanPtr spawnChild(const Config& config, const std::string& name, - SystemTime start_time) PURE; - - /** - * This method overrides any previous sampling decision associated with the trace instance. - * If the sampled parameter is false, this span and any subsequent child spans - * are not reported to the tracing system. - * @param sampled whether the span and any subsequent child spans should be sampled - */ - virtual void setSampled(bool sampled) PURE; - - /** - * Retrieve a key's value from the span's baggage. - * This baggage data could've been set by this span or any parent spans. - * @param key baggage key - * @return the baggage's value for the given input key - */ - virtual std::string getBaggage(absl::string_view key) PURE; - - /** - * Set a key/value pair in the current span's baggage. - * All subsequent child spans will have access to this baggage. - * @param key baggage key - * @param key baggage value - */ - virtual void setBaggage(absl::string_view key, absl::string_view value) PURE; - - /** - * Retrieve the trace ID associated with this span. - * The trace id may be generated for this span, propagated by parent spans, or - * not created yet. - * @return trace ID as a hex string - */ - virtual std::string getTraceIdAsHex() const PURE; -}; - -/** - * Tracing driver is responsible for span creation. - */ -class Driver { -public: - virtual ~Driver() = default; - - /** - * Start driver specific span. - */ - virtual SpanPtr startSpan(const Config& config, Http::RequestHeaderMap& request_headers, - const std::string& operation_name, SystemTime start_time, - const Tracing::Decision tracing_decision) PURE; -}; - -using DriverPtr = std::unique_ptr; - /** * HttpTracer is responsible for handling traces and delegate actions to the * corresponding drivers. diff --git a/include/envoy/tracing/trace_context.h b/include/envoy/tracing/trace_context.h new file mode 100644 index 0000000000000..e9dd49fb1ba76 --- /dev/null +++ b/include/envoy/tracing/trace_context.h @@ -0,0 +1,61 @@ +#pragma once + +#include + +#include "envoy/common/lower_case_string.h" +#include "envoy/common/pure.h" + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +namespace Envoy { +namespace Tracing { + +/** + * Protocol-independent abstraction for traceable stream. It hides the differences between different + * protocol requests and provides Tracer Driver with common methods for obtaining and setting the + * Tracing context. + */ +class TraceContext { +public: + virtual ~TraceContext() = default; + + /** + * Get tracing context value by key. + * + * @param key The context key of string view type. + * @return The optional context value of string_view type. + */ + virtual absl::optional getTraceContext(absl::string_view key) const PURE; + + /** + * Set new tracing context key/value pair. + * + * @param key The context key of string view type. + * @param value The context value of string view type. + */ + virtual void setTraceContext(absl::string_view key, absl::string_view value) PURE; + + /** + * Get tracing context value by case-insensitive key. + * + * @param key The case-insensitive context key. + * @return The optional context value of string_view type. + */ + virtual absl::optional getTraceContext(const LowerCaseString& key) const { + return getTraceContext(key.get()); + } + + /** + * Set new tracing context key/value pair. + * + * @param key The case-insensitive context key. + * @param value The context value of string view type. + */ + virtual void setTraceContext(const LowerCaseString& key, absl::string_view value) { + setTraceContext(key.get(), value); + } +}; + +} // namespace Tracing +} // namespace Envoy diff --git a/include/envoy/tracing/trace_driver.h b/include/envoy/tracing/trace_driver.h new file mode 100644 index 0000000000000..94c9ef4f6aa16 --- /dev/null +++ b/include/envoy/tracing/trace_driver.h @@ -0,0 +1,185 @@ +#pragma once + +#include +#include +#include + +#include "envoy/common/pure.h" +#include "envoy/http/header_map.h" +#include "envoy/stream_info/stream_info.h" +#include "envoy/tracing/trace_context.h" +#include "envoy/tracing/trace_reason.h" + +namespace Envoy { +namespace Tracing { + +class Span; +using SpanPtr = std::unique_ptr; + +constexpr uint32_t DefaultMaxPathTagLength = 256; + +enum class OperationName { Ingress, Egress }; + +/** + * The context for the custom tag to obtain the tag value. + */ +struct CustomTagContext { + const TraceContext* tracing_context; + const StreamInfo::StreamInfo* stream_info; +}; + +/** + * Tracing custom tag, with tag name and how it would be applied to the span. + */ +class CustomTag { +public: + virtual ~CustomTag() = default; + + /** + * @return the tag name view. + */ + virtual absl::string_view tag() const PURE; + + /** + * The way how to apply the custom tag to the span, + * generally obtain the tag value from the context and attached it to the span. + * @param span the active span. + * @param ctx the custom tag context. + */ + virtual void apply(Span& span, const CustomTagContext& ctx) const PURE; +}; + +using CustomTagConstSharedPtr = std::shared_ptr; +using CustomTagMap = absl::flat_hash_map; + +/** + * Tracing configuration, it carries additional data needed to populate the span. + */ +class Config { +public: + virtual ~Config() = default; + + /** + * @return operation name for tracing, e.g., ingress. + */ + virtual OperationName operationName() const PURE; + + /** + * @return custom tags to be attached to the active span. + */ + virtual const CustomTagMap* customTags() const PURE; + + /** + * @return true if spans should be annotated with more detailed information. + */ + virtual bool verbose() const PURE; + + /** + * @return the maximum length allowed for paths in the extracted HttpUrl tag. This is only used + * for HTTP protocol tracing. + */ + virtual uint32_t maxPathTagLength() const PURE; +}; + +/** + * Basic abstraction for span. + */ +class Span { +public: + virtual ~Span() = default; + + /** + * Set the operation name. + * @param operation the operation name + */ + virtual void setOperation(absl::string_view operation) PURE; + + /** + * Attach metadata to a Span, to be handled in an implementation-dependent fashion. + * @param name the name of the tag + * @param value the value to associate with the tag + */ + virtual void setTag(absl::string_view name, absl::string_view value) PURE; + + /** + * Record an event associated with a span, to be handled in an implementation-dependent fashion. + * @param timestamp the time of the event. + * @param event the name of the event. + */ + virtual void log(SystemTime timestamp, const std::string& event) PURE; + + /** + * Capture the final duration for this Span and carry out any work necessary to complete it. + * Once this method is called, the Span may be safely discarded. + */ + virtual void finishSpan() PURE; + + /** + * Mutate the provided tracing context with the context necessary to propagate this + * (implementation-specific) trace. + * @param tracing_context the tracing context to which propagation context will be added + */ + virtual void injectContext(TraceContext& tracing_context) PURE; + + /** + * Create and start a child Span, with this Span as its parent in the trace. + * @param config the tracing configuration + * @param name operation name captured by the spawned child + * @param start_time initial start time for the operation captured by the child + */ + virtual SpanPtr spawnChild(const Config& config, const std::string& name, + SystemTime start_time) PURE; + + /** + * This method overrides any previous sampling decision associated with the trace instance. + * If the sampled parameter is false, this span and any subsequent child spans + * are not reported to the tracing system. + * @param sampled whether the span and any subsequent child spans should be sampled + */ + virtual void setSampled(bool sampled) PURE; + + /** + * Retrieve a key's value from the span's baggage. + * This baggage data could've been set by this span or any parent spans. + * @param key baggage key + * @return the baggage's value for the given input key + */ + virtual std::string getBaggage(absl::string_view key) PURE; + + /** + * Set a key/value pair in the current span's baggage. + * All subsequent child spans will have access to this baggage. + * @param key baggage key + * @param key baggage value + */ + virtual void setBaggage(absl::string_view key, absl::string_view value) PURE; + + /** + * Retrieve the trace ID associated with this span. + * The trace id may be generated for this span, propagated by parent spans, or + * not created yet. + * @return trace ID as a hex string + */ + virtual std::string getTraceIdAsHex() const PURE; +}; + +/** + * Tracing driver is responsible for span creation. + */ +class Driver { +public: + virtual ~Driver() = default; + + /** + * Start driver specific span. + */ + virtual SpanPtr startSpan(const Config& config, TraceContext& tracing_context, + const std::string& operation_name, SystemTime start_time, + const Tracing::Decision tracing_decision) PURE; +}; + +using DriverPtr = std::unique_ptr; +using DriverSharedPtr = std::shared_ptr; + +} // namespace Tracing +} // namespace Envoy diff --git a/source/common/http/header_map_impl.cc b/source/common/http/header_map_impl.cc index cc83f950e7d27..544d50261023d 100644 --- a/source/common/http/header_map_impl.cc +++ b/source/common/http/header_map_impl.cc @@ -426,7 +426,7 @@ void HeaderMapImpl::addCopy(const LowerCaseString& key, absl::string_view value) void HeaderMapImpl::appendCopy(const LowerCaseString& key, absl::string_view value) { // TODO(#9221): converge on and document a policy for coalescing multiple headers. - auto entry = getExisting(key); + auto entry = getExisting(key.get()); if (!entry.empty()) { const std::string delimiter = (key == Http::Headers::get().Cookie ? "; " : ","); const uint64_t added_size = header_map_correctly_coalesce_cookies_ @@ -466,16 +466,16 @@ void HeaderMapImpl::verifyByteSizeInternalForTest() const { } HeaderMap::GetResult HeaderMapImpl::get(const LowerCaseString& key) const { - return HeaderMap::GetResult(const_cast(this)->getExisting(key)); + return HeaderMap::GetResult(const_cast(this)->getExisting(key.get())); } -HeaderMap::NonConstGetResult HeaderMapImpl::getExisting(const LowerCaseString& key) { +HeaderMap::NonConstGetResult HeaderMapImpl::getExisting(absl::string_view key) { // Attempt a trie lookup first to see if the user is requesting an O(1) header. This may be // relatively common in certain header matching / routing patterns. // TODO(mattklein123): Add inline handle support directly to the header matcher code to support // this use case more directly. HeaderMap::NonConstGetResult ret; - auto lookup = staticLookup(key.get()); + auto lookup = staticLookup(key); if (lookup.has_value()) { if (*lookup.value().entry_ != nullptr) { ret.push_back(*lookup.value().entry_); @@ -486,7 +486,7 @@ HeaderMap::NonConstGetResult HeaderMapImpl::getExisting(const LowerCaseString& k // If the requested header is not an O(1) header try using the lazy map to // search for it instead of iterating the headers list. if (headers_.maybeMakeMap()) { - HeaderList::HeaderLazyMap::iterator iter = headers_.mapFind(key.get()); + HeaderList::HeaderLazyMap::iterator iter = headers_.mapFind(key); if (iter != headers_.mapEnd()) { const HeaderList::HeaderNodeVector& v = iter->second; ASSERT(!v.empty()); // It's impossible to have a map entry with an empty vector as its value. @@ -502,7 +502,7 @@ HeaderMap::NonConstGetResult HeaderMapImpl::getExisting(const LowerCaseString& k // scan. Doing the trie lookup is wasteful in the miss case, but is present for code consistency // with other functions that do similar things. for (HeaderEntryImpl& header : headers_) { - if (header.key() == key.get().c_str()) { + if (header.key() == key) { ret.push_back(&header); } } @@ -556,16 +556,7 @@ size_t HeaderMapImpl::removeIf(const HeaderMap::HeaderMatchPredicate& predicate) return old_size - headers_.size(); } -size_t HeaderMapImpl::remove(const LowerCaseString& key) { - const size_t old_size = headers_.size(); - auto lookup = staticLookup(key.get()); - if (lookup.has_value()) { - removeInline(lookup.value().entry_); - } else { - subtractSize(headers_.remove(key.get())); - } - return old_size - headers_.size(); -} +size_t HeaderMapImpl::remove(const LowerCaseString& key) { return remove(key.get()); } size_t HeaderMapImpl::removePrefix(const LowerCaseString& prefix) { return HeaderMapImpl::removeIf([&prefix](const HeaderEntry& entry) -> bool { @@ -610,6 +601,17 @@ HeaderMapImpl::HeaderEntryImpl& HeaderMapImpl::maybeCreateInline(HeaderEntryImpl return **entry; } +size_t HeaderMapImpl::remove(absl::string_view key) { + const size_t old_size = headers_.size(); + auto lookup = staticLookup(key); + if (lookup.has_value()) { + removeInline(lookup.value().entry_); + } else { + subtractSize(headers_.remove(key)); + } + return old_size - headers_.size(); +} + size_t HeaderMapImpl::removeInline(HeaderEntryImpl** ptr_to_entry) { if (!*ptr_to_entry) { return 0; diff --git a/source/common/http/header_map_impl.h b/source/common/http/header_map_impl.h index 2f52e70c66691..3abb0b3eaeed8 100644 --- a/source/common/http/header_map_impl.h +++ b/source/common/http/header_map_impl.h @@ -322,7 +322,8 @@ class HeaderMapImpl : NonCopyable { HeaderEntryImpl& maybeCreateInline(HeaderEntryImpl** entry, const LowerCaseString& key); HeaderEntryImpl& maybeCreateInline(HeaderEntryImpl** entry, const LowerCaseString& key, HeaderString&& value); - HeaderMap::NonConstGetResult getExisting(const LowerCaseString& key); + HeaderMap::NonConstGetResult getExisting(absl::string_view key); + size_t remove(absl::string_view key); size_t removeInline(HeaderEntryImpl** entry); void updateSize(uint64_t from_size, uint64_t to_size); void addSize(uint64_t size); @@ -480,6 +481,27 @@ class RequestHeaderMapImpl final : public TypedHeaderMapImpl, INLINE_REQ_RESP_STRING_HEADERS(DEFINE_INLINE_HEADER_STRING_FUNCS) INLINE_REQ_RESP_NUMERIC_HEADERS(DEFINE_INLINE_HEADER_NUMERIC_FUNCS) + absl::optional getTraceContext(absl::string_view key) const override { + return getTraceContext(LowerCaseString(key)); + } + + void setTraceContext(absl::string_view key, absl::string_view value) override { + Http::LowerCaseString low_case_key{key}; + setCopy(low_case_key, value); + } + + absl::optional getTraceContext(const LowerCaseString& key) const override { + auto result = get(key); + if (!result.empty()) { + return result[0]->value().getStringView(); + } + return absl::nullopt; + } + + void setTraceContext(const LowerCaseString& key, absl::string_view value) override { + setReferenceKey(key, value); + } + protected: // NOTE: Because inline_headers_ is a variable size member, it must be the last member in the // most derived class. This forces the definition of the following three functions to also be diff --git a/source/common/tracing/BUILD b/source/common/tracing/BUILD index ef703c964a904..8dce4bdd7b64f 100644 --- a/source/common/tracing/BUILD +++ b/source/common/tracing/BUILD @@ -8,6 +8,27 @@ licenses(["notice"]) # Apache 2 envoy_package() +envoy_cc_library( + name = "null_span_lib", + hdrs = [ + "null_span_impl.h", + ], + deps = [ + "//include/envoy/tracing:trace_driver_interface", + "//source/common/common:empty_string", + ], +) + +envoy_cc_library( + name = "common_values_lib", + hdrs = [ + "common_values.h", + ], + deps = [ + "//source/common/singleton:const_singleton", + ], +) + envoy_cc_library( name = "http_tracer_lib", srcs = [ @@ -17,6 +38,8 @@ envoy_cc_library( "http_tracer_impl.h", ], deps = [ + ":common_values_lib", + ":null_span_lib", "//include/envoy/http:request_id_extension_interface", "//include/envoy/local_info:local_info_interface", "//include/envoy/runtime:runtime_interface", @@ -45,9 +68,9 @@ envoy_cc_library( ) envoy_cc_library( - name = "http_tracer_config_lib", + name = "tracer_config_lib", hdrs = [ - "http_tracer_config_impl.h", + "tracer_config_impl.h", ], deps = [ "//include/envoy/server:tracer_config_interface", diff --git a/source/common/tracing/common_values.h b/source/common/tracing/common_values.h new file mode 100644 index 0000000000000..41cb3947772f4 --- /dev/null +++ b/source/common/tracing/common_values.h @@ -0,0 +1,84 @@ +#pragma once + +#include + +#include "common/singleton/const_singleton.h" + +namespace Envoy { +namespace Tracing { + +/** + * 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 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"; + + // 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"; + + // Tag values. + const std::string Canceled = "canceled"; + const std::string Proxy = "proxy"; + const std::string True = "true"; +}; + +using Tags = ConstSingleton; + +class TracingLogValues { +public: + // OpenTracing standard key names. + const std::string EventKey = "event"; + + // Event names + const std::string LastDownstreamRxByteReceived = "last_downstream_rx_byte_received"; + const std::string FirstUpstreamTxByteSent = "first_upstream_tx_byte_sent"; + const std::string LastUpstreamTxByteSent = "last_upstream_tx_byte_sent"; + const std::string FirstUpstreamRxByteReceived = "first_upstream_rx_byte_received"; + const std::string LastUpstreamRxByteReceived = "last_upstream_rx_byte_received"; + const std::string FirstDownstreamTxByteSent = "first_downstream_tx_byte_sent"; + const std::string LastDownstreamTxByteSent = "last_downstream_tx_byte_sent"; +}; + +using Logs = ConstSingleton; + +} // namespace Tracing +} // namespace Envoy diff --git a/source/common/tracing/http_tracer_impl.cc b/source/common/tracing/http_tracer_impl.cc index 32c3a5224aa50..cc32ce09064a3 100644 --- a/source/common/tracing/http_tracer_impl.cc +++ b/source/common/tracing/http_tracer_impl.cc @@ -187,7 +187,7 @@ void HttpTracerUtility::finalizeDownstreamSpan(Span& span, addGrpcRequestTags(span, *request_headers); } } - CustomTagContext ctx{request_headers, stream_info}; + CustomTagContext ctx{request_headers, &stream_info}; const CustomTagMap* custom_tag_map = tracing_config.customTags(); if (custom_tag_map) { @@ -272,7 +272,7 @@ HttpTracerUtility::createCustomTag(const envoy::type::tracing::v3::CustomTag& ta } } -HttpTracerImpl::HttpTracerImpl(DriverPtr&& driver, const LocalInfo::LocalInfo& local_info) +HttpTracerImpl::HttpTracerImpl(DriverSharedPtr driver, const LocalInfo::LocalInfo& local_info) : driver_(std::move(driver)), local_info_(local_info) {} SpanPtr HttpTracerImpl::startSpan(const Config& config, Http::RequestHeaderMap& request_headers, @@ -317,12 +317,12 @@ RequestHeaderCustomTag::RequestHeaderCustomTag( default_value_(request_header.default_value()) {} absl::string_view RequestHeaderCustomTag::value(const CustomTagContext& ctx) const { - if (!ctx.request_headers) { + if (ctx.tracing_context == nullptr) { return default_value_; } // TODO(https://github.com/envoyproxy/envoy/issues/13454): Potentially populate all header values. - const auto entry = ctx.request_headers->get(name_); - return !entry.empty() ? entry[0]->value().getStringView() : default_value_; + const auto result = ctx.tracing_context->getTraceContext(name_.get()); + return result.has_value() ? result.value() : default_value_; } MetadataCustomTag::MetadataCustomTag(const std::string& tag, @@ -365,7 +365,11 @@ void MetadataCustomTag::apply(Span& span, const CustomTagContext& ctx) const { const envoy::config::core::v3::Metadata* MetadataCustomTag::metadata(const CustomTagContext& ctx) const { - const StreamInfo::StreamInfo& info = ctx.stream_info; + if (ctx.stream_info == nullptr) { + return nullptr; + } + const StreamInfo::StreamInfo& info = *ctx.stream_info; + switch (kind_) { case envoy::type::metadata::v3::MetadataKind::KindCase::kRequest: return &info.dynamicMetadata(); diff --git a/source/common/tracing/http_tracer_impl.h b/source/common/tracing/http_tracer_impl.h index 58950449adc2d..4c3b733ab0904 100644 --- a/source/common/tracing/http_tracer_impl.h +++ b/source/common/tracing/http_tracer_impl.h @@ -13,87 +13,15 @@ #include "envoy/type/tracing/v3/custom_tag.pb.h" #include "envoy/upstream/cluster_manager.h" -#include "common/common/empty_string.h" #include "common/config/metadata.h" #include "common/http/header_map_impl.h" #include "common/json/json_loader.h" +#include "common/tracing/common_values.h" +#include "common/tracing/null_span_impl.h" namespace Envoy { namespace Tracing { -/** - * 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 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"; - - // 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"; - - // Tag values. - const std::string Canceled = "canceled"; - const std::string Proxy = "proxy"; - const std::string True = "true"; -}; - -using Tags = ConstSingleton; - -class TracingLogValues { -public: - // OpenTracing standard key names. - const std::string EventKey = "event"; - - // Event names - const std::string LastDownstreamRxByteReceived = "last_downstream_rx_byte_received"; - const std::string FirstUpstreamTxByteSent = "first_upstream_tx_byte_sent"; - const std::string LastUpstreamTxByteSent = "last_upstream_tx_byte_sent"; - const std::string FirstUpstreamRxByteReceived = "first_upstream_rx_byte_received"; - const std::string LastUpstreamRxByteReceived = "last_upstream_rx_byte_received"; - const std::string FirstDownstreamTxByteSent = "first_downstream_tx_byte_sent"; - const std::string LastDownstreamTxByteSent = "last_downstream_tx_byte_sent"; -}; - -using Logs = ConstSingleton; - class HttpTracerUtility { public: /** @@ -157,28 +85,6 @@ class EgressConfigImpl : public Config { using EgressConfig = ConstSingleton; -class NullSpan : public Span { -public: - static NullSpan& instance() { - static NullSpan* instance = new NullSpan(); - return *instance; - } - - // Tracing::Span - void setOperation(absl::string_view) override {} - void setTag(absl::string_view, absl::string_view) override {} - void log(SystemTime, const std::string&) override {} - void finishSpan() override {} - void injectContext(Http::RequestHeaderMap&) override {} - void setBaggage(absl::string_view, absl::string_view) override {} - std::string getBaggage(absl::string_view) override { return EMPTY_STRING; } - std::string getTraceIdAsHex() const override { return EMPTY_STRING; } - SpanPtr spawnChild(const Config&, const std::string&, SystemTime) override { - return SpanPtr{new NullSpan()}; - } - void setSampled(bool) override {} -}; - class HttpNullTracer : public HttpTracer { public: // Tracing::HttpTracer @@ -190,15 +96,17 @@ class HttpNullTracer : public HttpTracer { class HttpTracerImpl : public HttpTracer { public: - HttpTracerImpl(DriverPtr&& driver, const LocalInfo::LocalInfo& local_info); + HttpTracerImpl(DriverSharedPtr driver, const LocalInfo::LocalInfo& local_info); // Tracing::HttpTracer SpanPtr startSpan(const Config& config, Http::RequestHeaderMap& request_headers, const StreamInfo::StreamInfo& stream_info, const Tracing::Decision tracing_decision) override; + DriverSharedPtr driverForTest() const { return driver_; } + private: - DriverPtr driver_; + DriverSharedPtr driver_; const LocalInfo::LocalInfo& local_info_; }; diff --git a/source/common/tracing/http_tracer_manager_impl.cc b/source/common/tracing/http_tracer_manager_impl.cc index 125e2a4e4e8bf..e25f5d99ba2d9 100644 --- a/source/common/tracing/http_tracer_manager_impl.cc +++ b/source/common/tracing/http_tracer_manager_impl.cc @@ -46,7 +46,9 @@ HttpTracerManagerImpl::getOrCreateHttpTracer(const envoy::config::trace::v3::Tra ProtobufTypes::MessagePtr message = Envoy::Config::Utility::translateToFactoryConfig( *config, factory_context_->messageValidationVisitor(), factory); - HttpTracerSharedPtr http_tracer = factory.createHttpTracer(*message, *factory_context_); + HttpTracerSharedPtr http_tracer = std::make_shared( + factory.createTracerDriver(*message, *factory_context_), + factory_context_->serverFactoryContext().localInfo()); http_tracers_.emplace(cache_key, http_tracer); // cache a weak reference return http_tracer; } diff --git a/source/common/tracing/null_span_impl.h b/source/common/tracing/null_span_impl.h new file mode 100644 index 0000000000000..5590d7c40d19a --- /dev/null +++ b/source/common/tracing/null_span_impl.h @@ -0,0 +1,36 @@ +#pragma once + +#include "envoy/tracing/trace_driver.h" + +#include "common/common/empty_string.h" + +namespace Envoy { +namespace Tracing { + +/** + * Null implementation of Span. + */ +class NullSpan : public Span { +public: + static NullSpan& instance() { + static NullSpan* instance = new NullSpan(); + return *instance; + } + + // Tracing::Span + void setOperation(absl::string_view) override {} + void setTag(absl::string_view, absl::string_view) override {} + void log(SystemTime, const std::string&) override {} + void finishSpan() override {} + void injectContext(Tracing::TraceContext&) override {} + void setBaggage(absl::string_view, absl::string_view) override {} + std::string getBaggage(absl::string_view) override { return EMPTY_STRING; } + std::string getTraceIdAsHex() const override { return EMPTY_STRING; } + SpanPtr spawnChild(const Config&, const std::string&, SystemTime) override { + return SpanPtr{new NullSpan()}; + } + void setSampled(bool) override {} +}; + +} // namespace Tracing +} // namespace Envoy diff --git a/source/common/tracing/http_tracer_config_impl.h b/source/common/tracing/tracer_config_impl.h similarity index 100% rename from source/common/tracing/http_tracer_config_impl.h rename to source/common/tracing/tracer_config_impl.h diff --git a/source/extensions/filters/network/http_connection_manager/BUILD b/source/extensions/filters/network/http_connection_manager/BUILD index 590a4a10a44a3..8de34a6201527 100644 --- a/source/extensions/filters/network/http_connection_manager/BUILD +++ b/source/extensions/filters/network/http_connection_manager/BUILD @@ -51,7 +51,7 @@ envoy_cc_extension( "//source/common/router:rds_lib", "//source/common/router:scoped_rds_lib", "//source/common/runtime:runtime_lib", - "//source/common/tracing:http_tracer_config_lib", + "//source/common/tracing:tracer_config_lib", "//source/common/tracing:http_tracer_lib", "//source/common/tracing:http_tracer_manager_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", diff --git a/source/extensions/filters/network/http_connection_manager/config.cc b/source/extensions/filters/network/http_connection_manager/config.cc index 4b6b0ba70c64a..0d5529c817d8f 100644 --- a/source/extensions/filters/network/http_connection_manager/config.cc +++ b/source/extensions/filters/network/http_connection_manager/config.cc @@ -33,8 +33,8 @@ #include "common/router/rds_impl.h" #include "common/router/scoped_rds.h" #include "common/runtime/runtime_impl.h" -#include "common/tracing/http_tracer_config_impl.h" #include "common/tracing/http_tracer_manager_impl.h" +#include "common/tracing/tracer_config_impl.h" #ifdef ENVOY_ENABLE_QUIC #include "common/quic/codec_impl.h" diff --git a/source/extensions/tracers/common/factory_base.h b/source/extensions/tracers/common/factory_base.h index 03e45d7615595..b31d22c3c28cc 100644 --- a/source/extensions/tracers/common/factory_base.h +++ b/source/extensions/tracers/common/factory_base.h @@ -14,12 +14,12 @@ namespace Common { template class FactoryBase : public Server::Configuration::TracerFactory { public: // Server::Configuration::TracerFactory - Tracing::HttpTracerSharedPtr - createHttpTracer(const Protobuf::Message& config, - Server::Configuration::TracerFactoryContext& context) override { - return createHttpTracerTyped(MessageUtil::downcastAndValidate( - config, context.messageValidationVisitor()), - context); + Tracing::DriverSharedPtr + createTracerDriver(const Protobuf::Message& config, + Server::Configuration::TracerFactoryContext& context) override { + return createTracerDriverTyped(MessageUtil::downcastAndValidate( + config, context.messageValidationVisitor()), + context); } ProtobufTypes::MessagePtr createEmptyConfigProto() override { @@ -32,9 +32,9 @@ template class FactoryBase : public Server::Configuration::T FactoryBase(const std::string& name) : name_(name) {} private: - virtual Tracing::HttpTracerSharedPtr - createHttpTracerTyped(const ConfigProto& proto_config, - Server::Configuration::TracerFactoryContext& context) PURE; + virtual Tracing::DriverSharedPtr + createTracerDriverTyped(const ConfigProto& proto_config, + Server::Configuration::TracerFactoryContext& context) PURE; const std::string name_; }; diff --git a/source/extensions/tracers/common/ot/BUILD b/source/extensions/tracers/common/ot/BUILD index beced5b3f219e..c8b386d0c3c87 100644 --- a/source/extensions/tracers/common/ot/BUILD +++ b/source/extensions/tracers/common/ot/BUILD @@ -18,6 +18,15 @@ envoy_cc_library( ], external_deps = ["opentracing"], deps = [ - "//source/common/tracing:http_tracer_lib", + "//include/envoy/runtime:runtime_interface", + "//include/envoy/thread_local:thread_local_interface", + "//include/envoy/tracing:trace_driver_interface", + "//include/envoy/upstream:cluster_manager_interface", + "//source/common/common:base64_lib", + "//source/common/common:empty_string", + "//source/common/http:header_map_lib", + "//source/common/json:json_loader_lib", + "//source/common/tracing:common_values_lib", + "//source/common/tracing:null_span_lib", ], ) diff --git a/source/extensions/tracers/common/ot/opentracing_driver_impl.cc b/source/extensions/tracers/common/ot/opentracing_driver_impl.cc index 18bf1e828dcc1..b5a5bc8706aea 100644 --- a/source/extensions/tracers/common/ot/opentracing_driver_impl.cc +++ b/source/extensions/tracers/common/ot/opentracing_driver_impl.cc @@ -7,7 +7,7 @@ #include "common/common/assert.h" #include "common/common/base64.h" #include "common/common/utility.h" -#include "common/tracing/http_tracer_impl.h" +#include "common/http/header_map_impl.h" namespace Envoy { namespace Extensions { @@ -19,67 +19,44 @@ Http::RegisterCustomInlineHeader Set(opentracing::string_view key, opentracing::string_view value) const override { - Http::LowerCaseString lowercase_key{key}; - request_headers_.remove(lowercase_key); - request_headers_.addCopy(std::move(lowercase_key), {value.data(), value.size()}); + trace_context_.setTraceContext(absl::string_view(key.data(), key.length()), + absl::string_view(value.data(), value.length())); return {}; } private: - Http::HeaderMap& request_headers_; + Tracing::TraceContext& trace_context_; }; -class OpenTracingHTTPHeadersReader : public opentracing::HTTPHeadersReader { +class OpenTracingHeadersReader : public opentracing::HTTPHeadersReader { public: - explicit OpenTracingHTTPHeadersReader(const Http::RequestHeaderMap& request_headers) - : request_headers_(request_headers) {} - - using OpenTracingCb = std::function(opentracing::string_view, - opentracing::string_view)>; + explicit OpenTracingHeadersReader(const Tracing::TraceContext& trace_context) + : trace_context_(trace_context) {} // opentracing::HTTPHeadersReader opentracing::expected LookupKey(opentracing::string_view key) const override { - const auto entry = request_headers_.get(Http::LowerCaseString{key}); - if (!entry.empty()) { - // This is an implicitly untrusted header, so only the first value is used. - return opentracing::string_view{entry[0]->value().getStringView().data(), - entry[0]->value().getStringView().length()}; - } else { - return opentracing::make_unexpected(opentracing::key_not_found_error); + auto lookup = trace_context_.getTraceContext(absl::string_view(key.data(), key.length())); + if (lookup.has_value()) { + return opentracing::string_view{lookup.value().data(), lookup.value().length()}; } + return opentracing::make_unexpected(opentracing::key_not_found_error); } - opentracing::expected ForeachKey(OpenTracingCb f) const override { - request_headers_.iterate(headerMapCallback(f)); - return {}; - } + using OpenTracingCb = std::function(opentracing::string_view, + opentracing::string_view)>; + opentracing::expected ForeachKey(OpenTracingCb) const override { return {}; } private: - const Http::RequestHeaderMap& request_headers_; - - static Http::HeaderMap::ConstIterateCb headerMapCallback(OpenTracingCb callback) { - return [callback = - std::move(callback)](const Http::HeaderEntry& header) -> Http::HeaderMap::Iterate { - opentracing::string_view key{header.key().getStringView().data(), - header.key().getStringView().length()}; - opentracing::string_view value{header.value().getStringView().data(), - header.value().getStringView().length()}; - if (callback(key, value)) { - return Http::HeaderMap::Iterate::Continue; - } else { - return Http::HeaderMap::Iterate::Break; - } - }; - } + const Tracing::TraceContext& trace_context_; }; } // namespace @@ -111,7 +88,7 @@ std::string OpenTracingSpan::getBaggage(absl::string_view key) { return span_->BaggageItem({key.data(), key.length()}); } -void OpenTracingSpan::injectContext(Http::RequestHeaderMap& request_headers) { +void OpenTracingSpan::injectContext(Tracing::TraceContext& trace_context) { if (driver_.propagationMode() == OpenTracingDriver::PropagationMode::SingleHeader) { // Inject the span context using Envoy's single-header format. std::ostringstream oss; @@ -123,12 +100,12 @@ void OpenTracingSpan::injectContext(Http::RequestHeaderMap& request_headers) { return; } const std::string current_span_context = oss.str(); - request_headers.setInline( - ot_span_context_handle.handle(), + trace_context.setTraceContext( + Http::CustomHeaders::get().OtSpanContext, Base64::encode(current_span_context.c_str(), current_span_context.length())); } else { // Inject the context using the tracer's standard HTTP header format. - const OpenTracingHTTPHeadersWriter writer{request_headers}; + const OpenTracingHeadersWriter writer{trace_context}; const opentracing::expected was_successful = span_->tracer().Inject(span_->context(), writer); if (!was_successful) { @@ -155,7 +132,7 @@ OpenTracingDriver::OpenTracingDriver(Stats::Scope& scope) : tracer_stats_{OPENTRACING_TRACER_STATS(POOL_COUNTER_PREFIX(scope, "tracing.opentracing."))} {} Tracing::SpanPtr OpenTracingDriver::startSpan(const Tracing::Config& config, - Http::RequestHeaderMap& request_headers, + Tracing::TraceContext& trace_context, const std::string& operation_name, SystemTime start_time, const Tracing::Decision tracing_decision) { @@ -164,10 +141,10 @@ Tracing::SpanPtr OpenTracingDriver::startSpan(const Tracing::Config& config, std::unique_ptr active_span; std::unique_ptr parent_span_ctx; if (propagation_mode == PropagationMode::SingleHeader && - request_headers.getInline(ot_span_context_handle.handle())) { + trace_context.getTraceContext(Http::CustomHeaders::get().OtSpanContext).has_value()) { opentracing::expected> parent_span_ctx_maybe; - std::string parent_context = Base64::decode( - std::string(request_headers.getInlineValue(ot_span_context_handle.handle()))); + std::string parent_context = Base64::decode(std::string( + trace_context.getTraceContext(Http::CustomHeaders::get().OtSpanContext).value())); if (!parent_context.empty()) { InputConstMemoryStream istream{parent_context.data(), parent_context.size()}; @@ -185,7 +162,7 @@ Tracing::SpanPtr OpenTracingDriver::startSpan(const Tracing::Config& config, tracerStats().span_context_extraction_error_.inc(); } } else if (propagation_mode == PropagationMode::TracerNative) { - const OpenTracingHTTPHeadersReader reader{request_headers}; + const OpenTracingHeadersReader reader{trace_context}; opentracing::expected> parent_span_ctx_maybe = tracer.Extract(reader); if (parent_span_ctx_maybe) { diff --git a/source/extensions/tracers/common/ot/opentracing_driver_impl.h b/source/extensions/tracers/common/ot/opentracing_driver_impl.h index ef10c15926677..a504c9746b706 100644 --- a/source/extensions/tracers/common/ot/opentracing_driver_impl.h +++ b/source/extensions/tracers/common/ot/opentracing_driver_impl.h @@ -3,11 +3,12 @@ #include #include "envoy/stats/scope.h" -#include "envoy/tracing/http_tracer.h" +#include "envoy/tracing/trace_driver.h" #include "common/common/empty_string.h" #include "common/common/logger.h" #include "common/singleton/const_singleton.h" +#include "common/tracing/common_values.h" #include "opentracing/ext/tags.h" #include "opentracing/tracer.h" @@ -37,7 +38,7 @@ class OpenTracingSpan : public Tracing::Span, Logger::Loggable( - proto_config, context.serverFactoryContext().clusterManager(), - context.serverFactoryContext().scope(), context.serverFactoryContext().threadLocal(), - context.serverFactoryContext().runtime()); - return std::make_shared(std::move(datadog_driver), - context.serverFactoryContext().localInfo()); + return std::make_shared(proto_config, context.serverFactoryContext().clusterManager(), + context.serverFactoryContext().scope(), + context.serverFactoryContext().threadLocal(), + context.serverFactoryContext().runtime()); } /** diff --git a/source/extensions/tracers/datadog/config.h b/source/extensions/tracers/datadog/config.h index 324c82e85f9b1..1808fddff0033 100644 --- a/source/extensions/tracers/datadog/config.h +++ b/source/extensions/tracers/datadog/config.h @@ -21,9 +21,9 @@ class DatadogTracerFactory : public Common::FactoryBase( - context.serverFactoryContext().scope(), library, config); - return std::make_shared(std::move(dynamic_driver), - context.serverFactoryContext().localInfo()); + return std::make_shared(context.serverFactoryContext().scope(), library, + config); } /** diff --git a/source/extensions/tracers/dynamic_ot/config.h b/source/extensions/tracers/dynamic_ot/config.h index 05fd2873132b8..4b9a761a262ea 100644 --- a/source/extensions/tracers/dynamic_ot/config.h +++ b/source/extensions/tracers/dynamic_ot/config.h @@ -20,9 +20,9 @@ class DynamicOpenTracingTracerFactory private: // FactoryBase - Tracing::HttpTracerSharedPtr - createHttpTracerTyped(const envoy::config::trace::v3::DynamicOtConfig& configuration, - Server::Configuration::TracerFactoryContext& context) override; + Tracing::DriverSharedPtr + createTracerDriverTyped(const envoy::config::trace::v3::DynamicOtConfig& configuration, + Server::Configuration::TracerFactoryContext& context) override; }; } // namespace DynamicOt diff --git a/source/extensions/tracers/dynamic_ot/dynamic_opentracing_driver_impl.h b/source/extensions/tracers/dynamic_ot/dynamic_opentracing_driver_impl.h index a872088b8e111..668e3f99ad739 100644 --- a/source/extensions/tracers/dynamic_ot/dynamic_opentracing_driver_impl.h +++ b/source/extensions/tracers/dynamic_ot/dynamic_opentracing_driver_impl.h @@ -2,7 +2,6 @@ #include "envoy/runtime/runtime.h" #include "envoy/thread_local/thread_local.h" -#include "envoy/tracing/http_tracer.h" #include "envoy/upstream/cluster_manager.h" #include "extensions/tracers/common/ot/opentracing_driver_impl.h" diff --git a/source/extensions/tracers/lightstep/BUILD b/source/extensions/tracers/lightstep/BUILD index 0bfc9f44ec6f4..58e7b0f858cda 100644 --- a/source/extensions/tracers/lightstep/BUILD +++ b/source/extensions/tracers/lightstep/BUILD @@ -24,7 +24,6 @@ envoy_cc_library( "//source/common/config:utility_lib", "//source/common/grpc:context_lib", "//source/common/stats:symbol_table_lib", - "//source/common/tracing:http_tracer_lib", "//source/common/upstream:cluster_update_tracker_lib", "//source/extensions/tracers/common/ot:opentracing_driver_lib", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", diff --git a/source/extensions/tracers/lightstep/config.cc b/source/extensions/tracers/lightstep/config.cc index 3a636b76dd9ab..42afd0f118381 100644 --- a/source/extensions/tracers/lightstep/config.cc +++ b/source/extensions/tracers/lightstep/config.cc @@ -5,7 +5,6 @@ #include "envoy/registry/registry.h" #include "common/common/utility.h" -#include "common/tracing/http_tracer_impl.h" #include "extensions/tracers/lightstep/lightstep_tracer_impl.h" @@ -18,7 +17,7 @@ namespace Lightstep { LightstepTracerFactory::LightstepTracerFactory() : FactoryBase("envoy.tracers.lightstep") {} -Tracing::HttpTracerSharedPtr LightstepTracerFactory::createHttpTracerTyped( +Tracing::DriverSharedPtr LightstepTracerFactory::createTracerDriverTyped( const envoy::config::trace::v3::LightstepConfig& proto_config, Server::Configuration::TracerFactoryContext& context) { auto opts = std::make_unique(); @@ -28,14 +27,12 @@ Tracing::HttpTracerSharedPtr LightstepTracerFactory::createHttpTracerTyped( opts->access_token.assign(access_token_sv.data(), access_token_sv.size()); opts->component_name = context.serverFactoryContext().localInfo().clusterName(); - Tracing::DriverPtr lightstep_driver = std::make_unique( + return std::make_shared( proto_config, context.serverFactoryContext().clusterManager(), context.serverFactoryContext().scope(), context.serverFactoryContext().threadLocal(), context.serverFactoryContext().runtime(), std::move(opts), Common::Ot::OpenTracingDriver::PropagationMode::TracerNative, context.serverFactoryContext().grpcContext()); - return std::make_shared(std::move(lightstep_driver), - context.serverFactoryContext().localInfo()); } /** diff --git a/source/extensions/tracers/lightstep/config.h b/source/extensions/tracers/lightstep/config.h index f14a45470ecf1..33cec8da3d605 100644 --- a/source/extensions/tracers/lightstep/config.h +++ b/source/extensions/tracers/lightstep/config.h @@ -20,9 +20,9 @@ class LightstepTracerFactory private: // FactoryBase - Tracing::HttpTracerSharedPtr - createHttpTracerTyped(const envoy::config::trace::v3::LightstepConfig& proto_config, - Server::Configuration::TracerFactoryContext& context) override; + Tracing::DriverSharedPtr + createTracerDriverTyped(const envoy::config::trace::v3::LightstepConfig& proto_config, + Server::Configuration::TracerFactoryContext& context) override; }; } // namespace Lightstep diff --git a/source/extensions/tracers/lightstep/lightstep_tracer_impl.cc b/source/extensions/tracers/lightstep/lightstep_tracer_impl.cc index 952d24e4284fc..b64da5876e4e0 100644 --- a/source/extensions/tracers/lightstep/lightstep_tracer_impl.cc +++ b/source/extensions/tracers/lightstep/lightstep_tracer_impl.cc @@ -14,7 +14,6 @@ #include "common/config/utility.h" #include "common/grpc/common.h" #include "common/http/message_impl.h" -#include "common/tracing/http_tracer_impl.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/tracers/lightstep/lightstep_tracer_impl.h b/source/extensions/tracers/lightstep/lightstep_tracer_impl.h index e99d92b5346e9..10820e4a3601e 100644 --- a/source/extensions/tracers/lightstep/lightstep_tracer_impl.h +++ b/source/extensions/tracers/lightstep/lightstep_tracer_impl.h @@ -7,7 +7,6 @@ #include "envoy/config/trace/v3/lightstep.pb.h" #include "envoy/runtime/runtime.h" #include "envoy/thread_local/thread_local.h" -#include "envoy/tracing/http_tracer.h" #include "envoy/upstream/cluster_manager.h" #include "common/buffer/buffer_impl.h" diff --git a/source/extensions/tracers/opencensus/BUILD b/source/extensions/tracers/opencensus/BUILD index a1c414cca9d7e..6b1ce66267e8e 100644 --- a/source/extensions/tracers/opencensus/BUILD +++ b/source/extensions/tracers/opencensus/BUILD @@ -42,8 +42,10 @@ envoy_cc_library( "opencensus_exporter_zipkin", ], deps = [ + "//source/common/tracing:common_values_lib", + "//source/common/tracing:null_span_lib", "//source/common/config:utility_lib", - "//source/common/tracing:http_tracer_lib", + "//include/envoy/tracing:trace_driver_interface", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", ] + envoy_select_google_grpc(["//source/common/grpc:google_async_client_lib"]), ) diff --git a/source/extensions/tracers/opencensus/config.cc b/source/extensions/tracers/opencensus/config.cc index 24a439a98a650..ae6756e9bbfff 100644 --- a/source/extensions/tracers/opencensus/config.cc +++ b/source/extensions/tracers/opencensus/config.cc @@ -4,8 +4,6 @@ #include "envoy/config/trace/v3/opencensus.pb.validate.h" #include "envoy/registry/registry.h" -#include "common/tracing/http_tracer_impl.h" - #include "extensions/tracers/opencensus/opencensus_tracer_impl.h" namespace Envoy { @@ -15,25 +13,23 @@ namespace OpenCensus { OpenCensusTracerFactory::OpenCensusTracerFactory() : FactoryBase("envoy.tracers.opencensus") {} -Tracing::HttpTracerSharedPtr OpenCensusTracerFactory::createHttpTracerTyped( +Tracing::DriverSharedPtr OpenCensusTracerFactory::createTracerDriverTyped( const envoy::config::trace::v3::OpenCensusConfig& proto_config, Server::Configuration::TracerFactoryContext& context) { // Since OpenCensus can only support a single tracing configuration per entire process, // we need to make sure that it is configured at most once. - if (tracer_) { + if (driver_) { if (Envoy::Protobuf::util::MessageDifferencer::Equals(config_, proto_config)) { - return tracer_; + return driver_; } else { throw EnvoyException("Opencensus has already been configured with a different config."); } } - Tracing::DriverPtr driver = - std::make_unique(proto_config, context.serverFactoryContext().localInfo(), - context.serverFactoryContext().api()); - tracer_ = std::make_shared(std::move(driver), - context.serverFactoryContext().localInfo()); + + driver_ = std::make_shared(proto_config, context.serverFactoryContext().localInfo(), + context.serverFactoryContext().api()); config_ = proto_config; - return tracer_; + return driver_; } /** diff --git a/source/extensions/tracers/opencensus/config.h b/source/extensions/tracers/opencensus/config.h index a5270a45cb865..5b853f9b9e1dd 100644 --- a/source/extensions/tracers/opencensus/config.h +++ b/source/extensions/tracers/opencensus/config.h @@ -22,13 +22,13 @@ class OpenCensusTracerFactory private: // FactoryBase - Tracing::HttpTracerSharedPtr - createHttpTracerTyped(const envoy::config::trace::v3::OpenCensusConfig& proto_config, - Server::Configuration::TracerFactoryContext& context) override; + Tracing::DriverSharedPtr + createTracerDriverTyped(const envoy::config::trace::v3::OpenCensusConfig& proto_config, + Server::Configuration::TracerFactoryContext& context) override; // Since OpenCensus can only support a single tracing configuration per entire process, // we need to make sure that it is configured at most once. - Tracing::HttpTracerSharedPtr tracer_; + Tracing::DriverSharedPtr driver_; envoy::config::trace::v3::OpenCensusConfig config_; }; diff --git a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc index ee0fc31e53ee6..2320f42b28c03 100644 --- a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc +++ b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc @@ -58,7 +58,7 @@ using Constants = ConstSingleton; class Span : public Tracing::Span { public: Span(const Tracing::Config& config, const envoy::config::trace::v3::OpenCensusConfig& oc_config, - Http::RequestHeaderMap& request_headers, const std::string& operation_name, + Tracing::TraceContext& trace_context, const std::string& operation_name, SystemTime start_time, const Tracing::Decision tracing_decision); // Used by spawnChild(). @@ -69,7 +69,7 @@ class Span : public Tracing::Span { void setTag(absl::string_view name, absl::string_view value) override; void log(SystemTime timestamp, const std::string& event) override; void finishSpan() override; - void injectContext(Http::RequestHeaderMap& request_headers) override; + void injectContext(Tracing::TraceContext& trace_context) override; Tracing::SpanPtr spawnChild(const Tracing::Config& config, const std::string& name, SystemTime start_time) override; void setSampled(bool sampled) override; @@ -86,7 +86,7 @@ class Span : public Tracing::Span { }; ::opencensus::trace::Span -startSpanHelper(const std::string& name, bool traced, const Http::RequestHeaderMap& request_headers, +startSpanHelper(const std::string& name, bool traced, const Tracing::TraceContext& trace_context, const envoy::config::trace::v3::OpenCensusConfig& oc_config) { // Determine if there is a parent context. using OpenCensusConfig = envoy::config::trace::v3::OpenCensusConfig; @@ -95,34 +95,32 @@ startSpanHelper(const std::string& name, bool traced, const Http::RequestHeaderM bool found = false; switch (incoming) { case OpenCensusConfig::TRACE_CONTEXT: { - const auto header = request_headers.get(Constants::get().TRACEPARENT); - if (!header.empty()) { + const auto header = trace_context.getTraceContext(Constants::get().TRACEPARENT); + if (header.has_value()) { found = true; // This is an implicitly untrusted header, so only the first value is used. - parent_ctx = ::opencensus::trace::propagation::FromTraceParentHeader( - header[0]->value().getStringView()); + parent_ctx = ::opencensus::trace::propagation::FromTraceParentHeader(header.value()); } break; } case OpenCensusConfig::GRPC_TRACE_BIN: { - const auto header = request_headers.get(Constants::get().GRPC_TRACE_BIN); - if (!header.empty()) { + const auto header = trace_context.getTraceContext(Constants::get().GRPC_TRACE_BIN); + if (header.has_value()) { found = true; // This is an implicitly untrusted header, so only the first value is used. parent_ctx = ::opencensus::trace::propagation::FromGrpcTraceBinHeader( - Base64::decodeWithoutPadding(header[0]->value().getStringView())); + Base64::decodeWithoutPadding(header.value())); } break; } case OpenCensusConfig::CLOUD_TRACE_CONTEXT: { - const auto header = request_headers.get(Constants::get().X_CLOUD_TRACE_CONTEXT); - if (!header.empty()) { + const auto header = trace_context.getTraceContext(Constants::get().X_CLOUD_TRACE_CONTEXT); + if (header.has_value()) { found = true; // This is an implicitly untrusted header, so only the first value is used. - parent_ctx = ::opencensus::trace::propagation::FromCloudTraceContextHeader( - header[0]->value().getStringView()); + parent_ctx = ::opencensus::trace::propagation::FromCloudTraceContextHeader(header.value()); } break; } @@ -132,27 +130,27 @@ startSpanHelper(const std::string& name, bool traced, const Http::RequestHeaderM absl::string_view b3_span_id; absl::string_view b3_sampled; absl::string_view b3_flags; - const auto h_b3_trace_id = request_headers.get(Constants::get().X_B3_TRACEID); - if (!h_b3_trace_id.empty()) { + const auto h_b3_trace_id = trace_context.getTraceContext(Constants::get().X_B3_TRACEID); + if (h_b3_trace_id.has_value()) { // This is an implicitly untrusted header, so only the first value is used. - b3_trace_id = h_b3_trace_id[0]->value().getStringView(); + b3_trace_id = h_b3_trace_id.value(); } - const auto h_b3_span_id = request_headers.get(Constants::get().X_B3_SPANID); - if (!h_b3_span_id.empty()) { + const auto h_b3_span_id = trace_context.getTraceContext(Constants::get().X_B3_SPANID); + if (h_b3_span_id.has_value()) { // This is an implicitly untrusted header, so only the first value is used. - b3_span_id = h_b3_span_id[0]->value().getStringView(); + b3_span_id = h_b3_span_id.value(); } - const auto h_b3_sampled = request_headers.get(Constants::get().X_B3_SAMPLED); - if (!h_b3_sampled.empty()) { + const auto h_b3_sampled = trace_context.getTraceContext(Constants::get().X_B3_SAMPLED); + if (h_b3_sampled.has_value()) { // This is an implicitly untrusted header, so only the first value is used. - b3_sampled = h_b3_sampled[0]->value().getStringView(); + b3_sampled = h_b3_sampled.value(); } - const auto h_b3_flags = request_headers.get(Constants::get().X_B3_FLAGS); - if (!h_b3_flags.empty()) { + const auto h_b3_flags = trace_context.getTraceContext(Constants::get().X_B3_FLAGS); + if (h_b3_flags.has_value()) { // This is an implicitly untrusted header, so only the first value is used. - b3_flags = h_b3_flags[0]->value().getStringView(); + b3_flags = h_b3_flags.value(); } - if (!h_b3_trace_id.empty() && !h_b3_span_id.empty()) { + if (h_b3_trace_id.has_value() && h_b3_span_id.has_value()) { found = true; parent_ctx = ::opencensus::trace::propagation::FromB3Headers(b3_trace_id, b3_span_id, b3_sampled, b3_flags); @@ -183,9 +181,9 @@ startSpanHelper(const std::string& name, bool traced, const Http::RequestHeaderM Span::Span(const Tracing::Config& config, const envoy::config::trace::v3::OpenCensusConfig& oc_config, - Http::RequestHeaderMap& request_headers, const std::string& operation_name, + Tracing::TraceContext& trace_context, const std::string& operation_name, SystemTime /*start_time*/, const Tracing::Decision tracing_decision) - : span_(startSpanHelper(operation_name, tracing_decision.traced, request_headers, oc_config)), + : span_(startSpanHelper(operation_name, tracing_decision.traced, trace_context, oc_config)), oc_config_(oc_config) { span_.AddAttribute("OperationName", config.operationName() == Tracing::OperationName::Ingress ? "Ingress" @@ -209,36 +207,36 @@ void Span::log(SystemTime /*timestamp*/, const std::string& event) { void Span::finishSpan() { span_.End(); } -void Span::injectContext(Http::RequestHeaderMap& request_headers) { +void Span::injectContext(Tracing::TraceContext& trace_context) { using OpenCensusConfig = envoy::config::trace::v3::OpenCensusConfig; const auto& ctx = span_.context(); for (const auto& outgoing : oc_config_.outgoing_trace_context()) { switch (outgoing) { case OpenCensusConfig::TRACE_CONTEXT: - request_headers.setReferenceKey(Constants::get().TRACEPARENT, - ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); + trace_context.setTraceContext(Constants::get().TRACEPARENT, + ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); break; case OpenCensusConfig::GRPC_TRACE_BIN: { std::string val = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(ctx); val = Base64::encode(val.data(), val.size(), /*add_padding=*/false); - request_headers.setReferenceKey(Constants::get().GRPC_TRACE_BIN, val); + trace_context.setTraceContext(Constants::get().GRPC_TRACE_BIN, val); break; } case OpenCensusConfig::CLOUD_TRACE_CONTEXT: - request_headers.setReferenceKey( + trace_context.setTraceContext( Constants::get().X_CLOUD_TRACE_CONTEXT, ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); break; case OpenCensusConfig::B3: - request_headers.setReferenceKey(Constants::get().X_B3_TRACEID, - ::opencensus::trace::propagation::ToB3TraceIdHeader(ctx)); - request_headers.setReferenceKey(Constants::get().X_B3_SPANID, - ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); - request_headers.setReferenceKey(Constants::get().X_B3_SAMPLED, - ::opencensus::trace::propagation::ToB3SampledHeader(ctx)); + trace_context.setTraceContext(Constants::get().X_B3_TRACEID, + ::opencensus::trace::propagation::ToB3TraceIdHeader(ctx)); + trace_context.setTraceContext(Constants::get().X_B3_SPANID, + ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); + trace_context.setTraceContext(Constants::get().X_B3_SAMPLED, + ::opencensus::trace::propagation::ToB3SampledHeader(ctx)); // OpenCensus's trace context propagation doesn't produce the // "X-B3-Flags:" header. break; @@ -384,10 +382,10 @@ void Driver::applyTraceConfig(const opencensus::proto::trace::v1::TraceConfig& c } Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, - Http::RequestHeaderMap& request_headers, + Tracing::TraceContext& trace_context, const std::string& operation_name, SystemTime start_time, const Tracing::Decision tracing_decision) { - return std::make_unique(config, oc_config_, request_headers, operation_name, start_time, + return std::make_unique(config, oc_config_, trace_context, operation_name, start_time, tracing_decision); } diff --git a/source/extensions/tracers/opencensus/opencensus_tracer_impl.h b/source/extensions/tracers/opencensus/opencensus_tracer_impl.h index 2c06d0c49a5db..5e65960a9d16e 100644 --- a/source/extensions/tracers/opencensus/opencensus_tracer_impl.h +++ b/source/extensions/tracers/opencensus/opencensus_tracer_impl.h @@ -3,7 +3,7 @@ #include "envoy/api/api.h" #include "envoy/config/trace/v3/opencensus.pb.h" #include "envoy/local_info/local_info.h" -#include "envoy/tracing/http_tracer.h" +#include "envoy/tracing/trace_driver.h" #include "common/common/logger.h" @@ -13,7 +13,7 @@ namespace Tracers { namespace OpenCensus { /** - * OpenCensus tracing driver. + * OpenCensus trace driver. */ class Driver : public Tracing::Driver, Logger::Loggable { public: @@ -23,7 +23,7 @@ class Driver : public Tracing::Driver, Logger::Loggable { /** * Implements the abstract Driver's startSpan operation. */ - Tracing::SpanPtr startSpan(const Tracing::Config& config, Http::RequestHeaderMap& request_headers, + Tracing::SpanPtr startSpan(const Tracing::Config& config, Tracing::TraceContext& trace_context, const std::string& operation_name, SystemTime start_time, const Tracing::Decision tracing_decision) override; diff --git a/source/extensions/tracers/skywalking/BUILD b/source/extensions/tracers/skywalking/BUILD index 41da2c3f61f37..060a372bef1ab 100644 --- a/source/extensions/tracers/skywalking/BUILD +++ b/source/extensions/tracers/skywalking/BUILD @@ -44,11 +44,12 @@ envoy_cc_library( ":trace_segment_reporter_lib", "//include/envoy/common:time_interface", "//include/envoy/server:tracer_config_interface", - "//include/envoy/tracing:http_tracer_interface", + "//include/envoy/tracing:trace_driver_interface", "//source/common/common:macros", "//source/common/http:header_map_lib", "//source/common/runtime:runtime_lib", - "//source/common/tracing:http_tracer_lib", + "//source/common/tracing:common_values_lib", + "//source/common/tracing:null_span_lib", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/tracers/skywalking/config.cc b/source/extensions/tracers/skywalking/config.cc index 4f9e15b12f2dc..12e1b43c01579 100644 --- a/source/extensions/tracers/skywalking/config.cc +++ b/source/extensions/tracers/skywalking/config.cc @@ -5,7 +5,6 @@ #include "envoy/registry/registry.h" #include "common/common/utility.h" -#include "common/tracing/http_tracer_impl.h" #include "extensions/tracers/skywalking/skywalking_tracer_impl.h" @@ -16,13 +15,10 @@ namespace SkyWalking { SkyWalkingTracerFactory::SkyWalkingTracerFactory() : FactoryBase("envoy.tracers.skywalking") {} -Tracing::HttpTracerSharedPtr SkyWalkingTracerFactory::createHttpTracerTyped( +Tracing::DriverSharedPtr SkyWalkingTracerFactory::createTracerDriverTyped( const envoy::config::trace::v3::SkyWalkingConfig& proto_config, Server::Configuration::TracerFactoryContext& context) { - Tracing::DriverPtr skywalking_driver = - std::make_unique(proto_config, context); - return std::make_shared(std::move(skywalking_driver), - context.serverFactoryContext().localInfo()); + return std::make_shared(proto_config, context); } /** diff --git a/source/extensions/tracers/skywalking/config.h b/source/extensions/tracers/skywalking/config.h index abeffe373e5d7..0fc1ad8dc9671 100644 --- a/source/extensions/tracers/skywalking/config.h +++ b/source/extensions/tracers/skywalking/config.h @@ -20,9 +20,9 @@ class SkyWalkingTracerFactory private: // FactoryBase - Tracing::HttpTracerSharedPtr - createHttpTracerTyped(const envoy::config::trace::v3::SkyWalkingConfig& proto_config, - Server::Configuration::TracerFactoryContext& context) override; + Tracing::DriverSharedPtr + createTracerDriverTyped(const envoy::config::trace::v3::SkyWalkingConfig& proto_config, + Server::Configuration::TracerFactoryContext& context) override; }; } // namespace SkyWalking diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc index 92e17d54966f7..a4c7fc9213c73 100644 --- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc +++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc @@ -45,14 +45,14 @@ Driver::Driver(const envoy::config::trace::v3::SkyWalkingConfig& proto_config, } Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, - Http::RequestHeaderMap& request_headers, + Tracing::TraceContext& trace_context, const std::string& operation_name, Envoy::SystemTime start_time, const Tracing::Decision decision) { auto& tracer = tls_slot_ptr_->getTyped().tracer(); TracingContextPtr tracing_context; // TODO(shikugawa): support extension span header. - auto propagation_header = request_headers.get(skywalkingPropagationHeaderKey()); - if (propagation_header.empty()) { + auto propagation_header = trace_context.getTraceContext(skywalkingPropagationHeaderKey()); + if (!propagation_header.has_value()) { tracing_context = tracing_context_factory_->create(); // Sampling status is always true on SkyWalking. But with disabling skip_analysis, // this span can't be analyzed. @@ -60,7 +60,7 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, tracing_context->setSkipAnalysis(); } } else { - auto header_value_string = propagation_header[0]->value().getStringView(); + auto header_value_string = propagation_header.value(); try { SpanContextPtr span_context = createSpanContext(header_value_string); tracing_context = tracing_context_factory_->create(span_context); diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.h b/source/extensions/tracers/skywalking/skywalking_tracer_impl.h index 0b64b37efe16c..b8956d232ebb6 100644 --- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.h +++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.h @@ -3,9 +3,7 @@ #include "envoy/config/trace/v3/skywalking.pb.h" #include "envoy/server/tracer_config.h" #include "envoy/thread_local/thread_local.h" -#include "envoy/tracing/http_tracer.h" - -#include "common/tracing/http_tracer_impl.h" +#include "envoy/tracing/trace_driver.h" #include "source/tracing_context_impl.h" @@ -27,7 +25,7 @@ class Driver : public Tracing::Driver, public Logger::LoggablecreateSW8HeaderValue(std::string(request_headers.getHostValue())); +void Span::injectContext(Tracing::TraceContext& trace_context) { + auto sw8_header = tracing_context_->createSW8HeaderValue( + std::string(trace_context.getTraceContext(Http::Headers::get().HostLegacy).value_or(""))); if (sw8_header.has_value()) { - request_headers.setReferenceKey(skywalkingPropagationHeaderKey(), sw8_header.value()); + trace_context.setTraceContext(skywalkingPropagationHeaderKey(), sw8_header.value()); } } diff --git a/source/extensions/tracers/skywalking/tracer.h b/source/extensions/tracers/skywalking/tracer.h index 3852d1718b90a..32bb7f3781c61 100644 --- a/source/extensions/tracers/skywalking/tracer.h +++ b/source/extensions/tracers/skywalking/tracer.h @@ -2,7 +2,7 @@ #include -#include "common/tracing/http_tracer_impl.h" +#include "envoy/tracing/trace_driver.h" #include "extensions/tracers/skywalking/trace_segment_reporter.h" @@ -64,7 +64,7 @@ class Span : public Tracing::Span { void setTag(absl::string_view name, absl::string_view value) override; void log(SystemTime timestamp, const std::string& event) override; void finishSpan() override; - void injectContext(Http::RequestHeaderMap& request_headers) override; + void injectContext(Tracing::TraceContext& trace_context) override; Tracing::SpanPtr spawnChild(const Tracing::Config& config, const std::string& name, SystemTime start_time) override; void setSampled(bool do_sample) override; diff --git a/source/extensions/tracers/xray/BUILD b/source/extensions/tracers/xray/BUILD index d8779c3bf2f2c..797e8a84e407d 100644 --- a/source/extensions/tracers/xray/BUILD +++ b/source/extensions/tracers/xray/BUILD @@ -41,7 +41,7 @@ envoy_cc_library( ":daemon_cc_proto", "//include/envoy/common:time_interface", "//include/envoy/server:tracer_config_interface", - "//include/envoy/tracing:http_tracer_interface", + "//include/envoy/tracing:trace_driver_interface", "//source/common/common:hex_lib", "//source/common/common:macros", "//source/common/common:random_generator_lib", @@ -49,7 +49,8 @@ envoy_cc_library( "//source/common/json:json_loader_lib", "//source/common/protobuf:utility_lib", "//source/common/runtime:runtime_lib", - "//source/common/tracing:http_tracer_lib", + "//source/common/tracing:common_values_lib", + "//source/common/tracing:null_span_lib", ], ) diff --git a/source/extensions/tracers/xray/config.cc b/source/extensions/tracers/xray/config.cc index 96c2c5a10dbd9..ff9bd156ea7f3 100644 --- a/source/extensions/tracers/xray/config.cc +++ b/source/extensions/tracers/xray/config.cc @@ -9,7 +9,6 @@ #include "common/common/utility.h" #include "common/config/datasource.h" -#include "common/tracing/http_tracer_impl.h" #include "extensions/tracers/xray/xray_tracer_impl.h" @@ -20,9 +19,9 @@ namespace XRay { XRayTracerFactory::XRayTracerFactory() : FactoryBase("envoy.tracers.xray") {} -Tracing::HttpTracerSharedPtr -XRayTracerFactory::createHttpTracerTyped(const envoy::config::trace::v3::XRayConfig& proto_config, - Server::Configuration::TracerFactoryContext& context) { +Tracing::DriverSharedPtr +XRayTracerFactory::createTracerDriverTyped(const envoy::config::trace::v3::XRayConfig& proto_config, + Server::Configuration::TracerFactoryContext& context) { std::string sampling_rules_json; try { sampling_rules_json = Config::DataSource::read(proto_config.sampling_rule_manifest(), true, @@ -51,10 +50,7 @@ XRayTracerFactory::createHttpTracerTyped(const envoy::config::trace::v3::XRayCon XRayConfiguration xconfig{endpoint, proto_config.segment_name(), sampling_rules_json, origin, std::move(aws)}; - auto xray_driver = std::make_unique(xconfig, context); - - return std::make_shared(std::move(xray_driver), - context.serverFactoryContext().localInfo()); + return std::make_shared(xconfig, context); } /** diff --git a/source/extensions/tracers/xray/config.h b/source/extensions/tracers/xray/config.h index 69e1201de2f94..00c5b3d5fa8ef 100644 --- a/source/extensions/tracers/xray/config.h +++ b/source/extensions/tracers/xray/config.h @@ -20,9 +20,9 @@ class XRayTracerFactory : public Common::FactoryBase { /** * Adds X-Ray trace header to the set of outgoing headers. */ - void injectContext(Http::RequestHeaderMap& request_headers) override; + void injectContext(Tracing::TraceContext& trace_context) override; /** * Gets the start time of this Span. diff --git a/source/extensions/tracers/xray/xray_tracer_impl.cc b/source/extensions/tracers/xray/xray_tracer_impl.cc index 77e240c783a23..dc86367640a84 100644 --- a/source/extensions/tracers/xray/xray_tracer_impl.cc +++ b/source/extensions/tracers/xray/xray_tracer_impl.cc @@ -2,6 +2,7 @@ #include "common/common/macros.h" #include "common/common/utility.h" +#include "common/http/header_map_impl.h" #include "extensions/tracers/xray/localized_sampling.h" #include "extensions/tracers/xray/tracer.h" @@ -62,7 +63,7 @@ Driver::Driver(const XRayConfiguration& config, } Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, - Http::RequestHeaderMap& request_headers, + Tracing::TraceContext& trace_context, const std::string& operation_name, Envoy::SystemTime start_time, const Tracing::Decision tracing_decision) { // First thing is to determine whether this request will be sampled or not. @@ -77,12 +78,12 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, UNREFERENCED_PARAMETER(config); // TODO(marcomagdy) - how do we factor this into the logic above UNREFERENCED_PARAMETER(tracing_decision); - const auto header = request_headers.get(Http::LowerCaseString(XRayTraceHeader)); + const auto header = trace_context.getTraceContext(absl::string_view(XRayTraceHeader)); absl::optional should_trace; XRayHeader xray_header; - if (!header.empty()) { + if (header.has_value()) { // This is an implicitly untrusted header, so only the first value is used. - Http::LowerCaseString lowered_header_value{std::string(header[0]->value().getStringView())}; + Http::LowerCaseString lowered_header_value{std::string(header.value())}; xray_header = parseXRayHeader(lowered_header_value); // if the sample_decision in the x-ray header is unknown then we try to make a decision based // on the sampling strategy @@ -98,9 +99,10 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, } if (!should_trace.has_value()) { - const SamplingRequest request{std::string{request_headers.getHostValue()}, - std::string{request_headers.getMethodValue()}, - std::string{request_headers.getPathValue()}}; + const SamplingRequest request{ + trace_context.getTraceContext(Http::Headers::get().HostLegacy).value_or(""), + trace_context.getTraceContext(Http::Headers::get().Method).value_or(""), + trace_context.getTraceContext(Http::Headers::get().Path).value_or("")}; should_trace = sampling_strategy_->shouldTrace(request); } @@ -108,8 +110,8 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, auto* tracer = tls_slot_ptr_->getTyped().tracer_.get(); if (should_trace.value()) { return tracer->startSpan(operation_name, start_time, - !header.empty() ? absl::optional(xray_header) - : absl::nullopt); + header.has_value() ? absl::optional(xray_header) + : absl::nullopt); } // instead of returning nullptr, we return a Span that is marked as not-sampled. diff --git a/source/extensions/tracers/xray/xray_tracer_impl.h b/source/extensions/tracers/xray/xray_tracer_impl.h index 57ed898cd1e5a..7421540848b8d 100644 --- a/source/extensions/tracers/xray/xray_tracer_impl.h +++ b/source/extensions/tracers/xray/xray_tracer_impl.h @@ -2,9 +2,7 @@ #include "envoy/server/tracer_config.h" #include "envoy/thread_local/thread_local.h" -#include "envoy/tracing/http_tracer.h" - -#include "common/tracing/http_tracer_impl.h" +#include "envoy/tracing/trace_driver.h" #include "extensions/tracers/xray/tracer.h" #include "extensions/tracers/xray/xray_configuration.h" @@ -19,7 +17,7 @@ class Driver : public Tracing::Driver, public Logger::Loggable( + return std::make_shared( proto_config, context.serverFactoryContext().clusterManager(), context.serverFactoryContext().scope(), context.serverFactoryContext().threadLocal(), context.serverFactoryContext().runtime(), context.serverFactoryContext().localInfo(), context.serverFactoryContext().api().randomGenerator(), context.serverFactoryContext().timeSource()); - - return std::make_shared(std::move(zipkin_driver), - context.serverFactoryContext().localInfo()); } /** diff --git a/source/extensions/tracers/zipkin/config.h b/source/extensions/tracers/zipkin/config.h index b91ef7cb7f350..8c879e64f5243 100644 --- a/source/extensions/tracers/zipkin/config.h +++ b/source/extensions/tracers/zipkin/config.h @@ -19,9 +19,9 @@ class ZipkinTracerFactory : public Common::FactoryBasevalue().getStringView(); + absl::string_view b3 = b3_header_entry.value(); int sampled_pos = 0; switch (b3.length()) { case 1: @@ -62,20 +62,20 @@ bool SpanContextExtractor::extractSampled(const Tracing::Decision tracing_decisi return getSamplingFlags(b3[sampled_pos], tracing_decision); } - auto x_b3_sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED); - if (x_b3_sampled_entry.empty()) { + auto x_b3_sampled_entry = trace_context_.getTraceContext(ZipkinCoreConstants::get().X_B3_SAMPLED); + if (!x_b3_sampled_entry.has_value()) { return tracing_decision.traced; } // Checking if sampled flag has been specified. Also checking for 'true' value, as some old // zipkin tracers may still use that value, although should be 0 or 1. // This is an implicitly untrusted header, so only the first value is used. - absl::string_view xb3_sampled = x_b3_sampled_entry[0]->value().getStringView(); + absl::string_view xb3_sampled = x_b3_sampled_entry.value(); sampled = xb3_sampled == SAMPLED || xb3_sampled == "true"; return sampled; } std::pair SpanContextExtractor::extractSpanContext(bool is_sampled) { - if (!request_headers_.get(ZipkinCoreConstants::get().B3).empty()) { + if (trace_context_.getTraceContext(ZipkinCoreConstants::get().B3).has_value()) { return extractSpanContextFromB3SingleFormat(is_sampled); } uint64_t trace_id(0); @@ -83,14 +83,14 @@ std::pair SpanContextExtractor::extractSpanContext(bool is_sa uint64_t span_id(0); uint64_t parent_id(0); - auto b3_trace_id_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID); - auto b3_span_id_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID); - if (!b3_span_id_entry.empty() && !b3_trace_id_entry.empty()) { + auto b3_trace_id_entry = trace_context_.getTraceContext(ZipkinCoreConstants::get().X_B3_TRACE_ID); + auto b3_span_id_entry = trace_context_.getTraceContext(ZipkinCoreConstants::get().X_B3_SPAN_ID); + if (b3_span_id_entry.has_value() && b3_trace_id_entry.has_value()) { // Extract trace id - which can either be 128 or 64 bit. For 128 bit, // it needs to be divided into two 64 bit numbers (high and low). // This is an implicitly untrusted header, so only the first value is used. - const std::string tid(b3_trace_id_entry[0]->value().getStringView()); - if (b3_trace_id_entry[0]->value().size() == 32) { + const std::string tid(b3_trace_id_entry.value()); + if (b3_trace_id_entry.value().size() == 32) { const std::string high_tid = tid.substr(0, 16); const std::string low_tid = tid.substr(16, 16); if (!StringUtil::atoull(high_tid.c_str(), trace_id_high, 16) || @@ -103,15 +103,16 @@ std::pair SpanContextExtractor::extractSpanContext(bool is_sa } // This is an implicitly untrusted header, so only the first value is used. - const std::string spid(b3_span_id_entry[0]->value().getStringView()); + const std::string spid(b3_span_id_entry.value()); if (!StringUtil::atoull(spid.c_str(), span_id, 16)) { throw ExtractorException(absl::StrCat("Invalid span id ", spid.c_str())); } - auto b3_parent_id_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID); - if (!b3_parent_id_entry.empty() && !b3_parent_id_entry[0]->value().empty()) { + auto b3_parent_id_entry = + trace_context_.getTraceContext(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID); + if (b3_parent_id_entry.has_value() && !b3_parent_id_entry.value().empty()) { // This is an implicitly untrusted header, so only the first value is used. - const std::string pspid(b3_parent_id_entry[0]->value().getStringView()); + const std::string pspid(b3_parent_id_entry.value()); if (!StringUtil::atoull(pspid.c_str(), parent_id, 16)) { throw ExtractorException(absl::StrCat("Invalid parent span id ", pspid.c_str())); } @@ -125,10 +126,10 @@ std::pair SpanContextExtractor::extractSpanContext(bool is_sa std::pair SpanContextExtractor::extractSpanContextFromB3SingleFormat(bool is_sampled) { - auto b3_head_entry = request_headers_.get(ZipkinCoreConstants::get().B3); - ASSERT(!b3_head_entry.empty()); + auto b3_head_entry = trace_context_.getTraceContext(ZipkinCoreConstants::get().B3); + ASSERT(b3_head_entry.has_value()); // This is an implicitly untrusted header, so only the first value is used. - const std::string b3(b3_head_entry[0]->value().getStringView()); + const std::string b3(b3_head_entry.value()); if (!b3.length()) { throw ExtractorException("Invalid input: empty"); } diff --git a/source/extensions/tracers/zipkin/span_context_extractor.h b/source/extensions/tracers/zipkin/span_context_extractor.h index 425a0d59973cc..30e39225e2592 100644 --- a/source/extensions/tracers/zipkin/span_context_extractor.h +++ b/source/extensions/tracers/zipkin/span_context_extractor.h @@ -1,7 +1,8 @@ #pragma once #include "envoy/common/exception.h" -#include "envoy/tracing/http_tracer.h" +#include "envoy/tracing/trace_context.h" +#include "envoy/tracing/trace_reason.h" #include "common/http/header_map_impl.h" @@ -21,7 +22,7 @@ struct ExtractorException : public EnvoyException { */ class SpanContextExtractor { public: - SpanContextExtractor(Http::RequestHeaderMap& request_headers); + SpanContextExtractor(Tracing::TraceContext& trace_context); ~SpanContextExtractor(); bool extractSampled(const Tracing::Decision tracing_decision); std::pair extractSpanContext(bool is_sampled); @@ -34,7 +35,7 @@ class SpanContextExtractor { */ std::pair extractSpanContextFromB3SingleFormat(bool is_sampled); bool tryExtractSampledFromB3SingleFormat(); - const Http::RequestHeaderMap& request_headers_; + const Tracing::TraceContext& trace_context_; }; } // namespace Zipkin diff --git a/source/extensions/tracers/zipkin/tracer.cc b/source/extensions/tracers/zipkin/tracer.cc index 90f1f1d72f495..95fb69340640c 100644 --- a/source/extensions/tracers/zipkin/tracer.cc +++ b/source/extensions/tracers/zipkin/tracer.cc @@ -3,7 +3,6 @@ #include #include "common/common/utility.h" -#include "common/tracing/http_tracer_impl.h" #include "extensions/tracers/zipkin/util.h" #include "extensions/tracers/zipkin/zipkin_core_constants.h" diff --git a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc index d25f143cec47e..ffe5443296d68 100644 --- a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc +++ b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc @@ -10,7 +10,7 @@ #include "common/http/headers.h" #include "common/http/message_impl.h" #include "common/http/utility.h" -#include "common/tracing/http_tracer_impl.h" +#include "common/tracing/null_span_impl.h" #include "extensions/tracers/zipkin/span_context_extractor.h" #include "extensions/tracers/zipkin/zipkin_core_constants.h" @@ -40,21 +40,21 @@ void ZipkinSpan::log(SystemTime timestamp, const std::string& event) { void ZipkinSpan::setBaggage(absl::string_view, absl::string_view) {} std::string ZipkinSpan::getBaggage(absl::string_view) { return EMPTY_STRING; } -void ZipkinSpan::injectContext(Http::RequestHeaderMap& request_headers) { +void ZipkinSpan::injectContext(Tracing::TraceContext& trace_context) { // Set the trace-id and span-id headers properly, based on the newly-created span structure. - request_headers.setReferenceKey(ZipkinCoreConstants::get().X_B3_TRACE_ID, - span_.traceIdAsHexString()); - request_headers.setReferenceKey(ZipkinCoreConstants::get().X_B3_SPAN_ID, span_.idAsHexString()); + trace_context.setTraceContext(ZipkinCoreConstants::get().X_B3_TRACE_ID, + span_.traceIdAsHexString()); + trace_context.setTraceContext(ZipkinCoreConstants::get().X_B3_SPAN_ID, span_.idAsHexString()); // Set the parent-span header properly, based on the newly-created span structure. if (span_.isSetParentId()) { - request_headers.setReferenceKey(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, - span_.parentIdAsHexString()); + trace_context.setTraceContext(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, + span_.parentIdAsHexString()); } // Set the sampled header. - request_headers.setReferenceKey(ZipkinCoreConstants::get().X_B3_SAMPLED, - span_.sampled() ? SAMPLED : NOT_SAMPLED); + trace_context.setTraceContext(ZipkinCoreConstants::get().X_B3_SAMPLED, + span_.sampled() ? SAMPLED : NOT_SAMPLED); } void ZipkinSpan::setSampled(bool sampled) { span_.setSampled(sampled); } @@ -108,23 +108,27 @@ Driver::Driver(const envoy::config::trace::v3::ZipkinConfig& zipkin_config, } Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, - Http::RequestHeaderMap& request_headers, const std::string&, + Tracing::TraceContext& trace_context, const std::string&, SystemTime start_time, const Tracing::Decision tracing_decision) { Tracer& tracer = *tls_->getTyped().tracer_; SpanPtr new_zipkin_span; - SpanContextExtractor extractor(request_headers); + SpanContextExtractor extractor(trace_context); bool sampled{extractor.extractSampled(tracing_decision)}; try { auto ret_span_context = extractor.extractSpanContext(sampled); if (!ret_span_context.second) { // Create a root Zipkin span. No context was found in the headers. - new_zipkin_span = - tracer.startSpan(config, std::string(request_headers.getHostValue()), start_time); + new_zipkin_span = tracer.startSpan( + config, + std::string(trace_context.getTraceContext(Http::Headers::get().HostLegacy).value_or("")), + start_time); new_zipkin_span->setSampled(sampled); } else { - new_zipkin_span = tracer.startSpan(config, std::string(request_headers.getHostValue()), - start_time, ret_span_context.first); + new_zipkin_span = tracer.startSpan( + config, + std::string(trace_context.getTraceContext(Http::Headers::get().HostLegacy).value_or("")), + start_time, ret_span_context.first); } } catch (const ExtractorException& e) { diff --git a/source/extensions/tracers/zipkin/zipkin_tracer_impl.h b/source/extensions/tracers/zipkin/zipkin_tracer_impl.h index c5a234fd8bb14..96765234a8818 100644 --- a/source/extensions/tracers/zipkin/zipkin_tracer_impl.h +++ b/source/extensions/tracers/zipkin/zipkin_tracer_impl.h @@ -5,7 +5,7 @@ #include "envoy/local_info/local_info.h" #include "envoy/runtime/runtime.h" #include "envoy/thread_local/thread_local.h" -#include "envoy/tracing/http_tracer.h" +#include "envoy/tracing/trace_driver.h" #include "envoy/upstream/cluster_manager.h" #include "common/common/empty_string.h" @@ -71,7 +71,7 @@ class ZipkinSpan : public Tracing::Span { void log(SystemTime timestamp, const std::string& event) override; - void injectContext(Http::RequestHeaderMap& request_headers) override; + void injectContext(Tracing::TraceContext& trace_context) override; Tracing::SpanPtr spawnChild(const Tracing::Config&, const std::string& name, SystemTime start_time) override; @@ -114,14 +114,14 @@ class Driver : public Tracing::Driver { /** * This function is inherited from the abstract Driver class. * - * It starts a new Zipkin span. Depending on the request headers, it can create a root span, + * It starts a new Zipkin span. Depending on the tracing context, it can create a root span, * a child span, or a shared-context span. * * The third parameter (operation_name) does not actually make sense for Zipkin. * Thus, this implementation of the virtual function startSpan() ignores the operation name * ("ingress" or "egress") passed by the caller. */ - Tracing::SpanPtr startSpan(const Tracing::Config&, Http::RequestHeaderMap& request_headers, + Tracing::SpanPtr startSpan(const Tracing::Config&, Tracing::TraceContext& trace_context, const std::string&, SystemTime start_time, const Tracing::Decision tracing_decision) override; diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc index 1a071d2b38089..d02d9d7659340 100644 --- a/test/common/http/conn_manager_impl_test.cc +++ b/test/common/http/conn_manager_impl_test.cc @@ -1128,8 +1128,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlow) { auto* span = new NiceMock(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)) .WillOnce( - Invoke([&](const Tracing::Config& config, const HeaderMap&, const StreamInfo::StreamInfo&, - const Tracing::Decision) -> Tracing::Span* { + Invoke([&](const Tracing::Config& config, const RequestHeaderMap&, + const StreamInfo::StreamInfo&, const Tracing::Decision) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Ingress, config.operationName()); return span; @@ -1286,8 +1286,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat auto* span = new NiceMock(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)) .WillOnce( - Invoke([&](const Tracing::Config& config, const HeaderMap&, const StreamInfo::StreamInfo&, - const Tracing::Decision) -> Tracing::Span* { + Invoke([&](const Tracing::Config& config, const RequestHeaderMap&, + const StreamInfo::StreamInfo&, const Tracing::Decision) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Ingress, config.operationName()); return span; @@ -1352,8 +1352,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat auto* span = new NiceMock(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)) .WillOnce( - Invoke([&](const Tracing::Config& config, const HeaderMap&, const StreamInfo::StreamInfo&, - const Tracing::Decision) -> Tracing::Span* { + Invoke([&](const Tracing::Config& config, const RequestHeaderMap&, + const StreamInfo::StreamInfo&, const Tracing::Decision) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Ingress, config.operationName()); return span; @@ -1419,8 +1419,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat auto* span = new NiceMock(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)) .WillOnce( - Invoke([&](const Tracing::Config& config, const HeaderMap&, const StreamInfo::StreamInfo&, - const Tracing::Decision) -> Tracing::Span* { + Invoke([&](const Tracing::Config& config, const RequestHeaderMap&, + const StreamInfo::StreamInfo&, const Tracing::Decision) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Ingress, config.operationName()); return span; @@ -1500,8 +1500,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato auto* span = new NiceMock(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)) .WillOnce( - Invoke([&](const Tracing::Config& config, const HeaderMap&, const StreamInfo::StreamInfo&, - const Tracing::Decision) -> Tracing::Span* { + Invoke([&](const Tracing::Config& config, const RequestHeaderMap&, + const StreamInfo::StreamInfo&, const Tracing::Decision) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Egress, config.operationName()); return span; @@ -1582,8 +1582,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato auto* span = new NiceMock(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)) .WillOnce( - Invoke([&](const Tracing::Config& config, const HeaderMap&, const StreamInfo::StreamInfo&, - const Tracing::Decision) -> Tracing::Span* { + Invoke([&](const Tracing::Config& config, const RequestHeaderMap&, + const StreamInfo::StreamInfo&, const Tracing::Decision) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Egress, config.operationName()); return span; @@ -1666,8 +1666,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato auto* span = new NiceMock(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)) .WillOnce( - Invoke([&](const Tracing::Config& config, const HeaderMap&, const StreamInfo::StreamInfo&, - const Tracing::Decision) -> Tracing::Span* { + Invoke([&](const Tracing::Config& config, const RequestHeaderMap&, + const StreamInfo::StreamInfo&, const Tracing::Decision) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Egress, config.operationName()); return span; diff --git a/test/common/tracing/BUILD b/test/common/tracing/BUILD index cf45ce5494e9d..3913de7c77a46 100644 --- a/test/common/tracing/BUILD +++ b/test/common/tracing/BUILD @@ -41,9 +41,9 @@ envoy_cc_test( "http_tracer_manager_impl_test.cc", ], deps = [ - "//source/common/tracing:http_tracer_config_lib", "//source/common/tracing:http_tracer_lib", "//source/common/tracing:http_tracer_manager_lib", + "//source/common/tracing:tracer_config_lib", "//test/mocks/server:instance_mocks", "//test/mocks/server:tracer_factory_mocks", "//test/mocks/tracing:tracing_mocks", diff --git a/test/common/tracing/http_tracer_impl_test.cc b/test/common/tracing/http_tracer_impl_test.cc index c94dee161313b..7942815006ec6 100644 --- a/test/common/tracing/http_tracer_impl_test.cc +++ b/test/common/tracing/http_tracer_impl_test.cc @@ -33,6 +33,7 @@ using testing::Eq; using testing::NiceMock; using testing::Return; using testing::ReturnPointee; +using testing::ReturnRef; namespace Envoy { namespace Tracing { @@ -699,6 +700,15 @@ TEST(HttpTracerUtilityTest, operationTypeToString) { EXPECT_EQ("egress", HttpTracerUtility::toString(OperationName::Egress)); } +TEST(EgressConfigImplTest, EgressConfigImplTest) { + EgressConfigImpl config_impl; + + EXPECT_EQ(OperationName::Egress, config_impl.operationName()); + EXPECT_EQ(nullptr, config_impl.customTags()); + EXPECT_EQ(false, config_impl.verbose()); + EXPECT_EQ(Tracing::DefaultMaxPathTagLength, config_impl.maxPathTagLength()); +} + TEST(HttpNullTracerTest, BasicFunctionality) { HttpNullTracer null_tracer; MockConfig config; @@ -724,19 +734,22 @@ TEST(HttpNullTracerTest, BasicFunctionality) { class HttpTracerImplTest : public testing::Test { public: HttpTracerImplTest() { - driver_ = new MockDriver(); + driver_ = new NiceMock(); DriverPtr driver_ptr(driver_); tracer_ = std::make_shared(std::move(driver_ptr), local_info_); } Http::TestRequestHeaderMapImpl request_headers_{ {":path", "/"}, {":method", "GET"}, {"x-request-id", "foo"}, {":authority", "test"}}; - Http::TestResponseHeaderMapImpl response_headers; - Http::TestResponseTrailerMapImpl response_trailers; - StreamInfo::MockStreamInfo stream_info_; + Http::TestResponseHeaderMapImpl response_headers_{{":status", "200"}, + {"content-type", "application/grpc"}, + {"grpc-status", "7"}, + {"grpc-message", "permission denied"}}; + Http::TestResponseTrailerMapImpl response_trailers_; + NiceMock stream_info_; NiceMock local_info_; - MockConfig config_; - MockDriver* driver_; + NiceMock config_; + NiceMock* driver_; HttpTracerSharedPtr tracer_; }; @@ -764,6 +777,58 @@ TEST_F(HttpTracerImplTest, BasicFunctionalityNodeSet) { tracer_->startSpan(config_, request_headers_, stream_info_, {Reason::Sampling, true}); } +TEST_F(HttpTracerImplTest, ChildUpstreamSpanTest) { + EXPECT_CALL(stream_info_, startTime()); + EXPECT_CALL(local_info_, nodeName()); + EXPECT_CALL(config_, operationName()).Times(2).WillRepeatedly(Return(OperationName::Egress)); + + NiceMock* span = new NiceMock(); + const std::string operation_name = "egress test"; + EXPECT_CALL(*driver_, startSpan_(_, _, operation_name, stream_info_.start_time_, _)) + .WillOnce(Return(span)); + EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); + EXPECT_CALL(*span, setTag(Eq(Tracing::Tags::get().NodeId), Eq("node_name"))); + + auto parent_span = + tracer_->startSpan(config_, request_headers_, stream_info_, {Reason::Sampling, true}); + + NiceMock* second_span = new NiceMock(); + + EXPECT_CALL(*span, spawnChild_(_, _, _)).WillOnce(Return(second_span)); + auto child_span = + parent_span->spawnChild(config_, "fake child of egress test", stream_info_.start_time_); + + const std::string expected_ip = "10.0.0.100"; + const auto remote_address = Network::Address::InstanceConstSharedPtr{ + new Network::Address::Ipv4Instance(expected_ip, 0, nullptr)}; + + absl::optional protocol = Http::Protocol::Http2; + absl::optional response_code(200); + const std::string cluster_name = "fake cluster"; + const std::string ob_cluster_name = "ob fake cluster"; + EXPECT_CALL(stream_info_, responseCode()).WillRepeatedly(ReturnPointee(&response_code)); + EXPECT_CALL(stream_info_, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + EXPECT_CALL(*(stream_info_.host_), address()).WillOnce(Return(remote_address)); + EXPECT_CALL(stream_info_.host_->cluster_, name()).WillOnce(ReturnRef(cluster_name)); + EXPECT_CALL(stream_info_.host_->cluster_, observabilityName()) + .WillOnce(ReturnRef(ob_cluster_name)); + + EXPECT_CALL(*second_span, setTag(_, _)).Times(testing::AnyNumber()); + EXPECT_CALL(*second_span, setTag(Eq(Tracing::Tags::get().HttpProtocol), Eq("HTTP/2"))); + EXPECT_CALL(*second_span, + setTag(Eq(Tracing::Tags::get().UpstreamAddress), Eq(expected_ip + ":0"))); + EXPECT_CALL(*second_span, setTag(Eq(Tracing::Tags::get().UpstreamCluster), Eq("fake cluster"))); + EXPECT_CALL(*second_span, + setTag(Eq(Tracing::Tags::get().UpstreamClusterName), Eq("ob fake cluster"))); + EXPECT_CALL(*second_span, setTag(Eq(Tracing::Tags::get().HttpStatusCode), Eq("200"))); + EXPECT_CALL(*second_span, setTag(Eq(Tracing::Tags::get().GrpcStatusCode), Eq("7"))); + EXPECT_CALL(*second_span, setTag(Eq(Tracing::Tags::get().GrpcMessage), Eq("permission denied"))); + EXPECT_CALL(*second_span, setTag(Eq(Tracing::Tags::get().Error), Eq(Tracing::Tags::get().True))); + + HttpTracerUtility::finalizeUpstreamSpan(*child_span, &response_headers_, &response_trailers_, + stream_info_, config_); +} + } // namespace } // namespace Tracing } // namespace Envoy diff --git a/test/common/tracing/http_tracer_manager_impl_test.cc b/test/common/tracing/http_tracer_manager_impl_test.cc index 67f802af9edc6..2e34ca1af03ae 100644 --- a/test/common/tracing/http_tracer_manager_impl_test.cc +++ b/test/common/tracing/http_tracer_manager_impl_test.cc @@ -1,6 +1,6 @@ -#include "common/tracing/http_tracer_config_impl.h" #include "common/tracing/http_tracer_impl.h" #include "common/tracing/http_tracer_manager_impl.h" +#include "common/tracing/tracer_config_impl.h" #include "test/mocks/server/instance.h" #include "test/mocks/server/tracer_factory.h" @@ -20,9 +20,9 @@ namespace Envoy { namespace Tracing { namespace { -class SampleTracer : public HttpTracer { +class SampleDriver : public Driver { public: - SpanPtr startSpan(const Config&, Http::RequestHeaderMap&, const StreamInfo::StreamInfo&, + SpanPtr startSpan(const Config&, TraceContext&, const std::string&, SystemTime, const Tracing::Decision) override { return nullptr; } @@ -30,10 +30,10 @@ class SampleTracer : public HttpTracer { class SampleTracerFactory : public Server::Configuration::TracerFactory { public: - Tracing::HttpTracerSharedPtr - createHttpTracer(const Protobuf::Message&, - Server::Configuration::TracerFactoryContext&) override { - return std::make_shared(); + Tracing::DriverSharedPtr + createTracerDriver(const Protobuf::Message&, + Server::Configuration::TracerFactoryContext&) override { + return std::make_shared(); } std::string name() const override { return "envoy.tracers.sample"; } @@ -69,8 +69,11 @@ TEST_F(HttpTracerManagerImplTest, ShouldUseProperTracerFactory) { auto http_tracer = http_tracer_manager_.getOrCreateHttpTracer(&tracing_config); + EXPECT_THAT(http_tracer.get(), WhenDynamicCastTo(NotNull())); + auto http_tracer_impl = dynamic_cast(http_tracer.get()); + // Should use proper TracerFactory. - EXPECT_THAT(http_tracer.get(), WhenDynamicCastTo(NotNull())); + EXPECT_THAT(http_tracer_impl->driverForTest().get(), WhenDynamicCastTo(NotNull())); } TEST_F(HttpTracerManagerImplTest, ShouldCacheAndReuseTracers) { @@ -162,23 +165,25 @@ class HttpTracerManagerImplCacheTest : public testing::Test { }; TEST_F(HttpTracerManagerImplCacheTest, ShouldCacheHttpTracersUsingWeakReferences) { - HttpTracer* expected_tracer = new NiceMock(); + Driver* expected_driver = new NiceMock(); // Expect HttpTracerManager to create a new HttpTracer. - EXPECT_CALL(tracer_factory_, createHttpTracer(_, _)) + EXPECT_CALL(tracer_factory_, createTracerDriver(_, _)) .WillOnce(InvokeWithoutArgs( - [expected_tracer] { return std::shared_ptr(expected_tracer); })); + [expected_driver] { return std::shared_ptr(expected_driver); })); auto actual_tracer_one = http_tracer_manager_.getOrCreateHttpTracer(&tracing_config_one_); - EXPECT_EQ(actual_tracer_one.get(), expected_tracer); + EXPECT_EQ(dynamic_cast(actual_tracer_one.get())->driverForTest().get(), + expected_driver); // Expect a new HttpTracer to be added to the cache. EXPECT_THAT(http_tracer_manager_.peekCachedTracersForTest(), SizeIs(1)); // Expect HttpTracerManager to re-use cached value. auto actual_tracer_two = http_tracer_manager_.getOrCreateHttpTracer(&tracing_config_one_); - EXPECT_EQ(actual_tracer_two.get(), expected_tracer); + EXPECT_EQ(dynamic_cast(actual_tracer_one.get())->driverForTest().get(), + expected_driver); // Expect no changes to the cache. EXPECT_THAT(http_tracer_manager_.peekCachedTracersForTest(), SizeIs(1)); @@ -194,25 +199,26 @@ TEST_F(HttpTracerManagerImplCacheTest, ShouldCacheHttpTracersUsingWeakReferences // Expect no more strong references to be left. EXPECT_EQ(weak_pointer.lock(), nullptr); - HttpTracer* expected_another_tracer = new NiceMock(); + Driver* expected_other_driver = new NiceMock(); // Expect HttpTracerManager to create a new HttpTracer once again. - EXPECT_CALL(tracer_factory_, createHttpTracer(_, _)) - .WillOnce(InvokeWithoutArgs([expected_another_tracer] { - return std::shared_ptr(expected_another_tracer); - })); + EXPECT_CALL(tracer_factory_, createTracerDriver(_, _)) + .WillOnce(InvokeWithoutArgs( + [expected_other_driver] { return std::shared_ptr(expected_other_driver); })); // Use a different config to guarantee that a new cache entry will be added anyway. auto actual_tracer_three = http_tracer_manager_.getOrCreateHttpTracer(&tracing_config_two_); - EXPECT_EQ(actual_tracer_three.get(), expected_another_tracer); + EXPECT_EQ(dynamic_cast(actual_tracer_three.get())->driverForTest().get(), + expected_other_driver); // Expect expired cache entries to be removed and a new HttpTracer to be added to the cache. EXPECT_THAT(http_tracer_manager_.peekCachedTracersForTest(), SizeIs(1)); // Expect HttpTracerManager to keep the right value in the cache. auto actual_tracer_four = http_tracer_manager_.getOrCreateHttpTracer(&tracing_config_two_); - EXPECT_EQ(actual_tracer_four.get(), expected_another_tracer); + EXPECT_EQ(dynamic_cast(actual_tracer_four.get())->driverForTest().get(), + expected_other_driver); // Expect no changes to the cache. EXPECT_THAT(http_tracer_manager_.peekCachedTracersForTest(), SizeIs(1)); } diff --git a/test/extensions/tracers/datadog/config_test.cc b/test/extensions/tracers/datadog/config_test.cc index 6171c0691e767..b591004204317 100644 --- a/test/extensions/tracers/datadog/config_test.cc +++ b/test/extensions/tracers/datadog/config_test.cc @@ -38,7 +38,7 @@ TEST(DatadogTracerConfigTest, DatadogHttpTracer) { DatadogTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr datadog_tracer = factory.createHttpTracer(*message, context); + auto datadog_tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, datadog_tracer); } diff --git a/test/extensions/tracers/dynamic_ot/config_test.cc b/test/extensions/tracers/dynamic_ot/config_test.cc index 951a71ba416e2..3ccabd8b3a3b7 100644 --- a/test/extensions/tracers/dynamic_ot/config_test.cc +++ b/test/extensions/tracers/dynamic_ot/config_test.cc @@ -49,7 +49,7 @@ TEST(DynamicOtTracerConfigTest, DynamicOpentracingHttpTracer) { DynamicOpenTracingTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - const Tracing::HttpTracerSharedPtr tracer = factory.createHttpTracer(*message, context); + auto tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, tracer); } diff --git a/test/extensions/tracers/lightstep/config_test.cc b/test/extensions/tracers/lightstep/config_test.cc index 83167e1de4335..6059f9ab3e938 100644 --- a/test/extensions/tracers/lightstep/config_test.cc +++ b/test/extensions/tracers/lightstep/config_test.cc @@ -41,7 +41,7 @@ TEST(LightstepTracerConfigTest, LightstepHttpTracer) { LightstepTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr lightstep_tracer = factory.createHttpTracer(*message, context); + auto lightstep_tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, lightstep_tracer); } diff --git a/test/extensions/tracers/opencensus/config_test.cc b/test/extensions/tracers/opencensus/config_test.cc index 0de2ac976df5c..ecb6b5d99c1c4 100644 --- a/test/extensions/tracers/opencensus/config_test.cc +++ b/test/extensions/tracers/opencensus/config_test.cc @@ -37,7 +37,7 @@ TEST(OpenCensusTracerConfigTest, InvalidStackdriverConfiguration) { auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - EXPECT_THROW_WITH_MESSAGE((factory.createHttpTracer(*message, context)), EnvoyException, + EXPECT_THROW_WITH_MESSAGE((factory.createTracerDriver(*message, context)), EnvoyException, "Opencensus stackdriver tracer only support GoogleGrpc."); } @@ -60,7 +60,7 @@ TEST(OpenCensusTracerConfigTest, InvalidOcagentConfiguration) { auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - EXPECT_THROW_WITH_MESSAGE((factory.createHttpTracer(*message, context)), EnvoyException, + EXPECT_THROW_WITH_MESSAGE((factory.createTracerDriver(*message, context)), EnvoyException, "Opencensus ocagent tracer only supports GoogleGrpc."); } @@ -77,7 +77,7 @@ TEST(OpenCensusTracerConfigTest, OpenCensusHttpTracer) { OpenCensusTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr tracer = factory.createHttpTracer(*message, context); + auto tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, tracer); } @@ -113,7 +113,7 @@ TEST(OpenCensusTracerConfigTest, OpenCensusHttpTracerWithTypedConfig) { OpenCensusTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr tracer = factory.createHttpTracer(*message, context); + auto tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, tracer); // Reset TraceParams back to default. @@ -147,7 +147,7 @@ TEST(OpenCensusTracerConfigTest, OpenCensusTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr tracer = factory.createHttpTracer(*message, context); + auto tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, tracer); // Reset TraceParams back to default. @@ -188,7 +188,7 @@ TEST(OpenCensusTracerConfigTest, OpenCensusHttpTracerGrpc) { auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); #ifdef ENVOY_GOOGLE_GRPC - Tracing::HttpTracerSharedPtr tracer = factory.createHttpTracer(*message, context); + auto tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, tracer); // Reset TraceParams back to default. @@ -196,7 +196,7 @@ TEST(OpenCensusTracerConfigTest, OpenCensusHttpTracerGrpc) { {32, 32, 128, 32, ::opencensus::trace::ProbabilitySampler(1e-4)}); #else EXPECT_THROW_WITH_MESSAGE( - (factory.createHttpTracer(*message, context)), EnvoyException, + (factory.createTracerDriver(*message, context)), EnvoyException, "Opencensus tracer: cannot handle ocagent google grpc service, google grpc is not built in."); #endif } @@ -219,12 +219,12 @@ TEST(OpenCensusTracerConfigTest, ShouldCreateAtMostOneOpenCensusTracer) { auto message_one = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr tracer_one = factory.createHttpTracer(*message_one, context); + auto tracer_one = factory.createTracerDriver(*message_one, context); EXPECT_NE(nullptr, tracer_one); auto message_two = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr tracer_two = factory.createHttpTracer(*message_two, context); + auto tracer_two = factory.createTracerDriver(*message_two, context); // Verify that no new tracer has been created. EXPECT_EQ(tracer_two, tracer_one); } @@ -242,13 +242,13 @@ TEST(OpenCensusTracerConfigTest, ShouldCacheFirstCreatedTracerUsingStrongReferen auto message_one = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - std::weak_ptr tracer_one = factory.createHttpTracer(*message_one, context); + std::weak_ptr tracer_one = factory.createTracerDriver(*message_one, context); // Verify that tracer factory keeps a strong reference. EXPECT_NE(nullptr, tracer_one.lock()); auto message_two = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr tracer_two = factory.createHttpTracer(*message_two, context); + auto tracer_two = factory.createTracerDriver(*message_two, context); EXPECT_NE(nullptr, tracer_two); // Verify that no new tracer has been created. EXPECT_EQ(tracer_two, tracer_one.lock()); @@ -273,7 +273,7 @@ TEST(OpenCensusTracerConfigTest, ShouldNotCacheInvalidConfiguration) { auto message_one = Config::Utility::translateToFactoryConfig( configuration_one.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - EXPECT_THROW_WITH_MESSAGE((factory.createHttpTracer(*message_one, context)), EnvoyException, + EXPECT_THROW_WITH_MESSAGE((factory.createTracerDriver(*message_one, context)), EnvoyException, "Opencensus ocagent tracer only supports GoogleGrpc."); const std::string yaml_two = R"EOF( @@ -293,12 +293,12 @@ TEST(OpenCensusTracerConfigTest, ShouldNotCacheInvalidConfiguration) { auto message_two = Config::Utility::translateToFactoryConfig( configuration_two.http(), ProtobufMessage::getStrictValidationVisitor(), factory); #ifdef ENVOY_GOOGLE_GRPC - Tracing::HttpTracerSharedPtr tracer_two = factory.createHttpTracer(*message_two, context); + auto tracer_two = factory.createTracerDriver(*message_two, context); // Verify that a new tracer has been created despite an earlier failed attempt. EXPECT_NE(nullptr, tracer_two); #else EXPECT_THROW_WITH_MESSAGE( - (factory.createHttpTracer(*message_two, context)), EnvoyException, + (factory.createTracerDriver(*message_two, context)), EnvoyException, "Opencensus tracer: cannot handle ocagent google grpc service, google grpc is not built in."); #endif } @@ -321,7 +321,7 @@ TEST(OpenCensusTracerConfigTest, ShouldRejectSubsequentCreateAttemptsWithDiffere auto message_one = Config::Utility::translateToFactoryConfig( configuration_one.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr tracer_one = factory.createHttpTracer(*message_one, context); + auto tracer_one = factory.createTracerDriver(*message_one, context); EXPECT_NE(nullptr, tracer_one); const std::string yaml_two = R"EOF( @@ -339,7 +339,7 @@ TEST(OpenCensusTracerConfigTest, ShouldRejectSubsequentCreateAttemptsWithDiffere auto message_two = Config::Utility::translateToFactoryConfig( configuration_two.http(), ProtobufMessage::getStrictValidationVisitor(), factory); // Verify that OpenCensus is only configured once in a lifetime. - EXPECT_THROW_WITH_MESSAGE((factory.createHttpTracer(*message_two, context)), EnvoyException, + EXPECT_THROW_WITH_MESSAGE((factory.createTracerDriver(*message_two, context)), EnvoyException, "Opencensus has already been configured with a different config."); } @@ -367,10 +367,10 @@ TEST(OpenCensusTracerConfigTest, OpenCensusHttpTracerStackdriverGrpc) { auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); #ifdef ENVOY_GOOGLE_GRPC - Tracing::HttpTracerSharedPtr tracer = factory.createHttpTracer(*message, context); + auto tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, tracer); #else - EXPECT_THROW_WITH_MESSAGE((factory.createHttpTracer(*message, context)), EnvoyException, + EXPECT_THROW_WITH_MESSAGE((factory.createTracerDriver(*message, context)), EnvoyException, "Opencensus tracer: cannot handle stackdriver google grpc service, " "google grpc is not built in."); #endif diff --git a/test/extensions/tracers/skywalking/config_test.cc b/test/extensions/tracers/skywalking/config_test.cc index 1f1082298f1fa..f865525e09a3b 100644 --- a/test/extensions/tracers/skywalking/config_test.cc +++ b/test/extensions/tracers/skywalking/config_test.cc @@ -45,7 +45,7 @@ TEST(SkyWalkingTracerConfigTest, SkyWalkingHttpTracer) { SkyWalkingTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr skywalking_tracer = factory.createHttpTracer(*message, context); + auto skywalking_tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, skywalking_tracer); } @@ -79,7 +79,7 @@ TEST(SkyWalkingTracerConfigTest, SkyWalkingHttpTracerWithClientConfig) { SkyWalkingTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr skywalking_tracer = factory.createHttpTracer(*message, context); + auto skywalking_tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, skywalking_tracer); } diff --git a/test/extensions/tracers/xray/config_test.cc b/test/extensions/tracers/xray/config_test.cc index 7008ef0a0c54e..26b613eaec3a9 100644 --- a/test/extensions/tracers/xray/config_test.cc +++ b/test/extensions/tracers/xray/config_test.cc @@ -43,7 +43,7 @@ TEST(XRayTracerConfigTest, XRayHttpTracerWithTypedConfig) { XRayTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr xray_tracer = factory.createHttpTracer(*message, context); + auto xray_tracer = factory.createTracerDriver(*message, context); ASSERT_NE(nullptr, xray_tracer); } @@ -78,7 +78,7 @@ TEST(XRayTracerConfigTest, XRayHttpTracerWithInvalidFileName) { auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr xray_tracer = factory.createHttpTracer(*message, context); + auto xray_tracer = factory.createTracerDriver(*message, context); ASSERT_NE(nullptr, xray_tracer); } @@ -104,7 +104,7 @@ TEST(XRayTracerConfigTest, ProtocolNotUDPThrows) { auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - ASSERT_THROW(factory.createHttpTracer(*message, context), EnvoyException); + ASSERT_THROW(factory.createTracerDriver(*message, context), EnvoyException); } TEST(XRayTracerConfigTest, UsingNamedPortThrows) { @@ -129,7 +129,7 @@ TEST(XRayTracerConfigTest, UsingNamedPortThrows) { auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - ASSERT_THROW(factory.createHttpTracer(*message, context), EnvoyException); + ASSERT_THROW(factory.createTracerDriver(*message, context), EnvoyException); } TEST(XRayTracerConfigTest, XRayHttpTracerWithSegmentFieldsTypedConfig) { @@ -162,7 +162,7 @@ TEST(XRayTracerConfigTest, XRayHttpTracerWithSegmentFieldsTypedConfig) { XRayTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr xray_tracer = factory.createHttpTracer(*message, context); + auto xray_tracer = factory.createTracerDriver(*message, context); ASSERT_NE(nullptr, xray_tracer); } diff --git a/test/extensions/tracers/zipkin/config_test.cc b/test/extensions/tracers/zipkin/config_test.cc index b0219b927665d..945a0e172d446 100644 --- a/test/extensions/tracers/zipkin/config_test.cc +++ b/test/extensions/tracers/zipkin/config_test.cc @@ -39,7 +39,7 @@ TEST(ZipkinTracerConfigTest, ZipkinHttpTracer) { ZipkinTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr zipkin_tracer = factory.createHttpTracer(*message, context); + auto zipkin_tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, zipkin_tracer); } @@ -63,7 +63,7 @@ TEST(ZipkinTracerConfigTest, ZipkinHttpTracerWithTypedConfig) { ZipkinTracerFactory factory; auto message = Config::Utility::translateToFactoryConfig( configuration.http(), ProtobufMessage::getStrictValidationVisitor(), factory); - Tracing::HttpTracerSharedPtr zipkin_tracer = factory.createHttpTracer(*message, context); + auto zipkin_tracer = factory.createTracerDriver(*message, context); EXPECT_NE(nullptr, zipkin_tracer); } diff --git a/test/mocks/server/tracer_factory.h b/test/mocks/server/tracer_factory.h index e342116ee2d5a..c9d4fa73e41b8 100644 --- a/test/mocks/server/tracer_factory.h +++ b/test/mocks/server/tracer_factory.h @@ -16,7 +16,7 @@ class MockTracerFactory : public TracerFactory { std::string name() const override { return name_; } MOCK_METHOD(ProtobufTypes::MessagePtr, createEmptyConfigProto, ()); - MOCK_METHOD(Tracing::HttpTracerSharedPtr, createHttpTracer, + MOCK_METHOD(Tracing::DriverSharedPtr, createTracerDriver, (const Protobuf::Message& config, TracerFactoryContext& context)); private: diff --git a/test/mocks/tracing/mocks.h b/test/mocks/tracing/mocks.h index 2d26d45798022..08605e020550b 100644 --- a/test/mocks/tracing/mocks.h +++ b/test/mocks/tracing/mocks.h @@ -5,6 +5,7 @@ #include "envoy/tracing/http_tracer.h" #include "envoy/tracing/http_tracer_manager.h" +#include "envoy/tracing/trace_driver.h" #include "gmock/gmock.h" @@ -35,7 +36,7 @@ class MockSpan : public Span { MOCK_METHOD(void, setTag, (absl::string_view name, absl::string_view value)); MOCK_METHOD(void, log, (SystemTime timestamp, const std::string& event)); MOCK_METHOD(void, finishSpan, ()); - MOCK_METHOD(void, injectContext, (Http::RequestHeaderMap & request_headers)); + MOCK_METHOD(void, injectContext, (TraceContext & trace_context)); MOCK_METHOD(void, setSampled, (const bool sampled)); MOCK_METHOD(void, setBaggage, (absl::string_view key, absl::string_view value)); MOCK_METHOD(std::string, getBaggage, (absl::string_view key)); @@ -62,7 +63,7 @@ class MockHttpTracer : public HttpTracer { } MOCK_METHOD(Span*, startSpan_, - (const Config& config, Http::HeaderMap& request_headers, + (const Config& config, Http::RequestHeaderMap& request_headers, const StreamInfo::StreamInfo& stream_info, const Tracing::Decision tracing_decision)); }; @@ -72,17 +73,15 @@ class MockDriver : public Driver { MockDriver(); ~MockDriver() override; - SpanPtr startSpan(const Config& config, Http::RequestHeaderMap& request_headers, + SpanPtr startSpan(const Config& config, TraceContext& trace_context, const std::string& operation_name, SystemTime start_time, const Tracing::Decision tracing_decision) override { - return SpanPtr{ - startSpan_(config, request_headers, operation_name, start_time, tracing_decision)}; + return SpanPtr{startSpan_(config, trace_context, operation_name, start_time, tracing_decision)}; } MOCK_METHOD(Span*, startSpan_, - (const Config& config, Http::HeaderMap& request_headers, - const std::string& operation_name, SystemTime start_time, - const Tracing::Decision tracing_decision)); + (const Config& config, TraceContext& trace_context, const std::string& operation_name, + SystemTime start_time, const Tracing::Decision tracing_decision)); }; class MockHttpTracerManager : public HttpTracerManager { diff --git a/test/test_common/utility.h b/test/test_common/utility.h index 4f2d61e4724dc..1a00130ef14d7 100644 --- a/test/test_common/utility.h +++ b/test/test_common/utility.h @@ -12,6 +12,7 @@ #include "envoy/stats/stats.h" #include "envoy/stats/store.h" #include "envoy/thread/thread.h" +#include "envoy/tracing/trace_context.h" #include "envoy/type/matcher/v3/string.pb.h" #include "envoy/type/v3/percent.pb.h" @@ -841,6 +842,31 @@ class ConditionalInitializer { bool ready_ ABSL_GUARDED_BY(mutex_){false}; }; +namespace Tracing { +class TestTraceContextImpl : public TraceContext { +public: + TestTraceContextImpl(const std::initializer_list>& values) { + for (const auto& value : values) { + context_map_[value.first] = value.second; + } + } + + absl::optional getTraceContext(absl::string_view key) const override { + auto iter = context_map_.find(std::string(key)); + if (iter == context_map_.end()) { + return absl::nullopt; + } + return iter->second; + } + + void setTraceContext(absl::string_view key, absl::string_view value) override { + context_map_[std::string(key)] = std::string(value); + } + + absl::flat_hash_map context_map_; +}; +} // namespace Tracing + namespace Http { /** @@ -1054,6 +1080,15 @@ class TestRequestHeaderMapImpl INLINE_REQ_NUMERIC_HEADERS(DEFINE_TEST_INLINE_NUMERIC_HEADER_FUNCS) INLINE_REQ_RESP_STRING_HEADERS(DEFINE_TEST_INLINE_STRING_HEADER_FUNCS) INLINE_REQ_RESP_NUMERIC_HEADERS(DEFINE_TEST_INLINE_NUMERIC_HEADER_FUNCS) + + absl::optional getTraceContext(absl::string_view key) const override { + ASSERT(header_map_); + return header_map_->getTraceContext(key); + } + void setTraceContext(absl::string_view key, absl::string_view value) override { + ASSERT(header_map_); + header_map_->setTraceContext(key, value); + } }; using TestRequestTrailerMapImpl = TestHeaderMapImplBase;