attributes_hashmap_test.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include <gtest/gtest.h>
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. #include <functional>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include "opentelemetry/nostd/function_ref.h"
  11. #include "opentelemetry/nostd/string_view.h"
  12. #include "opentelemetry/sdk/common/attributemap_hash.h"
  13. #include "opentelemetry/sdk/metrics/aggregation/aggregation.h"
  14. #include "opentelemetry/sdk/metrics/aggregation/drop_aggregation.h"
  15. #include "opentelemetry/sdk/metrics/state/attributes_hashmap.h"
  16. #include "opentelemetry/sdk/metrics/view/attributes_processor.h"
  17. using namespace opentelemetry::sdk::metrics;
  18. namespace nostd = opentelemetry::nostd;
  19. TEST(AttributesHashMap, BasicTests)
  20. {
  21. // Empty map
  22. AttributesHashMap hash_map;
  23. EXPECT_EQ(hash_map.Size(), 0);
  24. MetricAttributes m1 = {{"k1", "v1"}};
  25. EXPECT_EQ(hash_map.Get(m1), nullptr);
  26. EXPECT_EQ(hash_map.Has(m1), false);
  27. // Set
  28. std::unique_ptr<Aggregation> aggregation1(
  29. new DropAggregation()); // = std::unique_ptr<Aggregation>(new DropAggregation);
  30. hash_map.Set(m1, std::move(aggregation1));
  31. hash_map.Get(m1)->Aggregate(static_cast<int64_t>(1));
  32. EXPECT_EQ(hash_map.Size(), 1);
  33. EXPECT_EQ(hash_map.Has(m1), true);
  34. // Set same key again
  35. auto aggregation2 = std::unique_ptr<Aggregation>(new DropAggregation());
  36. hash_map.Set(m1, std::move(aggregation2));
  37. hash_map.Get(m1)->Aggregate(static_cast<int64_t>(1));
  38. EXPECT_EQ(hash_map.Size(), 1);
  39. EXPECT_EQ(hash_map.Has(m1), true);
  40. // Set more enteria
  41. auto aggregation3 = std::unique_ptr<Aggregation>(new DropAggregation());
  42. MetricAttributes m3 = {{"k1", "v1"}, {"k2", "v2"}};
  43. hash_map.Set(m3, std::move(aggregation3));
  44. EXPECT_EQ(hash_map.Has(m1), true);
  45. EXPECT_EQ(hash_map.Has(m3), true);
  46. hash_map.Get(m3)->Aggregate(static_cast<int64_t>(1));
  47. EXPECT_EQ(hash_map.Size(), 2);
  48. // GetOrSetDefault
  49. std::function<std::unique_ptr<Aggregation>()> create_default_aggregation =
  50. []() -> std::unique_ptr<Aggregation> {
  51. return std::unique_ptr<Aggregation>(new DropAggregation);
  52. };
  53. MetricAttributes m4 = {{"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}};
  54. hash_map.GetOrSetDefault(m4, create_default_aggregation)->Aggregate(static_cast<int64_t>(1));
  55. EXPECT_EQ(hash_map.Size(), 3);
  56. // Set attributes with different order - shouldn't create a new entry.
  57. MetricAttributes m5 = {{"k2", "v2"}, {"k1", "v1"}};
  58. EXPECT_EQ(hash_map.Has(m5), true);
  59. // Set attributes with different order - shouldn't create a new entry.
  60. MetricAttributes m6 = {{"k1", "v2"}, {"k2", "v1"}};
  61. EXPECT_EQ(hash_map.Has(m6), false);
  62. // GetAllEnteries
  63. size_t count = 0;
  64. hash_map.GetAllEnteries(
  65. [&count](const MetricAttributes & /* attributes */, Aggregation & /* aggregation */) {
  66. count++;
  67. return true;
  68. });
  69. EXPECT_EQ(count, hash_map.Size());
  70. }
  71. class MetricAttributeMapHashForCollision
  72. {
  73. public:
  74. size_t operator()(const MetricAttributes & /*attributes*/) const { return 42; }
  75. };
  76. TEST(AttributesHashMap, CollisionTest)
  77. {
  78. // The hash on MetricsAttributes will be ignored by MetricAttributeMapHashForCollision
  79. MetricAttributes m1 = {{"k1", "v1"}};
  80. MetricAttributes m2 = {{"k2", "v2"}};
  81. MetricAttributes m3 = {{"k1", "v1"}, {"k2", "v2"}};
  82. MetricAttributes m4 = {};
  83. AttributesHashMapWithCustomHash<MetricAttributeMapHashForCollision> hash_map;
  84. hash_map.Set(m1, std::unique_ptr<Aggregation>(new DropAggregation()));
  85. hash_map.Set(m2, std::unique_ptr<Aggregation>(new DropAggregation()));
  86. hash_map.Set(m3, std::unique_ptr<Aggregation>(new DropAggregation()));
  87. hash_map.Set(m4, std::unique_ptr<Aggregation>(new DropAggregation()));
  88. EXPECT_EQ(hash_map.Size(), 4);
  89. EXPECT_EQ(hash_map.Has(m1), true);
  90. EXPECT_EQ(hash_map.Has(m2), true);
  91. EXPECT_EQ(hash_map.Has(m3), true);
  92. EXPECT_EQ(hash_map.Has(m4), true);
  93. MetricAttributes m5 = {{"k2", "v1"}};
  94. EXPECT_EQ(hash_map.Has(m5), false);
  95. //
  96. // Verify only one bucket used based on the custom hash
  97. //
  98. size_t total_active_buckets = 0;
  99. size_t total_elements = 0;
  100. for (size_t i = 0; i < hash_map.BucketCount(); i++)
  101. {
  102. size_t bucket_size = hash_map.BucketSize(i);
  103. if (bucket_size > 0)
  104. {
  105. total_active_buckets++;
  106. total_elements += bucket_size;
  107. }
  108. }
  109. EXPECT_EQ(total_active_buckets, 1);
  110. EXPECT_EQ(total_elements, 4);
  111. }
  112. TEST(AttributesHashMap, HashConsistencyAcrossStringTypes)
  113. {
  114. const char *c_str = "teststring";
  115. std::string std_str = "teststring";
  116. nostd::string_view nostd_str_view = "teststring";
  117. #if __cplusplus >= 201703L
  118. std::string_view std_str_view = "teststring";
  119. #endif
  120. size_t hash_c_str = 0;
  121. size_t hash_std_str = 0;
  122. size_t hash_nostd_str_view = 0;
  123. #if __cplusplus >= 201703L
  124. size_t hash_std_str_view = 0;
  125. #endif
  126. opentelemetry::sdk::common::GetHash(hash_c_str, c_str);
  127. opentelemetry::sdk::common::GetHash(hash_std_str, std_str);
  128. opentelemetry::sdk::common::GetHash(hash_nostd_str_view, nostd_str_view);
  129. #if __cplusplus >= 201703L
  130. opentelemetry::sdk::common::GetHash(hash_std_str_view, std_str_view);
  131. #endif
  132. EXPECT_EQ(hash_c_str, hash_std_str);
  133. EXPECT_EQ(hash_c_str, hash_nostd_str_view);
  134. #if __cplusplus >= 201703L
  135. EXPECT_EQ(hash_c_str, hash_std_str_view);
  136. #endif
  137. }