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

Skeleton of a tracer for AWS X-Ray #8526

Merged
merged 19 commits into from
Oct 22, 2019
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ extensions/filters/common/original_src @snowp @klarose
/*/extensions/filters/network/sni_cluster @rshriram @lizan
# tracers.datadog extension
/*/extensions/tracers/datadog @cgilmour @palazzem
# tracers.xray extension
/*/extensions/tracers/xray @marcomagdy @lavignes
# mysql_proxy extension
/*/extensions/filters/network/mysql_proxy @rshriram @venilnoronha @mattklein123
# quic extension
Expand Down
18 changes: 18 additions & 0 deletions api/envoy/config/trace/v2/trace.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ option java_outer_classname = "TraceProto";
option java_multiple_files = true;
option java_package = "io.envoyproxy.envoy.config.trace.v2";

import "envoy/api/v2/core/base.proto";
import "envoy/api/v2/core/grpc_service.proto";

import "google/protobuf/any.proto";
Expand Down Expand Up @@ -34,6 +35,7 @@ message Tracing {
// - *envoy.dynamic.ot*
// - *envoy.tracers.datadog*
// - *envoy.tracers.opencensus*
// - *envoy.tracers.xray*
string name = 1 [(validate.rules).string = {min_bytes: 1}];

// Trace driver specific configuration which depends on the driver being instantiated.
Expand All @@ -44,6 +46,8 @@ message Tracing {
// - :ref:`DynamicOtConfig <envoy_api_msg_config.trace.v2.DynamicOtConfig>`
// - :ref:`DatadogConfig <envoy_api_msg_config.trace.v2.DatadogConfig>`
// - :ref:`OpenCensusConfig <envoy_api_msg_config.trace.v2.OpenCensusConfig>`
// [#comment: TODO(marco) when XRay is implemented, uncomment the following; - :ref:`XRayConfig
// <envoy_api_msg_config.trace.v2.XRayConfig>`]
oneof config_type {
google.protobuf.Struct config = 2;

Expand Down Expand Up @@ -197,6 +201,20 @@ message OpenCensusConfig {
repeated TraceContext outgoing_trace_context = 9;
}

// [#not-implemented-hide:]
// Configuration for AWS X-Ray tracer.
marcomagdy marked this conversation as resolved.
Show resolved Hide resolved
message XRayConfig {
// The endpoint of the X-Ray Daemon where the spans will be sent. Since by default daemon
// listens to localhost:2000, so the default value is 127.0.0.1:2000.
string daemon_endpoint = 1 [(validate.rules).string = {min_bytes: 1}];

// The custom name to name a X-Ray segment. By default will use cluster name.
string segment_name = 2;

// The location of custom sampling rule json file.
api.v2.core.DataSource sampling_rule_manifest = 3;
}

// Configuration structure.
message TraceServiceConfig {
// The upstream gRPC cluster that hosts the metrics service.
Expand Down
18 changes: 18 additions & 0 deletions api/envoy/config/trace/v3alpha/trace.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ option java_outer_classname = "TraceProto";
option java_multiple_files = true;
option java_package = "io.envoyproxy.envoy.config.trace.v3alpha";

import "envoy/api/v3alpha/core/base.proto";
import "envoy/api/v3alpha/core/grpc_service.proto";

import "google/protobuf/any.proto";
Expand Down Expand Up @@ -34,6 +35,7 @@ message Tracing {
// - *envoy.dynamic.ot*
// - *envoy.tracers.datadog*
// - *envoy.tracers.opencensus*
// - *envoy.tracers.xray*
string name = 1 [(validate.rules).string = {min_bytes: 1}];

// Trace driver specific configuration which depends on the driver being instantiated.
Expand All @@ -44,6 +46,8 @@ message Tracing {
// - :ref:`DynamicOtConfig <envoy_api_msg_config.trace.v3alpha.DynamicOtConfig>`
// - :ref:`DatadogConfig <envoy_api_msg_config.trace.v3alpha.DatadogConfig>`
// - :ref:`OpenCensusConfig <envoy_api_msg_config.trace.v3alpha.OpenCensusConfig>`
// [#comment: TODO(marco) when XRay is implemented, uncomment the following; - :ref:`XRayConfig
// <envoy_api_msg_config.trace.v3alpha.XRayConfig>`]
oneof config_type {
google.protobuf.Struct config = 2;

Expand Down Expand Up @@ -197,6 +201,20 @@ message OpenCensusConfig {
repeated TraceContext outgoing_trace_context = 9;
}

// [#not-implemented-hide:]
// Configuration for AWS X-Ray tracer.
message XRayConfig {
// The endpoint of the X-Ray Daemon where the spans will be sent. Since by default daemon
// listens to localhost:2000, so the default value is 127.0.0.1:2000.
string daemon_endpoint = 1 [(validate.rules).string = {min_bytes: 1}];

// The custom name to name a X-Ray segment. By default will use cluster name.
string segment_name = 2;

// The location of custom sampling rule json file.
api.v3alpha.core.DataSource sampling_rule_manifest = 3;
}

// Configuration structure.
message TraceServiceConfig {
// The upstream gRPC cluster that hosts the metrics service.
Expand Down
1 change: 1 addition & 0 deletions source/extensions/extensions_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ EXTENSIONS = {
"envoy.tracers.datadog": "//source/extensions/tracers/datadog:config",
"envoy.tracers.zipkin": "//source/extensions/tracers/zipkin:config",
"envoy.tracers.opencensus": "//source/extensions/tracers/opencensus:config",
"envoy.tracers.xray": "//source/extensions/tracers/xray:config",

#
# Transport sockets
Expand Down
2 changes: 2 additions & 0 deletions source/extensions/tracers/well_known_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class TracerNameValues {
const std::string Datadog = "envoy.tracers.datadog";
// OpenCensus tracer
const std::string OpenCensus = "envoy.tracers.opencensus";
// AWS XRay tracer
const std::string XRay = "envoy.tracers.xray";
};

using TracerNames = ConstSingleton<TracerNameValues>;
Expand Down
47 changes: 47 additions & 0 deletions source/extensions/tracers/xray/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
licenses(["notice"]) # Apache 2

# Trace driver for AWS X-Ray.

load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

envoy_package()

envoy_cc_library(
name = "xray_lib",
srcs = [
"util.cc",
"xray_tracer_impl.cc",
],
hdrs = [
"sampling_strategy.h",
"tracer.h",
"util.h",
"xray_configuration.h",
"xray_tracer_impl.h",
],
deps = [
"//include/envoy/common:time_interface",
"//include/envoy/server:instance_interface",
"//include/envoy/tracing:http_tracer_interface",
"//source/common/common:macros",
"//source/common/http:header_map_lib",
"//source/common/json:json_loader_lib",
"//source/common/tracing:http_tracer_lib",
],
)

envoy_cc_library(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
":xray_lib",
"//source/common/config:datasource_lib",
"//source/extensions/tracers:well_known_names",
"//source/extensions/tracers/common:factory_base_lib",
],
)
47 changes: 47 additions & 0 deletions source/extensions/tracers/xray/config.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "extensions/tracers/xray/config.h"

#include <string>

#include "envoy/registry/registry.h"

#include "common/common/utility.h"
#include "common/config/datasource.h"
#include "common/tracing/http_tracer_impl.h"

#include "extensions/tracers/well_known_names.h"
#include "extensions/tracers/xray/xray_tracer_impl.h"

namespace Envoy {
namespace Extensions {
namespace Tracers {
namespace XRay {

XRayTracerFactory::XRayTracerFactory() : FactoryBase(TracerNames::get().XRay) {}

Tracing::HttpTracerPtr
XRayTracerFactory::createHttpTracerTyped(const envoy::config::trace::v2::XRayConfig& proto_config,
Server::Instance& server) {
std::string sampling_rules_json;
try {
sampling_rules_json =
Config::DataSource::read(proto_config.sampling_rule_manifest(), true, server.api());
} catch (EnvoyException& e) {
ENVOY_LOG(error, "Failed to read sampling rules manifest because of {}.", e.what());
}

XRayConfiguration xconfig(proto_config.daemon_endpoint(), proto_config.segment_name(),
sampling_rules_json);
auto xray_driver = std::make_unique<XRay::Driver>(xconfig, server);

return std::make_unique<Tracing::HttpTracerImpl>(std::move(xray_driver), server.localInfo());
}

/**
* Static registration for the XRay tracer. @see RegisterFactory.
*/
REGISTER_FACTORY(XRayTracerFactory, Server::Configuration::TracerFactory);

} // namespace XRay
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
31 changes: 31 additions & 0 deletions source/extensions/tracers/xray/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "envoy/config/trace/v2/trace.pb.validate.h"

#include "common/common/logger.h"

#include "extensions/tracers/common/factory_base.h"

namespace Envoy {
namespace Extensions {
namespace Tracers {
namespace XRay {

/**
* Config registration for the XRay tracer. @see TracerFactory.
*/
class XRayTracerFactory : public Common::FactoryBase<envoy::config::trace::v2::XRayConfig>,
Logger::Loggable<Logger::Id::tracing> {
public:
XRayTracerFactory();

private:
Tracing::HttpTracerPtr
createHttpTracerTyped(const envoy::config::trace::v2::XRayConfig& proto_config,
Server::Instance& server) override;
};

} // namespace XRay
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
61 changes: 61 additions & 0 deletions source/extensions/tracers/xray/sampling_strategy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#pragma once

#include <memory>
#include <random>

#include "envoy/common/pure.h"

#include "common/common/macros.h"

#include "absl/strings/string_view.h"

namespace Envoy {
namespace Extensions {
namespace Tracers {
namespace XRay {

struct SamplingRequest {
/**
* Creates a new SamplingRequest
*
* @param host_name The host name the request.
* @param http_method The http method of the request e.g. GET, POST, etc.
* @param http_url The path part of the URL of the request.
* @param service The name of the service (user specified)
* @param service_type The type of the service (user specified)
*/
SamplingRequest(absl::string_view host_name, absl::string_view http_method,
absl::string_view http_url)
: host_(host_name), http_method_(http_method), http_url_(http_url) {}

const std::string host_;
const std::string http_method_;
const std::string http_url_;
};

/**
* Strategy provides an interface for implementing trace sampling strategies.
*/
class SamplingStrategy {
public:
explicit SamplingStrategy(uint64_t rng_seed) : rng_(rng_seed) {}
virtual ~SamplingStrategy() = default;

/**
* sampleRequest determines if the given request should be traced or not.
*/
virtual bool sampleRequest(const SamplingRequest& sampling_request) {
UNREFERENCED_PARAMETER(sampling_request); // unused for now
return rng_() % 100 == 42;
}

private:
std::mt19937 rng_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this is totally fine for this PR, but for the real implementation, you should obtain randomness via a Runtime::RandomGenerator (I think from factory context), to allow proper dependency injection and deterministic tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a reasonable explanation for this. But we'll talk about it in the next PRs

};

using SamplingStrategyPtr = std::unique_ptr<SamplingStrategy>;

} // namespace XRay
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
37 changes: 37 additions & 0 deletions source/extensions/tracers/xray/tracer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <string>

#include "envoy/common/time.h"
#include "envoy/tracing/http_tracer.h"

#include "extensions/tracers/xray/sampling_strategy.h"

#include "absl/strings/string_view.h"

namespace Envoy {
namespace Extensions {
namespace Tracers {
namespace XRay {

class Tracer {
public:
Tracer(absl::string_view segment_name, TimeSource& time_source)
: segment_name_(segment_name), time_source_(time_source) {
UNREFERENCED_PARAMETER(time_source_);
}

/**
* Starts a tracing span for XRay
*/
Tracing::SpanPtr startSpan() { return nullptr; }

private:
const std::string segment_name_;
TimeSource& time_source_;
};

} // namespace XRay
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
Loading