From 5067e49bce39e8dd4c3986042e558e965c73a253 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 2 Aug 2021 22:25:58 +0530 Subject: [PATCH] Move env-var read logic to common dir, and optional reading of env-var (#924) --- CMakeLists.txt | 7 ++++ .../exporters/otlp/otlp_grpc_exporter.h | 36 +++++++++++++++-- .../otlp/test/otlp_grpc_exporter_test.cc | 32 +++++++++++++++ .../exporters/zipkin/zipkin_exporter.h | 21 ++-------- .../opentelemetry/sdk/common/env_variables.h | 40 +++++++++++++++++++ sdk/src/resource/resource_detector.cc | 20 +++------- sdk/test/resource/resource_test.cc | 14 ++++--- 7 files changed, 130 insertions(+), 40 deletions(-) create mode 100644 sdk/include/opentelemetry/sdk/common/env_variables.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 822e78bf37..8cbd374b3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,7 +152,14 @@ option(WITH_ELASTICSEARCH option(WITH_JAEGER "Whether to include the Jaeger exporter" OFF) +option(WITH_NO_GETENV "Whether the platform supports environment variables" OFF) + option(BUILD_TESTING "Whether to enable tests" ON) + +if(WITH_NO_GENENV) + add_definitions(-DNO_GETENV) +endif() + if(WIN32) add_definitions(-DNOMINMAX) if(BUILD_TESTING) 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 b3df30d259..31ad058c6d 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h @@ -11,26 +11,56 @@ #include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/common/env_variables.h" + OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { namespace otlp { + +inline const std::string GetOtlpGrpcDefaultEndpoint() +{ + constexpr char kOtlpGrpcEndpointEnv[] = "OTEL_EXPORTER_OTLP_GRPC_ENDPOINT"; + constexpr char kOtlpGrpcEndpointDefault[] = "localhost:4317"; + + auto endpoint = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpGrpcEndpointEnv); + return endpoint.size() ? endpoint : kOtlpGrpcEndpointDefault; +} + +inline const bool GetOtlpGrpcDefaultIsSslEnable() +{ + constexpr char kOtlpGrpcIsSslEnableEnv[] = "OTEL_EXPORTER_OTLP_GRPC_SSL_ENABLE"; + auto ssl_enable = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpGrpcIsSslEnableEnv); + if (ssl_enable == "True" || ssl_enable == "TRUE" || ssl_enable == "true" || ssl_enable == "1") + { + return true; + } + return false; +} + +inline const std::string GetOtlpGrpcDefaultSslCertificate() +{ + constexpr char kOtlpGrpcSslCertificate[] = "OTEL_EXPORTER_OTLP_GRPC_SSL_CERTIFICATE"; + auto ssl_cert = opentelemetry::sdk::common::GetEnvironmentVariable(kOtlpGrpcSslCertificate); + 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 = "localhost:4317"; + std::string endpoint = GetOtlpGrpcDefaultEndpoint(); // 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 = false; + bool use_ssl_credentials = GetOtlpGrpcDefaultIsSslEnable(); // ssl_credentials_cacert_path specifies path to .pem file to be used for SSL encryption. std::string ssl_credentials_cacert_path = ""; // 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 = ""; + std::string ssl_credentials_cacert_as_string = GetOtlpGrpcDefaultSslCertificate(); }; /** diff --git a/exporters/otlp/test/otlp_grpc_exporter_test.cc b/exporters/otlp/test/otlp_grpc_exporter_test.cc index f7e82e6a46..13acd5b9ce 100644 --- a/exporters/otlp/test/otlp_grpc_exporter_test.cc +++ b/exporters/otlp/test/otlp_grpc_exporter_test.cc @@ -129,6 +129,38 @@ TEST_F(OtlpGrpcExporterTestPeer, ConfigSslCredentialsTest) EXPECT_EQ(GetOptions(exporter).ssl_credentials_cacert_as_string, cacert_str); EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); } + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcExporterTestPeer, ConfigFromEnv) +{ + const std::string cacert_str = "--begin and end fake cert--"; + const std::string cacert_env = "OTEL_EXPORTER_OTLP_GRPC_SSL_CERTIFICATE=" + cacert_str; + putenv(const_cast(cacert_env.data())); + char ssl_enable_env[] = "OTEL_EXPORTER_OTLP_GRPC_SSL_ENABLE=True"; + putenv(ssl_enable_env); + const std::string endpoint = "http://localhost:9999"; + const std::string endpoint_env = "OTEL_EXPORTER_OTLP_GRPC_ENDPOINT=" + endpoint; + putenv(const_cast(endpoint_env.data())); + + 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); +# if defined(_MSC_VER) + putenv("OTEL_EXPORTER_OTLP_GRPC_ENDPOINT="); + putenv("OTEL_EXPORTER_OTLP_GRPC_SSL_CERTIFICATE="); + putenv("OTEL_EXPORTER_OTLP_GRPC_SSL_ENABLE="); + +# else + unsetenv("OTEL_EXPORTER_OTLP_GRPC_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_GRPC_SSL_CERTIFICATE"); + unsetenv("OTEL_EXPORTER_OTLP_GRPC_SSL_ENABLE"); + +# endif +} +# endif + } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 7e9321435c..ec3f562b19 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -5,6 +5,7 @@ #include "opentelemetry/ext/http/client/http_client_factory.h" #include "opentelemetry/ext/http/common/url_parser.h" +#include "opentelemetry/sdk/common/env_variables.h" #include "opentelemetry/sdk/trace/exporter.h" #include "opentelemetry/sdk/trace/span_data.h" @@ -21,23 +22,9 @@ inline const std::string GetDefaultZipkinEndpoint() const char *otel_exporter_zipkin_endpoint_env = "OTEL_EXPORTER_ZIPKIN_ENDPOINT"; const char *kZipkinEndpointDefault = "http://localhost:9411/api/v2/spans"; -#if defined(_MSC_VER) - // avoid calling std::getenv which is deprecated in MSVC. - size_t required_size = 0; - getenv_s(&required_size, nullptr, 0, otel_exporter_zipkin_endpoint_env); - const char *endpoint_from_env = nullptr; - std::unique_ptr endpoint_buffer; - if (required_size > 0) - { - endpoint_buffer = std::unique_ptr{new char[required_size]}; - getenv_s(&required_size, endpoint_buffer.get(), required_size, - otel_exporter_zipkin_endpoint_env); - endpoint_from_env = endpoint_buffer.get(); - } -#else - auto endpoint_from_env = std::getenv(otel_exporter_zipkin_endpoint_env); -#endif - return std::string{endpoint_from_env ? endpoint_from_env : kZipkinEndpointDefault}; + auto endpoint = + opentelemetry::sdk::common::GetEnvironmentVariable(otel_exporter_zipkin_endpoint_env); + return endpoint.size() ? endpoint : kZipkinEndpointDefault; } enum class TransportFormat diff --git a/sdk/include/opentelemetry/sdk/common/env_variables.h b/sdk/include/opentelemetry/sdk/common/env_variables.h new file mode 100644 index 0000000000..63d16d12b5 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/common/env_variables.h @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ + +// Returns the env variable set. +inline const std::string GetEnvironmentVariable(const char *env_var_name) +{ + const char *endpoint_from_env = nullptr; + +#ifndef NO_GETENV +# if defined(_MSC_VER) + // avoid calling std::getenv which is deprecated in MSVC. + size_t required_size = 0; + getenv_s(&required_size, nullptr, 0, env_var_name); + std::unique_ptr endpoint_buffer; + if (required_size > 0) + { + endpoint_buffer = std::unique_ptr{new char[required_size]}; + getenv_s(&required_size, endpoint_buffer.get(), required_size, env_var_name); + endpoint_from_env = endpoint_buffer.get(); + } +# else + endpoint_from_env = std::getenv(env_var_name); +# endif +#endif + return endpoint_from_env == nullptr ? std::string() : endpoint_from_env; +} +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/sdk/src/resource/resource_detector.cc b/sdk/src/resource/resource_detector.cc index 586de79738..c60056539b 100644 --- a/sdk/src/resource/resource_detector.cc +++ b/sdk/src/resource/resource_detector.cc @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "opentelemetry/sdk/resource/resource_detector.h" -#include +#include "opentelemetry/sdk/common/env_variables.h" #include "opentelemetry/sdk/resource/resource.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -15,20 +15,12 @@ const char *OTEL_RESOURCE_ATTRIBUTES = "OTEL_RESOURCE_ATTRIBUTES"; Resource OTELResourceDetector::Detect() noexcept { -#if defined(_MSC_VER) - size_t required_size = 0; - getenv_s(&required_size, nullptr, 0, OTEL_RESOURCE_ATTRIBUTES); - if (required_size == 0) - return Resource(); - std::unique_ptr attributes_buffer{new char[required_size]}; - getenv_s(&required_size, attributes_buffer.get(), required_size, OTEL_RESOURCE_ATTRIBUTES); - char *attributes_str = attributes_buffer.get(); -#else - char *attributes_str = std::getenv(OTEL_RESOURCE_ATTRIBUTES); - if (attributes_str == nullptr) + auto attributes_str = + opentelemetry::sdk::common::GetEnvironmentVariable(OTEL_RESOURCE_ATTRIBUTES); + if (attributes_str.size() == 0) + { return Resource(); -#endif - + } ResourceAttributes attributes; std::istringstream iss(attributes_str); std::string token; diff --git a/sdk/test/resource/resource_test.cc b/sdk/test/resource/resource_test.cc index 0c1a17d5e3..f426c23fe3 100644 --- a/sdk/test/resource/resource_test.cc +++ b/sdk/test/resource/resource_test.cc @@ -155,6 +155,7 @@ TEST(ResourceTest, MergeEmptyString) EXPECT_EQ(received_attributes.size(), expected_attributes.size()); } +#ifndef NO_GETENV TEST(ResourceTest, OtelResourceDetector) { std::map expected_attributes = {{"k", "v"}}; @@ -175,21 +176,21 @@ TEST(ResourceTest, OtelResourceDetector) } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); -#if defined(_MSC_VER) +# if defined(_MSC_VER) putenv("OTEL_RESOURCE_ATTRIBUTES="); -#else +# else unsetenv("OTEL_RESOURCE_ATTRIBUTES"); -#endif +# endif } TEST(ResourceTest, OtelResourceDetectorEmptyEnv) { std::map expected_attributes = {}; -#if defined(_MSC_VER) +# if defined(_MSC_VER) putenv("OTEL_RESOURCE_ATTRIBUTES="); -#else +# else unsetenv("OTEL_RESOURCE_ATTRIBUTES"); -#endif +# endif OTELResourceDetector detector; auto resource = detector.Detect(); auto received_attributes = resource.GetAttributes(); @@ -204,3 +205,4 @@ TEST(ResourceTest, OtelResourceDetectorEmptyEnv) } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); } +#endif