Skip to content

Commit

Permalink
extensions: add OpenTelemetry tracer extension for exporting OTLP tra…
Browse files Browse the repository at this point in the history
…ces (envoyproxy#20281)

Signed-off-by: Alex Ellis <[email protected]>
  • Loading branch information
AlexanderEllis authored Jun 22, 2022
1 parent 6cc283c commit f7a8db0
Show file tree
Hide file tree
Showing 29 changed files with 1,669 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ extensions/filters/common/original_src @snowp @klarose
/*/extensions/tracers/xray @abaptiste @suniltheta @mattklein123
# tracers.skywalking extension
/*/extensions/tracers/skywalking @wbpcode @lizan @Shikugawa
# tracers.opentelemetry extension
/*/extensions/tracers/opentelemetry @alexanderellis @htuch
# quic extension
/*/extensions/quic/ @alyssawilk @danzh2010 @mattklein123 @mpwarres @wu-bin @ggreenway
# UDP packet writer
Expand Down
3 changes: 3 additions & 0 deletions api/bazel/external_proto_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ EXTERNAL_PROTO_GO_BAZEL_DEP_MAP = {
"@com_google_googleapis//google/api/expr/v1alpha1:syntax_proto": "@go_googleapis//google/api/expr/v1alpha1:expr_go_proto",
"@opencensus_proto//opencensus/proto/trace/v1:trace_proto": "@opencensus_proto//opencensus/proto/trace/v1:trace_proto_go",
"@opencensus_proto//opencensus/proto/trace/v1:trace_config_proto": "@opencensus_proto//opencensus/proto/trace/v1:trace_and_config_proto_go",
"@opentelemetry_proto//:trace": "@opentelemetry_proto//:trace_go_proto",
"@opentelemetry_proto//:logs": "@opentelemetry_proto//:logs_go_proto",
"@opentelemetry_proto//:common": "@opentelemetry_proto//:common_go_proto",
}
Expand All @@ -42,6 +43,7 @@ EXTERNAL_PROTO_CC_BAZEL_DEP_MAP = {
"@com_google_googleapis//google/api/expr/v1alpha1:syntax_proto": "@com_google_googleapis//google/api/expr/v1alpha1:syntax_cc_proto",
"@opencensus_proto//opencensus/proto/trace/v1:trace_proto": "@opencensus_proto//opencensus/proto/trace/v1:trace_proto_cc",
"@opencensus_proto//opencensus/proto/trace/v1:trace_config_proto": "@opencensus_proto//opencensus/proto/trace/v1:trace_config_proto_cc",
"@opentelemetry_proto//:trace": "@opentelemetry_proto//:trace_cc_proto",
"@opentelemetry_proto//:logs": "@opentelemetry_proto//:logs_cc_proto",
"@opentelemetry_proto//:common": "@opentelemetry_proto//:common_cc_proto",
}
Expand All @@ -52,6 +54,7 @@ EXTERNAL_PROTO_PY_BAZEL_DEP_MAP = {
"@com_google_googleapis//google/api/expr/v1alpha1:syntax_proto": "@com_google_googleapis//google/api/expr/v1alpha1:syntax_py_proto",
"@opencensus_proto//opencensus/proto/trace/v1:trace_proto": "@opencensus_proto//opencensus/proto/trace/v1:trace_proto_py",
"@opencensus_proto//opencensus/proto/trace/v1:trace_config_proto": "@opencensus_proto//opencensus/proto/trace/v1:trace_config_proto_py",
"@opentelemetry_proto//:trace": "@opentelemetry_proto//:trace_py_proto",
"@opentelemetry_proto//:logs": "@opentelemetry_proto//:logs_py_proto",
"@opentelemetry_proto//:common": "@opentelemetry_proto//:common_py_proto",
}
30 changes: 27 additions & 3 deletions api/bazel/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def api_dependencies():
)
external_http_archive(
name = "opentelemetry_proto",
build_file_content = OPENTELEMETRY_LOGS_BUILD_CONTENT,
build_file_content = OPENTELEMETRY_BUILD_CONTENT,
)
external_http_archive(
name = "com_github_bufbuild_buf",
Expand Down Expand Up @@ -111,7 +111,7 @@ go_proto_library(
)
"""

OPENTELEMETRY_LOGS_BUILD_CONTENT = """
OPENTELEMETRY_BUILD_CONTENT = """
load("@envoy_api//bazel:api_build_system.bzl", "api_cc_py_proto_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
Expand All @@ -123,6 +123,17 @@ api_cc_py_proto_library(
visibility = ["//visibility:public"],
)
api_cc_py_proto_library(
name = "resource",
srcs = [
"opentelemetry/proto/resource/v1/resource.proto",
],
deps = [
"//:common",
],
visibility = ["//visibility:public"],
)
go_proto_library(
name = "common_go_proto",
importpath = "go.opentelemetry.io/proto/otlp/common/v1",
Expand All @@ -137,10 +148,10 @@ api_cc_py_proto_library(
srcs = [
"opentelemetry/proto/collector/logs/v1/logs_service.proto",
"opentelemetry/proto/logs/v1/logs.proto",
"opentelemetry/proto/resource/v1/resource.proto",
],
deps = [
"//:common",
"//:resource",
],
visibility = ["//visibility:public"],
)
Expand All @@ -151,6 +162,19 @@ go_proto_library(
proto = ":logs",
visibility = ["//visibility:public"],
)
api_cc_py_proto_library(
name = "trace",
srcs = [
"opentelemetry/proto/collector/trace/v1/trace_service.proto",
"opentelemetry/proto/trace/v1/trace.proto",
],
deps = [
"//:common",
"//:resource",
],
visibility = ["//visibility:public"],
)
"""

BUF_BUILD_CONTENT = """
Expand Down
6 changes: 3 additions & 3 deletions api/bazel/repository_locations.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ REPOSITORY_LOCATIONS_SPEC = dict(
project_name = "OpenTelemetry Proto",
project_desc = "Language Independent Interface Types For OpenTelemetry",
project_url = "https://github.com/open-telemetry/opentelemetry-proto",
version = "0.11.0",
sha256 = "985367f8905e91018e636cbf0d83ab3f834b665c4f5899a27d10cae9657710e2",
release_date = "2021-10-07",
version = "0.18.0",
sha256 = "134ce87f0a623daac19b9507b92da0d9b82929e3db796bba631e422f6ea8d3b3",
release_date = "2022-05-17",
strip_prefix = "opentelemetry-proto-{version}",
urls = ["https://github.com/open-telemetry/opentelemetry-proto/archive/v{version}.tar.gz"],
use_category = ["api"],
Expand Down
26 changes: 26 additions & 0 deletions api/envoy/config/trace/v3/opentelemetry.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
syntax = "proto3";

package envoy.config.trace.v3;

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

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

option java_package = "io.envoyproxy.envoy.config.trace.v3";
option java_outer_classname = "OpentelemetryProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/trace/v3;tracev3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: OpenTelemetry tracer]

// Configuration for the OpenTelemetry tracer.
// [#extension: envoy.tracers.opentelemetry]
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.
core.v3.GrpcService grpc_service = 1 [(validate.rules).message = {required: true}];
}
1 change: 1 addition & 0 deletions api/envoy/config/trace/v3/trace.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import public "envoy/config/trace/v3/dynamic_ot.proto";
import public "envoy/config/trace/v3/http_tracer.proto";
import public "envoy/config/trace/v3/lightstep.proto";
import public "envoy/config/trace/v3/opencensus.proto";
import public "envoy/config/trace/v3/opentelemetry.proto";
import public "envoy/config/trace/v3/service.proto";
import public "envoy/config/trace/v3/zipkin.proto";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ void GrpcAccessLoggerImpl::initMessageRoot(
}

void GrpcAccessLoggerImpl::addEntry(opentelemetry::proto::logs::v1::LogRecord&& entry) {
root_->mutable_logs()->Add(std::move(entry));
root_->mutable_log_records()->Add(std::move(entry));
}

bool GrpcAccessLoggerImpl::isEmpty() { return root_->logs().empty(); }
bool GrpcAccessLoggerImpl::isEmpty() { return root_->log_records().empty(); }

// The message is already initialized in the c'tor, and only the logs are cleared.
void GrpcAccessLoggerImpl::initMessage() {}

void GrpcAccessLoggerImpl::clearMessage() { root_->clear_logs(); }
void GrpcAccessLoggerImpl::clearMessage() { root_->clear_log_records(); }

GrpcAccessLoggerCacheImpl::GrpcAccessLoggerCacheImpl(Grpc::AsyncClientManager& async_client_manager,
Stats::Scope& scope,
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 @@ -197,6 +197,7 @@ EXTENSIONS = {
"envoy.tracers.opencensus": "//source/extensions/tracers/opencensus:config",
"envoy.tracers.xray": "//source/extensions/tracers/xray:config",
"envoy.tracers.skywalking": "//source/extensions/tracers/skywalking:config",
"envoy.tracers.opentelemetry": "//source/extensions/tracers/opentelemetry: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 @@ -649,6 +649,11 @@ envoy.tracers.opencensus:
- envoy.tracers
security_posture: robust_to_untrusted_downstream
status: stable
envoy.tracers.opentelemetry:
categories:
- envoy.tracers
security_posture: unknown
status: wip
envoy.tracers.skywalking:
categories:
- envoy.tracers
Expand Down
59 changes: 59 additions & 0 deletions source/extensions/tracers/opentelemetry/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_extension",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

# Trace driver for OpenTelemetry: https://opentelemetry.io/

envoy_extension_package()

envoy_cc_extension(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
":opentelemetry_tracer_lib",
"//source/extensions/tracers/common:factory_base_lib",
"@envoy_api//envoy/config/trace/v3:pkg_cc_proto",
],
)

envoy_cc_library(
name = "opentelemetry_tracer_lib",
srcs = [
"opentelemetry_tracer_impl.cc",
"span_context_extractor.cc",
"tracer.cc",
],
hdrs = [
"opentelemetry_tracer_impl.h",
"span_context.h",
"span_context_extractor.h",
"tracer.h",
],
deps = [
":grpc_trace_exporter",
"//envoy/thread_local:thread_local_interface",
"//source/common/config:utility_lib",
"//source/common/tracing:http_tracer_lib",
"//source/extensions/tracers/common:factory_base_lib",
"@envoy_api//envoy/config/trace/v3:pkg_cc_proto",
"@opentelemetry_proto//:trace_cc_proto",
],
)

envoy_cc_library(
name = "grpc_trace_exporter",
srcs = ["grpc_trace_exporter.cc"],
hdrs = ["grpc_trace_exporter.h"],
deps = [
"//envoy/grpc:async_client_manager_interface",
"//source/common/grpc:typed_async_client_lib",
"//source/common/protobuf",
"@opentelemetry_proto//:trace_cc_proto",
],
)
32 changes: 32 additions & 0 deletions source/extensions/tracers/opentelemetry/config.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "source/extensions/tracers/opentelemetry/config.h"

#include "envoy/config/trace/v3/opentelemetry.pb.h"
#include "envoy/config/trace/v3/opentelemetry.pb.validate.h"
#include "envoy/registry/registry.h"

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

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

OpenTelemetryTracerFactory::OpenTelemetryTracerFactory()
: FactoryBase("envoy.tracers.opentelemetry") {}

Tracing::DriverSharedPtr OpenTelemetryTracerFactory::createTracerDriverTyped(
const envoy::config::trace::v3::OpenTelemetryConfig& proto_config,
Server::Configuration::TracerFactoryContext& context) {
return std::make_shared<Driver>(proto_config, context);
}

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

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

#include <string>

#include "envoy/config/trace/v3/opentelemetry.pb.h"
#include "envoy/config/trace/v3/opentelemetry.pb.validate.h"

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

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

/**
* Config registration for the OpenTelemetry tracer. @see TracerFactory.
*/
class OpenTelemetryTracerFactory
: Logger::Loggable<Logger::Id::tracing>,
public Common::FactoryBase<envoy::config::trace::v3::OpenTelemetryConfig> {
public:
OpenTelemetryTracerFactory();

private:
// FactoryBase
Tracing::DriverSharedPtr
createTracerDriverTyped(const envoy::config::trace::v3::OpenTelemetryConfig& proto_config,
Server::Configuration::TracerFactoryContext& context) override;
};

} // namespace OpenTelemetry
} // namespace Tracers
} // namespace Extensions
} // namespace Envoy
23 changes: 23 additions & 0 deletions source/extensions/tracers/opentelemetry/grpc_trace_exporter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "grpc_trace_exporter.h"
#include "source/extensions/tracers/opentelemetry/grpc_trace_exporter.h"

#include "source/common/common/logger.h"

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

OpenTelemetryGrpcTraceExporter::OpenTelemetryGrpcTraceExporter(
const Grpc::RawAsyncClientSharedPtr& client)
: client_(client, *Protobuf::DescriptorPool::generated_pool()->FindMethodByName(
"opentelemetry.proto.collector.trace.v1.TraceService.Export")) {}

bool OpenTelemetryGrpcTraceExporter::log(const ExportTraceServiceRequest& request) {
return client_.log(request);
}

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

0 comments on commit f7a8db0

Please sign in to comment.