meter_test.cc 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  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 <algorithm>
  7. #include <atomic>
  8. #include <iostream>
  9. #include <string>
  10. #include <thread>
  11. #include <utility>
  12. #include <vector>
  13. #include "common.h"
  14. #include <functional>
  15. #include "opentelemetry/context/context.h"
  16. #include "opentelemetry/metrics/async_instruments.h"
  17. #include "opentelemetry/metrics/meter.h"
  18. #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
  19. #include "opentelemetry/sdk/instrumentationscope/scope_configurator.h"
  20. #include "opentelemetry/sdk/metrics/instruments.h"
  21. #include "opentelemetry/sdk/metrics/meter_config.h"
  22. #include "opentelemetry/sdk/metrics/view/view_registry.h"
  23. #include "opentelemetry/sdk/resource/resource.h"
  24. #include <opentelemetry/sdk/metrics/view/view_registry_factory.h>
  25. #include "opentelemetry/metrics/meter_provider.h"
  26. #include "opentelemetry/metrics/observer_result.h"
  27. #include "opentelemetry/metrics/sync_instruments.h" // IWYU pragma: keep
  28. #include "opentelemetry/nostd/function_ref.h"
  29. #include "opentelemetry/nostd/shared_ptr.h"
  30. #include "opentelemetry/nostd/variant.h"
  31. #include "opentelemetry/sdk/common/attribute_utils.h"
  32. #include "opentelemetry/sdk/common/global_log_handler.h"
  33. #include "opentelemetry/sdk/metrics/data/metric_data.h"
  34. #include "opentelemetry/sdk/metrics/data/point_data.h"
  35. #include "opentelemetry/sdk/metrics/export/metric_producer.h"
  36. #include "opentelemetry/sdk/metrics/meter_provider.h"
  37. #include "opentelemetry/sdk/metrics/metric_reader.h"
  38. #include "opentelemetry/sdk/metrics/view/instrument_selector.h"
  39. #include "opentelemetry/sdk/metrics/view/meter_selector.h"
  40. #include "opentelemetry/sdk/metrics/view/view.h"
  41. using namespace opentelemetry;
  42. using namespace opentelemetry::sdk::instrumentationscope;
  43. using namespace opentelemetry::sdk::metrics;
  44. using namespace opentelemetry::sdk::common::internal_log;
  45. namespace
  46. {
  47. nostd::shared_ptr<metrics::Meter> InitMeter(MetricReader **metricReaderPtr,
  48. const std::string &meter_name = "meter_name")
  49. {
  50. static std::shared_ptr<metrics::MeterProvider> provider(new MeterProvider());
  51. std::unique_ptr<MetricReader> metric_reader(new MockMetricReader());
  52. *metricReaderPtr = metric_reader.get();
  53. auto p = std::static_pointer_cast<MeterProvider>(provider);
  54. p->AddMetricReader(std::move(metric_reader));
  55. auto meter = provider->GetMeter(meter_name);
  56. return meter;
  57. }
  58. void asyc_generate_measurements_long(opentelemetry::metrics::ObserverResult observer,
  59. void * /* state */)
  60. {
  61. auto observer_long =
  62. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<int64_t>>>(observer);
  63. observer_long->Observe(10);
  64. }
  65. void asyc_generate_measurements_double(opentelemetry::metrics::ObserverResult observer,
  66. void * /* state */)
  67. {
  68. auto observer_double =
  69. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<double>>>(observer);
  70. observer_double->Observe(10.2f);
  71. }
  72. std::shared_ptr<metrics::MeterProvider> GetMeterProviderWithScopeConfigurator(
  73. const ScopeConfigurator<MeterConfig> &meter_configurator,
  74. MetricReader **metric_reader_ptr)
  75. {
  76. auto views = ViewRegistryFactory::Create();
  77. auto resource = sdk::resource::Resource::Create({});
  78. std::unique_ptr<MetricReader> metric_reader(new MockMetricReader());
  79. *metric_reader_ptr = metric_reader.get();
  80. std::shared_ptr<metrics::MeterProvider> provider(
  81. new MeterProvider(std::move(views), resource,
  82. std::make_unique<ScopeConfigurator<MeterConfig>>(meter_configurator)));
  83. auto p = std::static_pointer_cast<MeterProvider>(provider);
  84. p->AddMetricReader(std::move(metric_reader));
  85. return p;
  86. }
  87. class TestLogHandler : public LogHandler
  88. {
  89. public:
  90. void Handle(LogLevel level,
  91. const char * /*file*/,
  92. int /*line*/,
  93. const char *msg,
  94. const sdk::common::AttributeMap & /*attributes*/) noexcept override
  95. {
  96. if (LogLevel::Warning == level)
  97. {
  98. std::cout << msg << std::endl;
  99. warnings.push_back(msg);
  100. }
  101. }
  102. bool HasNameCaseConflictWarning() const
  103. {
  104. return std::any_of(warnings.begin(), warnings.end(), [](const std::string &warning) {
  105. return warning.find("WarnOnNameCaseConflict") != std::string::npos;
  106. });
  107. }
  108. bool HasDuplicateInstrumentWarning() const
  109. {
  110. return std::any_of(warnings.begin(), warnings.end(), [](const std::string &warning) {
  111. return warning.find("WarnOnDuplicateInstrument") != std::string::npos;
  112. });
  113. }
  114. private:
  115. std::vector<std::string> warnings;
  116. };
  117. class MeterCreateInstrumentTest : public ::testing::Test
  118. {
  119. protected:
  120. void SetUp() override
  121. {
  122. ASSERT_TRUE(log_handler_ != nullptr);
  123. ASSERT_TRUE(metric_reader_ptr_ != nullptr);
  124. ASSERT_TRUE(provider_ != nullptr);
  125. GlobalLogHandler::SetLogHandler(std::static_pointer_cast<LogHandler>(log_handler_));
  126. GlobalLogHandler::SetLogLevel(LogLevel::Warning);
  127. provider_->AddMetricReader(metric_reader_ptr_);
  128. meter_ = provider_->GetMeter("test_meter");
  129. ASSERT_TRUE(meter_ != nullptr);
  130. }
  131. void TearDown() override {}
  132. void AddNameCorrectionView(const std::string &name,
  133. const std::string &unit,
  134. InstrumentType type,
  135. const std::string &new_name)
  136. {
  137. std::unique_ptr<View> corrective_view{new View(new_name)};
  138. std::unique_ptr<InstrumentSelector> instrument_selector{
  139. new InstrumentSelector(type, name, unit)};
  140. std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("test_meter", "", "")};
  141. provider_->AddView(std::move(instrument_selector), std::move(meter_selector),
  142. std::move(corrective_view));
  143. }
  144. void AddDescriptionCorrectionView(const std::string &name,
  145. const std::string &unit,
  146. InstrumentType type,
  147. const std::string &new_description)
  148. {
  149. std::unique_ptr<View> corrective_view{new View(name, new_description)};
  150. std::unique_ptr<InstrumentSelector> instrument_selector{
  151. new InstrumentSelector(type, name, unit)};
  152. std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("test_meter", "", "")};
  153. provider_->AddView(std::move(instrument_selector), std::move(meter_selector),
  154. std::move(corrective_view));
  155. }
  156. std::shared_ptr<sdk::metrics::MeterProvider> provider_{new sdk::metrics::MeterProvider()};
  157. std::shared_ptr<TestLogHandler> log_handler_{new TestLogHandler()};
  158. opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Meter> meter_{nullptr};
  159. std::shared_ptr<MetricReader> metric_reader_ptr_{new MockMetricReader()};
  160. };
  161. } // namespace
  162. TEST(MeterTest, BasicAsyncTests)
  163. {
  164. MetricReader *metric_reader_ptr = nullptr;
  165. auto meter = InitMeter(&metric_reader_ptr);
  166. auto observable_counter = meter->CreateInt64ObservableCounter("observable_counter");
  167. observable_counter->AddCallback(asyc_generate_measurements_long, nullptr);
  168. size_t count = 0;
  169. metric_reader_ptr->Collect([&count](ResourceMetrics &metric_data) {
  170. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  171. if (metric_data.scope_metric_data_.size())
  172. {
  173. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  174. if (metric_data.scope_metric_data_.size())
  175. {
  176. count += metric_data.scope_metric_data_[0].metric_data_.size();
  177. EXPECT_EQ(count, 1);
  178. }
  179. }
  180. return true;
  181. });
  182. observable_counter->RemoveCallback(asyc_generate_measurements_long, nullptr);
  183. }
  184. constexpr static unsigned MAX_THREADS = 25;
  185. constexpr static unsigned MAX_ITERATIONS_MT = 1000;
  186. TEST(MeterTest, StressMultiThread)
  187. {
  188. MetricReader *metric_reader_ptr = nullptr;
  189. auto meter = InitMeter(&metric_reader_ptr, "stress_test_meter");
  190. std::atomic<unsigned> threadCount(0);
  191. std::atomic<size_t> numIterations(MAX_ITERATIONS_MT);
  192. std::atomic<bool> do_collect{false}, do_sync_create{true}, do_async_create{false};
  193. std::vector<nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument>>
  194. observable_instruments;
  195. std::vector<std::thread> meter_operation_threads;
  196. std::atomic<size_t> instrument_id(0);
  197. while (numIterations--)
  198. {
  199. for (size_t i = 0; i < MAX_THREADS; i++)
  200. {
  201. if (threadCount++ < MAX_THREADS)
  202. {
  203. auto t = std::thread([&]() {
  204. std::this_thread::yield();
  205. if (do_sync_create.exchange(false))
  206. {
  207. std::string instrument_name = "test_couter_" + std::to_string(instrument_id);
  208. meter->CreateUInt64Counter(instrument_name, "", "");
  209. do_async_create.store(true);
  210. instrument_id++;
  211. }
  212. if (do_async_create.exchange(false))
  213. {
  214. std::cout << "\n creating async thread " << std::to_string(numIterations);
  215. auto observable_instrument = meter->CreateInt64ObservableUpDownCounter(
  216. "test_gauge_" + std::to_string(instrument_id));
  217. observable_instrument->AddCallback(asyc_generate_measurements_long, nullptr);
  218. observable_instruments.push_back(std::move(observable_instrument));
  219. do_collect.store(true);
  220. instrument_id++;
  221. }
  222. if (do_collect.exchange(false))
  223. {
  224. metric_reader_ptr->Collect([](ResourceMetrics & /* metric_data */) { return true; });
  225. do_sync_create.store(true);
  226. }
  227. });
  228. meter_operation_threads.push_back(std::move(t));
  229. }
  230. }
  231. }
  232. for (auto &t : meter_operation_threads)
  233. {
  234. if (t.joinable())
  235. {
  236. t.join();
  237. }
  238. }
  239. }
  240. TEST(MeterTest, MeterWithDisabledConfig)
  241. {
  242. ScopeConfigurator<MeterConfig> disable_all_scopes =
  243. ScopeConfigurator<MeterConfig>::Builder(MeterConfig::Disabled()).Build();
  244. MetricReader *metric_reader_ptr = nullptr;
  245. std::shared_ptr<metrics::MeterProvider> meter_provider =
  246. GetMeterProviderWithScopeConfigurator(disable_all_scopes, &metric_reader_ptr);
  247. auto meter = meter_provider->GetMeter("foo", "0.1.0", "https://opentelemetry.io/schemas/1.24.0");
  248. // Test all supported instruments from this meter - create instruments
  249. auto double_counter = meter->CreateDoubleCounter("double_counter");
  250. auto double_histogram = meter->CreateDoubleHistogram("double_histogram");
  251. auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter");
  252. auto double_obs_counter = meter->CreateDoubleObservableCounter("double_obs_counter");
  253. auto double_obs_gauge = meter->CreateDoubleObservableGauge("double_obs_gauge");
  254. auto double_obs_up_down_counter =
  255. meter->CreateDoubleObservableUpDownCounter("double_obs_up_down_counter");
  256. auto uint64_counter = meter->CreateUInt64Counter("uint64_counter");
  257. auto uint64_histogram = meter->CreateUInt64Histogram("uint64_histogram");
  258. auto int64_up_down_counter = meter->CreateInt64UpDownCounter("int64_up_down_counter");
  259. auto int64_obs_counter = meter->CreateInt64ObservableCounter("int64_obs_counter");
  260. auto int64_obs_gauge = meter->CreateInt64ObservableGauge("int64_obs_gauge");
  261. auto int64_obs_up_down_counter =
  262. meter->CreateInt64ObservableUpDownCounter("int64_obs_up_down_counter");
  263. // Invoke the created instruments
  264. double_counter->Add(1.0f);
  265. double_histogram->Record(23.2f, {});
  266. double_up_down_counter->Add(-2.4f);
  267. double_obs_counter->AddCallback(asyc_generate_measurements_double, nullptr);
  268. double_obs_gauge->AddCallback(asyc_generate_measurements_double, nullptr);
  269. double_obs_up_down_counter->AddCallback(asyc_generate_measurements_double, nullptr);
  270. uint64_counter->Add(1);
  271. uint64_histogram->Record(23, {});
  272. int64_up_down_counter->Add(-2);
  273. int64_obs_counter->AddCallback(asyc_generate_measurements_long, nullptr);
  274. int64_obs_gauge->AddCallback(asyc_generate_measurements_long, nullptr);
  275. int64_obs_up_down_counter->AddCallback(asyc_generate_measurements_long, nullptr);
  276. // No active instruments are expected - since all scopes are disabled.
  277. metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) {
  278. EXPECT_EQ(metric_data.scope_metric_data_.size(), 0);
  279. return true;
  280. });
  281. }
  282. TEST(MeterTest, MeterWithEnabledConfig)
  283. {
  284. ScopeConfigurator<MeterConfig> enable_all_scopes =
  285. ScopeConfigurator<MeterConfig>::Builder(MeterConfig::Enabled()).Build();
  286. MetricReader *metric_reader_ptr = nullptr;
  287. std::shared_ptr<metrics::MeterProvider> meter_provider =
  288. GetMeterProviderWithScopeConfigurator(enable_all_scopes, &metric_reader_ptr);
  289. auto meter = meter_provider->GetMeter("foo", "0.1.0", "https://opentelemetry.io/schemas/1.24.0");
  290. // Test all supported instruments from this meter - create instruments
  291. auto double_counter = meter->CreateDoubleCounter("double_counter");
  292. auto double_histogram = meter->CreateDoubleHistogram("double_histogram");
  293. auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter");
  294. auto double_obs_counter = meter->CreateDoubleObservableCounter("double_obs_counter");
  295. auto double_obs_gauge = meter->CreateDoubleObservableGauge("double_obs_gauge");
  296. auto double_obs_up_down_counter =
  297. meter->CreateDoubleObservableUpDownCounter("double_obs_up_down_counter");
  298. auto uint64_counter = meter->CreateUInt64Counter("uint64_counter");
  299. auto uint64_histogram = meter->CreateUInt64Histogram("uint64_histogram");
  300. auto int64_up_down_counter = meter->CreateInt64UpDownCounter("int64_up_down_counter");
  301. auto int64_obs_counter = meter->CreateInt64ObservableCounter("int64_obs_counter");
  302. auto int64_obs_gauge = meter->CreateInt64ObservableGauge("int64_obs_gauge");
  303. auto int64_obs_up_down_counter =
  304. meter->CreateInt64ObservableUpDownCounter("int64_obs_up_down_counter");
  305. // Invoke the created instruments
  306. double_counter->Add(1.0f);
  307. double_histogram->Record(23.2f, {});
  308. double_up_down_counter->Add(-2.4f);
  309. double_obs_counter->AddCallback(asyc_generate_measurements_double, nullptr);
  310. double_obs_gauge->AddCallback(asyc_generate_measurements_double, nullptr);
  311. double_obs_up_down_counter->AddCallback(asyc_generate_measurements_double, nullptr);
  312. uint64_counter->Add(1);
  313. uint64_histogram->Record(23, {});
  314. int64_up_down_counter->Add(-2);
  315. int64_obs_counter->AddCallback(asyc_generate_measurements_long, nullptr);
  316. int64_obs_gauge->AddCallback(asyc_generate_measurements_long, nullptr);
  317. int64_obs_up_down_counter->AddCallback(asyc_generate_measurements_long, nullptr);
  318. // Expected active instruments
  319. std::vector<std::pair<std::string, std::string>> active_scope_instrument_pairs;
  320. active_scope_instrument_pairs.emplace_back("foo", "double_counter");
  321. active_scope_instrument_pairs.emplace_back("foo", "double_histogram");
  322. active_scope_instrument_pairs.emplace_back("foo", "double_up_down_counter");
  323. active_scope_instrument_pairs.emplace_back("foo", "double_obs_up_down_counter");
  324. active_scope_instrument_pairs.emplace_back("foo", "double_obs_counter");
  325. active_scope_instrument_pairs.emplace_back("foo", "double_obs_gauge");
  326. active_scope_instrument_pairs.emplace_back("foo", "uint64_counter");
  327. active_scope_instrument_pairs.emplace_back("foo", "uint64_histogram");
  328. active_scope_instrument_pairs.emplace_back("foo", "int64_up_down_counter");
  329. active_scope_instrument_pairs.emplace_back("foo", "int64_obs_up_down_counter");
  330. active_scope_instrument_pairs.emplace_back("foo", "int64_obs_counter");
  331. active_scope_instrument_pairs.emplace_back("foo", "int64_obs_gauge");
  332. metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) {
  333. bool unexpected_instrument_found = false;
  334. std::string curr_scope_name = metric_data.scope_metric_data_.at(0).scope_->GetName();
  335. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  336. EXPECT_EQ(metric_data.scope_metric_data_.at(0).scope_->GetName(), "foo");
  337. EXPECT_EQ(metric_data.scope_metric_data_.at(0).metric_data_.size(), 12);
  338. for (const MetricData &md : metric_data.scope_metric_data_.at(0).metric_data_)
  339. {
  340. auto found_instrument = std::make_pair(curr_scope_name, md.instrument_descriptor.name_);
  341. // confirm if the found instrument is expected
  342. auto it = std::find(active_scope_instrument_pairs.begin(),
  343. active_scope_instrument_pairs.end(), found_instrument);
  344. if (it == active_scope_instrument_pairs.end())
  345. {
  346. // found instrument is not expected
  347. unexpected_instrument_found = true;
  348. break;
  349. }
  350. }
  351. EXPECT_FALSE(unexpected_instrument_found);
  352. return true;
  353. });
  354. }
  355. TEST(MeterTest, MeterWithCustomConfig)
  356. {
  357. // within the same call
  358. auto check_if_version_present = [](const InstrumentationScope &scope_info) {
  359. return !scope_info.GetVersion().empty();
  360. };
  361. // custom scope configurator that only disables meters with name "foo_library" or do not have
  362. // version information
  363. ScopeConfigurator<MeterConfig> custom_scope_configurator =
  364. ScopeConfigurator<MeterConfig>::Builder(MeterConfig::Disabled())
  365. .AddConditionNameEquals("foo_library", MeterConfig::Disabled())
  366. .AddCondition(check_if_version_present, MeterConfig::Enabled())
  367. .Build();
  368. MetricReader *metric_reader_ptr = nullptr;
  369. std::shared_ptr<metrics::MeterProvider> meter_provider =
  370. GetMeterProviderWithScopeConfigurator(custom_scope_configurator, &metric_reader_ptr);
  371. // The meter has version information and name is not "foo_library".
  372. // All instruments from this meter should be active and recording metrics.
  373. auto meter_enabled_expected_bar =
  374. meter_provider->GetMeter("bar_library", "0.1.0", "https://opentelemetry.io/schemas/1.24.0");
  375. // The meter has version information and name is "foo_library".
  376. // All instruments from this meter should be noop.
  377. auto meter_disabled_expected_foo =
  378. meter_provider->GetMeter("foo_library", "0.1.0", "https://opentelemetry.io/schemas/1.24.0");
  379. // This meter has no version information.
  380. // All instruments from this meter should be noop.
  381. auto meter_disabled_expected_baz =
  382. meter_provider->GetMeter("baz_library", "", "https://opentelemetry.io/schemas/1.24.0");
  383. // Create instruments from all meters
  384. auto double_counter_bar = meter_enabled_expected_bar->CreateDoubleCounter("double_counter");
  385. auto double_counter_foo = meter_disabled_expected_foo->CreateDoubleCounter("double_counter");
  386. auto double_counter_baz = meter_disabled_expected_baz->CreateDoubleCounter("double_counter");
  387. // Invoke created instruments at least once
  388. double_counter_bar->Add(1.0f);
  389. double_counter_foo->Add(1.0f);
  390. double_counter_baz->Add(1.0f);
  391. std::vector<std::pair<std::string, std::string>> active_scope_instrument_pairs;
  392. active_scope_instrument_pairs.emplace_back("bar_library", "double_counter");
  393. metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) {
  394. int found_instruments = 0;
  395. bool unexpected_instrument_found = false;
  396. for (const ScopeMetrics &sm : metric_data.scope_metric_data_)
  397. {
  398. std::string curr_scope = sm.scope_->GetName();
  399. for (const MetricData &md : sm.metric_data_)
  400. {
  401. found_instruments++;
  402. auto found_instrument = std::make_pair(curr_scope, md.instrument_descriptor.name_);
  403. // confirm if the found instrument is expected
  404. auto it = std::find(active_scope_instrument_pairs.begin(),
  405. active_scope_instrument_pairs.end(), found_instrument);
  406. if (it == active_scope_instrument_pairs.end())
  407. {
  408. // found instrument is not expected
  409. unexpected_instrument_found = true;
  410. break;
  411. }
  412. }
  413. }
  414. EXPECT_EQ(found_instruments, active_scope_instrument_pairs.size());
  415. EXPECT_FALSE(unexpected_instrument_found);
  416. return true;
  417. });
  418. }
  419. TEST_F(MeterCreateInstrumentTest, IdenticalSyncInstruments)
  420. {
  421. auto counter1 = meter_->CreateDoubleCounter("my_counter", "desc", "unit");
  422. auto counter2 = meter_->CreateDoubleCounter("my_counter", "desc", "unit");
  423. counter1->Add(1.0, {{"key", "value1"}});
  424. counter2->Add(2.5, {{"key", "value2"}});
  425. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  426. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  427. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  428. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 2);
  429. auto &point_data1 =
  430. metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_[0].point_data;
  431. auto &point_data2 =
  432. metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_[1].point_data;
  433. auto sum_point_data1 = nostd::get<sdk::metrics::SumPointData>(point_data1);
  434. auto sum_point_data2 = nostd::get<sdk::metrics::SumPointData>(point_data2);
  435. const double sum =
  436. nostd::get<double>(sum_point_data1.value_) + nostd::get<double>(sum_point_data2.value_);
  437. EXPECT_DOUBLE_EQ(sum, 3.5);
  438. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  439. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  440. return true;
  441. });
  442. }
  443. TEST_F(MeterCreateInstrumentTest, NameCaseConflictSyncInstruments)
  444. {
  445. auto counter1 = meter_->CreateUInt64Counter("My_CountER", "desc", "unit");
  446. auto counter2 = meter_->CreateUInt64Counter("my_counter", "desc", "unit");
  447. counter1->Add(1);
  448. counter2->Add(2);
  449. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  450. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  451. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  452. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  453. auto &point_data =
  454. metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_[0].point_data;
  455. auto sum_point_data = nostd::get<sdk::metrics::SumPointData>(point_data);
  456. const auto sum = nostd::get<int64_t>(sum_point_data.value_);
  457. EXPECT_EQ(sum, 3);
  458. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  459. EXPECT_TRUE(log_handler_->HasNameCaseConflictWarning());
  460. return true;
  461. });
  462. }
  463. TEST_F(MeterCreateInstrumentTest, ViewCorrectedNameCaseConflictSyncInstruments)
  464. {
  465. InstrumentDescriptor descriptor{"My_CountER", "desc", "unit", InstrumentType::kCounter,
  466. InstrumentValueType::kLong};
  467. AddNameCorrectionView(descriptor.name_, descriptor.unit_, descriptor.type_, "my_counter");
  468. auto counter1 =
  469. meter_->CreateUInt64Counter("My_CountER", descriptor.description_, descriptor.unit_);
  470. auto counter2 =
  471. meter_->CreateUInt64Counter("my_counter", descriptor.description_, descriptor.unit_);
  472. counter1->Add(1);
  473. counter2->Add(2);
  474. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  475. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  476. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  477. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  478. auto &point_data =
  479. metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_[0].point_data;
  480. auto sum_point_data = nostd::get<sdk::metrics::SumPointData>(point_data);
  481. const auto sum = nostd::get<int64_t>(sum_point_data.value_);
  482. EXPECT_EQ(sum, 3);
  483. // no warnings expected after correction with the view
  484. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  485. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  486. return true;
  487. });
  488. }
  489. TEST_F(MeterCreateInstrumentTest, DuplicateSyncInstrumentsByKind)
  490. {
  491. auto counter1 = meter_->CreateDoubleCounter("my_counter", "desc", "unit");
  492. auto counter2 = meter_->CreateUInt64Counter("my_counter", "desc", "unit");
  493. counter1->Add(1, {{"key", "value1"}});
  494. counter2->Add(1, {{"key", "value2"}});
  495. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  496. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  497. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 2);
  498. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  499. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[1].point_data_attr_.size(), 1);
  500. EXPECT_TRUE(log_handler_->HasDuplicateInstrumentWarning());
  501. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  502. return true;
  503. });
  504. }
  505. TEST_F(MeterCreateInstrumentTest, DuplicateSyncInstrumentsByUnits)
  506. {
  507. auto counter1 = meter_->CreateDoubleCounter("my_counter", "desc", "unit");
  508. auto counter2 = meter_->CreateDoubleCounter("my_counter", "desc", "another_unit");
  509. counter1->Add(1, {{"key", "value1"}});
  510. counter2->Add(1, {{"key", "value2"}});
  511. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  512. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  513. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 2);
  514. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  515. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[1].point_data_attr_.size(), 1);
  516. EXPECT_TRUE(log_handler_->HasDuplicateInstrumentWarning());
  517. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  518. return true;
  519. });
  520. }
  521. TEST_F(MeterCreateInstrumentTest, DuplicateSyncInstrumentsByDescription)
  522. {
  523. auto counter1 = meter_->CreateDoubleCounter("my_counter", "desc", "unit");
  524. auto counter2 = meter_->CreateDoubleCounter("my_counter", "another_desc", "unit");
  525. counter1->Add(1, {{"key", "value1"}});
  526. counter2->Add(1, {{"key", "value2"}});
  527. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  528. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  529. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 2);
  530. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  531. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[1].point_data_attr_.size(), 1);
  532. EXPECT_TRUE(log_handler_->HasDuplicateInstrumentWarning());
  533. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  534. return true;
  535. });
  536. }
  537. TEST_F(MeterCreateInstrumentTest, ViewCorrectedDuplicateSyncInstrumentsByDescription)
  538. {
  539. InstrumentDescriptor descriptor{"my_counter", "desc", "unit", InstrumentType::kCounter,
  540. InstrumentValueType::kDouble};
  541. AddDescriptionCorrectionView(descriptor.name_, descriptor.unit_, descriptor.type_,
  542. descriptor.description_);
  543. auto counter1 = meter_->CreateDoubleCounter("my_counter", "desc", "unit");
  544. auto counter2 = meter_->CreateDoubleCounter("my_counter", "another_desc", "unit");
  545. counter1->Add(1, {{"key", "value1"}});
  546. counter2->Add(1, {{"key", "value2"}});
  547. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  548. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  549. // only one metric_data object expected after correction with the view
  550. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  551. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 2);
  552. // no warnings expected after correction with the view
  553. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  554. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  555. return true;
  556. });
  557. }
  558. TEST_F(MeterCreateInstrumentTest, IdenticalAsyncInstruments)
  559. {
  560. auto observable_counter1 =
  561. meter_->CreateInt64ObservableCounter("observable_counter", "desc", "unit");
  562. auto observable_counter2 =
  563. meter_->CreateInt64ObservableCounter("observable_counter", "desc", "unit");
  564. auto callback1 = [](opentelemetry::metrics::ObserverResult observer, void * /* state */) {
  565. auto observer_long =
  566. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<int64_t>>>(observer);
  567. observer_long->Observe(12, {{"key", "value1"}});
  568. };
  569. auto callback2 = [](opentelemetry::metrics::ObserverResult observer, void * /* state */) {
  570. auto observer_long =
  571. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<int64_t>>>(observer);
  572. observer_long->Observe(2, {{"key", "value2"}});
  573. };
  574. observable_counter1->AddCallback(callback1, nullptr);
  575. observable_counter2->AddCallback(callback2, nullptr);
  576. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  577. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  578. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  579. auto &point_data_attr = metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_;
  580. EXPECT_EQ(point_data_attr.size(), 2);
  581. auto &point_data1 = point_data_attr[0].point_data;
  582. auto &point_data2 = point_data_attr[1].point_data;
  583. auto sum_point_data1 = nostd::get<sdk::metrics::SumPointData>(point_data1);
  584. auto sum_point_data2 = nostd::get<sdk::metrics::SumPointData>(point_data2);
  585. int64_t sum =
  586. nostd::get<int64_t>(sum_point_data1.value_) + nostd::get<int64_t>(sum_point_data2.value_);
  587. EXPECT_EQ(sum, 14);
  588. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  589. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  590. return true;
  591. });
  592. }
  593. TEST_F(MeterCreateInstrumentTest, NameCaseConflictAsyncInstruments)
  594. {
  595. auto observable_counter1 =
  596. meter_->CreateDoubleObservableCounter("OBServable_CounTER", "desc", "unit");
  597. auto observable_counter2 =
  598. meter_->CreateDoubleObservableCounter("observable_counter", "desc", "unit");
  599. auto callback1 = [](opentelemetry::metrics::ObserverResult observer, void * /* state */) {
  600. auto observer_double =
  601. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<double>>>(observer);
  602. observer_double->Observe(22.22, {{"key", "value1"}});
  603. };
  604. auto callback2 = [](opentelemetry::metrics::ObserverResult observer, void * /* state */) {
  605. auto observer_double =
  606. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<double>>>(observer);
  607. observer_double->Observe(55.55, {{"key", "value2"}});
  608. };
  609. observable_counter1->AddCallback(callback1, nullptr);
  610. observable_counter2->AddCallback(callback2, nullptr);
  611. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  612. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  613. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  614. auto &point_data_attr = metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_;
  615. EXPECT_EQ(point_data_attr.size(), 2);
  616. auto &point_data1 = point_data_attr[0].point_data;
  617. auto &point_data2 = point_data_attr[1].point_data;
  618. auto sum_point_data1 = nostd::get<sdk::metrics::SumPointData>(point_data1);
  619. auto sum_point_data2 = nostd::get<sdk::metrics::SumPointData>(point_data2);
  620. const double sum =
  621. nostd::get<double>(sum_point_data1.value_) + nostd::get<double>(sum_point_data2.value_);
  622. EXPECT_DOUBLE_EQ(sum, 77.77);
  623. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  624. EXPECT_TRUE(log_handler_->HasNameCaseConflictWarning());
  625. return true;
  626. });
  627. }
  628. TEST_F(MeterCreateInstrumentTest, ViewCorrectedNameCaseConflictAsyncInstruments)
  629. {
  630. AddNameCorrectionView("OBServable_CounTER", "unit", InstrumentType::kObservableCounter,
  631. "observable_counter");
  632. auto observable_counter1 =
  633. meter_->CreateDoubleObservableCounter("OBServable_CounTER", "desc", "unit");
  634. auto observable_counter2 =
  635. meter_->CreateDoubleObservableCounter("observable_counter", "desc", "unit");
  636. auto callback1 = [](opentelemetry::metrics::ObserverResult observer, void * /* state */) {
  637. auto observer_double =
  638. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<double>>>(observer);
  639. observer_double->Observe(22.22, {{"key", "value1"}});
  640. };
  641. auto callback2 = [](opentelemetry::metrics::ObserverResult observer, void * /* state */) {
  642. auto observer_double =
  643. nostd::get<nostd::shared_ptr<opentelemetry::metrics::ObserverResultT<double>>>(observer);
  644. observer_double->Observe(55.55, {{"key", "value2"}});
  645. };
  646. observable_counter1->AddCallback(callback1, nullptr);
  647. observable_counter2->AddCallback(callback2, nullptr);
  648. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  649. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  650. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  651. auto &point_data_attr = metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_;
  652. EXPECT_EQ(point_data_attr.size(), 2);
  653. auto &point_data1 = point_data_attr[0].point_data;
  654. auto &point_data2 = point_data_attr[1].point_data;
  655. auto sum_point_data1 = nostd::get<sdk::metrics::SumPointData>(point_data1);
  656. auto sum_point_data2 = nostd::get<sdk::metrics::SumPointData>(point_data2);
  657. const double sum =
  658. nostd::get<double>(sum_point_data1.value_) + nostd::get<double>(sum_point_data2.value_);
  659. EXPECT_DOUBLE_EQ(sum, 77.77);
  660. // no warnings expected after correction with the view
  661. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  662. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  663. return true;
  664. });
  665. }
  666. TEST_F(MeterCreateInstrumentTest, DuplicateAsyncInstrumentsByKind)
  667. {
  668. auto observable_counter1 = meter_->CreateDoubleObservableCounter("observable_counter");
  669. auto observable_counter2 = meter_->CreateDoubleObservableGauge("observable_counter");
  670. observable_counter1->AddCallback(asyc_generate_measurements_double, nullptr);
  671. observable_counter2->AddCallback(asyc_generate_measurements_double, nullptr);
  672. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  673. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  674. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 2);
  675. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  676. EXPECT_TRUE(log_handler_->HasDuplicateInstrumentWarning());
  677. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  678. return true;
  679. });
  680. }
  681. TEST_F(MeterCreateInstrumentTest, DuplicateAsyncInstrumentsByUnits)
  682. {
  683. auto observable_counter1 =
  684. meter_->CreateDoubleObservableCounter("observable_counter", "desc", "unit");
  685. auto observable_counter2 =
  686. meter_->CreateDoubleObservableCounter("observable_counter", "desc", "another_unit");
  687. observable_counter1->AddCallback(asyc_generate_measurements_double, nullptr);
  688. observable_counter2->AddCallback(asyc_generate_measurements_double, nullptr);
  689. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  690. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  691. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 2);
  692. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  693. EXPECT_TRUE(log_handler_->HasDuplicateInstrumentWarning());
  694. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  695. return true;
  696. });
  697. }
  698. TEST_F(MeterCreateInstrumentTest, DuplicateAsyncInstrumentsByDescription)
  699. {
  700. auto observable_counter1 =
  701. meter_->CreateDoubleObservableCounter("observable_counter", "desc", "unit");
  702. auto observable_counter2 =
  703. meter_->CreateDoubleObservableCounter("observable_counter", "another_desc", "unit");
  704. observable_counter1->AddCallback(asyc_generate_measurements_double, nullptr);
  705. observable_counter2->AddCallback(asyc_generate_measurements_double, nullptr);
  706. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  707. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  708. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 2);
  709. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  710. EXPECT_TRUE(log_handler_->HasDuplicateInstrumentWarning());
  711. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  712. return true;
  713. });
  714. }
  715. TEST_F(MeterCreateInstrumentTest, ViewCorrectedDuplicateAsyncInstrumentsByDescription)
  716. {
  717. InstrumentDescriptor descriptor{"observable_counter", "desc", "unit",
  718. InstrumentType::kObservableCounter, InstrumentValueType::kDouble};
  719. AddDescriptionCorrectionView(descriptor.name_, descriptor.unit_, descriptor.type_,
  720. descriptor.description_);
  721. auto observable_counter1 = meter_->CreateDoubleObservableCounter(
  722. descriptor.name_, descriptor.description_, descriptor.unit_);
  723. auto observable_counter2 =
  724. meter_->CreateDoubleObservableCounter(descriptor.name_, "another_desc", descriptor.unit_);
  725. observable_counter1->AddCallback(asyc_generate_measurements_double, nullptr);
  726. observable_counter2->AddCallback(asyc_generate_measurements_double, nullptr);
  727. metric_reader_ptr_->Collect([this](ResourceMetrics &metric_data) {
  728. EXPECT_EQ(metric_data.scope_metric_data_.size(), 1);
  729. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_.size(), 1);
  730. EXPECT_EQ(metric_data.scope_metric_data_[0].metric_data_[0].point_data_attr_.size(), 1);
  731. // no warnings expected after correction with the view
  732. EXPECT_FALSE(log_handler_->HasDuplicateInstrumentWarning());
  733. EXPECT_FALSE(log_handler_->HasNameCaseConflictWarning());
  734. return true;
  735. });
  736. }