Line data Source code
1 : #include "source/extensions/tracers/opentelemetry/http_trace_exporter.h" 2 : 3 : #include <chrono> 4 : #include <memory> 5 : #include <string> 6 : #include <vector> 7 : 8 : #include "source/common/common/enum_to_int.h" 9 : #include "source/common/common/logger.h" 10 : #include "source/common/protobuf/protobuf.h" 11 : 12 : namespace Envoy { 13 : namespace Extensions { 14 : namespace Tracers { 15 : namespace OpenTelemetry { 16 : 17 : OpenTelemetryHttpTraceExporter::OpenTelemetryHttpTraceExporter( 18 : Upstream::ClusterManager& cluster_manager, 19 : const envoy::config::core::v3::HttpService& http_service) 20 0 : : cluster_manager_(cluster_manager), http_service_(http_service) { 21 : 22 : // Prepare and store headers to be used later on each export request 23 0 : for (const auto& header_value_option : http_service_.request_headers_to_add()) { 24 0 : parsed_headers_to_add_.push_back({Http::LowerCaseString(header_value_option.header().key()), 25 0 : header_value_option.header().value()}); 26 0 : } 27 0 : } 28 : 29 0 : bool OpenTelemetryHttpTraceExporter::log(const ExportTraceServiceRequest& request) { 30 0 : std::string request_body; 31 : 32 0 : const auto ok = request.SerializeToString(&request_body); 33 0 : if (!ok) { 34 0 : ENVOY_LOG(warn, "Error while serializing the binary proto ExportTraceServiceRequest."); 35 0 : return false; 36 0 : } 37 : 38 0 : const auto thread_local_cluster = 39 0 : cluster_manager_.getThreadLocalCluster(http_service_.http_uri().cluster()); 40 0 : if (thread_local_cluster == nullptr) { 41 0 : ENVOY_LOG(error, "OTLP HTTP exporter failed: [cluster = {}] is not configured", 42 0 : http_service_.http_uri().cluster()); 43 0 : return false; 44 0 : } 45 : 46 0 : Http::RequestMessagePtr message = Http::Utility::prepareHeaders(http_service_.http_uri()); 47 : 48 : // The request follows the OTLP HTTP specification: 49 : // https://github.com/open-telemetry/opentelemetry-proto/blob/v1.0.0/docs/specification.md#otlphttp. 50 0 : message->headers().setReferenceMethod(Http::Headers::get().MethodValues.Post); 51 0 : message->headers().setReferenceContentType(Http::Headers::get().ContentTypeValues.Protobuf); 52 : 53 : // Add all custom headers to the request. 54 0 : for (const auto& header_pair : parsed_headers_to_add_) { 55 0 : message->headers().setReference(header_pair.first, header_pair.second); 56 0 : } 57 0 : message->body().add(request_body); 58 : 59 0 : const auto options = Http::AsyncClient::RequestOptions().setTimeout(std::chrono::milliseconds( 60 0 : DurationUtil::durationToMilliseconds(http_service_.http_uri().timeout()))); 61 : 62 0 : Http::AsyncClient::Request* in_flight_request = 63 0 : thread_local_cluster->httpAsyncClient().send(std::move(message), *this, options); 64 : 65 0 : if (in_flight_request == nullptr) { 66 0 : return false; 67 0 : } 68 : 69 0 : active_requests_.add(*in_flight_request); 70 0 : return true; 71 0 : } 72 : 73 : void OpenTelemetryHttpTraceExporter::onSuccess(const Http::AsyncClient::Request& request, 74 0 : Http::ResponseMessagePtr&& http_response) { 75 0 : active_requests_.remove(request); 76 0 : const auto response_code = Http::Utility::getResponseStatus(http_response->headers()); 77 0 : if (response_code != enumToInt(Http::Code::OK)) { 78 0 : ENVOY_LOG(error, 79 0 : "OTLP HTTP exporter received a non-success status code: {} while exporting the OTLP " 80 0 : "message", 81 0 : response_code); 82 0 : } 83 0 : } 84 : 85 : void OpenTelemetryHttpTraceExporter::onFailure(const Http::AsyncClient::Request& request, 86 0 : Http::AsyncClient::FailureReason reason) { 87 0 : active_requests_.remove(request); 88 0 : ENVOY_LOG(debug, "The OTLP export request failed. Reason {}", enumToInt(reason)); 89 0 : } 90 : 91 : } // namespace OpenTelemetry 92 : } // namespace Tracers 93 : } // namespace Extensions 94 : } // namespace Envoy