Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generic proxy: tracing support for the generic proxy based on the generic tracing #24790

Merged
merged 13 commits into from
Feb 14, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
deps = [
"//envoy/config/core/v3:pkg",
"//envoy/extensions/filters/network/http_connection_manager/v3:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
"@com_github_cncf_udpa//xds/annotations/v3:pkg",
"@com_github_cncf_udpa//xds/type/matcher/v3:pkg",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package envoy.extensions.filters.network.generic_proxy.v3;
import "contrib/envoy/extensions/filters/network/generic_proxy/v3/route.proto";
import "envoy/config/core/v3/config_source.proto";
import "envoy/config/core/v3/extension.proto";
import "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto";

import "xds/annotations/v3/status.proto";

Expand All @@ -22,7 +23,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
// Generic proxy.
// [#extension: envoy.filters.network.generic_proxy]

// [#next-free-field: 6]
// [#next-free-field: 7]
message GenericProxy {
// The human readable prefix to use when emitting statistics.
string stat_prefix = 1 [(validate.rules).string = {min_len: 1}];
Expand All @@ -47,6 +48,9 @@ message GenericProxy {
// happen.
// [#extension-category: envoy.generic_proxy.filters]
repeated config.core.v3.TypedExtensionConfig filters = 5;

// Tracing configuration for the generic proxy.
http_connection_manager.v3.HttpConnectionManager.Tracing tracing = 6;
}

message GenericRds {
Expand Down
3 changes: 3 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,8 @@ new_features:
- area: sni_dynamic_forward_proxy
change: |
added an option to dynamically set the host used by the SNI dynamic forward proxy filter, by setting a filter state object under the key ``envoy.upstream.dynamic_host``.
- area: generic_proxy
change: |
added :ref:`tracing support <envoy_v3_api_field_extensions.filters.network.generic_proxy.v3.GenericProxy.tracing>` for the generic proxy.
deprecated:
3 changes: 3 additions & 0 deletions contrib/generic_proxy/filters/network/source/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ envoy_cc_library(
"//source/common/common:linked_object",
"//source/common/common:minimal_logger_lib",
"//source/common/stream_info:stream_info_lib",
"//source/common/tracing:tracer_config_lib",
"//source/common/tracing:tracer_lib",
"//source/common/tracing:tracer_manager_lib",
"//source/extensions/filters/network/common:factory_base_lib",
"@envoy_api//contrib/envoy/extensions/filters/network/generic_proxy/v3:pkg_cc_proto",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
Expand Down
21 changes: 18 additions & 3 deletions contrib/generic_proxy/filters/network/source/config.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "contrib/generic_proxy/filters/network/source/config.h"

#include "source/common/tracing/tracer_manager_impl.h"

#include "contrib/generic_proxy/filters/network/source/rds.h"
#include "contrib/generic_proxy/filters/network/source/rds_impl.h"

Expand Down Expand Up @@ -89,24 +91,37 @@ Factory::createFilterFactoryFromProtoTyped(const ProxyConfig& proto_config,
SINGLETON_MANAGER_REGISTERED_NAME(generic_route_config_provider_manager),
[&context] { return std::make_shared<RouteConfigProviderManagerImpl>(context.admin()); });

auto tracer_manager = Tracing::TracerManagerImpl::singleton(context);

auto factories = factoriesFromProto(proto_config.codec_config(), context);
std::shared_ptr<ProxyFactory> custom_proxy_factory = std::move(factories.second);

Tracing::TracerSharedPtr tracer;
Tracing::ConnectionManagerTracingConfigPtr tracing_config;
if (proto_config.has_tracing()) {
if (proto_config.tracing().has_provider()) {
tracer = tracer_manager->getOrCreateTracer(&proto_config.tracing().provider());
}
tracing_config = std::make_unique<Tracing::ConnectionManagerTracingConfigImpl>(
context.direction(), proto_config.tracing());
}

const FilterConfigSharedPtr config = std::make_shared<FilterConfigImpl>(
proto_config.stat_prefix(), std::move(factories.first),
routeConfigProviderFromProto(proto_config, context, *route_config_provider_manager),
filtersFactoryFromProto(proto_config.filters(), proto_config.stat_prefix(), context),
context);
std::move(tracer), std::move(tracing_config), context);

return [route_config_provider_manager, config,
return [route_config_provider_manager, tracer_manager, config, &context,
custom_proxy_factory](Envoy::Network::FilterManager& filter_manager) -> void {
// Create filter by the custom filter factory if the custom filter factory is not null.
if (custom_proxy_factory != nullptr) {
custom_proxy_factory->createProxy(filter_manager, config);
return;
}

filter_manager.addReadFilter(std::make_shared<Filter>(config));
filter_manager.addReadFilter(std::make_shared<Filter>(
config, context.mainThreadDispatcher().timeSource(), context.runtime()));
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ envoy_cc_library(
hdrs = [
"stream.h",
],
deps = [
"//envoy/tracing:trace_context_interface",
],
)

envoy_cc_library(
Expand Down Expand Up @@ -91,5 +94,7 @@ envoy_cc_library(
":codec_interface",
":filter_interface",
":route_interface",
"//envoy/tracing:trace_config_interface",
"//envoy/tracing:tracer_interface",
],
)
16 changes: 16 additions & 0 deletions contrib/generic_proxy/filters/network/source/interface/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ class StreamFilterCallbacks {
* name will be used to get the config.
*/
virtual const RouteSpecificFilterConfig* perFilterConfig() const PURE;

/**
* @return StreamInfo::StreamInfo& the stream info object associated with the stream.
*/
virtual const StreamInfo::StreamInfo& streamInfo() const PURE;
virtual StreamInfo::StreamInfo& streamInfo() PURE;

/**
* @return Tracing::Span& the active span associated with the stream.
*/
virtual Tracing::Span& activeSpan() PURE;

/**
* @return const Tracing::Config& the tracing configuration.
*/
virtual OptRef<const Tracing::Config> tracingConfig() const PURE;
};

class DecoderFilterCallback : public virtual StreamFilterCallbacks {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include "envoy/tracing/trace_config.h"
#include "envoy/tracing/tracer.h"

#include "contrib/generic_proxy/filters/network/source/interface/codec.h"
#include "contrib/generic_proxy/filters/network/source/interface/filter.h"
#include "contrib/generic_proxy/filters/network/source/interface/route.h"
Expand Down Expand Up @@ -32,6 +35,16 @@ class FilterConfig : public FilterChainFactory {
* determine if they should be doing graceful closes on connections when possible.
*/
virtual const Network::DrainDecision& drainDecision() const PURE;

/**
* @return Tracing::Tracer tracing provider to use.
*/
virtual OptRef<Tracing::Tracer> tracingProvider() const PURE;

/**
* @return connection manager tracing config.
*/
virtual OptRef<const Tracing::ConnectionManagerTracingConfig> tracingConfig() const PURE;
};

} // namespace GenericProxy
Expand Down
34 changes: 8 additions & 26 deletions contrib/generic_proxy/filters/network/source/interface/stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <string>

#include "envoy/common/pure.h"
#include "envoy/tracing/trace_context.h"

#include "absl/status/status.h"
#include "absl/strings/string_view.h"
Expand Down Expand Up @@ -74,34 +75,15 @@ class StreamBase {
static constexpr absl::string_view name() { return "generic_proxy"; }
};

class Request : public StreamBase {
/**
* Using interface that provided by the TraceContext as the interface of generic request.
*/
class Request : public Tracing::TraceContext {
public:
/**
* Get request host.
*
* @return The host of generic request. The meaning of the return value may be different For
* different application protocols. It typically should be domain, VIP, or service name that
* used to represents target service instances.
*/
virtual absl::string_view host() const PURE;

/**
* Get request path.
*
* @return The path of generic request. The meaning of the return value may be different For
* different application protocols. It typically should be RPC service name that used to
* represents set of method or functionality provided by target service.
*/
virtual absl::string_view path() const PURE;

/**
* Get request method.
*
* @return The method of generic request. The meaning of the return value may be different For
* different application protocols.
*/
virtual absl::string_view method() const PURE;
// Used for matcher.
static constexpr absl::string_view name() { return "generic_proxy"; }
};

using RequestPtr = std::unique_ptr<Request>;
using RequestSharedPtr = std::shared_ptr<Request>;

Expand Down
79 changes: 70 additions & 9 deletions contrib/generic_proxy/filters/network/source/proxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,59 @@ namespace Extensions {
namespace NetworkFilters {
namespace GenericProxy {

namespace {

Tracing::Decision tracingDecision(const Tracing::ConnectionManagerTracingConfig& tracing_config,
Runtime::Loader& runtime) {
bool traced = runtime.snapshot().featureEnabled("tracing.random_sampling",
tracing_config.getRandomSampling());

if (traced) {
return {Tracing::Reason::Sampling, true};
}
return {Tracing::Reason::NotTraceable, false};
}

} // namespace

ActiveStream::ActiveStream(Filter& parent, RequestPtr request)
: parent_(parent), downstream_request_stream_(std::move(request)) {}
: parent_(parent), downstream_request_stream_(std::move(request)),
stream_info_(parent_.time_source_,
parent_.callbacks_->connection().connectionInfoProviderSharedPtr()) {

ActiveStream::~ActiveStream() {
for (auto& filter : decoder_filters_) {
filter->filter_->onDestroy();
connection_manager_tracing_config_ = parent_.config_->tracingConfig();

auto tracer = parent_.config_->tracingProvider();

if (!connection_manager_tracing_config_.has_value() || !tracer.has_value()) {
return;
}
for (auto& filter : encoder_filters_) {
if (filter->isDualFilter()) {
continue;
}
filter->filter_->onDestroy();

auto decision = tracingDecision(connection_manager_tracing_config_.value(), parent_.runtime_);
if (decision.traced) {
stream_info_.setTraceReason(decision.reason);
}
active_span_ = tracer->startSpan(*this, *downstream_request_stream_, stream_info_, decision);
}

Tracing::OperationName ActiveStream::operationName() const {
ASSERT(connection_manager_tracing_config_.has_value());
return connection_manager_tracing_config_->operationName();
}

const Tracing::CustomTagMap* ActiveStream::customTags() const {
ASSERT(connection_manager_tracing_config_.has_value());
return &connection_manager_tracing_config_->getCustomTags();
}

bool ActiveStream::verbose() const {
ASSERT(connection_manager_tracing_config_.has_value());
return connection_manager_tracing_config_->verbose();
}

uint32_t ActiveStream::maxPathTagLength() const {
ASSERT(connection_manager_tracing_config_.has_value());
return connection_manager_tracing_config_->maxPathTagLength();
}

Envoy::Event::Dispatcher& ActiveStream::dispatcher() { return parent_.connection().dispatcher(); }
Expand Down Expand Up @@ -119,6 +159,25 @@ void ActiveStream::initializeFilterChain(FilterChainFactory& factory) {
std::reverse(encoder_filters_.begin(), encoder_filters_.end());
}

void ActiveStream::completeRequest() {
stream_info_.onRequestComplete();

if (active_span_) {
Tracing::TracerUtility::finalizeSpan(*active_span_, *downstream_request_stream_, stream_info_,
*this, false);
}

for (auto& filter : decoder_filters_) {
filter->filter_->onDestroy();
}
for (auto& filter : encoder_filters_) {
if (filter->isDualFilter()) {
continue;
}
filter->filter_->onDestroy();
}
}

Envoy::Network::FilterStatus Filter::onData(Envoy::Buffer::Instance& data, bool) {
if (downstream_connection_closed_) {
return Envoy::Network::FilterStatus::StopIteration;
Expand Down Expand Up @@ -151,6 +210,8 @@ void Filter::newDownstreamRequest(RequestPtr request) {
}

void Filter::deferredStream(ActiveStream& stream) {
stream.completeRequest();

if (!stream.inserted()) {
return;
}
Expand Down
Loading