// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/common/key_value_iterable_view.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/common/attribute_utils.h" #include "opentelemetry/sdk/resource/experimental_semantic_conventions.h" #include "opentelemetry/sdk/resource/resource_detector.h" #include #include #include #include #if defined(_MSC_VER) # include "opentelemetry/sdk/common/env_variables.h" using opentelemetry::sdk::common::setenv; using opentelemetry::sdk::common::unsetenv; #endif using namespace opentelemetry::sdk::resource; namespace nostd = opentelemetry::nostd; class TestResource : public Resource { public: TestResource(ResourceAttributes attributes = ResourceAttributes()) : Resource(attributes) {} }; TEST(ResourceTest, create_without_servicename) { ResourceAttributes expected_attributes = { {"service", "backend"}, {"version", (uint32_t)1}, {"cost", 234.23}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkLanguage), "cpp"}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkName), "opentelemetry"}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkVersion), OPENTELEMETRY_SDK_VERSION}, {OTEL_GET_RESOURCE_ATTR(AttrServiceName), "unknown_service"}}; ResourceAttributes attributes = { {"service", "backend"}, {"version", (uint32_t)1}, {"cost", 234.23}}; auto resource = Resource::Create(attributes); auto received_attributes = resource.GetAttributes(); for (auto &e : received_attributes) { EXPECT_TRUE(expected_attributes.find(e.first) != expected_attributes.end()); if (expected_attributes.find(e.first) != expected_attributes.end()) { if (e.first == "version") EXPECT_EQ(nostd::get(expected_attributes.find(e.first)->second), nostd::get(e.second)); else if (e.first == "cost") EXPECT_EQ(nostd::get(expected_attributes.find(e.first)->second), nostd::get(e.second)); else EXPECT_EQ(opentelemetry::nostd::get(expected_attributes.find(e.first)->second), opentelemetry::nostd::get(e.second)); } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); // for missing service.name } TEST(ResourceTest, create_with_servicename) { ResourceAttributes expected_attributes = { {"version", (uint32_t)1}, {"cost", 234.23}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkLanguage), "cpp"}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkName), "opentelemetry"}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkVersion), OPENTELEMETRY_SDK_VERSION}, {OTEL_GET_RESOURCE_ATTR(AttrServiceName), "backend"}, }; ResourceAttributes attributes = { {"service.name", "backend"}, {"version", (uint32_t)1}, {"cost", 234.23}}; auto resource = Resource::Create(attributes); auto received_attributes = resource.GetAttributes(); for (auto &e : received_attributes) { EXPECT_TRUE(expected_attributes.find(e.first) != expected_attributes.end()); if (expected_attributes.find(e.first) != expected_attributes.end()) { if (e.first == "version") EXPECT_EQ(nostd::get(expected_attributes.find(e.first)->second), nostd::get(e.second)); else if (e.first == "cost") EXPECT_EQ(nostd::get(expected_attributes.find(e.first)->second), nostd::get(e.second)); else EXPECT_EQ(nostd::get(expected_attributes.find(e.first)->second), nostd::get(e.second)); } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); // for missing service.name } TEST(ResourceTest, create_with_emptyatrributes) { ResourceAttributes expected_attributes = { {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkLanguage), "cpp"}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkName), "opentelemetry"}, {OTEL_GET_RESOURCE_ATTR(AttrTelemetrySdkVersion), OPENTELEMETRY_SDK_VERSION}, {OTEL_GET_RESOURCE_ATTR(AttrServiceName), "unknown_service"}, }; ResourceAttributes attributes = {}; auto resource = Resource::Create(attributes); auto received_attributes = resource.GetAttributes(); for (auto &e : received_attributes) { EXPECT_TRUE(expected_attributes.find(e.first) != expected_attributes.end()); if (expected_attributes.find(e.first) != expected_attributes.end()) { EXPECT_EQ(opentelemetry::nostd::get(expected_attributes.find(e.first)->second), opentelemetry::nostd::get(e.second)); } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); // for missing service.name } TEST(ResourceTest, create_with_schemaurl) { const std::string schema_url = "https://opentelemetry.io/schemas/1.2.0"; ResourceAttributes attributes = {}; auto resource = Resource::Create(attributes, schema_url); auto received_schema_url = resource.GetSchemaURL(); EXPECT_EQ(received_schema_url, schema_url); } TEST(ResourceTest, Merge) { TestResource resource1(ResourceAttributes({{"service", "backend"}})); TestResource resource2(ResourceAttributes({{"host", "service-host"}})); std::map expected_attributes = {{"service", "backend"}, {"host", "service-host"}}; auto merged_resource = resource1.Merge(resource2); auto received_attributes = merged_resource.GetAttributes(); for (auto &e : received_attributes) { EXPECT_TRUE(expected_attributes.find(e.first) != expected_attributes.end()); if (expected_attributes.find(e.first) != expected_attributes.end()) { EXPECT_EQ(expected_attributes.find(e.first)->second, nostd::get(e.second)); } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); } TEST(ResourceTest, MergeEmptyString) { TestResource resource1({{"service", "backend"}, {"host", "service-host"}}); TestResource resource2({{"service", ""}, {"host", "another-service-host"}}); std::map expected_attributes = {{"service", ""}, {"host", "another-service-host"}}; auto merged_resource = resource1.Merge(resource2); auto received_attributes = merged_resource.GetAttributes(); for (auto &e : received_attributes) { EXPECT_TRUE(expected_attributes.find(e.first) != expected_attributes.end()); if (expected_attributes.find(e.first) != expected_attributes.end()) { EXPECT_EQ(expected_attributes.find(e.first)->second, nostd::get(e.second)); } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); } #ifndef NO_GETENV TEST(ResourceTest, OtelResourceDetector) { std::map expected_attributes = {{"k", "v"}}; setenv("OTEL_RESOURCE_ATTRIBUTES", "k=v", 1); OTELResourceDetector detector; auto resource = detector.Detect(); auto received_attributes = resource.GetAttributes(); for (auto &e : received_attributes) { EXPECT_TRUE(expected_attributes.find(e.first) != expected_attributes.end()); if (expected_attributes.find(e.first) != expected_attributes.end()) { EXPECT_EQ(expected_attributes.find(e.first)->second, nostd::get(e.second)); } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); unsetenv("OTEL_RESOURCE_ATTRIBUTES"); } TEST(ResourceTest, OtelResourceDetectorEmptyEnv) { std::map expected_attributes = {}; unsetenv("OTEL_RESOURCE_ATTRIBUTES"); OTELResourceDetector detector; auto resource = detector.Detect(); auto received_attributes = resource.GetAttributes(); for (auto &e : received_attributes) { EXPECT_TRUE(expected_attributes.find(e.first) != expected_attributes.end()); if (expected_attributes.find(e.first) != expected_attributes.end()) { EXPECT_EQ(expected_attributes.find(e.first)->second, nostd::get(e.second)); } } EXPECT_EQ(received_attributes.size(), expected_attributes.size()); } #endif