From 269ff8f9e470b702c118bd99d225ddf081f67d9a Mon Sep 17 00:00:00 2001 From: owentou Date: Mon, 20 Sep 2021 22:27:00 +0800 Subject: [PATCH] 1. Add `otlp_environment.h` to maintain shared codes of `OtlpGrpcExporter` and `OtlpHttpExporter` 2. Add `timeout` and `metadata` options for `OtlpGrpcExporter` 3. Load environment variables `OTEL_EXPORTER_OTLP_TIMEOUT` , `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` , `OTEL_EXPORTER_OTLP_HEADERS` , `OTEL_EXPORTER_OTLP_TRACES_HEADERS` to initialize default options of `OtlpGrpcExporter` and `OtlpHttpExporter` 4. Load environment variables `OTEL_EXPORTER_OTLP_ENDPOINT` , `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` to initialize default options of `OtlpHttpExporter` Signed-off-by: owentou --- CHANGELOG.md | 2 + exporters/otlp/BUILD | 2 + exporters/otlp/README.md | 12 +- .../exporters/otlp/otlp_environment.h | 203 ++++++++++++++++++ .../exporters/otlp/otlp_grpc_exporter.h | 67 +----- .../exporters/otlp/otlp_http_exporter.h | 19 +- exporters/otlp/src/otlp_grpc_exporter.cc | 10 + exporters/otlp/src/otlp_http_exporter.cc | 29 ++- .../otlp/test/otlp_grpc_exporter_test.cc | 32 +++ .../otlp/test/otlp_http_exporter_test.cc | 58 ++++- 10 files changed, 354 insertions(+), 80 deletions(-) create mode 100644 exporters/otlp/include/opentelemetry/exporters/otlp/otlp_environment.h diff --git a/CHANGELOG.md b/CHANGELOG.md index bb17c1697f..49bfcfebf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ Increment the: ## [Unreleased] +* Support environment variables for both `OtlpGrpcExporter` and `OtlpHttpExporter` ([#983](https://github.com/open-telemetry/opentelemetry-cpp/pull/983)) + ## [1.0.0] 2021-09-16 ### API diff --git a/exporters/otlp/BUILD b/exporters/otlp/BUILD index 134950b0f0..02b888f1b6 100644 --- a/exporters/otlp/BUILD +++ b/exporters/otlp/BUILD @@ -40,6 +40,7 @@ cc_library( "src/otlp_grpc_exporter.cc", ], hdrs = [ + "include/opentelemetry/exporters/otlp/otlp_environment.h", "include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h", "include/opentelemetry/exporters/otlp/protobuf_include_prefix.h", "include/opentelemetry/exporters/otlp/protobuf_include_suffix.h", @@ -61,6 +62,7 @@ cc_library( "src/otlp_http_exporter.cc", ], hdrs = [ + "include/opentelemetry/exporters/otlp/otlp_environment.h", "include/opentelemetry/exporters/otlp/otlp_http_exporter.h", "include/opentelemetry/exporters/otlp/protobuf_include_prefix.h", "include/opentelemetry/exporters/otlp/protobuf_include_suffix.h", diff --git a/exporters/otlp/README.md b/exporters/otlp/README.md index 7bb5fd951b..e0b1b7f4bb 100644 --- a/exporters/otlp/README.md +++ b/exporters/otlp/README.md @@ -54,16 +54,24 @@ auto exporter = std::unique_ptr(new otlp::OtlpHttpExport | | `OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE` | | | | `ssl_credentials_cacert_as_string` | `OTEL_EXPORTER_OTLP_CERTIFICATE_STRING` | `""` | SSL Certifcate as in-memory string | | | `OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE_STRING` | | | | +| `timeout` | `OTEL_EXPORTER_OTLP_TIMEOUT` | `10s` | GRPC deadline | +| | `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` | | | +| `metadata` | `OTEL_EXPORTER_OTLP_HEADERS` | | Custom metadata for GRPC | +| | `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | | | ### Configuration options ( OTLP HTTP Exporter ) | Option | Env Variable |Default | Description | | ------------ |-----|------------ |------| -| `url` | n/a | `http://localhost:4317/v1/traces` | The OTLP HTTP endpoint to connect to | +| `url` | `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4317/v1/traces` | The OTLP HTTP endpoint to connect to | +| | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | | | | `content_type` | n/a | `application/json` | Data format used - JSON or Binary | | `json_bytes_mapping` | n/a | `JsonBytesMappingKind::kHexId` | Encoding used for trace_id and span_id | | `use_json_name` | n/a | `false` | Whether to use json name of protobuf field to set the key of json | -| `timeout` | n/a | `30000 ms` | http timeout | +| `timeout` | `OTEL_EXPORTER_OTLP_TIMEOUT` | `10s` | http timeout | +| | `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` | | +| `http_headers` | `OTEL_EXPORTER_OTLP_HEADERS` | | http headers | +| | `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | | | ## Example diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_environment.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_environment.h new file mode 100644 index 0000000000..a641268595 --- /dev/null +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_environment.h @@ -0,0 +1,203 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include +#include +#include + +#include "opentelemetry/nostd/string_view.h" + +#include "opentelemetry/sdk/common/attribute_utils.h" +#include "opentelemetry/sdk/common/env_variables.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +inline const std::string GetOtlpDefaultGrpcEndpoint() +{ + constexpr char kOtlpTracesEndpointEnv[] = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"; + constexpr char kOtlpEndpointEnv[] = "OTEL_EXPORTER_OTLP_ENDPOINT"; + constexpr char kOtlpEndpointDefault[] = "http://localhost:4317"; + + auto endpoint = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesEndpointEnv); + if (endpoint.empty()) + { + endpoint = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpEndpointEnv); + } + return endpoint.size() ? endpoint : kOtlpEndpointDefault; +} + +inline const std::string GetOtlpDefaultHttpEndpoint() +{ + constexpr char kOtlpTracesEndpointEnv[] = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"; + constexpr char kOtlpEndpointEnv[] = "OTEL_EXPORTER_OTLP_ENDPOINT"; + constexpr char kOtlpEndpointDefault[] = "http://localhost:4317/v1/traces"; + + auto endpoint = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesEndpointEnv); + if (endpoint.empty()) + { + endpoint = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpEndpointEnv); + } + return endpoint.size() ? endpoint : kOtlpEndpointDefault; +} + +inline const bool GetOtlpDefaultIsSslEnable() +{ + constexpr char kOtlpTracesIsSslEnableEnv[] = "OTEL_EXPORTER_OTLP_TRACES_SSL_ENABLE"; + constexpr char kOtlpIsSslEnableEnv[] = "OTEL_EXPORTER_OTLP_SSL_ENABLE"; + + auto ssl_enable = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesIsSslEnableEnv); + if (ssl_enable.empty()) + { + ssl_enable = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpIsSslEnableEnv); + } + if (ssl_enable == "True" || ssl_enable == "TRUE" || ssl_enable == "true" || ssl_enable == "1") + { + return true; + } + return false; +} + +inline const std::string GetOtlpDefaultSslCertificatePath() +{ + constexpr char kOtlpTracesSslCertificate[] = "OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE"; + constexpr char kOtlpSslCertificate[] = "OTEL_EXPORTER_OTLP_CERTIFICATE "; + auto ssl_cert_path = + opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesSslCertificate); + if (ssl_cert_path.empty()) + { + ssl_cert_path = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpSslCertificate); + } + return ssl_cert_path.size() ? ssl_cert_path : ""; +} + +inline const std::string GetOtlpDefaultSslCertificateString() +{ + constexpr char kOtlpTracesSslCertificateString[] = "OTEL_EXPORTER_OTLP_CERTIFICATE_STRING"; + constexpr char kOtlpSslCertificateString[] = "OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE_STRING "; + auto ssl_cert = + opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesSslCertificateString); + if (ssl_cert.empty()) + { + ssl_cert = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpSslCertificateString); + } + return ssl_cert.size() ? ssl_cert : ""; +} + +inline const std::chrono::system_clock::duration GetOtlpTimeoutFromString(const char *input) +{ + if (nullptr == input || 0 == *input) + { + return std::chrono::duration_cast( + std::chrono::seconds{10}); + } + + std::chrono::system_clock::duration::rep result = 0; + // Skip spaces + for (; *input && (' ' == *input || '\t' == *input || '\r' == *input || '\n' == *input); ++input) + ; + + for (; *input && (*input >= '0' && *input <= '9'); ++input) + { + result = result * 10 + (*input - '0'); + } + + opentelemetry::nostd::string_view unit{input}; + if ("ns" == unit) + { + return std::chrono::duration_cast( + std::chrono::nanoseconds{result}); + } + else if ("us" == unit) + { + return std::chrono::duration_cast( + std::chrono::microseconds{result}); + } + else if ("ms" == unit) + { + return std::chrono::duration_cast( + std::chrono::milliseconds{result}); + } + else if ("m" == unit) + { + return std::chrono::duration_cast( + std::chrono::minutes{result}); + } + else if ("h" == unit) + { + return std::chrono::duration_cast( + std::chrono::hours{result}); + } + else + { + return std::chrono::duration_cast( + std::chrono::seconds{result}); + } +} + +inline const std::chrono::system_clock::duration GetOtlpDefaultTimeout() +{ + constexpr char kOtlpTracesTimeoutEnv[] = "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT"; + constexpr char kOtlpTimeoutEnv[] = "OTEL_EXPORTER_OTLP_TIMEOUT"; + + auto timeout = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesTimeoutEnv); + if (timeout.empty()) + { + timeout = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTimeoutEnv); + } + return GetOtlpTimeoutFromString(timeout.c_str()); +} + +struct cmp_ic +{ + bool operator()(const std::string &s1, const std::string &s2) const + { + return std::lexicographical_compare( + s1.begin(), s1.end(), s2.begin(), s2.end(), + [](char c1, char c2) { return ::tolower(c1) < ::tolower(c2); }); + } +}; +using OtlpHeaders = std::multimap; + +inline void DumpOtlpHeaders(OtlpHeaders &output, const char *env_var_name) +{ + auto value = opentelemetry::sdk::common::GetEnvironmentVariable(env_var_name); + if (value.empty()) + { + return; + } + + opentelemetry::common::KeyValueStringTokenizer tokenizer{value}; + opentelemetry::nostd::string_view header_key; + opentelemetry::nostd::string_view header_value; + bool header_valid = true; + + while (tokenizer.next(header_valid, header_key, header_value)) + { + if (header_valid) + { + output.emplace(std::make_pair((std::string)header_key, (std::string)header_value)); + } + } +} + +inline OtlpHeaders GetOtlpDefaultHeaders() +{ + constexpr char kOtlpTracesHeadersEnv[] = "OTEL_EXPORTER_OTLP_TRACES_HEADERS"; + constexpr char kOtlpHeadersEnv[] = "OTEL_EXPORTER_OTLP_HEADERS"; + + OtlpHeaders result; + DumpOtlpHeaders(result, kOtlpHeadersEnv); + DumpOtlpHeaders(result, kOtlpTracesHeadersEnv); + return result; +} + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h index af3c97b4ab..66ae76fcfc 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" #include "opentelemetry/proto/collector/trace/v1/trace_service.grpc.pb.h" @@ -11,7 +13,7 @@ #include "opentelemetry/sdk/trace/exporter.h" -#include "opentelemetry/sdk/common/env_variables.h" +#include "opentelemetry/exporters/otlp/otlp_environment.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -19,70 +21,13 @@ namespace exporter namespace otlp { -inline const std::string GetOtlpDefaultEndpoint() -{ - constexpr char kOtlpTracesEndpointEnv[] = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"; - constexpr char kOtlpEndpointEnv[] = "OTEL_EXPORTER_OTLP_ENDPOINT"; - constexpr char kOtlpEndpointDefault[] = "http://localhost:4317"; - - auto endpoint = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesEndpointEnv); - if (endpoint.size() == 0) - { - endpoint = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpEndpointEnv); - } - return endpoint.size() ? endpoint : kOtlpEndpointDefault; -} - -inline const bool GetOtlpDefaultIsSslEnable() -{ - constexpr char kOtlpTracesIsSslEnableEnv[] = "OTEL_EXPORTER_OTLP_TRACES_SSL_ENABLE"; - constexpr char kOtlpIsSslEnableEnv[] = "OTEL_EXPORTER_OTLP_SSL_ENABLE"; - - auto ssl_enable = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesIsSslEnableEnv); - if (ssl_enable.size() == 0) - { - ssl_enable = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpIsSslEnableEnv); - } - if (ssl_enable == "True" || ssl_enable == "TRUE" || ssl_enable == "true" || ssl_enable == "1") - { - return true; - } - return false; -} - -inline const std::string GetOtlpDefaultSslCertificatePath() -{ - constexpr char kOtlpTracesSslCertificate[] = "OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE"; - constexpr char kOtlpSslCertificate[] = "OTEL_EXPORTER_OTLP_CERTIFICATE "; - auto ssl_cert_path = - opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesSslCertificate); - if (ssl_cert_path.size() == 0) - { - ssl_cert_path = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpSslCertificate); - } - return ssl_cert_path.size() ? ssl_cert_path : ""; -} - -inline const std::string GetOtlpDefaultSslCertificateString() -{ - constexpr char kOtlpTracesSslCertificateString[] = "OTEL_EXPORTER_OTLP_CERTIFICATE_STRING"; - constexpr char kOtlpSslCertificateString[] = "OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE_STRING "; - auto ssl_cert = - opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpTracesSslCertificateString); - if (ssl_cert.size() == 0) - { - ssl_cert = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpSslCertificateString); - } - return ssl_cert.size() ? ssl_cert : ""; -} - /** * Struct to hold OTLP exporter options. */ struct OtlpGrpcExporterOptions { // The endpoint to export to. By default the OpenTelemetry Collector's default endpoint. - std::string endpoint = GetOtlpDefaultEndpoint(); + std::string endpoint = GetOtlpDefaultGrpcEndpoint(); // By default when false, uses grpc::InsecureChannelCredentials(); If true, // uses ssl_credentials_cacert_path if non-empty, else uses ssl_credentials_cacert_as_string bool use_ssl_credentials = GetOtlpDefaultIsSslEnable(); @@ -91,6 +36,10 @@ struct OtlpGrpcExporterOptions // ssl_credentials_cacert_as_string in-memory string representation of .pem file to be used for // SSL encryption. std::string ssl_credentials_cacert_as_string = GetOtlpDefaultSslCertificateString(); + // Timeout for grpc deadline + std::chrono::system_clock::duration timeout = GetOtlpDefaultTimeout(); + // Additional HTTP headers + OtlpHeaders metadata = GetOtlpDefaultHeaders(); }; /** diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter.h index 0d6f04e653..c51c1cf266 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter.h @@ -3,23 +3,23 @@ #pragma once +#include +#include +#include +#include + // We need include exporter.h first, which will include Windows.h with NOMINMAX on Windows #include "opentelemetry/sdk/trace/exporter.h" #include "opentelemetry/ext/http/client/http_client.h" -#include -#include -#include -#include +#include "opentelemetry/exporters/otlp/otlp_environment.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { namespace otlp { -// The default URL path to post trace data. -constexpr char kDefaultTracePath[] = "/v1/traces"; // The default URL path to post metric data. constexpr char kDefaultMetricsPath[] = "/v1/metrics"; // The default URL path to post metric data. @@ -50,7 +50,7 @@ struct OtlpHttpExporterOptions // @see // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md // @see https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver - std::string url = std::string("http://localhost:4317") + kDefaultTracePath; + std::string url = GetOtlpDefaultHttpEndpoint(); // By default, post json data HttpRequestContentType content_type = HttpRequestContentType::kJson; @@ -67,7 +67,10 @@ struct OtlpHttpExporterOptions bool console_debug = false; // TODO: Enable/disable to verify SSL certificate - std::chrono::milliseconds timeout = std::chrono::milliseconds(30000); + std::chrono::system_clock::duration timeout = GetOtlpDefaultTimeout(); + + // Additional HTTP headers + OtlpHeaders http_headers = GetOtlpDefaultHeaders(); }; /** diff --git a/exporters/otlp/src/otlp_grpc_exporter.cc b/exporters/otlp/src/otlp_grpc_exporter.cc index dec65fadda..a9080cfa39 100644 --- a/exporters/otlp/src/otlp_grpc_exporter.cc +++ b/exporters/otlp/src/otlp_grpc_exporter.cc @@ -110,6 +110,16 @@ sdk::common::ExportResult OtlpGrpcExporter::Export( grpc::ClientContext context; proto::collector::trace::v1::ExportTraceServiceResponse response; + if (options_.timeout.count() > 0) + { + context.set_deadline(std::chrono::system_clock::now() + options_.timeout); + } + + for (auto &header : options_.metadata) + { + context.AddMetadata(header.first, header.second); + } + grpc::Status status = trace_service_stub_->Export(&context, request, &response); if (!status.ok()) diff --git a/exporters/otlp/src/otlp_http_exporter.cc b/exporters/otlp/src/otlp_http_exporter.cc index 80cbfa40c7..d27c9fac3b 100644 --- a/exporters/otlp/src/otlp_http_exporter.cc +++ b/exporters/otlp/src/otlp_http_exporter.cc @@ -16,6 +16,8 @@ #include "opentelemetry/proto/collector/trace/v1/trace_service.pb.h" #include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" + +#include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/sdk_config.h" #include @@ -548,10 +550,12 @@ sdk::common::ExportResult OtlpHttpExporter::Export( // Return failure if this exporter has been shutdown if (is_shutdown_) { + const char *error_message = "[OTLP HTTP Exporter] Export failed, exporter is shutdown"; if (options_.console_debug) { - std::cerr << "[OTLP HTTP Exporter] Export failed, exporter is shutdown" << std::endl; + std::cerr << error_message << std::endl; } + OTEL_INTERNAL_LOG_ERROR(error_message); return sdk::common::ExportResult::kFailure; } @@ -562,11 +566,13 @@ sdk::common::ExportResult OtlpHttpExporter::Export( auto parse_url = opentelemetry::ext::http::common::UrlParser(std::string(options_.url)); if (!parse_url.success_) { + std::string error_message = + "[OTLP HTTP Exporter] Export failed, invalid url: " + options_.url; if (options_.console_debug) { - std::cerr << "[OTLP HTTP Exporter] Export failed, invalid url: " << options_.url - << std::endl; + std::cerr << error_message << std::endl; } + OTEL_INTERNAL_LOG_ERROR(error_message.c_str()); return sdk::common::ExportResult::kFailure; } @@ -629,11 +635,16 @@ sdk::common::ExportResult OtlpHttpExporter::Export( // Send the request auto session = http_client_->CreateSession(options_.url); auto request = session->CreateRequest(); + + for (auto &header : options_.http_headers) + { + request->AddHeader(header.first, header.second); + } request->SetUri(http_uri_); - request->SetTimeoutMs(options_.timeout); + request->SetTimeoutMs(std::chrono::duration_cast(options_.timeout)); request->SetMethod(http_client::Method::Post); request->SetBody(body_vec); - request->AddHeader("Content-Type", content_type); + request->ReplaceHeader("Content-Type", content_type); // Send the request std::unique_ptr handler(new ResponseHandler(options_.console_debug)); @@ -642,9 +653,11 @@ sdk::common::ExportResult OtlpHttpExporter::Export( // Wait for the response to be received if (options_.console_debug) { - OTEL_INTERNAL_LOG_DEBUG("[OTLP HTTP Exporter] DEBUG: Waiting for response from " - << options_.url << " (timeout = " << options_.timeout.count() - << " milliseconds)"); + OTEL_INTERNAL_LOG_DEBUG( + "[OTLP HTTP Exporter] DEBUG: Waiting for response from " + << options_.url << " (timeout = " + << std::chrono::duration_cast(options_.timeout).count() + << " milliseconds)"); } bool write_successful = handler->waitForResponse(); diff --git a/exporters/otlp/test/otlp_grpc_exporter_test.cc b/exporters/otlp/test/otlp_grpc_exporter_test.cc index 23c27242be..aaadf82038 100644 --- a/exporters/otlp/test/otlp_grpc_exporter_test.cc +++ b/exporters/otlp/test/otlp_grpc_exporter_test.cc @@ -146,20 +146,52 @@ TEST_F(OtlpGrpcExporterTestPeer, ConfigFromEnv) const std::string endpoint = "http://localhost:9999"; const std::string endpoint_env = "OTEL_EXPORTER_OTLP_ENDPOINT=" + endpoint; putenv(const_cast(endpoint_env.data())); + putenv("OTEL_EXPORTER_OTLP_TIMEOUT=20050ms"); + putenv("OTEL_EXPORTER_OTLP_HEADERS=custom-header-a=a1,custom-header-b=b"); + putenv("OTEL_EXPORTER_OTLP_TRACES_HEADERS=custom-header-a=a2"); std::unique_ptr exporter(new OtlpGrpcExporter()); EXPECT_EQ(GetOptions(exporter).ssl_credentials_cacert_as_string, cacert_str); EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + EXPECT_EQ(GetOptions(exporter).timeout.count(), + std::chrono::duration_cast( + std::chrono::milliseconds{20050}) + .count()); + EXPECT_EQ(GetOptions(exporter).metadata.size(), 3); + { + // Test custom-header-b + auto range = GetOptions(exporter).metadata.equal_range("custom-header-b"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("b")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } + { + // Test custom-header-a + auto range = GetOptions(exporter).metadata.equal_range("custom-header-a"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("a1")); + ++range.first; + EXPECT_EQ(range.first->second, std::string("a2")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } # if defined(_MSC_VER) putenv("OTEL_EXPORTER_OTLP_ENDPOINT="); putenv("OTEL_EXPORTER_OTLP_CERTIFICATE_STRING="); putenv("OTEL_EXPORTER_OTLP_SSL_ENABLE="); + putenv("OTEL_EXPORTER_OTLP_TIMEOUT="); + putenv("OTEL_EXPORTER_OTLP_HEADERS="); + putenv("OTEL_EXPORTER_OTLP_TRACES_HEADERS="); # else unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); unsetenv("OTEL_EXPORTER_OTLP_CERTIFICATE_STRING"); unsetenv("OTEL_EXPORTER_OTLP_SSL_ENABLE"); + unsetenv("OTEL_EXPORTER_OTLP_TIMEOUT"); + unsetenv("OTEL_EXPORTER_OTLP_HEADERS"); + unsetenv("OTEL_EXPORTER_OTLP_TRACES_HEADERS"); # endif } diff --git a/exporters/otlp/test/otlp_http_exporter_test.cc b/exporters/otlp/test/otlp_http_exporter_test.cc index daab046439..f7febab79b 100644 --- a/exporters/otlp/test/otlp_http_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_exporter_test.cc @@ -59,10 +59,10 @@ class OtlpHttpExporterTestPeer : public ::testing::Test, public HTTP_SERVER_NS:: int port = server_.addListeningPort(14371); std::ostringstream os; os << "localhost:" << port; - server_address_ = "http://" + os.str() + kDefaultTracePath; + server_address_ = "http://" + os.str() + "/v1/traces"; server_.setServerName(os.str()); server_.setKeepalive(false); - server_.addHandler(kDefaultTracePath, *this); + server_.addHandler("/v1/traces", *this); server_.start(); is_running_ = true; } @@ -89,7 +89,7 @@ class OtlpHttpExporterTestPeer : public ::testing::Test, public HTTP_SERVER_NS:: int response_status = 0; - if (request.uri == kDefaultTracePath) + if (request.uri == "/v1/traces") { response.headers["Content-Type"] = "application/json"; std::unique_lock lk(mtx_requests); @@ -327,6 +327,58 @@ TEST_F(OtlpHttpExporterTestPeer, ConfigJsonBytesMappingTest) EXPECT_EQ(GetOptions(exporter).json_bytes_mapping, JsonBytesMappingKind::kHex); } +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpHttpExporterTestPeer, ConfigFromEnv) +{ + const std::string url = "http://localhost:9999/v1/traces"; + const std::string url_env = "OTEL_EXPORTER_OTLP_ENDPOINT=" + url; + putenv(const_cast(url_env.data())); + putenv("OTEL_EXPORTER_OTLP_TIMEOUT=20s"); + putenv("OTEL_EXPORTER_OTLP_HEADERS=custom-header-a=a1,custom-header-b=b"); + putenv("OTEL_EXPORTER_OTLP_TRACES_HEADERS=custom-header-a=a2"); + + std::unique_ptr exporter(new OtlpHttpExporter()); + EXPECT_EQ(GetOptions(exporter).url, url); + EXPECT_EQ( + GetOptions(exporter).timeout.count(), + std::chrono::duration_cast(std::chrono::seconds{20}) + .count()); + EXPECT_EQ(GetOptions(exporter).http_headers.size(), 3); + { + // Test custom-header-b + auto range = GetOptions(exporter).http_headers.equal_range("custom-header-b"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("b")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } + { + // Test custom-header-a + auto range = GetOptions(exporter).http_headers.equal_range("custom-header-a"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("a1")); + ++range.first; + EXPECT_EQ(range.first->second, std::string("a2")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } +# if defined(_MSC_VER) + putenv("OTEL_EXPORTER_OTLP_ENDPOINT="); + putenv("OTEL_EXPORTER_OTLP_TIMEOUT="); + putenv("OTEL_EXPORTER_OTLP_HEADERS="); + putenv("OTEL_EXPORTER_OTLP_TRACES_HEADERS="); + +# else + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_TIMEOUT"); + unsetenv("OTEL_EXPORTER_OTLP_HEADERS"); + unsetenv("OTEL_EXPORTER_OTLP_TRACES_HEADERS"); + +# endif +} +# endif + } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE