| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- #include <gtest/gtest.h>
- #include <stdint.h>
- #include <cstdlib>
- #include <map>
- #include <string>
- #include <unordered_map>
- #include <utility>
- #include "opentelemetry/nostd/variant.h"
- #include "opentelemetry/sdk/common/attribute_utils.h"
- #include "opentelemetry/sdk/resource/resource.h"
- #include "opentelemetry/sdk/resource/resource_detector.h"
- #include "opentelemetry/sdk/version/version.h"
- #include "opentelemetry/semconv/service_attributes.h"
- #include "opentelemetry/semconv/telemetry_attributes.h"
- #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;
- namespace semconv = opentelemetry::semconv;
- class TestResource : public Resource
- {
- public:
- TestResource(const ResourceAttributes &attributes = ResourceAttributes(),
- const std::string &schema_url = {})
- : Resource(attributes, schema_url)
- {}
- };
- class TestResourceDetector : public ResourceDetector
- {
- public:
- TestResourceDetector() = default;
- Resource Detect() noexcept override { return Create(attributes, schema_url); }
- ResourceAttributes attributes;
- std::string schema_url;
- };
- TEST(ResourceTest, create_without_servicename)
- {
- ResourceAttributes expected_attributes = {
- {"service", "backend"},
- {"version", static_cast<uint32_t>(1)},
- {"cost", 234.23},
- {semconv::telemetry::kTelemetrySdkLanguage, "cpp"},
- {semconv::telemetry::kTelemetrySdkName, "opentelemetry"},
- {semconv::telemetry::kTelemetrySdkVersion, OPENTELEMETRY_SDK_VERSION},
- {semconv::service::kServiceName, "unknown_service"}};
- ResourceAttributes attributes = {
- {"service", "backend"}, {"version", static_cast<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<uint32_t>(expected_attributes.find(e.first)->second),
- nostd::get<uint32_t>(e.second));
- else if (e.first == "cost")
- EXPECT_EQ(nostd::get<double>(expected_attributes.find(e.first)->second),
- nostd::get<double>(e.second));
- else
- EXPECT_EQ(opentelemetry::nostd::get<std::string>(expected_attributes.find(e.first)->second),
- opentelemetry::nostd::get<std::string>(e.second));
- }
- }
- EXPECT_EQ(received_attributes.size(), expected_attributes.size()); // for missing service.name
- }
- TEST(ResourceTest, create_with_servicename)
- {
- ResourceAttributes expected_attributes = {
- {"version", static_cast<uint32_t>(1)},
- {"cost", 234.23},
- {semconv::telemetry::kTelemetrySdkLanguage, "cpp"},
- {semconv::telemetry::kTelemetrySdkName, "opentelemetry"},
- {semconv::telemetry::kTelemetrySdkVersion, OPENTELEMETRY_SDK_VERSION},
- {semconv::service::kServiceName, "backend"},
- };
- ResourceAttributes attributes = {
- {"service.name", "backend"}, {"version", static_cast<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<uint32_t>(expected_attributes.find(e.first)->second),
- nostd::get<uint32_t>(e.second));
- else if (e.first == "cost")
- EXPECT_EQ(nostd::get<double>(expected_attributes.find(e.first)->second),
- nostd::get<double>(e.second));
- else
- EXPECT_EQ(nostd::get<std::string>(expected_attributes.find(e.first)->second),
- nostd::get<std::string>(e.second));
- }
- }
- EXPECT_EQ(received_attributes.size(), expected_attributes.size()); // for missing service.name
- }
- TEST(ResourceTest, create_with_emptyatrributes)
- {
- ResourceAttributes expected_attributes = {
- {semconv::telemetry::kTelemetrySdkLanguage, "cpp"},
- {semconv::telemetry::kTelemetrySdkName, "opentelemetry"},
- {semconv::telemetry::kTelemetrySdkVersion, OPENTELEMETRY_SDK_VERSION},
- {semconv::service::kServiceName, "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<std::string>(expected_attributes.find(e.first)->second),
- opentelemetry::nostd::get<std::string>(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);
- const 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<std::string, std::string> 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<std::string>(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<std::string, std::string> 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<std::string>(e.second));
- }
- }
- EXPECT_EQ(received_attributes.size(), expected_attributes.size());
- }
- TEST(ResourceTest, MergeSchemaUrl)
- {
- const std::string url = "https://opentelemetry.io/schemas/v3.1.4";
- TestResource resource_empty_url({}, "");
- TestResource resource_some_url({}, url);
- TestResource resource_different_url({}, "different");
- // Specified behavior:
- auto merged_both_empty = resource_empty_url.Merge(resource_empty_url);
- EXPECT_TRUE(merged_both_empty.GetSchemaURL().empty());
- auto merged_old_empty = resource_empty_url.Merge(resource_some_url);
- EXPECT_EQ(merged_old_empty.GetSchemaURL(), url);
- auto merged_updating_empty = resource_some_url.Merge(resource_empty_url);
- EXPECT_EQ(merged_updating_empty.GetSchemaURL(), url);
- auto merged_same_url = resource_some_url.Merge(resource_some_url);
- EXPECT_EQ(merged_same_url.GetSchemaURL(), url);
- // Implementation-defined behavior:
- auto merged_different_url = resource_different_url.Merge(resource_some_url);
- EXPECT_EQ(merged_different_url.GetSchemaURL(), url);
- }
- #ifndef NO_GETENV
- TEST(ResourceTest, OtelResourceDetector)
- {
- std::map<std::string, std::string> 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<std::string>(e.second));
- }
- }
- EXPECT_EQ(received_attributes.size(), expected_attributes.size());
- unsetenv("OTEL_RESOURCE_ATTRIBUTES");
- }
- TEST(ResourceTest, OtelResourceDetectorServiceNameOverride)
- {
- std::map<std::string, std::string> expected_attributes = {{"service.name", "new_name"}};
- setenv("OTEL_RESOURCE_ATTRIBUTES", "service.name=old_name", 1);
- setenv("OTEL_SERVICE_NAME", "new_name", 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<std::string>(e.second));
- }
- }
- EXPECT_EQ(received_attributes.size(), expected_attributes.size());
- unsetenv("OTEL_SERVICE_NAME");
- unsetenv("OTEL_RESOURCE_ATTRIBUTES");
- }
- TEST(ResourceTest, OtelResourceDetectorEmptyEnv)
- {
- std::map<std::string, std::string> 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<std::string>(e.second));
- }
- }
- EXPECT_EQ(received_attributes.size(), expected_attributes.size());
- }
- #endif
- TEST(ResourceTest, DerivedResourceDetector)
- {
- TestResourceDetector detector;
- detector.attributes = {{"key", "value"}};
- detector.schema_url = "https://opentelemetry.io/schemas/v3.1.4";
- const auto resource = detector.Detect();
- const auto received_attributes = resource.GetAttributes();
- EXPECT_EQ(received_attributes.size(), 1);
- EXPECT_EQ(resource.GetSchemaURL(), detector.schema_url);
- EXPECT_TRUE(received_attributes.find("key") != received_attributes.end());
- }
|