From ed46cdd2848ab085a5da4f994af737f852b8e18a Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Fri, 1 Sep 2023 17:39:55 +0000 Subject: [PATCH] add _total suffix to prometheus counters --- CHANGELOG.md | 3 ++ .../exporters/prometheus/exporter_utils.h | 2 + exporters/prometheus/src/exporter_utils.cc | 44 ++++++++++++++----- .../prometheus/test/exporter_utils_test.cc | 16 +++---- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c4ce6f45f..71ac83b1a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ Increment the: ## [Unreleased] +* [EXPORTER] Add _total suffixes to Prometheus counters + [#2288](https://github.com/open-telemetry/opentelemetry-cpp/pull/2288) + ## [1.11.0] 2023-08-21 * [BUILD] Fix more cases for symbol name for 32-bit win32 DLL build diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index ce7f0a1191..5d9d2e0fe9 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -44,6 +44,8 @@ class PrometheusExporterUtils static opentelemetry::sdk::metrics::AggregationType getAggregationType( const opentelemetry::sdk::metrics::PointType &point_type); + static inline bool endsWith(std::string const &value, std::string const &ending); + /** * Translate the OTel metric type to Prometheus metric type */ diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 966d665df6..499e0426cd 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -38,24 +38,37 @@ std::vector PrometheusExporterUtils::TranslateT { for (const auto &metric_data : instrumentation_info.metric_data_) { - auto origin_name = metric_data.instrument_descriptor.name_; - auto unit = metric_data.instrument_descriptor.unit_; - auto sanitized = SanitizeNames(origin_name); + if (metric_data.point_data_attr_.empty()) + { + continue; + } prometheus_client::MetricFamily metric_family; + auto front = metric_data.point_data_attr_.front(); + auto kind = getAggregationType(front.point_data); + bool is_monotonic = true; + if (kind == sdk::metrics::AggregationType::kSum) + { + is_monotonic = nostd::get(front.point_data).is_monotonic_; + } + auto type = TranslateType(kind, is_monotonic); + metric_family.type = type; + auto origin_name = metric_data.instrument_descriptor.name_; + auto unit = metric_data.instrument_descriptor.unit_; + auto sanitized = SanitizeNames(origin_name); + if (type == prometheus_client::MetricType::Counter && endsWith(sanitized, "_total")) + { + // trim _total from counters, since it will be appended after the unit. + sanitized = sanitized.substr(0, sanitized.length() - sizeof("_total")); + } metric_family.name = sanitized + "_" + unit; + if (type == prometheus_client::MetricType::Counter) + { + metric_family.name += "_total"; + } metric_family.help = metric_data.instrument_descriptor.description_; auto time = metric_data.end_ts.time_since_epoch(); for (const auto &point_data_attr : metric_data.point_data_attr_) { - auto kind = getAggregationType(point_data_attr.point_data); - bool is_monotonic = true; - if (kind == sdk::metrics::AggregationType::kSum) - { - is_monotonic = - nostd::get(point_data_attr.point_data).is_monotonic_; - } - const prometheus_client::MetricType type = TranslateType(kind, is_monotonic); - metric_family.type = type; if (type == prometheus_client::MetricType::Histogram) // Histogram { auto histogram_point_data = @@ -121,6 +134,13 @@ std::vector PrometheusExporterUtils::TranslateT return output; } +inline bool PrometheusExporterUtils::endsWith(std::string const &value, std::string const &ending) +{ + if (ending.size() > value.size()) + return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + /** * Sanitize the given metric name or label according to Prometheus rule. * diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index 2eac7a6d8b..f3ac5d52de 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -38,9 +38,9 @@ void assert_basic(prometheus_client::MetricFamily &metric, int label_num, std::vector vals) { - ASSERT_EQ(metric.name, sanitized_name + "_unit"); // name sanitized - ASSERT_EQ(metric.help, description); // description not changed - ASSERT_EQ(metric.type, type); // type translated + ASSERT_EQ(metric.name, sanitized_name); // name sanitized + ASSERT_EQ(metric.help, description); // description not changed + ASSERT_EQ(metric.type, type); // type translated auto metric_data = metric.metric[0]; ASSERT_EQ(metric_data.label.size(), label_num); @@ -114,8 +114,8 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) auto metric1 = translated[0]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 1, - vals); + assert_basic(metric1, "library_name_unit_total", "description", + prometheus_client::MetricType::Counter, 1, vals); } TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) @@ -127,7 +127,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) auto metric1 = translated[0]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 1, + assert_basic(metric1, "library_name_unit", "description", prometheus_client::MetricType::Gauge, 1, vals); } @@ -140,8 +140,8 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) auto metric = translated[0]; std::vector vals = {3, 900.5, 4}; - assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, 1, - vals); + assert_basic(metric, "library_name_unit", "description", prometheus_client::MetricType::Histogram, + 1, vals); assert_histogram(metric, std::list{10.1, 20.2, 30.2}, {200, 300, 400, 500}); }