LCOV - code coverage report
Current view: top level - source/extensions/tracers/common/ot - opentracing_driver_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 0 130 0.0 %
Date: 2024-01-05 06:35:25 Functions: 0 19 0.0 %

          Line data    Source code
       1             : #include "source/extensions/tracers/common/ot/opentracing_driver_impl.h"
       2             : 
       3             : #include <sstream>
       4             : 
       5             : #include "envoy/stats/scope.h"
       6             : 
       7             : #include "source/common/common/assert.h"
       8             : #include "source/common/common/base64.h"
       9             : #include "source/common/common/utility.h"
      10             : #include "source/common/http/header_map_impl.h"
      11             : #include "source/common/tracing/common_values.h"
      12             : #include "source/common/tracing/null_span_impl.h"
      13             : #include "source/common/tracing/trace_context_impl.h"
      14             : 
      15             : namespace Envoy {
      16             : namespace Extensions {
      17             : namespace Tracers {
      18             : namespace Common {
      19             : namespace Ot {
      20             : 
      21             : Http::RegisterCustomInlineHeader<Http::CustomInlineHeaderRegistry::Type::RequestHeaders>
      22             :     ot_span_context_handle(Http::CustomHeaders::get().OtSpanContext);
      23             : 
      24             : namespace {
      25             : 
      26           0 : const Tracing::TraceContextHandler& otSpanContextHeader() {
      27           0 :   CONSTRUCT_ON_FIRST_USE(Tracing::TraceContextHandler, Http::CustomHeaders::get().OtSpanContext);
      28           0 : }
      29             : 
      30             : /**
      31             :  * TODO(wbpcode): Use opentracing::TextMapWriter to replace opentracing::HTTPHeadersWriter.
      32             :  */
      33             : class OpenTracingHeadersWriter : public opentracing::HTTPHeadersWriter {
      34             : public:
      35             :   explicit OpenTracingHeadersWriter(Tracing::TraceContext& trace_context)
      36           0 :       : trace_context_(trace_context) {}
      37             : 
      38             :   // opentracing::HTTPHeadersWriter
      39             :   opentracing::expected<void> Set(opentracing::string_view key,
      40           0 :                                   opentracing::string_view value) const override {
      41           0 :     Http::LowerCaseString lowercase_key{{key.data(), key.size()}};
      42           0 :     trace_context_.set(lowercase_key, {value.data(), value.size()});
      43           0 :     return {};
      44           0 :   }
      45             : 
      46             : private:
      47             :   Tracing::TraceContext& trace_context_;
      48             : };
      49             : 
      50             : /**
      51             :  * TODO(wbpcode): Use opentracing::TextMapReader to replace opentracing::HTTPHeadersReader.
      52             :  */
      53             : class OpenTracingHeadersReader : public opentracing::HTTPHeadersReader {
      54             : public:
      55             :   explicit OpenTracingHeadersReader(const Tracing::TraceContext& trace_context)
      56           0 :       : trace_context_(trace_context) {}
      57             : 
      58             :   using OpenTracingCb = std::function<opentracing::expected<void>(opentracing::string_view,
      59             :                                                                   opentracing::string_view)>;
      60             : 
      61             :   // opentracing::HTTPHeadersReader
      62             :   opentracing::expected<opentracing::string_view>
      63           0 :   LookupKey(opentracing::string_view key) const override {
      64           0 :     Http::LowerCaseString lowercase_key{{key.data(), key.size()}};
      65           0 :     const auto entry = trace_context_.get(lowercase_key);
      66           0 :     if (entry.has_value()) {
      67           0 :       return opentracing::string_view{entry.value().data(), entry.value().length()};
      68           0 :     } else {
      69           0 :       return opentracing::make_unexpected(opentracing::key_not_found_error);
      70           0 :     }
      71           0 :   }
      72             : 
      73           0 :   opentracing::expected<void> ForeachKey(OpenTracingCb f) const override {
      74           0 :     trace_context_.forEach([cb = std::move(f)](absl::string_view key, absl::string_view val) {
      75           0 :       opentracing::string_view opentracing_key{key.data(), key.length()};
      76           0 :       opentracing::string_view opentracing_val{val.data(), val.length()};
      77           0 :       return static_cast<bool>(cb(opentracing_key, opentracing_val));
      78           0 :     });
      79           0 :     return {};
      80           0 :   }
      81             : 
      82             : private:
      83             :   const Tracing::TraceContext& trace_context_;
      84             : };
      85             : } // namespace
      86             : 
      87             : OpenTracingSpan::OpenTracingSpan(OpenTracingDriver& driver,
      88             :                                  std::unique_ptr<opentracing::Span>&& span)
      89           0 :     : driver_{driver}, span_(std::move(span)) {}
      90             : 
      91           0 : void OpenTracingSpan::finishSpan() { span_->FinishWithOptions(finish_options_); }
      92             : 
      93           0 : void OpenTracingSpan::setOperation(absl::string_view operation) {
      94           0 :   span_->SetOperationName({operation.data(), operation.length()});
      95           0 : }
      96             : 
      97           0 : void OpenTracingSpan::setTag(absl::string_view name, absl::string_view value) {
      98           0 :   span_->SetTag({name.data(), name.length()},
      99           0 :                 opentracing::v2::string_view{value.data(), value.length()});
     100           0 : }
     101             : 
     102           0 : void OpenTracingSpan::log(SystemTime timestamp, const std::string& event) {
     103           0 :   opentracing::LogRecord record{timestamp, {{Tracing::Logs::get().EventKey, event}}};
     104           0 :   finish_options_.log_records.emplace_back(std::move(record));
     105           0 : }
     106             : 
     107           0 : void OpenTracingSpan::setBaggage(absl::string_view key, absl::string_view value) {
     108           0 :   span_->SetBaggageItem({key.data(), key.length()}, {value.data(), value.length()});
     109           0 : }
     110             : 
     111           0 : std::string OpenTracingSpan::getBaggage(absl::string_view key) {
     112           0 :   return span_->BaggageItem({key.data(), key.length()});
     113           0 : }
     114             : 
     115             : void OpenTracingSpan::injectContext(Tracing::TraceContext& trace_context,
     116           0 :                                     const Upstream::HostDescriptionConstSharedPtr&) {
     117           0 :   if (driver_.propagationMode() == OpenTracingDriver::PropagationMode::SingleHeader) {
     118             :     // Inject the span context using Envoy's single-header format.
     119           0 :     std::ostringstream oss;
     120           0 :     const opentracing::expected<void> was_successful =
     121           0 :         span_->tracer().Inject(span_->context(), oss);
     122           0 :     if (!was_successful) {
     123           0 :       ENVOY_LOG(debug, "Failed to inject span context: {}", was_successful.error().message());
     124           0 :       driver_.tracerStats().span_context_injection_error_.inc();
     125           0 :       return;
     126           0 :     }
     127           0 :     const std::string current_span_context = oss.str();
     128           0 :     otSpanContextHeader().setRefKey(
     129           0 :         trace_context, Base64::encode(current_span_context.c_str(), current_span_context.length()));
     130           0 :   } else {
     131             :     // Inject the context using the tracer's standard header format.
     132           0 :     const OpenTracingHeadersWriter writer{trace_context};
     133           0 :     const opentracing::expected<void> was_successful =
     134           0 :         span_->tracer().Inject(span_->context(), writer);
     135           0 :     if (!was_successful) {
     136           0 :       ENVOY_LOG(debug, "Failed to inject span context: {}", was_successful.error().message());
     137           0 :       driver_.tracerStats().span_context_injection_error_.inc();
     138           0 :       return;
     139           0 :     }
     140           0 :   }
     141           0 : }
     142             : 
     143           0 : void OpenTracingSpan::setSampled(bool sampled) {
     144           0 :   span_->SetTag(opentracing::ext::sampling_priority, sampled ? 1 : 0);
     145           0 : }
     146             : 
     147             : Tracing::SpanPtr OpenTracingSpan::spawnChild(const Tracing::Config&, const std::string& name,
     148           0 :                                              SystemTime start_time) {
     149           0 :   std::unique_ptr<opentracing::Span> ot_span = span_->tracer().StartSpan(
     150           0 :       name, {opentracing::ChildOf(&span_->context()), opentracing::StartTimestamp(start_time)});
     151           0 :   RELEASE_ASSERT(ot_span != nullptr, "");
     152           0 :   return Tracing::SpanPtr{new OpenTracingSpan{driver_, std::move(ot_span)}};
     153           0 : }
     154             : 
     155             : OpenTracingDriver::OpenTracingDriver(Stats::Scope& scope)
     156           0 :     : tracer_stats_{OPENTRACING_TRACER_STATS(POOL_COUNTER_PREFIX(scope, "tracing.opentracing."))} {}
     157             : 
     158             : Tracing::SpanPtr OpenTracingDriver::startSpan(const Tracing::Config& config,
     159             :                                               Tracing::TraceContext& trace_context,
     160             :                                               const StreamInfo::StreamInfo& stream_info,
     161             :                                               const std::string& operation_name,
     162           0 :                                               Tracing::Decision tracing_decision) {
     163           0 :   const PropagationMode propagation_mode = this->propagationMode();
     164           0 :   const opentracing::Tracer& tracer = this->tracer();
     165           0 :   std::unique_ptr<opentracing::Span> active_span;
     166           0 :   std::unique_ptr<opentracing::SpanContext> parent_span_ctx;
     167             : 
     168           0 :   const auto entry = otSpanContextHeader().get(trace_context);
     169           0 :   if (propagation_mode == PropagationMode::SingleHeader && entry.has_value()) {
     170           0 :     opentracing::expected<std::unique_ptr<opentracing::SpanContext>> parent_span_ctx_maybe;
     171           0 :     std::string parent_context = Base64::decode(std::string(entry.value()));
     172             : 
     173           0 :     if (!parent_context.empty()) {
     174           0 :       InputConstMemoryStream istream{parent_context.data(), parent_context.size()};
     175           0 :       parent_span_ctx_maybe = tracer.Extract(istream);
     176           0 :     } else {
     177           0 :       parent_span_ctx_maybe =
     178           0 :           opentracing::make_unexpected(opentracing::span_context_corrupted_error);
     179           0 :     }
     180             : 
     181           0 :     if (parent_span_ctx_maybe) {
     182           0 :       parent_span_ctx = std::move(*parent_span_ctx_maybe);
     183           0 :     } else {
     184           0 :       ENVOY_LOG(debug, "Failed to extract span context: {}",
     185           0 :                 parent_span_ctx_maybe.error().message());
     186           0 :       tracerStats().span_context_extraction_error_.inc();
     187           0 :     }
     188           0 :   } else if (propagation_mode == PropagationMode::TracerNative) {
     189           0 :     const OpenTracingHeadersReader reader{trace_context};
     190           0 :     opentracing::expected<std::unique_ptr<opentracing::SpanContext>> parent_span_ctx_maybe =
     191           0 :         tracer.Extract(reader);
     192           0 :     if (parent_span_ctx_maybe) {
     193           0 :       parent_span_ctx = std::move(*parent_span_ctx_maybe);
     194           0 :     } else {
     195           0 :       ENVOY_LOG(debug, "Failed to extract span context: {}",
     196           0 :                 parent_span_ctx_maybe.error().message());
     197           0 :       tracerStats().span_context_extraction_error_.inc();
     198           0 :     }
     199           0 :   }
     200           0 :   opentracing::StartSpanOptions options;
     201           0 :   options.references.emplace_back(opentracing::SpanReferenceType::ChildOfRef,
     202           0 :                                   parent_span_ctx.get());
     203           0 :   options.start_system_timestamp = stream_info.startTime();
     204           0 :   if (!tracing_decision.traced) {
     205           0 :     options.tags.emplace_back(opentracing::ext::sampling_priority, 0);
     206           0 :   }
     207           0 :   active_span = tracer.StartSpanWithOptions(operation_name, options);
     208           0 :   RELEASE_ASSERT(active_span != nullptr, "");
     209           0 :   active_span->SetTag(opentracing::ext::span_kind,
     210           0 :                       config.operationName() == Tracing::OperationName::Egress
     211           0 :                           ? opentracing::ext::span_kind_rpc_client
     212           0 :                           : opentracing::ext::span_kind_rpc_server);
     213           0 :   return Tracing::SpanPtr{new OpenTracingSpan{*this, std::move(active_span)}};
     214           0 : }
     215             : 
     216             : } // namespace Ot
     217             : } // namespace Common
     218             : } // namespace Tracers
     219             : } // namespace Extensions
     220             : } // namespace Envoy

Generated by: LCOV version 1.15