Skip to content

Commit

Permalink
Allow specifying samplers for the OpenTelemetry tracer via a new conf…
Browse files Browse the repository at this point in the history
…iguration. (envoyproxy#30259)

Signed-off-by: thomas.ebner <[email protected]>
Signed-off-by: Joao Grassi <[email protected]>
  • Loading branch information
samohte authored Oct 30, 2023
1 parent 8b9054c commit c600637
Show file tree
Hide file tree
Showing 28 changed files with 957 additions and 15 deletions.
1 change: 1 addition & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ proto_library(
"//envoy/extensions/stat_sinks/open_telemetry/v3:pkg",
"//envoy/extensions/stat_sinks/wasm/v3:pkg",
"//envoy/extensions/tracers/opentelemetry/resource_detectors/v3:pkg",
"//envoy/extensions/tracers/opentelemetry/samplers/v3:pkg",
"//envoy/extensions/transport_sockets/alts/v3:pkg",
"//envoy/extensions/transport_sockets/http_11_proxy/v3:pkg",
"//envoy/extensions/transport_sockets/internal_upstream/v3:pkg",
Expand Down
9 changes: 9 additions & 0 deletions api/envoy/config/trace/v3/opentelemetry.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;

// Configuration for the OpenTelemetry tracer.
// [#extension: envoy.tracers.opentelemetry]
// [#next-free-field: 6]
message OpenTelemetryConfig {
// The upstream gRPC cluster that will receive OTLP traces.
// Note that the tracer drops traces if the server does not read data fast enough.
Expand Down Expand Up @@ -48,4 +49,12 @@ message OpenTelemetryConfig {
// An ordered list of resource detectors
// [#extension-category: envoy.tracers.opentelemetry.resource_detectors]
repeated core.v3.TypedExtensionConfig resource_detectors = 4;

// Specifies the sampler to be used by the OpenTelemetry tracer.
// The configured sampler implements the Sampler interface defined by the OpenTelemetry specification.
// This field can be left empty. In this case, the default Envoy sampling decision is used.
//
// See: `OpenTelemetry sampler specification <https://opentelemetry.io/docs/specs/otel/trace/sdk/#sampler>`_
// [#extension-category: envoy.tracers.opentelemetry.samplers]
core.v3.TypedExtensionConfig sampler = 5;
}
9 changes: 9 additions & 0 deletions api/envoy/extensions/tracers/opentelemetry/samplers/v3/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
syntax = "proto3";

package envoy.extensions.tracers.opentelemetry.samplers.v3;

import "udpa/annotations/status.proto";

option java_package = "io.envoyproxy.envoy.extensions.tracers.opentelemetry.samplers.v3";
option java_outer_classname = "AlwaysOnSamplerProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/tracers/opentelemetry/samplers/v3;samplersv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Always On Sampler config]
// Configuration for the "AlwaysOn" Sampler extension.
// The sampler follows the "AlwaysOn" implementation from the OpenTelemetry
// SDK specification.
//
// See:
// `AlwaysOn sampler specification <https://opentelemetry.io/docs/specs/otel/trace/sdk/#alwayson>`_
// [#extension: envoy.tracers.opentelemetry.samplers.always_on]

message AlwaysOnSamplerConfig {
}
1 change: 1 addition & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ proto_library(
"//envoy/extensions/stat_sinks/open_telemetry/v3:pkg",
"//envoy/extensions/stat_sinks/wasm/v3:pkg",
"//envoy/extensions/tracers/opentelemetry/resource_detectors/v3:pkg",
"//envoy/extensions/tracers/opentelemetry/samplers/v3:pkg",
"//envoy/extensions/transport_sockets/alts/v3:pkg",
"//envoy/extensions/transport_sockets/http_11_proxy/v3:pkg",
"//envoy/extensions/transport_sockets/internal_upstream/v3:pkg",
Expand Down
3 changes: 3 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,8 @@ new_features:
- area: tracing
change: |
Added support for configuring resource detectors on the OpenTelemetry tracer.
- area: tracing
change: |
Added support to configure a sampler for the OpenTelemetry tracer.
deprecated:
10 changes: 10 additions & 0 deletions docs/root/api-v3/config/trace/opentelemetry/samplers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
OpenTelemetry Samplers
======================

Samplers that can be configured with the OpenTelemetry Tracer:

.. toctree::
:glob:
:maxdepth: 3

../../../extensions/tracers/opentelemetry/samplers/v3/*
1 change: 1 addition & 0 deletions docs/root/api-v3/config/trace/trace.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ HTTP tracers

v3/*
opentelemetry/resource_detectors
opentelemetry/samplers
6 changes: 6 additions & 0 deletions source/extensions/extensions_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ EXTENSIONS = {

"envoy.tracers.opentelemetry.resource_detectors.environment": "//source/extensions/tracers/opentelemetry/resource_detectors/environment:config",

#
# OpenTelemetry tracer samplers
#

"envoy.tracers.opentelemetry.samplers.always_on": "//source/extensions/tracers/opentelemetry/samplers/always_on:config",

#
# Transport sockets
#
Expand Down
7 changes: 7 additions & 0 deletions source/extensions/extensions_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,13 @@ envoy.tracers.opentelemetry:
status: wip
type_urls:
- envoy.config.trace.v3.OpenTelemetryConfig
envoy.tracers.opentelemetry.samplers.always_on:
categories:
- envoy.tracers.opentelemetry.samplers
security_posture: unknown
status: wip
type_urls:
- envoy.extensions.tracers.opentelemetry.samplers.v3.AlwaysOnSamplerConfig
envoy.tracers.skywalking:
categories:
- envoy.tracers
Expand Down
1 change: 1 addition & 0 deletions source/extensions/tracers/opentelemetry/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ envoy_cc_library(
"//source/common/tracing:http_tracer_lib",
"//source/extensions/tracers/common:factory_base_lib",
"//source/extensions/tracers/opentelemetry/resource_detectors:resource_detector_lib",
"//source/extensions/tracers/opentelemetry/samplers:sampler_lib",
"@envoy_api//envoy/config/trace/v3:pkg_cc_proto",
"@opentelemetry_proto//:trace_cc_proto",
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "source/extensions/tracers/opentelemetry/http_trace_exporter.h"
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h"
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.h"
#include "source/extensions/tracers/opentelemetry/samplers/sampler.h"
#include "source/extensions/tracers/opentelemetry/span_context.h"
#include "source/extensions/tracers/opentelemetry/span_context_extractor.h"
#include "source/extensions/tracers/opentelemetry/trace_exporter.h"
Expand All @@ -25,6 +26,25 @@ namespace Extensions {
namespace Tracers {
namespace OpenTelemetry {

namespace {

SamplerSharedPtr
tryCreateSamper(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetry_config,
Server::Configuration::TracerFactoryContext& context) {
SamplerSharedPtr sampler;
if (opentelemetry_config.has_sampler()) {
auto& sampler_config = opentelemetry_config.sampler();
auto* factory = Envoy::Config::Utility::getFactory<SamplerFactory>(sampler_config);
if (!factory) {
throw EnvoyException(fmt::format("Sampler factory not found: '{}'", sampler_config.name()));
}
sampler = factory->createSampler(sampler_config.typed_config(), context);
}
return sampler;
}

} // namespace

Driver::Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetry_config,
Server::Configuration::TracerFactoryContext& context)
: Driver(opentelemetry_config, context, ResourceProviderImpl{}) {}
Expand All @@ -46,9 +66,12 @@ Driver::Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetr
"OpenTelemetry tracer will be disabled.");
}

// Create the sampler if configured
SamplerSharedPtr sampler = tryCreateSamper(opentelemetry_config, context);

// Create the tracer in Thread Local Storage.
tls_slot_ptr_->set([opentelemetry_config, &factory_context, this,
resource_ptr](Event::Dispatcher& dispatcher) {
tls_slot_ptr_->set([opentelemetry_config, &factory_context, this, resource_ptr,
sampler](Event::Dispatcher& dispatcher) {
OpenTelemetryTraceExporterPtr exporter;
if (opentelemetry_config.has_grpc_service()) {
Grpc::AsyncClientFactoryPtr&& factory =
Expand All @@ -63,8 +86,7 @@ Driver::Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetr
}
TracerPtr tracer = std::make_unique<Tracer>(
std::move(exporter), factory_context.timeSource(), factory_context.api().randomGenerator(),
factory_context.runtime(), dispatcher, tracing_stats_, resource_ptr);

factory_context.runtime(), dispatcher, tracing_stats_, resource_ptr, sampler);
return std::make_shared<TlsTracer>(std::move(tracer));
});
}
Expand All @@ -81,7 +103,6 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config,
// No propagation header, so we can create a fresh span with the given decision.
Tracing::SpanPtr new_open_telemetry_span =
tracer.startSpan(config, operation_name, stream_info.startTime(), tracing_decision);
new_open_telemetry_span->setSampled(tracing_decision.traced);
return new_open_telemetry_span;
} else {
// Try to extract the span context. If we can't, just return a null span.
Expand Down
25 changes: 25 additions & 0 deletions source/extensions/tracers/opentelemetry/samplers/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "sampler_lib",
srcs = [
],
hdrs = [
"sampler.h",
],
deps = [
"//envoy/config:typed_config_interface",
"//envoy/server:tracer_config_interface",
"//source/common/common:logger_lib",
"//source/common/config:utility_lib",
"@opentelemetry_proto//:trace_cc_proto",
],
)
33 changes: 33 additions & 0 deletions source/extensions/tracers/opentelemetry/samplers/always_on/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_extension",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_extension(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
":always_on_sampler_lib",
"//envoy/registry",
"//source/common/config:utility_lib",
"@envoy_api//envoy/extensions/tracers/opentelemetry/samplers/v3:pkg_cc_proto",
],
)

envoy_cc_library(
name = "always_on_sampler_lib",
srcs = ["always_on_sampler.cc"],
hdrs = ["always_on_sampler.h"],
deps = [
"//source/common/config:datasource_lib",
"//source/extensions/tracers/opentelemetry:opentelemetry_tracer_lib",
"//source/extensions/tracers/opentelemetry/samplers:sampler_lib",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "source/extensions/tracers/opentelemetry/samplers/always_on/always_on_sampler.h"

#include <memory>
#include <sstream>
#include <string>

#include "source/common/config/datasource.h"
#include "source/extensions/tracers/opentelemetry/span_context.h"

namespace Envoy {
namespace Extensions {
namespace Tracers {
namespace OpenTelemetry {

SamplingResult
AlwaysOnSampler::shouldSample(const absl::optional<SpanContext> parent_context,
const std::string& /*trace_id*/, const std::string& /*name*/,
::opentelemetry::proto::trace::v1::Span::SpanKind /*kind*/,
const std::map<std::string, std::string>& /*attributes*/,
const std::vector<SpanContext>& /*links*/) {
SamplingResult result;
result.decision = Decision::RECORD_AND_SAMPLE;
if (parent_context.has_value()) {
result.tracestate = parent_context.value().tracestate();
}
return result;
}

std::string AlwaysOnSampler::getDescription() const { return "AlwaysOnSampler"; }

} // namespace OpenTelemetry
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include "envoy/server/factory_context.h"

#include "source/common/common/logger.h"
#include "source/common/config/datasource.h"
#include "source/extensions/tracers/opentelemetry/samplers/sampler.h"

namespace Envoy {
namespace Extensions {
namespace Tracers {
namespace OpenTelemetry {

/**
* @brief A sampler which samples every span.
* https://opentelemetry.io/docs/specs/otel/trace/sdk/#alwayson
* - Returns RECORD_AND_SAMPLE always.
* - Description MUST be AlwaysOnSampler.
*
*/
class AlwaysOnSampler : public Sampler, Logger::Loggable<Logger::Id::tracing> {
public:
explicit AlwaysOnSampler(const Protobuf::Message& /*config*/,
Server::Configuration::TracerFactoryContext& /*context*/) {}
SamplingResult shouldSample(const absl::optional<SpanContext> parent_context,
const std::string& trace_id, const std::string& name,
::opentelemetry::proto::trace::v1::Span::SpanKind spankind,
const std::map<std::string, std::string>& attributes,
const std::vector<SpanContext>& links) override;
std::string getDescription() const override;

private:
};

} // namespace OpenTelemetry
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "source/extensions/tracers/opentelemetry/samplers/always_on/config.h"

#include "envoy/server/tracer_config.h"

#include "source/common/config/utility.h"
#include "source/extensions/tracers/opentelemetry/samplers/always_on/always_on_sampler.h"

namespace Envoy {
namespace Extensions {
namespace Tracers {
namespace OpenTelemetry {

SamplerSharedPtr
AlwaysOnSamplerFactory::createSampler(const Protobuf::Message& config,
Server::Configuration::TracerFactoryContext& context) {
return std::make_shared<AlwaysOnSampler>(config, context);
}

/**
* Static registration for the Env sampler factory. @see RegisterFactory.
*/
REGISTER_FACTORY(AlwaysOnSamplerFactory, SamplerFactory);

} // namespace OpenTelemetry
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
Loading

0 comments on commit c600637

Please sign in to comment.