Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 17 additions & 0 deletions api/envoy/config/trace/v3/opentelemetry.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ package envoy.config.trace.v3;

import "envoy/config/core/v3/grpc_service.proto";

import "google/protobuf/any.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.config.trace.v3";
option java_outer_classname = "OpentelemetryProto";
Expand All @@ -14,6 +17,16 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: OpenTelemetry tracer]

message ResourceDetector {
// The name of the resource detector to instantiate.
string name = 1 [(validate.rules).string = {min_len: 1}];

// Resource detector specific configuration which depends on the detector being
// instantiated. See the supported detectors for further documentation.
// Not required for detectors that don't need a config. E.g., Environment variable Detector
google.protobuf.Any typed_config = 2;
}

// Configuration for the OpenTelemetry tracer.
// [#extension: envoy.tracers.opentelemetry]
message OpenTelemetryConfig {
Expand All @@ -25,4 +38,8 @@ message OpenTelemetryConfig {
// The name for the service. This will be populated in the ResourceSpan Resource attributes.
// If it is not provided, it will default to "unknown_service:envoy".
string service_name = 2;

// An ordered list of resource detectors
// [#extension-category: envoy.tracers.opentelemetry.resource_detectors]
repeated ResourceDetector resource_detectors = 3;
}
6 changes: 6 additions & 0 deletions source/extensions/extensions_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ EXTENSIONS = {
"envoy.tracers.skywalking": "//source/extensions/tracers/skywalking:config",
"envoy.tracers.opentelemetry": "//source/extensions/tracers/opentelemetry:config",

#
# OpenTelemetry Resource Detectors
#

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

#
# Transport sockets
#
Expand Down
5 changes: 5 additions & 0 deletions source/extensions/extensions_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1630,3 +1630,8 @@ envoy.config_mux.sotw_grpc_mux_factory:
- envoy.config_mux
security_posture: unknown
status: stable
envoy.tracers.opentelemetry.resource_detectors.environment:
categories:
- envoy.tracers.opentelemetry.resource_detectors
security_posture: unknown
status: wip
1 change: 1 addition & 0 deletions source/extensions/tracers/opentelemetry/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ envoy_cc_library(
"//source/common/config:utility_lib",
"//source/common/tracing:http_tracer_lib",
"//source/extensions/tracers/common:factory_base_lib",
"//source/extensions/tracers/opentelemetry/resource_detectors:resource_detector_lib",
"@envoy_api//envoy/config/trace/v3:pkg_cc_proto",
"@opentelemetry_proto//:trace_cc_proto",
],
Expand Down
5 changes: 4 additions & 1 deletion source/extensions/tracers/opentelemetry/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "source/common/common/logger.h"
#include "source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.h"
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.h"

namespace Envoy {
namespace Extensions {
Expand All @@ -18,7 +19,9 @@ OpenTelemetryTracerFactory::OpenTelemetryTracerFactory()
Tracing::DriverSharedPtr OpenTelemetryTracerFactory::createTracerDriverTyped(
const envoy::config::trace::v3::OpenTelemetryConfig& proto_config,
Server::Configuration::TracerFactoryContext& context) {
return std::make_shared<Driver>(proto_config, context);

ResourceProviderImpl resource_provider;
Comment thread
joaopgrassi marked this conversation as resolved.
Outdated
return std::make_shared<Driver>(proto_config, context, resource_provider);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "source/common/common/logger.h"
#include "source/common/config/utility.h"
#include "source/common/tracing/http_tracer_impl.h"
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h"
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.h"

#include "opentelemetry/proto/collector/trace/v1/trace_service.pb.h"
#include "opentelemetry/proto/trace/v1/trace.pb.h"
Expand All @@ -21,13 +23,17 @@ namespace Tracers {
namespace OpenTelemetry {

Driver::Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetry_config,
Server::Configuration::TracerFactoryContext& context)
Server::Configuration::TracerFactoryContext& context,
const ResourceProvider& resource_provider)
: tls_slot_ptr_(context.serverFactoryContext().threadLocal().allocateSlot()),
tracing_stats_{OPENTELEMETRY_TRACER_STATS(
POOL_COUNTER_PREFIX(context.serverFactoryContext().scope(), "tracing.opentelemetry"))} {
auto& factory_context = context.serverFactoryContext();
Resource resource = resource_provider.getResource(opentelemetry_config, context);

// Create the tracer in Thread Local Storage.
tls_slot_ptr_->set([opentelemetry_config, &factory_context, this](Event::Dispatcher& dispatcher) {
tls_slot_ptr_->set([opentelemetry_config, &factory_context, this,
resource](Event::Dispatcher& dispatcher) {
OpenTelemetryGrpcTraceExporterPtr exporter;
if (opentelemetry_config.has_grpc_service()) {
Grpc::AsyncClientFactoryPtr&& factory =
Expand All @@ -39,7 +45,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_, opentelemetry_config.service_name());
factory_context.runtime(), dispatcher, tracing_stats_, resource);

return std::make_shared<TlsTracer>(std::move(tracer));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "source/common/singleton/const_singleton.h"
#include "source/extensions/tracers/common/factory_base.h"
#include "source/extensions/tracers/opentelemetry/grpc_trace_exporter.h"
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.h"
#include "source/extensions/tracers/opentelemetry/tracer.h"

namespace Envoy {
Expand All @@ -30,7 +31,8 @@ using OpenTelemetryConstants = ConstSingleton<OpenTelemetryConstantValues>;
class Driver : Logger::Loggable<Logger::Id::tracing>, public Tracing::Driver {
public:
Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetry_config,
Server::Configuration::TracerFactoryContext& context);
Server::Configuration::TracerFactoryContext& context,
const ResourceProvider& resource_provider);

// Tracing::Driver
Tracing::SpanPtr startSpan(const Tracing::Config& config, Tracing::TraceContext& trace_context,
Expand Down
27 changes: 27 additions & 0 deletions source/extensions/tracers/opentelemetry/resource_detectors/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "resource_detector_lib",
srcs = [
"resource_provider.cc",
],
hdrs = [
"resource_detector.h",
"resource_provider.h",
],
deps = [
"//envoy/config:typed_config_interface",
"//envoy/server:tracer_config_interface",
"//source/common/common:logger_lib",
"//source/common/config:utility_lib",
"@envoy_api//envoy/config/trace/v3:pkg_cc_proto",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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 = [
":resource_detector_environment_lib",
"//envoy/registry",
"//source/common/config:utility_lib",
],
)

envoy_cc_library(
name = "resource_detector_environment_lib",
srcs = ["environment_resource_detector.cc"],
hdrs = ["environment_resource_detector.h"],
deps = [
"//source/common/config:datasource_lib",
"//source/extensions/tracers/opentelemetry/resource_detectors:resource_detector_lib",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "config.h"

#include "source/common/config/utility.h"

#include "environment_resource_detector.h"

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

ResourceDetectorPtr EnvironmentResourceDetectorFactory::createResourceDetector(
Server::Configuration::TracerFactoryContext& context) {
return std::make_shared<EnvironmentResourceDetector>(context);
}

/**
* Static registration for the Env resource detector factory. @see RegisterFactory.
*/
REGISTER_FACTORY(EnvironmentResourceDetectorFactory, ResourceDetectorFactory);

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

#include <string>

#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h"

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

/**
* Config registration for the Environment resource detector. @see ResourceDetectorFactory.
*/
class EnvironmentResourceDetectorFactory : public ResourceDetectorFactory {
public:
/**
* @brief Create a Resource Detector that reads from the OTEL_RESOURCE_ATTRIBUTES
* environment variable.
*
* @param context
* @return ResourceDetectorPtr
*/
ResourceDetectorPtr
createResourceDetector(Server::Configuration::TracerFactoryContext& context) override;

std::string name() const override {
return "envoy.tracers.opentelemetry.resource_detectors.environment";
}
};

DECLARE_FACTORY(EnvironmentResourceDetectorFactory);

} // namespace OpenTelemetry
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "environment_resource_detector.h"

#include <sstream>
#include <string>

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

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

constexpr absl::string_view kOtelResourceAttributesEnv = "OTEL_RESOURCE_ATTRIBUTES";

/**
* @brief Detects a resource from the OTEL_RESOURCE_ATTRIBUTES environment variable
* Based on the OTel C++ SDK:
* https://github.com/open-telemetry/opentelemetry-cpp/blob/v1.11.0/sdk/src/resource/resource_detector.cc
*
* @return Resource A resource with the attributes from the OTEL_RESOURCE_ATTRIBUTES environment
* variable.
*/
Resource EnvironmentResourceDetector::detect() {
Comment thread
joaopgrassi marked this conversation as resolved.
Outdated
envoy::config::core::v3::DataSource ds;
ds.set_environment_variable(kOtelResourceAttributesEnv);

Resource resource;
resource.schemaUrl = "";

TRY_NEEDS_AUDIT {
auto attributes_str = Config::DataSource::read(ds, true, context_.serverFactoryContext().api());
if (attributes_str.empty()) {
return resource;
}

std::istringstream iss(attributes_str);
std::string token;
while (std::getline(iss, token, ',')) {
size_t pos = token.find('=');
std::string key = token.substr(0, pos);
std::string value = token.substr(pos + 1);
resource.attributes[key] = value;
}
}
END_TRY catch (const EnvoyException& e) {
ENVOY_LOG(error, "Failed to read resource attributes: {}.", e.what());
}

return resource;
}

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

#include "envoy/server/factory_context.h"

#include "source/common/common/logger.h"
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h"

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

/**
* @brief A resource detector that extracts attributes from the OTEL_RESOURCE_ATTRIBUTES environment
* variable.
* @see
* https://github.com/open-telemetry/opentelemetry-specification/blob/v1.24.0/specification/resource/sdk.md#detecting-resource-information-from-the-environment
*
*/
class EnvironmentResourceDetector : public ResourceDetector, Logger::Loggable<Logger::Id::tracing> {
public:
EnvironmentResourceDetector(Server::Configuration::TracerFactoryContext& context)
: context_(context) {}
Resource detect() override;

private:
Server::Configuration::TracerFactoryContext&
context_; // TODO, is keeping a reference ok (ownership)?
};

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