exporter_utils_test.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include <gtest/gtest.h>
  4. #include <prometheus/client_metric.h>
  5. #include <prometheus/metric_family.h>
  6. #include <prometheus/metric_type.h>
  7. #include <stddef.h>
  8. #include <limits>
  9. #include <list>
  10. #include <string>
  11. #include <utility>
  12. #include <vector>
  13. #include "opentelemetry/common/timestamp.h"
  14. #include "opentelemetry/exporters/prometheus/exporter_utils.h"
  15. #include "opentelemetry/nostd/unique_ptr.h"
  16. #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
  17. #include "opentelemetry/sdk/metrics/data/metric_data.h"
  18. #include "opentelemetry/sdk/metrics/export/metric_producer.h"
  19. #include "opentelemetry/sdk/metrics/instruments.h"
  20. #include "opentelemetry/sdk/resource/resource.h"
  21. #include "opentelemetry/version.h"
  22. #include "prometheus_test_helper.h"
  23. using opentelemetry::exporter::metrics::PrometheusExporterUtils;
  24. namespace metric_sdk = opentelemetry::sdk::metrics;
  25. namespace prometheus_client = ::prometheus;
  26. OPENTELEMETRY_BEGIN_NAMESPACE
  27. namespace exporter
  28. {
  29. namespace metrics
  30. {
  31. class SanitizeNameTester
  32. {
  33. public:
  34. static std::string sanitize(std::string name)
  35. {
  36. return PrometheusExporterUtils::SanitizeNames(std::move(name));
  37. }
  38. static std::string getPrometheusUnit(const std::string &unit_abbreviation)
  39. {
  40. return PrometheusExporterUtils::GetPrometheusUnit(unit_abbreviation);
  41. }
  42. static std::string getPrometheusPerUnit(const std::string &per_unit_abbreviation)
  43. {
  44. return PrometheusExporterUtils::GetPrometheusPerUnit(per_unit_abbreviation);
  45. }
  46. static std::string removeUnitPortionInBraces(const std::string &unit)
  47. {
  48. return PrometheusExporterUtils::RemoveUnitPortionInBraces(unit);
  49. }
  50. static std::string convertRateExpressedToPrometheusUnit(const std::string &rate_expressed_unit)
  51. {
  52. return PrometheusExporterUtils::ConvertRateExpressedToPrometheusUnit(rate_expressed_unit);
  53. }
  54. static std::string cleanUpString(const std::string &str)
  55. {
  56. return PrometheusExporterUtils::CleanUpString(str);
  57. }
  58. static std::string getEquivalentPrometheusUnit(const std::string &raw_metric_unit_name)
  59. {
  60. return PrometheusExporterUtils::GetEquivalentPrometheusUnit(raw_metric_unit_name);
  61. }
  62. static std::string mapToPrometheusName(const std::string &name,
  63. const std::string &unit,
  64. prometheus_client::MetricType prometheus_type,
  65. bool without_units = false,
  66. bool without_type_suffix = false)
  67. {
  68. return PrometheusExporterUtils::MapToPrometheusName(name, unit, prometheus_type, without_units,
  69. without_type_suffix);
  70. }
  71. };
  72. } // namespace metrics
  73. } // namespace exporter
  74. template <typename T>
  75. void assert_basic(prometheus_client::MetricFamily &metric,
  76. const std::string &expected_name,
  77. const std::string &description,
  78. prometheus_client::MetricType type,
  79. size_t label_num,
  80. std::vector<T> vals)
  81. {
  82. ASSERT_EQ(metric.name, expected_name); // name sanitized
  83. ASSERT_EQ(metric.help, description); // description not changed
  84. ASSERT_EQ(metric.type, type); // type translated
  85. // Prometheus metric data points should not have explicit timestamps
  86. for (const prometheus::ClientMetric &cm : metric.metric)
  87. {
  88. ASSERT_EQ(cm.timestamp_ms, 0);
  89. }
  90. auto metric_data = metric.metric[0];
  91. ASSERT_EQ(metric_data.label.size(), label_num);
  92. switch (type)
  93. {
  94. case prometheus_client::MetricType::Counter: {
  95. ASSERT_DOUBLE_EQ(metric_data.counter.value, vals[0]);
  96. break;
  97. }
  98. case prometheus_client::MetricType::Histogram: {
  99. ASSERT_DOUBLE_EQ(metric_data.histogram.sample_count, vals[0]);
  100. ASSERT_DOUBLE_EQ(metric_data.histogram.sample_sum, vals[1]);
  101. auto buckets = metric_data.histogram.bucket;
  102. ASSERT_EQ(buckets.size(), vals[2]);
  103. break;
  104. }
  105. case prometheus_client::MetricType::Gauge: {
  106. ASSERT_DOUBLE_EQ(metric_data.gauge.value, vals[0]);
  107. break;
  108. }
  109. break;
  110. case prometheus_client::MetricType::Summary:
  111. // Summary and Info type not supported
  112. ASSERT_TRUE(false);
  113. break;
  114. case prometheus::MetricType::Untyped:
  115. default:
  116. break;
  117. }
  118. }
  119. void assert_histogram(prometheus_client::MetricFamily &metric,
  120. const std::list<double> &boundaries,
  121. std::vector<int> correct)
  122. {
  123. int cumulative_count = 0;
  124. auto buckets = metric.metric[0].histogram.bucket;
  125. auto boundary_it = boundaries.cbegin();
  126. for (size_t i = 0; i < buckets.size(); i++)
  127. {
  128. auto bucket = buckets[i];
  129. if (i != buckets.size() - 1)
  130. {
  131. ASSERT_DOUBLE_EQ(*boundary_it++, bucket.upper_bound);
  132. }
  133. else
  134. {
  135. ASSERT_DOUBLE_EQ(std::numeric_limits<double>::infinity(), bucket.upper_bound);
  136. }
  137. cumulative_count += correct[i];
  138. ASSERT_EQ(cumulative_count, bucket.cumulative_count);
  139. }
  140. }
  141. TEST(PrometheusExporterUtils, TranslateToPrometheusEmptyInputReturnsEmptyCollection)
  142. {
  143. metric_sdk::ResourceMetrics metrics_data = {};
  144. auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data);
  145. ASSERT_EQ(translated.size(), 0);
  146. }
  147. TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter)
  148. {
  149. opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create(
  150. {{"service.name", "test_service"},
  151. {"service.namespace", "test_namespace"},
  152. {"service.instance.id", "localhost:8000"},
  153. {"custom_resource_attr", "custom_resource_value"}});
  154. TestDataPoints dp;
  155. metric_sdk::ResourceMetrics metrics_data = dp.CreateSumPointData();
  156. metrics_data.resource_ = &resource;
  157. auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data);
  158. ASSERT_EQ(translated.size(), 2);
  159. auto metric1 = translated[1];
  160. std::vector<int> vals = {10};
  161. assert_basic(metric1, "library_name_unit_total", "description",
  162. prometheus_client::MetricType::Counter, 3, vals);
  163. int checked_label_num = 0;
  164. for (auto &label : translated[0].metric[0].label)
  165. {
  166. if (label.name == "service_namespace")
  167. {
  168. ASSERT_EQ(label.value, "test_namespace");
  169. checked_label_num++;
  170. }
  171. else if (label.name == "service_name")
  172. {
  173. ASSERT_EQ(label.value, "test_service");
  174. checked_label_num++;
  175. }
  176. else if (label.name == "service_instance_id")
  177. {
  178. ASSERT_EQ(label.value, "localhost:8000");
  179. checked_label_num++;
  180. }
  181. else if (label.name == "custom_resource_attr")
  182. {
  183. ASSERT_EQ(label.value, "custom_resource_value");
  184. checked_label_num++;
  185. }
  186. }
  187. ASSERT_EQ(checked_label_num, 4);
  188. }
  189. TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue)
  190. {
  191. opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create(
  192. {{"service.name", "test_service"},
  193. {"service.instance.id", "localhost:8000"},
  194. {"custom_resource_attr", "custom_resource_value"}});
  195. TestDataPoints dp;
  196. metric_sdk::ResourceMetrics metrics_data = dp.CreateLastValuePointData();
  197. metrics_data.resource_ = &resource;
  198. auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data);
  199. ASSERT_EQ(translated.size(), 2);
  200. auto metric1 = translated[1];
  201. std::vector<int> vals = {10};
  202. assert_basic(metric1, "library_name_unit", "description", prometheus_client::MetricType::Gauge, 3,
  203. vals);
  204. int checked_label_num = 0;
  205. for (auto &label : translated[0].metric[0].label)
  206. {
  207. if (label.name == "service_name")
  208. {
  209. ASSERT_EQ(label.value, "test_service");
  210. checked_label_num++;
  211. }
  212. else if (label.name == "service_instance_id")
  213. {
  214. ASSERT_EQ(label.value, "localhost:8000");
  215. checked_label_num++;
  216. }
  217. else if (label.name == "custom_resource_attr")
  218. {
  219. ASSERT_EQ(label.value, "custom_resource_value");
  220. checked_label_num++;
  221. }
  222. }
  223. ASSERT_EQ(checked_label_num, 3);
  224. }
  225. TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal)
  226. {
  227. opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create(
  228. {{"service.instance.id", "localhost:8001"},
  229. {"custom_resource_attr", "custom_resource_value"}});
  230. TestDataPoints dp;
  231. metric_sdk::ResourceMetrics metrics_data = dp.CreateHistogramPointData();
  232. metrics_data.resource_ = &resource;
  233. auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data);
  234. ASSERT_EQ(translated.size(), 2);
  235. auto metric = translated[1];
  236. std::vector<double> vals = {3, 900.5, 4};
  237. assert_basic(metric, "library_name_unit", "description", prometheus_client::MetricType::Histogram,
  238. 3, vals);
  239. assert_histogram(metric, std::list<double>{10.1, 20.2, 30.2}, {200, 300, 400, 500});
  240. int checked_label_num = 0;
  241. for (auto &label : translated[0].metric[0].label)
  242. {
  243. if (label.name == "service_name")
  244. {
  245. // default service name is "unknown_service"
  246. ASSERT_EQ(label.value, "unknown_service");
  247. checked_label_num++;
  248. }
  249. else if (label.name == "service_instance_id")
  250. {
  251. ASSERT_EQ(label.value, "localhost:8001");
  252. checked_label_num++;
  253. }
  254. else if (label.name == "custom_resource_attr")
  255. {
  256. ASSERT_EQ(label.value, "custom_resource_value");
  257. checked_label_num++;
  258. }
  259. }
  260. ASSERT_EQ(checked_label_num, 3);
  261. }
  262. class SanitizeTest : public ::testing::Test
  263. {
  264. Resource resource_ = Resource::Create({});
  265. nostd::unique_ptr<InstrumentationScope> instrumentation_scope_ =
  266. InstrumentationScope::Create("library_name", "1.2.0");
  267. protected:
  268. void CheckSanitizeLabel(const std::string &original, const std::string &sanitized)
  269. {
  270. metric_sdk::InstrumentDescriptor instrument_descriptor{
  271. "name", "description", "unit", metric_sdk::InstrumentType::kCounter,
  272. metric_sdk::InstrumentValueType::kDouble};
  273. auto result = PrometheusExporterUtils::TranslateToPrometheus(
  274. {&resource_,
  275. std::vector<metric_sdk::ScopeMetrics>{
  276. {instrumentation_scope_.get(),
  277. std::vector<metric_sdk::MetricData>{
  278. {instrument_descriptor, {}, {}, {}, {{{{original, "value"}}, {}}}}}}}},
  279. false);
  280. EXPECT_EQ(result.begin()->metric.begin()->label.begin()->name, sanitized);
  281. }
  282. };
  283. TEST_F(SanitizeTest, Label)
  284. {
  285. CheckSanitizeLabel("name", "name");
  286. CheckSanitizeLabel("name?", "name_");
  287. CheckSanitizeLabel("name???", "name_");
  288. CheckSanitizeLabel("name?__", "name_");
  289. CheckSanitizeLabel("name?__name", "name_name");
  290. CheckSanitizeLabel("name?__name:", "name_name_");
  291. }
  292. TEST_F(SanitizeTest, Name) {}
  293. class AttributeCollisionTest : public ::testing::Test
  294. {
  295. Resource resource_ = Resource::Create(ResourceAttributes{});
  296. nostd::unique_ptr<InstrumentationScope> instrumentation_scope_ =
  297. InstrumentationScope::Create("library_name", "1.2.0");
  298. metric_sdk::InstrumentDescriptor instrument_descriptor_{"library_name", "description", "unit",
  299. metric_sdk::InstrumentType::kCounter,
  300. metric_sdk::InstrumentValueType::kDouble};
  301. protected:
  302. void CheckTranslation(const metric_sdk::PointAttributes &attrs,
  303. const std::vector<prometheus::ClientMetric::Label> &expected)
  304. {
  305. std::vector<prometheus::MetricFamily> result = PrometheusExporterUtils::TranslateToPrometheus(
  306. {&resource_,
  307. std::vector<metric_sdk::ScopeMetrics>{
  308. {instrumentation_scope_.get(),
  309. std::vector<metric_sdk::MetricData>{
  310. {instrument_descriptor_, {}, {}, {}, {{attrs, {}}}}}}}},
  311. false);
  312. for (auto &expected_kv : expected)
  313. {
  314. bool found = false;
  315. for (auto &found_kv : result.begin()->metric.begin()->label)
  316. {
  317. if (found_kv.name == expected_kv.name)
  318. {
  319. EXPECT_EQ(found_kv.value, expected_kv.value);
  320. found = true;
  321. }
  322. }
  323. EXPECT_TRUE(found);
  324. }
  325. }
  326. };
  327. TEST_F(AttributeCollisionTest, SeparatesDistinctKeys)
  328. {
  329. CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}}, {{"foo_a", "value1"},
  330. {"foo_b", "value2"},
  331. {"otel_scope_name", "library_name"},
  332. {"otel_scope_version", "1.2.0"}});
  333. }
  334. TEST(PrometheusExporterUtils, PrometheusUnit)
  335. {
  336. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("d"), "days");
  337. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("h"), "hours");
  338. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("min"), "minutes");
  339. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("s"), "seconds");
  340. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("ms"), "milliseconds");
  341. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("us"), "microseconds");
  342. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("ns"), "nanoseconds");
  343. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("By"), "bytes");
  344. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("KiBy"), "kibibytes");
  345. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("MiBy"), "mebibytes");
  346. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("GiBy"), "gibibytes");
  347. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("TiBy"), "tibibytes");
  348. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("KBy"), "kilobytes");
  349. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("MBy"), "megabytes");
  350. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("GBy"), "gigabytes");
  351. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("TBy"), "terabytes");
  352. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("By"), "bytes");
  353. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("KBy"), "kilobytes");
  354. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("MBy"), "megabytes");
  355. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("GBy"), "gigabytes");
  356. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("TBy"), "terabytes");
  357. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("m"), "meters");
  358. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("V"), "volts");
  359. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("A"), "amperes");
  360. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("J"), "joules");
  361. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("W"), "watts");
  362. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("g"), "grams");
  363. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("Cel"), "celsius");
  364. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("Hz"), "hertz");
  365. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("1"), "");
  366. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("%"), "percent");
  367. }
  368. TEST(PrometheusExporterUtils, PrometheusPerUnit)
  369. {
  370. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("s"), "second");
  371. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("m"), "minute");
  372. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("h"), "hour");
  373. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("d"), "day");
  374. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("w"), "week");
  375. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("mo"), "month");
  376. ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("y"), "year");
  377. }
  378. TEST(PrometheusExporterUtils, RemoveUnitPortionInBraces)
  379. {
  380. ASSERT_EQ(exporter::metrics::SanitizeNameTester::removeUnitPortionInBraces("{unit}"), "");
  381. ASSERT_EQ(exporter::metrics::SanitizeNameTester::removeUnitPortionInBraces("unit{unit}"), "unit");
  382. ASSERT_EQ(exporter::metrics::SanitizeNameTester::removeUnitPortionInBraces("unit_{unit}"),
  383. "unit_");
  384. }
  385. TEST(PrometheusExporterUtils, ConvertRateExpressedToPrometheusUnit)
  386. {
  387. ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/d"),
  388. "unit_per_day");
  389. ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/s"),
  390. "unit_per_second");
  391. ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/"),
  392. "unit/");
  393. ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit"),
  394. "unit");
  395. ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/m"),
  396. "unit_per_minute");
  397. ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("/m"),
  398. "_per_minute");
  399. }
  400. TEST(PromentheusExporterUtils, PrometheusNameMapping)
  401. {
  402. // General test cases on unit expansions and name sanitization
  403. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  404. "sample_metric___name", "g", prometheus::MetricType::Counter),
  405. "sample_metric_name_grams_total");
  406. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  407. "sample_metric_name", "s", prometheus::MetricType::Counter),
  408. "sample_metric_name_seconds_total");
  409. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  410. "sample_metric_name", "s", prometheus::MetricType::Gauge),
  411. "sample_metric_name_seconds");
  412. // Test without_units & without_type_suffix with Counters and unit = 1
  413. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  414. "sample_metric_name", "1", prometheus::MetricType::Counter),
  415. "sample_metric_name_total");
  416. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  417. "sample_metric_name", "1", prometheus::MetricType::Counter, true, false),
  418. "sample_metric_name_total");
  419. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  420. "sample_metric_name", "1", prometheus::MetricType::Counter, false, true),
  421. "sample_metric_name");
  422. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  423. "sample_metric_name", "1", prometheus::MetricType::Counter, true, true),
  424. "sample_metric_name");
  425. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  426. "sample_metric_name", "1", prometheus::MetricType::Counter, true, true),
  427. "sample_metric_name");
  428. // Test without_units & without_type_suffix with Counters and non-special units
  429. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  430. "sample_metric_name", "%", prometheus::MetricType::Counter),
  431. "sample_metric_name_percent_total");
  432. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  433. "sample_metric_name", "m", prometheus::MetricType::Counter, true, false),
  434. "sample_metric_name_total");
  435. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  436. "sample_metric_name", "By", prometheus::MetricType::Counter, false, true),
  437. "sample_metric_name_bytes");
  438. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  439. "sample_metric_name", "s", prometheus::MetricType::Counter, true, true),
  440. "sample_metric_name");
  441. // Special case Gauges & ratio
  442. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  443. "sample_metric_name", "1", prometheus::MetricType::Gauge),
  444. "sample_metric_name_ratio");
  445. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  446. "sample_metric_name", "1", prometheus::MetricType::Gauge, false, true),
  447. "sample_metric_name_ratio");
  448. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  449. "sample_metric_name", "1", prometheus::MetricType::Gauge, true, false),
  450. "sample_metric_name");
  451. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  452. "sample_metric_name", "1", prometheus::MetricType::Gauge, true, true),
  453. "sample_metric_name");
  454. // Test without_type_suffix affects only counters
  455. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  456. "sample_metric_name", "Hz", prometheus::MetricType::Counter),
  457. "sample_metric_name_hertz_total");
  458. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  459. "sample_metric_name", "Hz", prometheus::MetricType::Counter, false, true),
  460. "sample_metric_name_hertz");
  461. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  462. "sample_metric_name", "Hz", prometheus::MetricType::Gauge),
  463. "sample_metric_name_hertz");
  464. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  465. "sample_metric_name", "Hz", prometheus::MetricType::Gauge, false, true),
  466. "sample_metric_name_hertz");
  467. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  468. "sample_metric_name", "Hz", prometheus::MetricType::Histogram),
  469. "sample_metric_name_hertz");
  470. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  471. "sample_metric_name", "Hz", prometheus::MetricType::Histogram, false, true),
  472. "sample_metric_name_hertz");
  473. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  474. "sample_metric_name", "Hz", prometheus::MetricType::Summary),
  475. "sample_metric_name_hertz");
  476. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  477. "sample_metric_name", "Hz", prometheus::MetricType::Summary, false, true),
  478. "sample_metric_name_hertz");
  479. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  480. "sample_metric_name", "Hz", prometheus::MetricType::Info),
  481. "sample_metric_name_hertz");
  482. ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
  483. "sample_metric_name", "Hz", prometheus::MetricType::Info, false, true),
  484. "sample_metric_name_hertz");
  485. }
  486. TEST_F(AttributeCollisionTest, JoinsCollidingKeys)
  487. {
  488. CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, {{"foo_a", "value1;value2"},
  489. {"otel_scope_name", "library_name"},
  490. {"otel_scope_version", "1.2.0"}});
  491. }
  492. TEST_F(AttributeCollisionTest, DropsInvertedKeys)
  493. {
  494. CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}, {"foo__a", "value3"}},
  495. {{"foo_a", "value1"},
  496. {"foo_b", "value2"},
  497. {"otel_scope_name", "library_name"},
  498. {"otel_scope_version", "1.2.0"}});
  499. }
  500. OPENTELEMETRY_END_NAMESPACE