-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
opentelemetry tracer: add OTLP/HTTP exporter (#29207)
* Refactor gRPC exporter to use general base class we can later reuse Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Update OpenTelemetryConfig with HTTP-related config Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Write and wire up HTTP trace exporter Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Code formatting Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Proto format Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Add basic tests Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * code format Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Add additional counters for http exporter and test Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Formatting Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Coverage improvements Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Formatting Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Add higher level Driver test for HTTP exporting Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * More formatting Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Clang tidy Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> * Refactor config and add HTTP headers Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Modify tests Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Fix lint errors Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Revert oneof in proto config Re-allow not having a grpc_service specified to keep the existing behavior. Added a condition to fail-fast when both exporters are configured. Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * PR suggestions Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Add HttpService config type Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Fix format issues Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Fix lint/format/docs issues Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Hostname -> Authority Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Use HttpUri type Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * PR suggestions Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Improve log messages Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Fix format Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * PR suggestions Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * PR suggestions Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Revert stats for http exporter Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Fix spelling Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Add changelog Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Properly manage in-flight http requests in the exporter Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Add proto migrate oneof annotation Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Clarify http headers do not support formatting Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Prepare headers when creating the HTTP exporter Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> * Revert test change Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> --------- Signed-off-by: Alex Ellis <ellisonjtk@gmail.com> Signed-off-by: Joao Grassi <joao.grassi@dynatrace.com> Co-authored-by: Alex Ellis <ellisonjtk@gmail.com>
- Loading branch information
1 parent
525b1d2
commit 767cb40
Showing
20 changed files
with
566 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
syntax = "proto3"; | ||
|
||
package envoy.config.core.v3; | ||
|
||
import "envoy/config/core/v3/base.proto"; | ||
import "envoy/config/core/v3/http_uri.proto"; | ||
|
||
import "udpa/annotations/status.proto"; | ||
import "validate/validate.proto"; | ||
|
||
option java_package = "io.envoyproxy.envoy.config.core.v3"; | ||
option java_outer_classname = "HttpServiceProto"; | ||
option java_multiple_files = true; | ||
option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/core/v3;corev3"; | ||
option (udpa.annotations.file_status).package_version_status = ACTIVE; | ||
|
||
// [#protodoc-title: HTTP services] | ||
|
||
// HTTP service configuration. | ||
message HttpService { | ||
// The service's HTTP URI. For example: | ||
// | ||
// .. code-block:: yaml | ||
// | ||
// http_uri: | ||
// uri: https://www.myserviceapi.com/v1/data | ||
// cluster: www.myserviceapi.com|443 | ||
// | ||
HttpUri http_uri = 1; | ||
|
||
// Specifies a list of HTTP headers that should be added to each request | ||
// handled by this virtual host. | ||
repeated HeaderValueOption request_headers_to_add = 2 | ||
[(validate.rules).repeated = {max_items: 1000}]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
source/extensions/tracers/opentelemetry/http_trace_exporter.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#include "source/extensions/tracers/opentelemetry/http_trace_exporter.h" | ||
|
||
#include <chrono> | ||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "source/common/common/enum_to_int.h" | ||
#include "source/common/common/logger.h" | ||
#include "source/common/protobuf/protobuf.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
OpenTelemetryHttpTraceExporter::OpenTelemetryHttpTraceExporter( | ||
Upstream::ClusterManager& cluster_manager, | ||
const envoy::config::core::v3::HttpService& http_service) | ||
: cluster_manager_(cluster_manager), http_service_(http_service) { | ||
|
||
// Prepare and store headers to be used later on each export request | ||
for (const auto& header_value_option : http_service_.request_headers_to_add()) { | ||
parsed_headers_to_add_.push_back({Http::LowerCaseString(header_value_option.header().key()), | ||
header_value_option.header().value()}); | ||
} | ||
} | ||
|
||
bool OpenTelemetryHttpTraceExporter::log(const ExportTraceServiceRequest& request) { | ||
std::string request_body; | ||
|
||
const auto ok = request.SerializeToString(&request_body); | ||
if (!ok) { | ||
ENVOY_LOG(warn, "Error while serializing the binary proto ExportTraceServiceRequest."); | ||
return false; | ||
} | ||
|
||
const auto thread_local_cluster = | ||
cluster_manager_.getThreadLocalCluster(http_service_.http_uri().cluster()); | ||
if (thread_local_cluster == nullptr) { | ||
ENVOY_LOG(error, "OTLP HTTP exporter failed: [cluster = {}] is not configured", | ||
http_service_.http_uri().cluster()); | ||
return false; | ||
} | ||
|
||
Http::RequestMessagePtr message = Http::Utility::prepareHeaders(http_service_.http_uri()); | ||
|
||
// The request follows the OTLP HTTP specification: | ||
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.0.0/docs/specification.md#otlphttp. | ||
message->headers().setReferenceMethod(Http::Headers::get().MethodValues.Post); | ||
message->headers().setReferenceContentType(Http::Headers::get().ContentTypeValues.Protobuf); | ||
|
||
// Add all custom headers to the request. | ||
for (const auto& header_pair : parsed_headers_to_add_) { | ||
message->headers().setReference(header_pair.first, header_pair.second); | ||
} | ||
message->body().add(request_body); | ||
|
||
const auto options = Http::AsyncClient::RequestOptions().setTimeout(std::chrono::milliseconds( | ||
DurationUtil::durationToMilliseconds(http_service_.http_uri().timeout()))); | ||
|
||
Http::AsyncClient::Request* in_flight_request = | ||
thread_local_cluster->httpAsyncClient().send(std::move(message), *this, options); | ||
|
||
if (in_flight_request == nullptr) { | ||
return false; | ||
} | ||
|
||
active_requests_.add(*in_flight_request); | ||
return true; | ||
} | ||
|
||
void OpenTelemetryHttpTraceExporter::onSuccess(const Http::AsyncClient::Request& request, | ||
Http::ResponseMessagePtr&& http_response) { | ||
active_requests_.remove(request); | ||
const auto response_code = Http::Utility::getResponseStatus(http_response->headers()); | ||
if (response_code != enumToInt(Http::Code::OK)) { | ||
ENVOY_LOG(error, | ||
"OTLP HTTP exporter received a non-success status code: {} while exporting the OTLP " | ||
"message", | ||
response_code); | ||
} | ||
} | ||
|
||
void OpenTelemetryHttpTraceExporter::onFailure(const Http::AsyncClient::Request& request, | ||
Http::AsyncClient::FailureReason reason) { | ||
active_requests_.remove(request); | ||
ENVOY_LOG(debug, "The OTLP export request failed. Reason {}", enumToInt(reason)); | ||
} | ||
|
||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
48 changes: 48 additions & 0 deletions
48
source/extensions/tracers/opentelemetry/http_trace_exporter.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#pragma once | ||
|
||
#include "envoy/config/core/v3/http_service.pb.h" | ||
#include "envoy/upstream/cluster_manager.h" | ||
|
||
#include "source/common/common/logger.h" | ||
#include "source/common/http/async_client_impl.h" | ||
#include "source/common/http/async_client_utility.h" | ||
#include "source/common/http/headers.h" | ||
#include "source/common/http/message_impl.h" | ||
#include "source/common/http/utility.h" | ||
#include "source/extensions/tracers/opentelemetry/trace_exporter.h" | ||
|
||
#include "opentelemetry/proto/collector/trace/v1/trace_service.pb.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
/** | ||
* Exporter for OTLP traces over HTTP. | ||
*/ | ||
class OpenTelemetryHttpTraceExporter : public OpenTelemetryTraceExporter, | ||
public Http::AsyncClient::Callbacks { | ||
public: | ||
OpenTelemetryHttpTraceExporter(Upstream::ClusterManager& cluster_manager, | ||
const envoy::config::core::v3::HttpService& http_service); | ||
|
||
bool log(const ExportTraceServiceRequest& request) override; | ||
|
||
// Http::AsyncClient::Callbacks. | ||
void onSuccess(const Http::AsyncClient::Request&, Http::ResponseMessagePtr&&) override; | ||
void onFailure(const Http::AsyncClient::Request&, Http::AsyncClient::FailureReason) override; | ||
void onBeforeFinalizeUpstreamSpan(Tracing::Span&, const Http::ResponseHeaderMap*) override {} | ||
|
||
private: | ||
Upstream::ClusterManager& cluster_manager_; | ||
envoy::config::core::v3::HttpService http_service_; | ||
// Track active HTTP requests to be able to cancel them on destruction. | ||
Http::AsyncClientRequestTracker active_requests_; | ||
std::vector<std::pair<const Http::LowerCaseString, const std::string>> parsed_headers_to_add_; | ||
}; | ||
|
||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
source/extensions/tracers/opentelemetry/span_context_extractor.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.