envoy tracer 模块分析

同事给我的关于tracer 的分享:

envoy code trace

source/common/http/conn_manager_impl.cc: : 828
void ConnectionManagerImpl::ActiveStream::decodeHeaders(RequestHeaderMapPtr&& headers,
                                                        bool end_stream) {

....
  // Check if tracing is enabled at all.
  if (connection_manager_.config_.tracingConfig()) {
    traceRequest();
  }
}

source/common/http/conn_manager_impl.cc: 1064

active_span_ = connection_manager_.tracer().startSpan(
      *this, *request_headers_, filter_manager_.streamInfo(), tracing_decision);

void ConnectionManagerImpl::ActiveStream::traceRequest() {
  const Tracing::Decision tracing_decision =
      Tracing::HttpTracerUtility::shouldTraceRequest(filter_manager_.streamInfo());
  ConnectionManagerImpl::chargeTracingStats(tracing_decision.reason,
                                            connection_manager_.config_.tracingStats());

  active_span_ = connection_manager_.tracer().startSpan(
      *this, *request_headers_, filter_manager_.streamInfo(), tracing_decision);

  if (!active_span_) {
    return;
  }

  // TODO: Need to investigate the following code based on the cached route, as may
  // be broken in the case a filter changes the route.

  // If a decorator has been defined, apply it to the active span.
  if (hasCachedRoute() && cached_route_.value()->decorator()) {
    const Router::Decorator* decorator = cached_route_.value()->decorator();

    decorator->apply(*active_span_);

    state_.decorated_propagate_ = decorator->propagate();

    // Cache decorated operation.
    if (!decorator->getOperation().empty()) {
      decorated_operation_ = &decorator->getOperation();
    }
  }

  if (connection_manager_.config_.tracingConfig()->operation_name_ ==
      Tracing::OperationName::Egress) {
    // For egress (outbound) requests, pass the decorator's operation name (if defined and
    // propagation enabled) as a request header to enable the receiving service to use it in its
    // server span.
    if (decorated_operation_ && state_.decorated_propagate_) {
      request_headers_->setEnvoyDecoratorOperation(*decorated_operation_);
    }
  } else {
    const HeaderEntry* req_operation_override = request_headers_->EnvoyDecoratorOperation();

    // For ingress (inbound) requests, if a decorator operation name has been provided, it
    // should be used to override the active span's operation.
    if (req_operation_override) {
      if (!req_operation_override->value().empty()) {
        active_span_->setOperation(req_operation_override->value().getStringView());

        // Clear the decorated operation so won't be used in the response header, as
        // it has been overridden by the inbound decorator operation request header.
        decorated_operation_ = nullptr;
      }
      // Remove header so not propagated to service
      request_headers_->removeEnvoyDecoratorOperation();
    }
  }
}

source/common/tracing/http_tracer_impl.h: 97

class HttpTracerImpl : public HttpTracer {
public:
  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:
  DriverSharedPtr driver_;
  const LocalInfo::LocalInfo& local_info_;
};


source/common/tracing/http_tracer_impl.cc: 259

构造中的DriverSharedPtr driver : 应该就是zipkin (default)

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,
                                  const StreamInfo::StreamInfo& stream_info,
                                  const Tracing::Decision tracing_decision) {
  std::string span_name = HttpTracerUtility::toString(config.operationName());

  if (config.operationName() == OperationName::Egress) {
    span_name.append(" ");
    span_name.append(std::string(request_headers.getHostValue()));
  }

  SpanPtr active_span = driver_->startSpan(config, request_headers, span_name,
                                           stream_info.startTime(), tracing_decision);

  // Set tags related to the local environment
  if (active_span) {
    active_span->setTag(Tracing::Tags::get().NodeId, local_info_.nodeName());
    active_span->setTag(Tracing::Tags::get().Zone, local_info_.zoneName());
  }

  return active_span;
}

source/extensions/tracers/zipkin/tracer.cc : 57 
两个接口: 
一: 没有父节点

SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name,
                          SystemTime timestamp) 


二: 有父节点                          

SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name,
                          SystemTime timestamp, const SpanContext& previous_context) {
  SpanPtr span_ptr = std::make_unique<Span>(time_source_);
  Annotation annotation;
  uint64_t timestamp_micro;

  timestamp_micro =
      std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count();

  span_ptr->setName(span_name);

  // Set the span's kind (client or server)
  if (config.operationName() == Tracing::OperationName::Egress) {
    annotation.setValue(CLIENT_SEND);
  } else {
    annotation.setValue(SERVER_RECV);
  }

  // Set the span's id and parent id
  if (config.operationName() == Tracing::OperationName::Egress || !shared_span_context_) {
    // We need to create a new span that is a child of the previous span; no shared context

    // Create a new span id
    uint64_t random_number = random_generator_.random();
    span_ptr->setId(random_number);

    // Set the parent id to the id of the previous span
    span_ptr->setParentId(previous_context.id());

    // Set the timestamp globally for the span
    span_ptr->setTimestamp(timestamp_micro);
  } else if (config.operationName() == Tracing::OperationName::Ingress) {
    // We need to create a new span that will share context with the previous span

    // Initialize the shared context for the new span
    span_ptr->setId(previous_context.id());
    if (previous_context.parentId()) {
      span_ptr->setParentId(previous_context.parentId());
    }
  } else {
    return span_ptr; // return an empty span
  }

  // Build the endpoint
  Endpoint ep(service_name_, address_);

  // Add the newly-created annotation to the span
  annotation.setEndpoint(std::move(ep));
  annotation.setTimestamp(timestamp_micro);
  span_ptr->addAnnotation(std::move(annotation));

  // Keep the same trace id
  span_ptr->setTraceId(previous_context.traceId());
  if (previous_context.is128BitTraceId()) {
    span_ptr->setTraceIdHigh(previous_context.traceIdHigh());
  }

  // Keep the same sampled flag
  span_ptr->setSampled(previous_context.sampled());

  int64_t start_time_micro = std::chrono::duration_cast<std::chrono::microseconds>(
                                 time_source_.monotonicTime().time_since_epoch())
                                 .count();
  span_ptr->setStartTime(start_time_micro);

  span_ptr->setTracer(this);

  return span_ptr;
}

zipkin driver 构造函数信息
source/extensions/tracers/zipkin/zipkin_tracer_impl.cc : 72

Driver::Driver(const envoy::config::trace::v3::ZipkinConfig& zipkin_config,
               Upstream::ClusterManager& cluster_manager, Stats::Scope& scope,
               ThreadLocal::SlotAllocator& tls, Runtime::Loader& runtime,
               const LocalInfo::LocalInfo& local_info, Random::RandomGenerator& random_generator,
               TimeSource& time_source)
    : cm_(cluster_manager), tracer_stats_{ZIPKIN_TRACER_STATS(
                                POOL_COUNTER_PREFIX(scope, "tracing.zipkin."))},
      tls_(tls.allocateSlot()), runtime_(runtime), local_info_(local_info),
      time_source_(time_source)


      
      
      
      
上报span信息 : 
source/extensions/tracers/zipkin/zipkin_tracer_impl.cc: 165 

ReporterImpl::reportSpan -> ReporterImpl::flushSpans
void ReporterImpl::reportSpan(Span&& span) {
  span_buffer_->addSpan(std::move(span));

  const uint64_t min_flush_spans =
      driver_.runtime().snapshot().getInteger("tracing.zipkin.min_flush_spans", 5U);

  if (span_buffer_->pendingSpans() == min_flush_spans) {
    flushSpans();
  }
}


source/extensions/tracers/zipkin/zipkin_tracer_impl.cc : 182 
序列化并发送请求给 zipkin server

void ReporterImpl::flushSpans() {
  if (span_buffer_->pendingSpans()) {
    driver_.tracerStats().spans_sent_.add(span_buffer_->pendingSpans());
    const std::string request_body = span_buffer_->serialize();
    Http::RequestMessagePtr message = std::make_unique<Http::RequestMessageImpl>();
    message->headers().setReferenceMethod(Http::Headers::get().MethodValues.Post);
    message->headers().setPath(collector_.endpoint_);
    message->headers().setHost(driver_.hostname());
    message->headers().setReferenceContentType(
        collector_.version_ == envoy::config::trace::v3::ZipkinConfig::HTTP_PROTO
            ? Http::Headers::get().ContentTypeValues.Protobuf
            : Http::Headers::get().ContentTypeValues.Json);

    message->body().add(request_body);

    const uint64_t timeout =
        driver_.runtime().snapshot().getInteger("tracing.zipkin.request_timeout", 5000U);

    if (collector_cluster_.threadLocalCluster().has_value()) {
      Http::AsyncClient::Request* request =
          collector_cluster_.threadLocalCluster()->get().httpAsyncClient().send(
              std::move(message), *this,
              Http::AsyncClient::RequestOptions().setTimeout(std::chrono::milliseconds(timeout)));
      if (request) {
        active_requests_.add(*request);
      }
    } else {
      ENVOY_LOG(debug, "collector cluster '{}' does not exist", driver_.cluster());
      driver_.tracerStats().reports_skipped_no_cluster_.inc();
    }

    span_buffer_->clear();
  }
}      
source/extensions/tracers/zipkin/span_buffer.cc: 62 spanbuffer 序列化  
zipkin_span.toJson()

std::string JsonV1Serializer::serialize(const std::vector<Span>& zipkin_spans) {
  const std::string serialized_elements =
      absl::StrJoin(zipkin_spans, ",", [](std::string* element, const Span& zipkin_span) {
        absl::StrAppend(element, zipkin_span.toJson());
      });
  return absl::StrCat("[", serialized_elements, "]");
}


结束计时: 
source/extensions/tracers/zipkin/zipkin_tracer_impl.cc: 24

void ZipkinSpan::finishSpan() { span_.finish(); }


Span::finish()内部:setDuration
  if (monotonic_start_time_) {
    const int64_t monotonic_stop_time = std::chrono::duration_cast<std::chrono::microseconds>(
                                            time_source_.monotonicTime().time_since_epoch())
                                            .count();
    setDuration(monotonic_stop_time - monotonic_start_time_);
  }
  
source/extensions/tracers/zipkin/zipkin_core_types.h : 415
  /**
   * Sets the span's duration attribute.
   */
  void setDuration(const int64_t val) { duration_ = val; }
source/extensions/tracers/zipkin/zipkin_core_types.cc: 190
void Span::finish() {
  // Assumption: Span will have only one annotation when this method is called.
  SpanContext context(*this);
  if (annotations_[0].value() == SERVER_RECV) {
    // Need to set the SS annotation
    Annotation ss;
    ss.setEndpoint(annotations_[0].endpoint());
    ss.setTimestamp(std::chrono::duration_cast<std::chrono::microseconds>(
                        time_source_.systemTime().time_since_epoch())
                        .count());
    ss.setValue(SERVER_SEND);
    annotations_.push_back(std::move(ss));
  } else if (annotations_[0].value() == CLIENT_SEND) {
    // Need to set the CR annotation.
    Annotation cr;
    const uint64_t stop_timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
                                        time_source_.systemTime().time_since_epoch())
                                        .count();
    cr.setEndpoint(annotations_[0].endpoint());
    cr.setTimestamp(stop_timestamp);
    cr.setValue(CLIENT_RECV);
    annotations_.push_back(std::move(cr));
  }

  if (monotonic_start_time_) {
    const int64_t monotonic_stop_time = std::chrono::duration_cast<std::chrono::microseconds>(
                                            time_source_.monotonicTime().time_since_epoch())
                                            .count();
    setDuration(monotonic_stop_time - monotonic_start_time_);
  }

  if (auto t = tracer()) {
    t->reportSpan(std::move(*this));
  }
}

source/common/http/filter_manager.cc:  1290 

FilterManager::encodeTrailers -> FilterManager::maybeEndEncode -> filter_manager_callbacks_.endStream() 
->connection_manager_.doEndStream(*this); -> 

void FilterManager::encodeTrailers(ActiveStreamEncoderFilter* filter,
                                   ResponseTrailerMap& trailers) {
  filter_manager_callbacks_.resetIdleTimer();

  // Filter iteration may start at the current filter.
  std::list<ActiveStreamEncoderFilterPtr>::iterator entry =
      commonEncodePrefix(filter, true, FilterIterationStartState::CanStartFromCurrent);
  for (; entry != encoder_filters_.end(); entry++) {
    (*entry)->maybeEvaluateMatchTreeWithNewData(
        [&](auto& matching_data) { matching_data.onResponseTrailers(trailers); });

    if ((*entry)->skipFilter()) {
      continue;
    }

    // If the filter pointed by entry has stopped for all frame type, return now.
    if ((*entry)->stoppedAll()) {
      return;
    }
    ASSERT(!(state_.filter_call_state_ & FilterCallState::EncodeTrailers));
    state_.filter_call_state_ |= FilterCallState::EncodeTrailers;
    FilterTrailersStatus status = (*entry)->handle_->encodeTrailers(trailers);
    (*entry)->handle_->encodeComplete();
    (*entry)->end_stream_ = true;
    state_.filter_call_state_ &= ~FilterCallState::EncodeTrailers;
    ENVOY_STREAM_LOG(trace, "encode trailers called: filter={} status={}", *this,
                     static_cast<const void*>((*entry).get()), static_cast<uint64_t>(status));
    if (!(*entry)->commonHandleAfterTrailersCallback(status)) {
      return;
    }
  }

  filter_manager_callbacks_.encodeTrailers(trailers);
  maybeEndEncode(true);
}


source/common/http/filter_manager.cc: 1326:

void FilterManager::maybeEndEncode(bool end_stream) {
  if (end_stream) {
    filter_manager_callbacks_.endStream();
  }
}


source/common/http/conn_manager_impl.h: 252:
正常关闭: 
   

void ActiveStream :: endStream() override {
      ASSERT(!state_.codec_saw_local_complete_);
      state_.codec_saw_local_complete_ = true;
      filter_manager_.streamInfo().onLastDownstreamTxByteSent();
      request_response_timespan_->complete();
      connection_manager_.doEndStream(*this);
    }

source/common/http/conn_manager_impl.cc: 188
ConnectionManagerImpl::doEndStream(ActiveStream& stream) {
if (!reset_stream) {
    doDeferredStreamDestroy(stream);
  }
}


或者:

void ConnectionManagerImpl::ActiveStream::onResetStream(StreamResetReason reset_reason,
                                                        absl::string_view) {
                                                        connection_manager_.doDeferredStreamDestroy(*this);
                                                        }

void ConnectionManagerImpl::doDeferredStreamDestroy(ActiveStream& stream) {
stream.completeRequest();
}

ConnectionManagerImpl: http Network::Filter 

source/common/http/conn_manager_impl.cc : 688 
请求结束,关闭span

void ConnectionManagerImpl::ActiveStream::completeRequest() {
  filter_manager_.streamInfo().onRequestComplete();

  if (connection_manager_.remote_close_) {
    filter_manager_.streamInfo().setResponseCodeDetails(
        StreamInfo::ResponseCodeDetails::get().DownstreamRemoteDisconnect);
    filter_manager_.streamInfo().setResponseFlag(
        StreamInfo::ResponseFlag::DownstreamConnectionTermination);
  }
  // TODO(danzh) bring HTTP/3 to parity here.
  if (connection_manager_.codec_->protocol() != Protocol::Http3) {
    ASSERT(filter_manager_.streamInfo().responseCodeDetails().has_value());
  }
  connection_manager_.stats_.named_.downstream_rq_active_.dec();
  if (filter_manager_.streamInfo().healthCheck()) {
    connection_manager_.config_.tracingStats().health_check_.inc();
  }

  if (active_span_) {
    Tracing::HttpTracerUtility::finalizeDownstreamSpan(
        *active_span_, request_headers_.get(), response_headers_.get(), response_trailers_.get(),
        filter_manager_.streamInfo(), *this);
  }
  if (state_.successful_upgrade_) {
    connection_manager_.stats_.named_.downstream_cx_upgrades_active_.dec();
  }
}

HttpTracerUtility::finalizeDownstreamSpan -> span.finishSpan()


source/common/tracing/http_tracer_impl.cc : 134 
最后调用span.finishSpan(); 

void HttpTracerUtility::finalizeDownstreamSpan(Span& span,
                                               const Http::RequestHeaderMap* request_headers,
                                               const Http::ResponseHeaderMap* response_headers,
                                               const Http::ResponseTrailerMap* response_trailers,
                                               const StreamInfo::StreamInfo& stream_info,
                                               const Config& tracing_config) {
  // Pre response data.
  if (request_headers) {
    if (request_headers->RequestId()) {
      span.setTag(Tracing::Tags::get().GuidXRequestId, request_headers->getRequestIdValue());
    }
    span.setTag(
        Tracing::Tags::get().HttpUrl,
        Http::Utility::buildOriginalUri(*request_headers, tracing_config.maxPathTagLength()));
    span.setTag(Tracing::Tags::get().HttpMethod, request_headers->getMethodValue());
    span.setTag(Tracing::Tags::get().DownstreamCluster,
                valueOrDefault(request_headers->EnvoyDownstreamServiceCluster(), "-"));
    span.setTag(Tracing::Tags::get().UserAgent, valueOrDefault(request_headers->UserAgent(), "-"));
    span.setTag(
        Tracing::Tags::get().HttpProtocol,
        Formatter::SubstitutionFormatUtils::protocolToStringOrDefault(stream_info.protocol()));

    const auto& remote_address = stream_info.downstreamAddressProvider().directRemoteAddress();

    if (remote_address->type() == Network::Address::Type::Ip) {
      const auto remote_ip = remote_address->ip();
      span.setTag(Tracing::Tags::get().PeerAddress, remote_ip->addressAsString());
    } else {
      span.setTag(Tracing::Tags::get().PeerAddress, remote_address->logicalName());
    }

    if (request_headers->ClientTraceId()) {
      span.setTag(Tracing::Tags::get().GuidXClientTraceId,
                  request_headers->getClientTraceIdValue());
    }

    if (Grpc::Common::isGrpcRequestHeaders(*request_headers)) {
      addGrpcRequestTags(span, *request_headers);
    }
  }
  CustomTagContext ctx{request_headers, stream_info};

  const CustomTagMap* custom_tag_map = tracing_config.customTags();
  if (custom_tag_map) {
    for (const auto& it : *custom_tag_map) {
      it.second->apply(span, ctx);
    }
  }
  span.setTag(Tracing::Tags::get().RequestSize, std::to_string(stream_info.bytesReceived()));
  span.setTag(Tracing::Tags::get().ResponseSize, std::to_string(stream_info.bytesSent()));

  setCommonTags(span, response_headers, response_trailers, stream_info, tracing_config);

  span.finishSpan();
}


HttpTracerUtility::finalizeUpstreamSpan() -> span.finishSpan();
source/common/tracing/http_tracer_impl.cc : 190

void HttpTracerUtility::finalizeUpstreamSpan(Span& span,
                                             const Http::ResponseHeaderMap* response_headers,
                                             const Http::ResponseTrailerMap* response_trailers,
                                             const StreamInfo::StreamInfo& stream_info,
                                             const Config& tracing_config) {
  span.setTag(
      Tracing::Tags::get().HttpProtocol,
      Formatter::SubstitutionFormatUtils::protocolToStringOrDefault(stream_info.protocol()));

  if (stream_info.upstreamHost()) {
    span.setTag(Tracing::Tags::get().UpstreamAddress,
                stream_info.upstreamHost()->address()->asStringView());
  }

  setCommonTags(span, response_headers, response_trailers, stream_info, tracing_config);

  span.finishSpan();
}


source/common/http/conn_manager_impl.cc : 689
   调用:Tracing::HttpTracerUtility::finalizeDownstreamSpan 

void ConnectionManagerImpl::ActiveStream::completeRequest() {
  filter_manager_.streamInfo().onRequestComplete();

  if (connection_manager_.remote_close_) {
    filter_manager_.streamInfo().setResponseCodeDetails(
        StreamInfo::ResponseCodeDetails::get().DownstreamRemoteDisconnect);
    filter_manager_.streamInfo().setResponseFlag(
        StreamInfo::ResponseFlag::DownstreamConnectionTermination);
  }
  // TODO(danzh) bring HTTP/3 to parity here.
  if (connection_manager_.codec_->protocol() != Protocol::Http3) {
    ASSERT(filter_manager_.streamInfo().responseCodeDetails().has_value());
  }
  connection_manager_.stats_.named_.downstream_rq_active_.dec();
  if (filter_manager_.streamInfo().healthCheck()) {
    connection_manager_.config_.tracingStats().health_check_.inc();
  }

  if (active_span_) {
    Tracing::HttpTracerUtility::finalizeDownstreamSpan(
        *active_span_, request_headers_.get(), response_headers_.get(), response_trailers_.get(),
        filter_manager_.streamInfo(), *this);
  }
  if (state_.successful_upgrade_) {
    connection_manager_.stats_.named_.downstream_cx_upgrades_active_.dec();
  }
}

source/common/http/async_client_impl.cc : 277 
void AsyncRequestImpl::onComplete() {
  callbacks_.onBeforeFinalizeUpstreamSpan(*child_span_, &response_->headers());

  Tracing::HttpTracerUtility::finalizeUpstreamSpan(*child_span_, &response_->headers(),
                                                   response_->trailers(), streamInfo(),
                                                   Tracing::EgressConfig::get());

  callbacks_.onSuccess(*this, std::move(response_));
}

source/common/http/async_client_impl.cc: 302

void AsyncRequestImpl::onReset() {
  if (!cancelled_) {
    // Set "error reason" tag related to reset. The tagging for "error true" is done inside the
    // Tracing::HttpTracerUtility::finalizeUpstreamSpan.
    child_span_->setTag(Tracing::Tags::get().ErrorReason, "Reset");
  }

  callbacks_.onBeforeFinalizeUpstreamSpan(*child_span_,
                                          remoteClosed() ? &response_->headers() : nullptr);

  // Finalize the span based on whether we received a response or not.
  Tracing::HttpTracerUtility::finalizeUpstreamSpan(
      *child_span_, remoteClosed() ? &response_->headers() : nullptr,
      remoteClosed() ? response_->trailers() : nullptr, streamInfo(), Tracing::EgressConfig::get());

  if (!cancelled_) {
    // In this case we don't have a valid response so we do need to raise a failure.
    callbacks_.onFailure(*this, AsyncClient::FailureReason::Reset);
  }
}


source/common/router/upstream_request.cc : 67

UpstreamRequest::~UpstreamRequest() {
  if (span_ != nullptr) {
    Tracing::HttpTracerUtility::finalizeUpstreamSpan(*span_, upstream_headers_.get(),
                                                     upstream_trailers_.get(), stream_info_,
                                                     Tracing::EgressConfig::get());
  }

  if (per_try_timeout_ != nullptr) {
    // Allows for testing.
    per_try_timeout_->disableTimer();
  }
  if (max_stream_duration_timer_ != nullptr) {
    max_stream_duration_timer_->disableTimer();
  }
  clearRequestEncoder();


  

  
source/common/router/upstream_request.cc: 44 

UpstreamRequest 构造函数中根据配置是否创建子span 

UpstreamRequest 的parent 应该是router filter

UpstreamRequest::UpstreamRequest(RouterFilterInterface& parent,
                                 std::unique_ptr<GenericConnPool>&& conn_pool)
    : parent_(parent), conn_pool_(std::move(conn_pool)), grpc_rq_success_deferred_(false),
      stream_info_(parent_.callbacks()->dispatcher().timeSource(), nullptr),
      start_time_(parent_.callbacks()->dispatcher().timeSource().monotonicTime()),
      calling_encode_headers_(false), upstream_canary_(false), decode_complete_(false),
      encode_complete_(false), encode_trailers_(false), retried_(false), awaiting_headers_(true),
      outlier_detection_timeout_recorded_(false),
      create_per_try_timeout_on_request_complete_(false), paused_for_connect_(false),
      record_timeout_budget_(parent_.cluster()->timeoutBudgetStats().has_value()) {
  if (parent_.config().start_child_span_) {
    span_ = parent_.callbacks()->activeSpan().spawnChild(
        parent_.callbacks()->tracingConfig(), "router " + parent.cluster()->name() + " egress",
        parent.timeSource().systemTime());
    if (parent.attemptCount() != 1) {
      // This is a retry request, add this metadata to span.
      span_->setTag(Tracing::Tags::get().RetryCount, std::to_string(parent.attemptCount() - 1));
    }
  }

  stream_info_.healthCheck(parent_.callbacks()->streamInfo().healthCheck());
}

router 配置项是否开启start_child_span

api/envoy/extensions/filters/http/router/v3/router.proto :31 
  // Whether to start a child span for egress routed calls. This can be
  // useful in scenarios where other filters (auth, ratelimit, etc.) make
  // outbound calls and have child spans rooted at the same ingress
  // parent. Defaults to false.
  bool start_child_span = 2;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值