Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/common/random_generator.h" 4 : #include "envoy/config/trace/v3/zipkin.pb.h" 5 : #include "envoy/local_info/local_info.h" 6 : #include "envoy/runtime/runtime.h" 7 : #include "envoy/thread_local/thread_local.h" 8 : #include "envoy/tracing/trace_driver.h" 9 : #include "envoy/upstream/cluster_manager.h" 10 : 11 : #include "source/common/common/empty_string.h" 12 : #include "source/common/http/async_client_utility.h" 13 : #include "source/common/http/header_map_impl.h" 14 : #include "source/common/json/json_loader.h" 15 : #include "source/common/tracing/common_values.h" 16 : #include "source/common/tracing/null_span_impl.h" 17 : #include "source/common/upstream/cluster_update_tracker.h" 18 : #include "source/extensions/tracers/zipkin/span_buffer.h" 19 : #include "source/extensions/tracers/zipkin/tracer.h" 20 : #include "source/extensions/tracers/zipkin/zipkin_core_constants.h" 21 : 22 : namespace Envoy { 23 : namespace Extensions { 24 : namespace Tracers { 25 : namespace Zipkin { 26 : 27 : #define ZIPKIN_TRACER_STATS(COUNTER) \ 28 : COUNTER(spans_sent) \ 29 : COUNTER(timer_flushed) \ 30 : COUNTER(reports_skipped_no_cluster) \ 31 : COUNTER(reports_sent) \ 32 : COUNTER(reports_dropped) \ 33 : COUNTER(reports_failed) 34 : 35 : struct ZipkinTracerStats { 36 : ZIPKIN_TRACER_STATS(GENERATE_COUNTER_STRUCT) 37 : }; 38 : 39 : /** 40 : * Class for Zipkin spans, wrapping a Zipkin::Span object. 41 : */ 42 : class ZipkinSpan : public Tracing::Span { 43 : public: 44 : /** 45 : * Constructor. Wraps a Zipkin::Span object. 46 : * 47 : * @param span to be wrapped. 48 : */ 49 : ZipkinSpan(Zipkin::Span& span, Zipkin::Tracer& tracer); 50 : 51 : /** 52 : * Calls Zipkin::Span::finishSpan() to perform all actions needed to finalize the span. 53 : * This function is called by Tracing::HttpTracerUtility::finalizeSpan(). 54 : */ 55 : void finishSpan() override; 56 : 57 : /** 58 : * This method sets the operation name on the span. 59 : * @param operation the operation name 60 : */ 61 : void setOperation(absl::string_view operation) override; 62 : 63 : /** 64 : * This function adds a Zipkin "string" binary annotation to this span. 65 : * In Zipkin, binary annotations of the type "string" allow arbitrary key-value pairs 66 : * to be associated with a span. 67 : * 68 : * Note that Tracing::HttpTracerUtility::finalizeSpan() makes several calls to this function, 69 : * associating several key-value pairs with this span. 70 : */ 71 : void setTag(absl::string_view name, absl::string_view value) override; 72 : 73 : void log(SystemTime timestamp, const std::string& event) override; 74 : 75 : void injectContext(Tracing::TraceContext& trace_context, 76 : const Upstream::HostDescriptionConstSharedPtr&) override; 77 : Tracing::SpanPtr spawnChild(const Tracing::Config&, const std::string& name, 78 : SystemTime start_time) override; 79 : 80 : void setSampled(bool sampled) override; 81 : 82 : // TODO(#11622): Implement baggage storage for zipkin spans 83 : void setBaggage(absl::string_view, absl::string_view) override; 84 : std::string getBaggage(absl::string_view) override; 85 : 86 : // TODO: This method is unimplemented for Zipkin. 87 0 : std::string getTraceIdAsHex() const override { return EMPTY_STRING; }; 88 : 89 : /** 90 : * @return a reference to the Zipkin::Span object. 91 : */ 92 0 : Zipkin::Span& span() { return span_; } 93 : 94 : private: 95 : Zipkin::Span span_; 96 : Zipkin::Tracer& tracer_; 97 : }; 98 : 99 : using ZipkinSpanPtr = std::unique_ptr<ZipkinSpan>; 100 : 101 : /** 102 : * Class for a Zipkin-specific Driver. 103 : */ 104 : class Driver : public Tracing::Driver { 105 : public: 106 : /** 107 : * Constructor. It adds itself and a newly-created Zipkin::Tracer object to a thread-local store. 108 : * Also, it associates the given random-number generator to the Zipkin::Tracer object it creates. 109 : */ 110 : Driver(const envoy::config::trace::v3::ZipkinConfig& zipkin_config, 111 : Upstream::ClusterManager& cluster_manager, Stats::Scope& scope, 112 : ThreadLocal::SlotAllocator& tls, Runtime::Loader& runtime, 113 : const LocalInfo::LocalInfo& localinfo, Random::RandomGenerator& random_generator, 114 : TimeSource& time_source); 115 : 116 : /** 117 : * This function is inherited from the abstract Driver class. 118 : * 119 : * It starts a new Zipkin span. Depending on the request headers, it can create a root span, 120 : * a child span, or a shared-context span. 121 : * 122 : * The third parameter (operation_name) does not actually make sense for Zipkin. 123 : * Thus, this implementation of the virtual function startSpan() ignores the operation name 124 : * ("ingress" or "egress") passed by the caller. 125 : */ 126 : Tracing::SpanPtr startSpan(const Tracing::Config& config, Tracing::TraceContext& trace_context, 127 : const StreamInfo::StreamInfo& stream_info, 128 : const std::string& operation_name, 129 : Tracing::Decision tracing_decision) override; 130 : 131 : // Getters to return the ZipkinDriver's key members. 132 0 : Upstream::ClusterManager& clusterManager() { return cm_; } 133 0 : const std::string& cluster() { return cluster_; } 134 0 : const std::string& hostname() { return hostname_; } 135 0 : Runtime::Loader& runtime() { return runtime_; } 136 0 : ZipkinTracerStats& tracerStats() { return tracer_stats_; } 137 : 138 : private: 139 : /** 140 : * Thread-local store containing ZipkinDriver and Zipkin::Tracer objects. 141 : */ 142 : struct TlsTracer : ThreadLocal::ThreadLocalObject { 143 : TlsTracer(TracerPtr&& tracer, Driver& driver); 144 : 145 : TracerPtr tracer_; 146 : Driver& driver_; 147 : }; 148 : 149 : Upstream::ClusterManager& cm_; 150 : std::string cluster_; 151 : std::string hostname_; 152 : ZipkinTracerStats tracer_stats_; 153 : ThreadLocal::SlotPtr tls_; 154 : Runtime::Loader& runtime_; 155 : const LocalInfo::LocalInfo& local_info_; 156 : TimeSource& time_source_; 157 : }; 158 : 159 : /** 160 : * Information about the Zipkin collector. 161 : */ 162 : struct CollectorInfo { 163 : // The Zipkin collector endpoint/path to receive the collected trace data. 164 : std::string endpoint_; 165 : 166 : // The version of the collector. This is related to endpoint's supported payload specification and 167 : // transport. 168 : envoy::config::trace::v3::ZipkinConfig::CollectorEndpointVersion version_; 169 : 170 : bool shared_span_context_{DEFAULT_SHARED_SPAN_CONTEXT}; 171 : }; 172 : 173 : /** 174 : * This class derives from the abstract Zipkin::Reporter. 175 : * It buffers spans and relies on Http::AsyncClient to send spans to 176 : * Zipkin using JSON over HTTP. 177 : * 178 : * Two runtime parameters control the span buffering/flushing behavior, namely: 179 : * tracing.zipkin.min_flush_spans and tracing.zipkin.flush_interval_ms. 180 : * 181 : * Up to `tracing.zipkin.min_flush_spans` will be buffered. Spans are flushed (sent to Zipkin) 182 : * either when the buffer is full, or when a timer, set to `tracing.zipkin.flush_interval_ms`, 183 : * expires, whichever happens first. 184 : * 185 : * The default values for the runtime parameters are 5 spans and 5000ms. 186 : */ 187 : class ReporterImpl : Logger::Loggable<Logger::Id::tracing>, 188 : public Reporter, 189 : public Http::AsyncClient::Callbacks { 190 : public: 191 : /** 192 : * Constructor. 193 : * 194 : * @param driver ZipkinDriver to be associated with the reporter. 195 : * @param dispatcher Controls the timer used to flush buffered spans. 196 : * @param collector holds the endpoint version and path information. 197 : * when making HTTP POST requests carrying spans. This value comes from the 198 : * Zipkin-related tracing configuration. 199 : */ 200 : ReporterImpl(Driver& driver, Event::Dispatcher& dispatcher, const CollectorInfo& collector); 201 : 202 : /** 203 : * Implementation of Zipkin::Reporter::reportSpan(). 204 : * 205 : * Buffers the given span and calls flushSpans() if the buffer is full. 206 : * 207 : * @param span The span to be buffered. 208 : */ 209 : void reportSpan(Span&& span) override; 210 : 211 : // Http::AsyncClient::Callbacks. 212 : // The callbacks below record Zipkin-span-related stats. 213 : void onSuccess(const Http::AsyncClient::Request&, Http::ResponseMessagePtr&&) override; 214 : void onFailure(const Http::AsyncClient::Request&, Http::AsyncClient::FailureReason) override; 215 0 : void onBeforeFinalizeUpstreamSpan(Tracing::Span&, const Http::ResponseHeaderMap*) override {} 216 : 217 : /** 218 : * Creates a heap-allocated ZipkinReporter. 219 : * 220 : * @param driver ZipkinDriver to be associated with the reporter. 221 : * @param dispatcher Controls the timer used to flush buffered spans. 222 : * @param collector holds the endpoint version and path information. 223 : * when making HTTP POST requests carrying spans. This value comes from the 224 : * Zipkin-related tracing configuration. 225 : * 226 : * @return Pointer to the newly-created ZipkinReporter. 227 : */ 228 : static ReporterPtr newInstance(Driver& driver, Event::Dispatcher& dispatcher, 229 : const CollectorInfo& collector); 230 : 231 : private: 232 : /** 233 : * Enables the span-flushing timer. 234 : */ 235 : void enableTimer(); 236 : 237 : /** 238 : * Removes all spans from the span buffer and sends them to Zipkin using Http::AsyncClient. 239 : */ 240 : void flushSpans(); 241 : 242 : Driver& driver_; 243 : Event::TimerPtr flush_timer_; 244 : const CollectorInfo collector_; 245 : SpanBufferPtr span_buffer_; 246 : Upstream::ClusterUpdateTracker collector_cluster_; 247 : // Track active HTTP requests to be able to cancel them on destruction. 248 : Http::AsyncClientRequestTracker active_requests_; 249 : }; 250 : } // namespace Zipkin 251 : } // namespace Tracers 252 : } // namespace Extensions 253 : } // namespace Envoy