From 58ab43726efc57619f055ea69e456839901d843e Mon Sep 17 00:00:00 2001 From: Joao Grassi Date: Fri, 10 Nov 2023 11:53:20 +0100 Subject: [PATCH 1/6] Add Dynatrace resource detector Co-authored-by: Thomas Ebner <96168670+samohte@users.noreply.github.com> Signed-off-by: Joao Grassi --- .../v3/dynatrace_resource_detector.proto | 25 ++++ source/extensions/extensions_build_config.bzl | 1 + source/extensions/extensions_metadata.yaml | 7 + .../resource_detectors/dynatrace/BUILD | 39 ++++++ .../resource_detectors/dynatrace/config.cc | 37 +++++ .../resource_detectors/dynatrace/config.h | 48 +++++++ .../dynatrace_metadata_file_reader.cc | 56 ++++++++ .../dynatrace_metadata_file_reader.h | 49 +++++++ .../dynatrace/dynatrace_resource_detector.cc | 57 ++++++++ .../dynatrace/dynatrace_resource_detector.h | 60 ++++++++ .../resource_detectors/dynatrace/BUILD | 51 +++++++ .../dynatrace/config_test.cc | 36 +++++ ...race_resource_detector_integration_test.cc | 76 ++++++++++ .../dynatrace_resource_detector_test.cc | 131 ++++++++++++++++++ tools/spelling/spelling_dictionary.txt | 1 + 15 files changed, 674 insertions(+) create mode 100644 api/envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.proto create mode 100644 source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD create mode 100644 source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.cc create mode 100644 source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.h create mode 100644 source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc create mode 100644 source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h create mode 100644 source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc create mode 100644 source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h create mode 100644 test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD create mode 100644 test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config_test.cc create mode 100644 test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_integration_test.cc create mode 100644 test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc diff --git a/api/envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.proto b/api/envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.proto new file mode 100644 index 0000000000000..adb072f759905 --- /dev/null +++ b/api/envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +package envoy.extensions.tracers.opentelemetry.resource_detectors.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.tracers.opentelemetry.resource_detectors.v3"; +option java_outer_classname = "DynatraceResourceDetectorProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/tracers/opentelemetry/resource_detectors/v3;resource_detectorsv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Dynatrace Resource Detector config] + +// Configuration for the Dynatrace Resource Detector extension. +// The resource detector reads from the Dynatrace enrichment files +// and adds host/process related attributes to the OpenTelemetry resource. +// +// See: +// +// `Enrich ingested data with Dynatrace-specific dimensions `_ +// +// [#extension: envoy.tracers.opentelemetry.resource_detectors.dynatrace] +message DynatraceResourceDetectorConfig { +} diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index 423eb9ea01905..efa1de486e610 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -271,6 +271,7 @@ EXTENSIONS = { # "envoy.tracers.opentelemetry.resource_detectors.environment": "//source/extensions/tracers/opentelemetry/resource_detectors/environment:config", + "envoy.tracers.opentelemetry.resource_detectors.dynatrace": "//source/extensions/tracers/opentelemetry/resource_detectors/dynatrace:config", # # OpenTelemetry tracer samplers diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 1678188d6ac46..739f8a5003d37 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -1697,3 +1697,10 @@ envoy.tracers.opentelemetry.resource_detectors.environment: status: wip type_urls: - envoy.extensions.tracers.opentelemetry.resource_detectors.v3.EnvironmentResourceDetectorConfig +envoy.tracers.opentelemetry.resource_detectors.dynatrace: + categories: + - envoy.tracers.opentelemetry.resource_detectors + security_posture: unknown + status: wip + type_urls: + - envoy.extensions.tracers.opentelemetry.resource_detectors.v3.DynatraceResourceDetectorConfig diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD new file mode 100644 index 0000000000000..d9eaeeacb3ce4 --- /dev/null +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD @@ -0,0 +1,39 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + deps = [ + ":dynatrace_resource_detector_lib", + "//envoy/registry", + "//source/common/config:utility_lib", + "@envoy_api//envoy/extensions/tracers/opentelemetry/resource_detectors/v3:pkg_cc_proto", + ], +) + +envoy_cc_library( + name = "dynatrace_resource_detector_lib", + srcs = [ + "dynatrace_metadata_file_reader.cc", + "dynatrace_resource_detector.cc", + ], + hdrs = [ + "dynatrace_metadata_file_reader.h", + "dynatrace_resource_detector.h", + ], + deps = [ + "//source/common/config:datasource_lib", + "//source/extensions/tracers/opentelemetry/resource_detectors:resource_detector_lib", + "@envoy_api//envoy/extensions/tracers/opentelemetry/resource_detectors/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.cc new file mode 100644 index 0000000000000..564c2cf291cdb --- /dev/null +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.cc @@ -0,0 +1,37 @@ +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.h" + +#include "envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.pb.h" +#include "envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.pb.validate.h" + +#include "source/common/config/utility.h" +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h" +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +ResourceDetectorPtr DynatraceResourceDetectorFactory::createResourceDetector( + const Protobuf::Message& message, Server::Configuration::TracerFactoryContext& context) { + + auto mptr = Envoy::Config::Utility::translateAnyToFactoryConfig( + dynamic_cast(message), context.messageValidationVisitor(), *this); + + const auto& proto_config = MessageUtil::downcastAndValidate< + const envoy::extensions::tracers::opentelemetry::resource_detectors::v3:: + DynatraceResourceDetectorConfig&>(*mptr, context.messageValidationVisitor()); + + DynatraceMetadataFileReaderPtr reader = std::make_unique(); + return std::make_unique(proto_config, std::move(reader)); +} + +/** + * Static registration for the Dynatrace resource detector factory. @see RegisterFactory. + */ +REGISTER_FACTORY(DynatraceResourceDetectorFactory, ResourceDetectorFactory); + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.h b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.h new file mode 100644 index 0000000000000..f3063484aeb9b --- /dev/null +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include "envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.pb.h" + +#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +/** + * Config registration for the Dynatrace resource detector. @see ResourceDetectorFactory. + */ +class DynatraceResourceDetectorFactory : public ResourceDetectorFactory { +public: + /** + * @brief Creates a Resource Detector that reads from the Dynatrace enrichment files. + * + * @see + * https://docs.dynatrace.com/docs/shortlink/enrichment-files#oneagent-virtual-files + * + * @param message The resource detector configuration. + * @param context The tracer factory context. + * @return ResourceDetectorPtr + */ + ResourceDetectorPtr + createResourceDetector(const Protobuf::Message& message, + Server::Configuration::TracerFactoryContext& context) override; + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + + std::string name() const override { + return "envoy.tracers.opentelemetry.resource_detectors.dynatrace"; + } +}; + +DECLARE_FACTORY(DynatraceResourceDetectorFactory); + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc new file mode 100644 index 0000000000000..88c24827bc046 --- /dev/null +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc @@ -0,0 +1,56 @@ +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h" + +#include +#include +#include +#include + +#include "envoy/common/exception.h" + +#include "source/common/common/logger.h" + +#include "absl/strings/str_cat.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +namespace { + +bool isIndirectionFile(const std::string& file_name) { + return absl::StartsWith(file_name, "dt_metadata_"); +} + +const std::string readFile(const std::string& file_name) { + if (file_name.empty()) { + return ""; + } + + std::ifstream file(file_name); + if (file.fail()) { + throw EnvoyException(absl::StrCat("Unable to read Dynatrace enrichment file: ", file_name)); + } + + std::stringstream file_string; + file_string << file.rdbuf(); + + return file_string.str(); +} + +} // namespace + +std::string DynatraceMetadataFileReaderImpl::readEnrichmentFile(const std::string& file_name) { + bool indirectionFile = isIndirectionFile(file_name); + if (indirectionFile) { + std::string indirection_file = readFile(file_name); + return readFile(indirection_file); + } else { + return readFile(file_name); + } +} + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h new file mode 100644 index 0000000000000..6408480c284ae --- /dev/null +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +#include "envoy/common/pure.h" + +#include "absl/strings/match.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +/** + * @brief A file reader that reads the content of the Dynatrace metadata enrichment files. + * When OneAgent is monitoring your application, it provides access to the enrichment files. + * These files do not physically exists in your file system, but are provided by the OneAgent on + * demand. This allows obtaining not only information about the host, but also about process. + * + * @see + * https://docs.dynatrace.com/docs/shortlink/enrichment-files#oneagent-virtual-files + * + */ +class DynatraceMetadataFileReader { +public: + virtual ~DynatraceMetadataFileReader() = default; + + /** + * @brief Reads the enrichment file and returns the enrichment metadata. + * + * @param file_name The file name. + * @return const std::string String (java-like properties) containing the enrichment metadata. + */ + virtual std::string readEnrichmentFile(const std::string& file_name) PURE; +}; + +using DynatraceMetadataFileReaderPtr = std::unique_ptr; + +class DynatraceMetadataFileReaderImpl : public DynatraceMetadataFileReader { +public: + std::string readEnrichmentFile(const std::string& file_name) override; +}; + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc new file mode 100644 index 0000000000000..ee31ba22e1788 --- /dev/null +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc @@ -0,0 +1,57 @@ +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h" + +#include +#include + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { +namespace { + +void addAttributes(const std::string& content, Resource& resource) { + for (const auto& line : StringUtil::splitToken(content, "\n", false, true)) { + const auto keyValue = StringUtil::splitToken(line, "="); + if (keyValue.size() != 2) { + continue; + } + + const std::string key = std::string(keyValue[0]); + const std::string value = std::string(keyValue[1]); + resource.attributes_[key] = value; + } +} + +} // namespace + +Resource DynatraceResourceDetector::detect() { + Resource resource; + resource.schemaUrl_ = ""; + int failureCount = 0; + + for (const auto& file_name : DT_METADATA_FILES) { + TRY_NEEDS_AUDIT { + std::string content = dynatrace_file_reader_->readEnrichmentFile(std::string(file_name)); + if (content.empty()) { + failureCount++; + } else { + addAttributes(content, resource); + } + } + END_TRY catch (const EnvoyException&) { failureCount++; } + } + + if (failureCount > 0) { + ENVOY_LOG( + warn, + "Dynatrace OpenTelemetry resource detector is configured but could not detect attributes. " + "Check the Dynatrace deployment status to ensure it is correctly deployed."); + } + + return resource; +} + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h new file mode 100644 index 0000000000000..4b40c8d154cce --- /dev/null +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +#include "envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.pb.h" + +#include "source/common/common/logger.h" +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h" +#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +constexpr std::array DT_METADATA_FILES = { + "dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties", + "/var/lib/dynatrace/enrichment/dt_metadata.properties", + "/var/lib/dynatrace/enrichment/dt_host_metadata.properties"}; + +/** + * @brief A resource detector that reads the content of the Dynatrace metadata enrichment files. + * When OneAgent is monitoring your application, it provides access to the enrichment files. + * These files do not physically exists in your file system, but are provided by the OneAgent on + * demand. This allows obtaining not only information about the host, but also about process. + * + * Dynatrace can be deployed in multiple ways and flavors, depending on the environment. + * The available Dynatrace enrichment files vary depending on how it is deployed. E.g. In k8s via + * the Dynatrace operator. + * + * Since the resource detector is not aware how Dynatrace is deployed, the detector attempts to + * read all Dynatrace enrichment files. In such cases, reading some of these files may fail but + * this is expected and does not classify as a problem with the detector. The detector may also not + * detect any attributes, for example when a Dynatrace deployment is not successful. In such cases, + * Envoy will be started with no enrichment but Dynatrace users have the means to find out which + * Dynatrace deployment is failing. + * + * @see + * https://docs.dynatrace.com/docs/shortlink/enrichment-files + * + */ +class DynatraceResourceDetector : public ResourceDetector, Logger::Loggable { +public: + DynatraceResourceDetector(const envoy::extensions::tracers::opentelemetry::resource_detectors:: + v3::DynatraceResourceDetectorConfig& config, + DynatraceMetadataFileReaderPtr dynatrace_file_reader) + : config_(config), dynatrace_file_reader_(std::move(dynatrace_file_reader)) {} + Resource detect() override; + +private: + const envoy::extensions::tracers::opentelemetry::resource_detectors::v3:: + DynatraceResourceDetectorConfig config_; + DynatraceMetadataFileReaderPtr dynatrace_file_reader_; +}; + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD new file mode 100644 index 0000000000000..5e20245c6f7ac --- /dev/null +++ b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD @@ -0,0 +1,51 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_extension_cc_test( + name = "config_test", + srcs = ["config_test.cc"], + extension_names = ["envoy.tracers.opentelemetry.resource_detectors.dynatrace"], + deps = [ + "//envoy/registry", + "//source/extensions/tracers/opentelemetry/resource_detectors/dynatrace:config", + "//source/extensions/tracers/opentelemetry/resource_detectors/dynatrace:dynatrace_resource_detector_lib", + "//test/mocks/server:tracer_factory_context_mocks", + "//test/test_common:utility_lib", + ], +) + +envoy_extension_cc_test( + name = "dynatrace_resource_detector_test", + srcs = ["dynatrace_resource_detector_test.cc"], + extension_names = ["envoy.tracers.opentelemetry.resource_detectors.dynatrace"], + deps = [ + "//source/extensions/tracers/opentelemetry/resource_detectors/dynatrace:dynatrace_resource_detector_lib", + "//test/mocks/server:tracer_factory_context_mocks", + "//test/test_common:utility_lib", + "@envoy_api//envoy/extensions/tracers/opentelemetry/resource_detectors/v3:pkg_cc_proto", + ], +) + +envoy_extension_cc_test( + name = "dynatrace_resource_detector_integration_test", + srcs = [ + "dynatrace_resource_detector_integration_test.cc", + ], + extension_names = ["envoy.tracers.opentelemetry.resource_detectors.dynatrace"], + deps = [ + "//source/exe:main_common_lib", + "//test/integration:http_integration_lib", + "//test/test_common:utility_lib", + "@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config_test.cc b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config_test.cc new file mode 100644 index 0000000000000..9d769cc62dc62 --- /dev/null +++ b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config_test.cc @@ -0,0 +1,36 @@ +#include "envoy/registry/registry.h" + +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/config.h" + +#include "test/mocks/server/tracer_factory_context.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +TEST(DynatraceResourceDetectorFactoryTest, Basic) { + auto* factory = Registry::FactoryRegistry::getFactory( + "envoy.tracers.opentelemetry.resource_detectors.dynatrace"); + ASSERT_NE(factory, nullptr); + + envoy::config::core::v3::TypedExtensionConfig typed_config; + const std::string yaml = R"EOF( + name: envoy.tracers.opentelemetry.resource_detectors.dynatrace + typed_config: + "@type": type.googleapis.com/envoy.extensions.tracers.opentelemetry.resource_detectors.v3.DynatraceResourceDetectorConfig + )EOF"; + TestUtility::loadFromYaml(yaml, typed_config); + + NiceMock context; + EXPECT_NE(factory->createResourceDetector(typed_config.typed_config(), context), nullptr); + EXPECT_STREQ(factory->name().c_str(), "envoy.tracers.opentelemetry.resource_detectors.dynatrace"); +} + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_integration_test.cc b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_integration_test.cc new file mode 100644 index 0000000000000..6b43580101f59 --- /dev/null +++ b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_integration_test.cc @@ -0,0 +1,76 @@ +#include +#include + +#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h" + +#include "test/integration/http_integration.h" +#include "test/test_common/utility.h" + +#include "absl/strings/match.h" +#include "absl/strings/string_view.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { +namespace { + +class DynatraceResourceDetectorIntegrationTest + : public Envoy::HttpIntegrationTest, + public testing::TestWithParam { +public: + DynatraceResourceDetectorIntegrationTest() + : HttpIntegrationTest(Http::CodecType::HTTP1, GetParam()) { + + const std::string yaml_string = R"EOF( + provider: + name: envoy.tracers.opentelemetry + typed_config: + "@type": type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig + grpc_service: + envoy_grpc: + cluster_name: opentelemetry_collector + timeout: 0.250s + service_name: "a_service_name" + resource_detectors: + - name: envoy.tracers.opentelemetry.resource_detectors.dynatrace + typed_config: + "@type": type.googleapis.com/envoy.extensions.tracers.opentelemetry.resource_detectors.v3.DynatraceResourceDetectorConfig + )EOF"; + + auto tracing_config = + std::make_unique<::envoy::extensions::filters::network::http_connection_manager::v3:: + HttpConnectionManager_Tracing>(); + TestUtility::loadFromYaml(yaml_string, *tracing_config.get()); + config_helper_.addConfigModifier( + [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& + hcm) -> void { hcm.set_allocated_tracing(tracing_config.release()); }); + + initialize(); + codec_client_ = makeHttpConnection(lookupPort("http")); + } +}; + +INSTANTIATE_TEST_SUITE_P(IpVersions, DynatraceResourceDetectorIntegrationTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); + +// Verify Envoy starts even when the Dynatrace resource detector wasn't able to detect any +// attributes +TEST_P(DynatraceResourceDetectorIntegrationTest, TestWithNoDynatraceDeployed) { + Http::TestRequestHeaderMapImpl request_headers{ + {":method", "GET"}, {":path", "/test/long/url"}, {":scheme", "http"}, {":authority", "host"}}; + + auto response = sendRequestAndWaitForResponse(request_headers, 0, default_response_headers_, 0); + + ASSERT_TRUE(response->waitForEndStream()); + EXPECT_TRUE(response->complete()); + EXPECT_EQ(response->headers().getStatusValue(), "200"); +} + +} // namespace +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc new file mode 100644 index 0000000000000..3bcdc4c0ba758 --- /dev/null +++ b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc @@ -0,0 +1,131 @@ +#include +#include + +#include "envoy/extensions/tracers/opentelemetry/resource_detectors/v3/dynatrace_resource_detector.pb.h" +#include "envoy/registry/registry.h" + +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h" +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h" + +#include "test/mocks/server/tracer_factory_context.h" +#include "test/test_common/environment.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using testing::Return; + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +class MockDynatraceFileReader : public DynatraceMetadataFileReader { +public: + MOCK_METHOD(std::string, readEnrichmentFile, (const std::string& file_path)); +}; + +TEST(DynatraceResourceDetectorTest, DynatraceNotDeployed) { + NiceMock context; + + auto dt_file_reader = std::make_unique>(); + EXPECT_CALL(*dt_file_reader, readEnrichmentFile(_)).WillRepeatedly(Return("")); + + envoy::extensions::tracers::opentelemetry::resource_detectors::v3::DynatraceResourceDetectorConfig + config; + + auto detector = std::make_shared(config, std::move(dt_file_reader)); + Resource resource = detector->detect(); + + EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(0, resource.attributes_.size()); +} + +TEST(DynatraceResourceDetectorTest, OnlyOneAgentInstalled) { + NiceMock context; + ResourceAttributes expected_attributes = { + {"dt.entity.host", "HOST-abc"}, + {"dt.entity.process_group_instance", "PROCESS_GROUP_INSTANCE-abc"}}; + + auto dt_file_reader = std::make_unique>(); + + std::string host_attrs = fmt::format(R"EOF( +dt.entity.host=HOST-abc +dt.host_group.id= +)EOF"); + + std::string process_attrs = fmt::format(R"EOF( +dt.entity.process_group_instance=PROCESS_GROUP_INSTANCE-abc +)EOF"); + + EXPECT_CALL(*dt_file_reader, + readEnrichmentFile("dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties")) + .WillRepeatedly(Return(process_attrs)); + EXPECT_CALL(*dt_file_reader, + readEnrichmentFile("/var/lib/dynatrace/enrichment/dt_host_metadata.properties")) + .WillRepeatedly(Return(host_attrs)); + + EXPECT_CALL(*dt_file_reader, + readEnrichmentFile("/var/lib/dynatrace/enrichment/dt_metadata.properties")) + .WillRepeatedly(Return("")); + + envoy::extensions::tracers::opentelemetry::resource_detectors::v3::DynatraceResourceDetectorConfig + config; + + auto detector = std::make_shared(config, std::move(dt_file_reader)); + Resource resource = detector->detect(); + + EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(2, resource.attributes_.size()); + + for (auto& actual : resource.attributes_) { + auto expected = expected_attributes.find(actual.first); + + EXPECT_TRUE(expected != expected_attributes.end()); + EXPECT_EQ(expected->second, actual.second); + } +} + +TEST(DynatraceResourceDetectorTest, Dynatracek8sOperator) { + NiceMock context; + ResourceAttributes expected_attributes = {{"k8s.pod.uid", "123"}, {"k8s.pod.name", "envoy"}}; + + auto dt_file_reader = std::make_unique>(); + + std::string k8s_attrs = fmt::format(R"EOF( +k8s.pod.uid=123 +k8s.pod.name=envoy +)EOF"); + + EXPECT_CALL(*dt_file_reader, + readEnrichmentFile("dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties")) + .WillRepeatedly(Return("")); + EXPECT_CALL(*dt_file_reader, + readEnrichmentFile("/var/lib/dynatrace/enrichment/dt_host_metadata.properties")) + .WillRepeatedly(Return("")); + EXPECT_CALL(*dt_file_reader, + readEnrichmentFile("/var/lib/dynatrace/enrichment/dt_metadata.properties")) + .WillRepeatedly(Return(k8s_attrs)); + + envoy::extensions::tracers::opentelemetry::resource_detectors::v3::DynatraceResourceDetectorConfig + config; + + auto detector = std::make_shared(config, std::move(dt_file_reader)); + Resource resource = detector->detect(); + + EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(2, resource.attributes_.size()); + + for (auto& actual : resource.attributes_) { + auto expected = expected_attributes.find(actual.first); + + EXPECT_TRUE(expected != expected_attributes.end()); + EXPECT_EQ(expected->second, actual.second); + } +} + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index 7ec5fa1b49e79..eac4211946596 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -34,6 +34,7 @@ Bencoded CIO deadcode DFP +Dynatrace DOM Gasd GiB From 446a31de3e2a01fd1ff64d74866b39ddef0bbd6b Mon Sep 17 00:00:00 2001 From: Joao Grassi Date: Tue, 14 Nov 2023 12:51:24 +0100 Subject: [PATCH 2/6] PR suggestions Signed-off-by: Joao Grassi --- .../dynatrace/dynatrace_metadata_file_reader.cc | 2 +- .../dynatrace/dynatrace_resource_detector.cc | 4 ++-- .../dynatrace/dynatrace_resource_detector.h | 14 +++++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc index 88c24827bc046..1e3a67115c6a8 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc @@ -22,7 +22,7 @@ bool isIndirectionFile(const std::string& file_name) { return absl::StartsWith(file_name, "dt_metadata_"); } -const std::string readFile(const std::string& file_name) { +std::string readFile(const std::string& file_name) { if (file_name.empty()) { return ""; } diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc index ee31ba22e1788..1827b54c60d05 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc @@ -29,9 +29,9 @@ Resource DynatraceResourceDetector::detect() { resource.schemaUrl_ = ""; int failureCount = 0; - for (const auto& file_name : DT_METADATA_FILES) { + for (const auto& file_name : DynatraceResourceDetector::dynatraceMetadataFiles()) { TRY_NEEDS_AUDIT { - std::string content = dynatrace_file_reader_->readEnrichmentFile(std::string(file_name)); + std::string content = dynatrace_file_reader_->readEnrichmentFile(file_name); if (content.empty()) { failureCount++; } else { diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h index 4b40c8d154cce..ba201fe884e5f 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.h @@ -14,11 +14,6 @@ namespace Extensions { namespace Tracers { namespace OpenTelemetry { -constexpr std::array DT_METADATA_FILES = { - "dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties", - "/var/lib/dynatrace/enrichment/dt_metadata.properties", - "/var/lib/dynatrace/enrichment/dt_host_metadata.properties"}; - /** * @brief A resource detector that reads the content of the Dynatrace metadata enrichment files. * When OneAgent is monitoring your application, it provides access to the enrichment files. @@ -48,6 +43,15 @@ class DynatraceResourceDetector : public ResourceDetector, Logger::Loggable& dynatraceMetadataFiles() { + CONSTRUCT_ON_FIRST_USE(std::vector, + { + "dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties", + "/var/lib/dynatrace/enrichment/dt_metadata.properties", + "/var/lib/dynatrace/enrichment/dt_host_metadata.properties", + }); + } + private: const envoy::extensions::tracers::opentelemetry::resource_detectors::v3:: DynatraceResourceDetectorConfig config_; From 04ad023d9408c29e597ad2926ee6d2675edafcd5 Mon Sep 17 00:00:00 2001 From: Joao Grassi Date: Tue, 14 Nov 2023 16:07:58 +0100 Subject: [PATCH 3/6] Add tests for Dynatrace file reader Signed-off-by: Joao Grassi --- .../resource_detectors/dynatrace/BUILD | 5 ++- .../dynatrace_metadata_file_reader_test.cc | 43 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader_test.cc diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD index 5e20245c6f7ac..a80ff2f8974f5 100644 --- a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD +++ b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/BUILD @@ -26,7 +26,10 @@ envoy_extension_cc_test( envoy_extension_cc_test( name = "dynatrace_resource_detector_test", - srcs = ["dynatrace_resource_detector_test.cc"], + srcs = [ + "dynatrace_metadata_file_reader_test.cc", + "dynatrace_resource_detector_test.cc", + ], extension_names = ["envoy.tracers.opentelemetry.resource_detectors.dynatrace"], deps = [ "//source/extensions/tracers/opentelemetry/resource_detectors/dynatrace:dynatrace_resource_detector_lib", diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader_test.cc b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader_test.cc new file mode 100644 index 0000000000000..58132e9070641 --- /dev/null +++ b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader_test.cc @@ -0,0 +1,43 @@ +#include +#include + +#include "source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.h" + +#include "test/test_common/environment.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using testing::Return; + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace OpenTelemetry { + +TEST(DynatraceMetadataFileReaderTest, DynatraceNotDeployed) { + const std::string indirection_file = "dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties"; + + DynatraceMetadataFileReaderPtr reader = std::make_unique(); + + EXPECT_THROW(reader->readEnrichmentFile(indirection_file), EnvoyException); +} + +TEST(DynatraceMetadataFileReaderTest, DtMetadataFile) { + const std::string expected_data = "attribute=value"; + const std::string metadata_file = "dt_metadata.properties"; + + TestEnvironment::writeStringToFileForTest(metadata_file, expected_data); + + DynatraceMetadataFileReaderPtr reader = std::make_unique(); + + std::string actual_data = + reader->readEnrichmentFile(TestEnvironment::temporaryPath(metadata_file)); + + EXPECT_EQ(actual_data, expected_data); +} + +} // namespace OpenTelemetry +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy From 247367139a97a5af9d8c7ca80d6613d0162ef19d Mon Sep 17 00:00:00 2001 From: Joao Grassi Date: Tue, 21 Nov 2023 11:15:55 +0100 Subject: [PATCH 4/6] PR suggestions Signed-off-by: Joao Grassi --- .../dynatrace/dynatrace_metadata_file_reader.cc | 6 ++---- .../dynatrace/dynatrace_resource_detector.cc | 17 +++++++---------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc index 1e3a67115c6a8..858cc93d25819 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc @@ -41,10 +41,8 @@ std::string readFile(const std::string& file_name) { } // namespace std::string DynatraceMetadataFileReaderImpl::readEnrichmentFile(const std::string& file_name) { - bool indirectionFile = isIndirectionFile(file_name); - if (indirectionFile) { - std::string indirection_file = readFile(file_name); - return readFile(indirection_file); + if (const bool indirectionFile = isIndirectionFile(file_name); indirectionFile) { + return readFile(readFile(file_name)); } else { return readFile(file_name); } diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc index 1827b54c60d05..842094856e04c 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc @@ -11,14 +11,11 @@ namespace { void addAttributes(const std::string& content, Resource& resource) { for (const auto& line : StringUtil::splitToken(content, "\n", false, true)) { - const auto keyValue = StringUtil::splitToken(line, "="); - if (keyValue.size() != 2) { + const auto key_value = StringUtil::splitToken(line, "="); + if (key_value.size() != 2) { continue; } - - const std::string key = std::string(keyValue[0]); - const std::string value = std::string(keyValue[1]); - resource.attributes_[key] = value; + resource.attributes_[std::string(key_value[0])] = std::string(key_value[1]); } } @@ -27,21 +24,21 @@ void addAttributes(const std::string& content, Resource& resource) { Resource DynatraceResourceDetector::detect() { Resource resource; resource.schemaUrl_ = ""; - int failureCount = 0; + int failure_count = 0; for (const auto& file_name : DynatraceResourceDetector::dynatraceMetadataFiles()) { TRY_NEEDS_AUDIT { std::string content = dynatrace_file_reader_->readEnrichmentFile(file_name); if (content.empty()) { - failureCount++; + failure_count++; } else { addAttributes(content, resource); } } - END_TRY catch (const EnvoyException&) { failureCount++; } + END_TRY catch (const EnvoyException&) { failure_count++; } } - if (failureCount > 0) { + if (failure_count > 0) { ENVOY_LOG( warn, "Dynatrace OpenTelemetry resource detector is configured but could not detect attributes. " From c9b130b1d1d7487838019fa9bfb81bcfb8ca1087 Mon Sep 17 00:00:00 2001 From: Joao Grassi Date: Tue, 21 Nov 2023 11:18:48 +0100 Subject: [PATCH 5/6] schemaUrl_ -> schema_url_ Signed-off-by: Joao Grassi --- .../dynatrace/dynatrace_resource_detector.cc | 2 +- .../environment_resource_detector.cc | 2 +- .../resource_detectors/resource_detector.h | 2 +- .../resource_detectors/resource_provider.cc | 3 +- .../tracers/opentelemetry/tracer.cc | 2 +- .../dynatrace_resource_detector_test.cc | 6 ++-- .../environment_resource_detector_test.cc | 2 +- .../resource_provider_test.cc | 28 +++++++++---------- 8 files changed, 24 insertions(+), 23 deletions(-) diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc index 842094856e04c..b8c98d81201bc 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector.cc @@ -23,7 +23,7 @@ void addAttributes(const std::string& content, Resource& resource) { Resource DynatraceResourceDetector::detect() { Resource resource; - resource.schemaUrl_ = ""; + resource.schema_url_ = ""; int failure_count = 0; for (const auto& file_name : DynatraceResourceDetector::dynatraceMetadataFiles()) { diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector.cc b/source/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector.cc index 3c69e32b76f3d..c56894c25c425 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector.cc @@ -26,7 +26,7 @@ Resource EnvironmentResourceDetector::detect() { ds.set_environment_variable(kOtelResourceAttributesEnv); Resource resource; - resource.schemaUrl_ = ""; + resource.schema_url_ = ""; std::string attributes_str = ""; attributes_str = Config::DataSource::read(ds, true, context_.serverFactoryContext().api()); diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h b/source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h index 69894b9176808..61079815aa104 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h +++ b/source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h @@ -25,7 +25,7 @@ using ResourceAttributes = std::map; * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.26.0/specification/resource/sdk.md */ struct Resource { - std::string schemaUrl_{""}; + std::string schema_url_{""}; ResourceAttributes attributes_{}; virtual ~Resource() = default; diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.cc b/source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.cc index a8f106cc3729d..370d6a44d414e 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/resource_provider.cc @@ -63,7 +63,8 @@ void mergeResource(Resource& old_resource, const Resource& updating_resource) { // The schemaUrl is merged, regardless if the resources being merged // have attributes or not. This behavior is compliant with the OTel spec. // see: https://github.com/envoyproxy/envoy/pull/29547#discussion_r1344540427 - old_resource.schemaUrl_ = resolveSchemaUrl(old_resource.schemaUrl_, updating_resource.schemaUrl_); + old_resource.schema_url_ = + resolveSchemaUrl(old_resource.schema_url_, updating_resource.schema_url_); if (isEmptyResource(updating_resource)) { return; diff --git a/source/extensions/tracers/opentelemetry/tracer.cc b/source/extensions/tracers/opentelemetry/tracer.cc index 73325ac7f317e..9b26fbc16245a 100644 --- a/source/extensions/tracers/opentelemetry/tracer.cc +++ b/source/extensions/tracers/opentelemetry/tracer.cc @@ -152,7 +152,7 @@ void Tracer::flushSpans() { ExportTraceServiceRequest request; // A request consists of ResourceSpans. ::opentelemetry::proto::trace::v1::ResourceSpans* resource_span = request.add_resource_spans(); - resource_span->set_schema_url(resource_->schemaUrl_); + resource_span->set_schema_url(resource_->schema_url_); // add resource attributes for (auto const& att : resource_->attributes_) { diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc index 3bcdc4c0ba758..2db7439d00215 100644 --- a/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc +++ b/test/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_resource_detector_test.cc @@ -38,7 +38,7 @@ TEST(DynatraceResourceDetectorTest, DynatraceNotDeployed) { auto detector = std::make_shared(config, std::move(dt_file_reader)); Resource resource = detector->detect(); - EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(resource.schema_url_, ""); EXPECT_EQ(0, resource.attributes_.size()); } @@ -76,7 +76,7 @@ dt.entity.process_group_instance=PROCESS_GROUP_INSTANCE-abc auto detector = std::make_shared(config, std::move(dt_file_reader)); Resource resource = detector->detect(); - EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(resource.schema_url_, ""); EXPECT_EQ(2, resource.attributes_.size()); for (auto& actual : resource.attributes_) { @@ -114,7 +114,7 @@ k8s.pod.name=envoy auto detector = std::make_shared(config, std::move(dt_file_reader)); Resource resource = detector->detect(); - EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(resource.schema_url_, ""); EXPECT_EQ(2, resource.attributes_.size()); for (auto& actual : resource.attributes_) { diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector_test.cc b/test/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector_test.cc index e88f0dd5e72a6..3a596f3d0e222 100644 --- a/test/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector_test.cc +++ b/test/extensions/tracers/opentelemetry/resource_detectors/environment/environment_resource_detector_test.cc @@ -71,7 +71,7 @@ TEST(EnvironmentResourceDetectorTest, EnvVariablePresentAndWithAttributes) { auto detector = std::make_unique(config, context); Resource resource = detector->detect(); - EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(resource.schema_url_, ""); EXPECT_EQ(2, resource.attributes_.size()); for (auto& actual : resource.attributes_) { diff --git a/test/extensions/tracers/opentelemetry/resource_detectors/resource_provider_test.cc b/test/extensions/tracers/opentelemetry/resource_detectors/resource_provider_test.cc index 8f49c4d93ca7c..657365baa8894 100644 --- a/test/extensions/tracers/opentelemetry/resource_detectors/resource_provider_test.cc +++ b/test/extensions/tracers/opentelemetry/resource_detectors/resource_provider_test.cc @@ -79,7 +79,7 @@ TEST_F(ResourceProviderTest, NoResourceDetectorsConfigured) { ResourceProviderImpl resource_provider; Resource resource = resource_provider.getResource(opentelemetry_config, context_); - EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(resource.schema_url_, ""); // Only the service name was added to the resource EXPECT_EQ(1, resource.attributes_.size()); @@ -100,7 +100,7 @@ TEST_F(ResourceProviderTest, ServiceNameNotProvided) { ResourceProviderImpl resource_provider; Resource resource = resource_provider.getResource(opentelemetry_config, context_); - EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(resource.schema_url_, ""); // service.name receives the unknown value when not configured EXPECT_EQ(1, resource.attributes_.size()); @@ -151,7 +151,7 @@ TEST_F(ResourceProviderTest, MultipleResourceDetectorsConfigured) { ResourceProviderImpl resource_provider; Resource resource = resource_provider.getResource(opentelemetry_config, context_); - EXPECT_EQ(resource.schemaUrl_, ""); + EXPECT_EQ(resource.schema_url_, ""); // The resource should contain all 3 merged attributes // service.name + 1 for each detector @@ -225,7 +225,7 @@ TEST_F(ResourceProviderTest, OldSchemaEmptyUpdatingSet) { // Updating resource is empty (no attributes) Resource updating_resource; - updating_resource.schemaUrl_ = expected_schema_url; + updating_resource.schema_url_ = expected_schema_url; auto detector_a = std::make_unique>(); EXPECT_CALL(*detector_a, detect()).WillOnce(Return(old_resource)); @@ -265,17 +265,17 @@ TEST_F(ResourceProviderTest, OldSchemaEmptyUpdatingSet) { Resource resource = resource_provider.getResource(opentelemetry_config, context_); // OTel spec says the updating schema should be used - EXPECT_EQ(expected_schema_url, resource.schemaUrl_); + EXPECT_EQ(expected_schema_url, resource.schema_url_); } // Test merge when old schema url is not empty but updating is TEST_F(ResourceProviderTest, OldSchemaSetUpdatingEmpty) { std::string expected_schema_url = "my.schema/v1"; Resource old_resource = resource_a_; - old_resource.schemaUrl_ = expected_schema_url; + old_resource.schema_url_ = expected_schema_url; Resource updating_resource = resource_b_; - updating_resource.schemaUrl_ = ""; + updating_resource.schema_url_ = ""; auto detector_a = std::make_unique>(); EXPECT_CALL(*detector_a, detect()).WillOnce(Return(old_resource)); @@ -315,17 +315,17 @@ TEST_F(ResourceProviderTest, OldSchemaSetUpdatingEmpty) { Resource resource = resource_provider.getResource(opentelemetry_config, context_); // OTel spec says the updating schema should be used - EXPECT_EQ(expected_schema_url, resource.schemaUrl_); + EXPECT_EQ(expected_schema_url, resource.schema_url_); } // Test merge when both old and updating schema url are set and equal TEST_F(ResourceProviderTest, OldAndUpdatingSchemaAreEqual) { std::string expected_schema_url = "my.schema/v1"; Resource old_resource = resource_a_; - old_resource.schemaUrl_ = expected_schema_url; + old_resource.schema_url_ = expected_schema_url; Resource updating_resource = resource_b_; - updating_resource.schemaUrl_ = expected_schema_url; + updating_resource.schema_url_ = expected_schema_url; auto detector_a = std::make_unique>(); EXPECT_CALL(*detector_a, detect()).WillOnce(Return(old_resource)); @@ -364,17 +364,17 @@ TEST_F(ResourceProviderTest, OldAndUpdatingSchemaAreEqual) { ResourceProviderImpl resource_provider; Resource resource = resource_provider.getResource(opentelemetry_config, context_); - EXPECT_EQ(expected_schema_url, resource.schemaUrl_); + EXPECT_EQ(expected_schema_url, resource.schema_url_); } // Test merge when both old and updating schema url are set but different TEST_F(ResourceProviderTest, OldAndUpdatingSchemaAreDifferent) { std::string expected_schema_url = "my.schema/v1"; Resource old_resource = resource_a_; - old_resource.schemaUrl_ = expected_schema_url; + old_resource.schema_url_ = expected_schema_url; Resource updating_resource = resource_b_; - updating_resource.schemaUrl_ = "my.schema/v2"; + updating_resource.schema_url_ = "my.schema/v2"; auto detector_a = std::make_unique>(); EXPECT_CALL(*detector_a, detect()).WillOnce(Return(old_resource)); @@ -414,7 +414,7 @@ TEST_F(ResourceProviderTest, OldAndUpdatingSchemaAreDifferent) { Resource resource = resource_provider.getResource(opentelemetry_config, context_); // OTel spec says Old schema should be used - EXPECT_EQ(expected_schema_url, resource.schemaUrl_); + EXPECT_EQ(expected_schema_url, resource.schema_url_); } } // namespace From a4f9bb03436540b46c90c977e3840f9715bdbf5a Mon Sep 17 00:00:00 2001 From: Joao Grassi Date: Thu, 23 Nov 2023 09:29:39 +0100 Subject: [PATCH 6/6] PR suggestions and changelog Signed-off-by: Joao Grassi --- changelogs/current.yaml | 3 +++ .../dynatrace/dynatrace_metadata_file_reader.cc | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 5e3489b53212f..8eaacaa90666d 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -185,5 +185,8 @@ new_features: Ratelimit supports optional additional prefix to use when emitting statistics with :ref:`stat_prefix ` configuration flag. +- area: tracing + change: | + Added support to configure a Dynatrace resource detector for the OpenTelemetry tracer. deprecated: diff --git a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc index 858cc93d25819..7bac5001fc8cc 100644 --- a/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc +++ b/source/extensions/tracers/opentelemetry/resource_detectors/dynatrace/dynatrace_metadata_file_reader.cc @@ -41,7 +41,7 @@ std::string readFile(const std::string& file_name) { } // namespace std::string DynatraceMetadataFileReaderImpl::readEnrichmentFile(const std::string& file_name) { - if (const bool indirectionFile = isIndirectionFile(file_name); indirectionFile) { + if (const bool indirection_file = isIndirectionFile(file_name); indirection_file) { return readFile(readFile(file_name)); } else { return readFile(file_name);