metric_collector_test.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include <gtest/gtest.h>
  4. #include <stdint.h>
  5. #include <algorithm>
  6. #include <map>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include <vector>
  11. #include "common.h"
  12. #include "gmock/gmock.h"
  13. #include "opentelemetry/common/key_value_iterable_view.h"
  14. #include "opentelemetry/context/context.h"
  15. #include "opentelemetry/metrics/sync_instruments.h" // IWYU pragma: keep
  16. #include "opentelemetry/nostd/string_view.h"
  17. #include "opentelemetry/nostd/variant.h"
  18. #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
  19. #include "opentelemetry/sdk/metrics/data/metric_data.h"
  20. #include "opentelemetry/sdk/metrics/data/point_data.h"
  21. #include "opentelemetry/sdk/metrics/export/metric_filter.h"
  22. #include "opentelemetry/sdk/metrics/export/metric_producer.h"
  23. #include "opentelemetry/sdk/metrics/instruments.h"
  24. #include "opentelemetry/sdk/metrics/meter.h"
  25. #include "opentelemetry/sdk/metrics/meter_context.h"
  26. #include "opentelemetry/sdk/metrics/metric_reader.h"
  27. #include "opentelemetry/sdk/metrics/state/metric_collector.h"
  28. #include "opentelemetry/sdk/metrics/view/view_registry.h"
  29. #include "opentelemetry/sdk/metrics/view/view_registry_factory.h"
  30. #if defined(__GNUC__) || defined(__clang__) || defined(__apple_build_version__)
  31. # pragma GCC diagnostic push
  32. # pragma GCC diagnostic ignored "-Wunused-parameter"
  33. #endif
  34. using namespace opentelemetry;
  35. using namespace opentelemetry::sdk::instrumentationscope;
  36. using namespace opentelemetry::sdk::metrics;
  37. using namespace testing;
  38. using M = std::map<std::string, std::string>;
  39. namespace
  40. {
  41. MetricFilter::TestMetricFn AcceptAllTestMetricFn()
  42. {
  43. return [](const InstrumentationScope &scope, nostd::string_view name, const InstrumentType &type,
  44. nostd::string_view unit) -> MetricFilter::MetricFilterResult {
  45. return MetricFilter::MetricFilterResult::kAccept;
  46. };
  47. }
  48. MetricFilter::TestMetricFn DropAllTestMetricFn()
  49. {
  50. return [](const InstrumentationScope &scope, nostd::string_view name, const InstrumentType &type,
  51. nostd::string_view unit) -> MetricFilter::MetricFilterResult {
  52. return MetricFilter::MetricFilterResult::kDrop;
  53. };
  54. }
  55. MetricFilter::TestMetricFn AcceptPartialAllTestMetricFn()
  56. {
  57. return [](const InstrumentationScope &scope, nostd::string_view name, const InstrumentType &type,
  58. nostd::string_view unit) -> MetricFilter::MetricFilterResult {
  59. return MetricFilter::MetricFilterResult::kAcceptPartial;
  60. };
  61. }
  62. MetricFilter::TestAttributesFn AcceptAllTestAttributesFn()
  63. {
  64. return [](const InstrumentationScope &scope, nostd::string_view name, const InstrumentType &type,
  65. nostd::string_view unit,
  66. const PointAttributes &attributes) -> MetricFilter::AttributesFilterResult {
  67. return MetricFilter::AttributesFilterResult::kAccept;
  68. };
  69. }
  70. MetricFilter::TestAttributesFn DropAllTestAttributesFn()
  71. {
  72. return [](const InstrumentationScope &scope, nostd::string_view name, const InstrumentType &type,
  73. nostd::string_view unit,
  74. const PointAttributes &attributes) -> MetricFilter::AttributesFilterResult {
  75. return MetricFilter::AttributesFilterResult::kDrop;
  76. };
  77. }
  78. } // namespace
  79. class testing::MetricCollectorTest : public Test
  80. {
  81. public:
  82. std::weak_ptr<MetricCollector> AddMetricReaderToMeterContext(
  83. std::shared_ptr<MeterContext> context,
  84. std::shared_ptr<MetricReader> reader,
  85. std::unique_ptr<MetricFilter> metric_filter = nullptr) noexcept
  86. {
  87. auto collector = std::shared_ptr<MetricCollector>{
  88. new MetricCollector(context.get(), std::move(reader), std::move(metric_filter))};
  89. context->collectors_.push_back(collector);
  90. return std::weak_ptr<MetricCollector>(collector);
  91. }
  92. };
  93. TEST_F(MetricCollectorTest, CollectWithMetricFilterTestMetricTest1)
  94. {
  95. auto context = std::shared_ptr<MeterContext>(new MeterContext(ViewRegistryFactory::Create()));
  96. auto scope = InstrumentationScope::Create("CollectWithMetricFilterTestMetricTest1");
  97. auto meter = std::shared_ptr<Meter>(new Meter(context, std::move(scope)));
  98. context->AddMeter(meter);
  99. auto filter = MetricFilter::Create(AcceptAllTestMetricFn(), DropAllTestAttributesFn());
  100. auto reader = std::shared_ptr<MetricReader>(new MockMetricReader());
  101. auto collector = AddMetricReaderToMeterContext(context, reader, std::move(filter)).lock();
  102. auto instrument_1_name = "instrument_1";
  103. auto instrument_1 = meter->CreateUInt64Counter(instrument_1_name);
  104. auto instrument_2_name = "instrument_2";
  105. auto instrument_2 = meter->CreateUInt64Counter(instrument_2_name);
  106. M m_2 = {{"stream", "1"}};
  107. instrument_2->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_2),
  108. opentelemetry::context::Context{});
  109. auto instrument_3_name = "instrument_3";
  110. auto instrument_3 = meter->CreateUInt64Counter(instrument_3_name);
  111. for (int s = 1; s <= 10; ++s)
  112. {
  113. for (int i = 0; i < s; ++i)
  114. {
  115. M m_3 = {{"stream", std::to_string(s)}};
  116. instrument_3->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_3),
  117. opentelemetry::context::Context{});
  118. }
  119. }
  120. auto resource_metrics = collector->Produce().points_;
  121. for (const ScopeMetrics &scope_metrics : resource_metrics.scope_metric_data_)
  122. {
  123. for (const MetricData &metric : scope_metrics.metric_data_)
  124. {
  125. auto instrument_name = metric.instrument_descriptor.name_;
  126. ASSERT_TRUE(instrument_name == instrument_2_name || instrument_name == instrument_3_name);
  127. if (instrument_name == instrument_2_name)
  128. {
  129. EXPECT_EQ(metric.point_data_attr_.size(), 1);
  130. }
  131. else if (instrument_name == instrument_3_name)
  132. {
  133. EXPECT_EQ(metric.point_data_attr_.size(), 10);
  134. }
  135. }
  136. }
  137. }
  138. TEST_F(MetricCollectorTest, CollectWithMetricFilterTestMetricTest2)
  139. {
  140. auto context = std::shared_ptr<MeterContext>(new MeterContext(ViewRegistryFactory::Create()));
  141. auto scope = InstrumentationScope::Create("CollectWithMetricFilterTestMetricTest2");
  142. auto meter = std::shared_ptr<Meter>(new Meter(context, std::move(scope)));
  143. context->AddMeter(meter);
  144. auto filter = MetricFilter::Create(DropAllTestMetricFn(), AcceptAllTestAttributesFn());
  145. auto reader = std::shared_ptr<MetricReader>(new MockMetricReader());
  146. auto collector = AddMetricReaderToMeterContext(context, reader, std::move(filter)).lock();
  147. auto instrument_1_name = "instrument_1";
  148. auto instrument_1 = meter->CreateUInt64Counter(instrument_1_name);
  149. auto instrument_2_name = "instrument_2";
  150. auto instrument_2 = meter->CreateUInt64Counter(instrument_2_name);
  151. M m_2 = {{"stream", "1"}};
  152. instrument_2->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_2),
  153. opentelemetry::context::Context{});
  154. auto instrument_3_name = "instrument_3";
  155. auto instrument_3 = meter->CreateUInt64Counter(instrument_3_name);
  156. for (int s = 1; s <= 10; ++s)
  157. {
  158. for (int i = 0; i < s; ++i)
  159. {
  160. M m_3 = {{"stream", std::to_string(s)}};
  161. instrument_3->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_3),
  162. opentelemetry::context::Context{});
  163. }
  164. }
  165. auto resource_metrics = collector->Produce().points_;
  166. EXPECT_EQ(resource_metrics.scope_metric_data_.size(), 0);
  167. }
  168. TEST_F(MetricCollectorTest, CollectWithMetricFilterTestMetricTest3)
  169. {
  170. auto context = std::shared_ptr<MeterContext>(new MeterContext(ViewRegistryFactory::Create()));
  171. auto scope = InstrumentationScope::Create("CollectWithMetricFilterTestMetricTest3");
  172. auto meter = std::shared_ptr<Meter>(new Meter(context, std::move(scope)));
  173. context->AddMeter(meter);
  174. auto test_metric_fn = [](const InstrumentationScope &scope, nostd::string_view name,
  175. const InstrumentType &type,
  176. nostd::string_view unit) -> MetricFilter::MetricFilterResult {
  177. std::string name_copy = {name.begin(), name.end()};
  178. if (name_copy.find("_accept") != std::string::npos)
  179. {
  180. return MetricFilter::MetricFilterResult::kAccept;
  181. }
  182. return MetricFilter::MetricFilterResult::kDrop;
  183. };
  184. auto filter = MetricFilter::Create(test_metric_fn, DropAllTestAttributesFn());
  185. auto reader = std::shared_ptr<MetricReader>(new MockMetricReader());
  186. auto collector = AddMetricReaderToMeterContext(context, reader, std::move(filter)).lock();
  187. auto instrument_1_name = "instrument_1";
  188. auto instrument_1 = meter->CreateUInt64Counter(instrument_1_name);
  189. auto instrument_2_name = "instrument_2";
  190. auto instrument_2 = meter->CreateUInt64Counter(instrument_2_name);
  191. M m_2 = {{"stream", "1"}};
  192. instrument_2->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_2),
  193. opentelemetry::context::Context{});
  194. auto instrument_3_name = "instrument_3_accept";
  195. auto instrument_3 = meter->CreateUInt64Counter(instrument_3_name);
  196. for (int s = 1; s <= 10; ++s)
  197. {
  198. for (int i = 0; i < s; ++i)
  199. {
  200. M m_3 = {{"stream", std::to_string(s)}};
  201. instrument_3->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_3),
  202. opentelemetry::context::Context{});
  203. }
  204. }
  205. auto resource_metrics = collector->Produce().points_;
  206. for (const ScopeMetrics &scope_metrics : resource_metrics.scope_metric_data_)
  207. {
  208. for (const MetricData &metric : scope_metrics.metric_data_)
  209. {
  210. auto instrument_name = metric.instrument_descriptor.name_;
  211. ASSERT_EQ(instrument_name, instrument_3_name);
  212. EXPECT_EQ(metric.point_data_attr_.size(), 10);
  213. }
  214. }
  215. }
  216. TEST_F(MetricCollectorTest, CollectWithMetricFilterTestAttributesTest1)
  217. {
  218. auto context = std::shared_ptr<MeterContext>(new MeterContext(ViewRegistryFactory::Create()));
  219. auto scope = InstrumentationScope::Create("CollectWithMetricFilterTestAttributesTest1");
  220. auto meter = std::shared_ptr<Meter>(new Meter(context, std::move(scope)));
  221. context->AddMeter(meter);
  222. auto test_attributes_fn =
  223. [](const InstrumentationScope &scope, nostd::string_view name, const InstrumentType &type,
  224. nostd::string_view unit,
  225. const PointAttributes &attributes) -> MetricFilter::AttributesFilterResult {
  226. if (attributes.GetAttributes().find("stream") != attributes.GetAttributes().end())
  227. {
  228. return MetricFilter::AttributesFilterResult::kAccept;
  229. }
  230. return MetricFilter::AttributesFilterResult::kDrop;
  231. };
  232. auto filter = MetricFilter::Create(AcceptPartialAllTestMetricFn(), test_attributes_fn);
  233. auto reader = std::shared_ptr<MetricReader>(new MockMetricReader());
  234. auto collector = AddMetricReaderToMeterContext(context, reader, std::move(filter)).lock();
  235. auto instrument_1_name = "instrument_1";
  236. auto instrument_1 = meter->CreateUInt64Counter(instrument_1_name);
  237. M m_1 = {{"ocean", "1"}};
  238. instrument_1->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_1),
  239. opentelemetry::context::Context{});
  240. auto instrument_2_name = "instrument_2";
  241. auto instrument_2 = meter->CreateUInt64Counter(instrument_2_name);
  242. M m_2 = {{"stream", "1"}, {"river", "10"}};
  243. instrument_2->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_2),
  244. opentelemetry::context::Context{});
  245. auto instrument_3_name = "instrument_3";
  246. auto instrument_3 = meter->CreateUInt64Counter(instrument_3_name);
  247. for (int s = 1; s <= 10; ++s)
  248. {
  249. for (int i = 0; i < s; ++i)
  250. {
  251. M m_3 = {{"stream", std::to_string(s)}, {"river", std::to_string(s * 10)}};
  252. instrument_3->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_3),
  253. opentelemetry::context::Context{});
  254. }
  255. }
  256. auto resource_metrics = collector->Produce().points_;
  257. for (const ScopeMetrics &scope_metrics : resource_metrics.scope_metric_data_)
  258. {
  259. for (const MetricData &metric : scope_metrics.metric_data_)
  260. {
  261. auto instrument_name = metric.instrument_descriptor.name_;
  262. ASSERT_TRUE(instrument_name == instrument_2_name || instrument_name == instrument_3_name);
  263. if (instrument_name == instrument_2_name)
  264. {
  265. EXPECT_EQ(metric.point_data_attr_.size(), 1);
  266. }
  267. else if (instrument_name == instrument_3_name)
  268. {
  269. EXPECT_EQ(metric.point_data_attr_.size(), 10);
  270. for (const PointDataAttributes &pda : metric.point_data_attr_)
  271. {
  272. auto sum_point_data = nostd::get<SumPointData>(pda.point_data);
  273. auto value = nostd::get<int64_t>(sum_point_data.value_);
  274. auto stream =
  275. std::stoi(nostd::get<std::string>(pda.attributes.GetAttributes().at("stream")));
  276. auto river =
  277. std::stoi(nostd::get<std::string>(pda.attributes.GetAttributes().at("river")));
  278. std::vector<int64_t> stream_v = {value, stream};
  279. std::vector<int64_t> river_v = {value, river};
  280. EXPECT_THAT(stream_v, AnyOf(ElementsAre(1, 1), ElementsAre(2, 2), ElementsAre(3, 3),
  281. ElementsAre(4, 4), ElementsAre(5, 5), ElementsAre(6, 6),
  282. ElementsAre(7, 7), ElementsAre(8, 8), ElementsAre(9, 9),
  283. ElementsAre(10, 10)));
  284. EXPECT_THAT(river_v, AnyOf(ElementsAre(1, 10), ElementsAre(2, 20), ElementsAre(3, 30),
  285. ElementsAre(4, 40), ElementsAre(5, 50), ElementsAre(6, 60),
  286. ElementsAre(7, 70), ElementsAre(8, 80), ElementsAre(9, 90),
  287. ElementsAre(10, 100)));
  288. }
  289. }
  290. }
  291. }
  292. }
  293. TEST_F(MetricCollectorTest, CollectWithMetricFilterTestAttributesTest2)
  294. {
  295. auto context = std::shared_ptr<MeterContext>(new MeterContext(ViewRegistryFactory::Create()));
  296. auto scope = InstrumentationScope::Create("CollectWithMetricFilterTestAttributesTest2");
  297. auto meter = std::shared_ptr<Meter>(new Meter(context, std::move(scope)));
  298. context->AddMeter(meter);
  299. auto test_attributes_fn =
  300. [](const InstrumentationScope &scope, nostd::string_view name, const InstrumentType &type,
  301. nostd::string_view unit,
  302. const PointAttributes &attributes) -> MetricFilter::AttributesFilterResult {
  303. if (attributes.GetAttributes().find("stream") != attributes.GetAttributes().end())
  304. {
  305. auto stream = nostd::get<std::string>(attributes.GetAttributes().at("stream"));
  306. if (std::stoi(stream) >= 4 && std::stoi(stream) <= 6)
  307. {
  308. return MetricFilter::AttributesFilterResult::kAccept;
  309. }
  310. }
  311. return MetricFilter::AttributesFilterResult::kDrop;
  312. };
  313. auto filter = MetricFilter::Create(AcceptPartialAllTestMetricFn(), test_attributes_fn);
  314. auto reader = std::shared_ptr<MetricReader>(new MockMetricReader());
  315. auto collector = AddMetricReaderToMeterContext(context, reader, std::move(filter)).lock();
  316. auto instrument_1_name = "instrument_1";
  317. auto instrument_1 = meter->CreateUInt64Counter(instrument_1_name);
  318. M m_1 = {{"ocean", "1"}};
  319. instrument_1->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_1),
  320. opentelemetry::context::Context{});
  321. auto instrument_2_name = "instrument_2";
  322. auto instrument_2 = meter->CreateUInt64Counter(instrument_2_name);
  323. M m_2 = {{"stream", "1"}, {"river", "10"}};
  324. instrument_2->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_2),
  325. opentelemetry::context::Context{});
  326. auto instrument_3_name = "instrument_3";
  327. auto instrument_3 = meter->CreateUInt64Counter(instrument_3_name);
  328. for (int s = 1; s <= 10; ++s)
  329. {
  330. for (int i = 0; i < s; ++i)
  331. {
  332. M m_3 = {{"stream", std::to_string(s)}, {"river", std::to_string(s * 10)}};
  333. instrument_3->Add(1, opentelemetry::common::KeyValueIterableView<M>(m_3),
  334. opentelemetry::context::Context{});
  335. }
  336. }
  337. auto resource_metrics = collector->Produce().points_;
  338. for (const ScopeMetrics &scope_metrics : resource_metrics.scope_metric_data_)
  339. {
  340. for (const MetricData &metric : scope_metrics.metric_data_)
  341. {
  342. auto instrument_name = metric.instrument_descriptor.name_;
  343. ASSERT_EQ(instrument_name, instrument_3_name);
  344. EXPECT_EQ(metric.point_data_attr_.size(), 3);
  345. for (const PointDataAttributes &pda : metric.point_data_attr_)
  346. {
  347. auto sum_point_data = nostd::get<SumPointData>(pda.point_data);
  348. auto value = nostd::get<int64_t>(sum_point_data.value_);
  349. auto stream =
  350. std::stoi(nostd::get<std::string>(pda.attributes.GetAttributes().at("stream")));
  351. auto river = std::stoi(nostd::get<std::string>(pda.attributes.GetAttributes().at("river")));
  352. std::vector<int64_t> stream_v = {value, stream};
  353. std::vector<int64_t> river_v = {value, river};
  354. EXPECT_THAT(stream_v, AnyOf(ElementsAre(4, 4), ElementsAre(5, 5), ElementsAre(6, 6)));
  355. EXPECT_THAT(river_v, AnyOf(ElementsAre(4, 40), ElementsAre(5, 50), ElementsAre(6, 60)));
  356. }
  357. }
  358. }
  359. }
  360. #if defined(__GNUC__) || defined(__clang__) || defined(__apple_build_version__)
  361. # pragma GCC diagnostic pop
  362. #endif