From 5430f52a6914666472130ccd1b06854efc42f25c Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Fri, 1 Sep 2023 20:02:56 +0000 Subject: [PATCH 1/3] Add otel_scope_name and otel_scope_version labels to the prometheus exporter --- CHANGELOG.md | 3 + .../exporters/prometheus/exporter_utils.h | 5 +- exporters/prometheus/src/exporter_utils.cc | 61 +++++++++++++------ .../prometheus/test/exporter_utils_test.cc | 6 +- .../sdk/metrics/export/metric_producer.h | 2 +- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f2ce9e4d0..57307f67fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,9 @@ Increment the: [#2224](https://github.com/open-telemetry/opentelemetry-cpp/pull/2224) * [REMOVAL] Drop C++11 support [#2342](https://github.com/open-telemetry/opentelemetry-cpp/pull/2342) +* [EXPORTER] Add otel_scope_name and otel_scope_version labels to the prometheus + exporter. + [#2293](https://github.com/open-telemetry/opentelemetry-cpp/pull/2293) Important changes: diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index 07d2c396c6..21b83d675f 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -48,6 +48,7 @@ class PrometheusExporterUtils template static void SetData(std::vector values, const opentelemetry::sdk::metrics::PointAttributes &labels, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, ::prometheus::MetricType type, ::prometheus::MetricFamily *metric_family); @@ -60,13 +61,15 @@ class PrometheusExporterUtils const std::vector &boundaries, const std::vector &counts, const opentelemetry::sdk::metrics::PointAttributes &labels, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, ::prometheus::MetricFamily *metric_family); /** * Set time and labels to metric data */ static void SetMetricBasic(::prometheus::ClientMetric &metric, - const opentelemetry::sdk::metrics::PointAttributes &labels); + const opentelemetry::sdk::metrics::PointAttributes &labels, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope); /** * Convert attribute value to string diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index a840b087ff..eed158c1af 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -22,6 +22,10 @@ namespace metrics { namespace { + +static constexpr const char *kScopeNameKey = "otel_scope_name"; +static constexpr const char *kScopeVersionKey = "otel_scope_version"; + /** * Sanitize the given metric name by replacing invalid characters with _, * ensuring that multiple consecutive _ characters are collapsed to a single _. @@ -150,7 +154,7 @@ std::vector PrometheusExporterUtils::TranslateT sum = nostd::get(histogram_point_data.sum_); } SetData(std::vector{sum, (double)histogram_point_data.count_}, boundaries, counts, - point_data_attr.attributes, &metric_family); + point_data_attr.attributes, instrumentation_info.scope_, &metric_family); } else if (type == prometheus_client::MetricType::Gauge) { @@ -160,14 +164,14 @@ std::vector PrometheusExporterUtils::TranslateT auto last_value_point_data = nostd::get(point_data_attr.point_data); std::vector values{last_value_point_data.value_}; - SetData(values, point_data_attr.attributes, type, &metric_family); + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, &metric_family); } else if (nostd::holds_alternative(point_data_attr.point_data)) { auto sum_point_data = nostd::get(point_data_attr.point_data); std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, type, &metric_family); + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, &metric_family); } else { @@ -183,7 +187,7 @@ std::vector PrometheusExporterUtils::TranslateT auto sum_point_data = nostd::get(point_data_attr.point_data); std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, type, &metric_family); + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, &metric_family); } else { @@ -257,14 +261,16 @@ prometheus_client::MetricType PrometheusExporterUtils::TranslateType( * sum => Prometheus Counter */ template -void PrometheusExporterUtils::SetData(std::vector values, - const metric_sdk::PointAttributes &labels, - prometheus_client::MetricType type, - prometheus_client::MetricFamily *metric_family) +void PrometheusExporterUtils::SetData( + std::vector values, + const metric_sdk::PointAttributes &labels, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, + prometheus_client::MetricType type, + prometheus_client::MetricFamily *metric_family) { metric_family->metric.emplace_back(); prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, labels); + SetMetricBasic(metric, labels, scope); SetValue(values, type, &metric); } @@ -273,15 +279,17 @@ void PrometheusExporterUtils::SetData(std::vector values, * Histogram => Prometheus Histogram */ template -void PrometheusExporterUtils::SetData(std::vector values, - const std::vector &boundaries, - const std::vector &counts, - const metric_sdk::PointAttributes &labels, - prometheus_client::MetricFamily *metric_family) +void PrometheusExporterUtils::SetData( + std::vector values, + const std::vector &boundaries, + const std::vector &counts, + const metric_sdk::PointAttributes &labels, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, + prometheus_client::MetricFamily *metric_family) { metric_family->metric.emplace_back(); prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, labels); + SetMetricBasic(metric, labels, scope); SetValue(values, boundaries, counts, &metric); } @@ -289,7 +297,8 @@ void PrometheusExporterUtils::SetData(std::vector values, * Set labels to metric data */ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &metric, - const metric_sdk::PointAttributes &labels) + const metric_sdk::PointAttributes &labels, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope) { if (labels.empty()) { @@ -300,7 +309,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me // Note that attribute keys are sorted, but sanitized keys can be out-of-order. // We could sort the sanitized keys again, but this seems too expensive to do // in this hot code path. Instead, we ignore out-of-order keys and emit a warning. - metric.label.reserve(labels.size()); + metric.label.reserve(labels.size() + 2); std::string previous_key; for (auto const &label : labels) { @@ -324,6 +333,24 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me << "'. Ignoring this label."); } } + if (!scope) + { + return; + } + auto scope_name = scope->GetName(); + if (!scope_name.empty()) + { + metric.label.emplace_back(); + metric.label.back().name = kScopeNameKey; + metric.label.back().value = std::move(scope_name); + } + auto scope_version = scope->GetVersion(); + if (!scope_version.empty()) + { + metric.label.emplace_back(); + metric.label.back().name = kScopeVersionKey; + metric.label.back().value = std::move(scope_version); + } } std::string PrometheusExporterUtils::AttributeValueToString( diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index c2a6273397..0b5f062bcd 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -105,7 +105,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) auto metric1 = translated[0]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 1, + assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 3, vals); } @@ -119,7 +119,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", "description", prometheus_client::MetricType::Gauge, 3, vals); } @@ -133,7 +133,7 @@ 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, + assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, 3, vals); assert_histogram(metric, std::list{10.1, 20.2, 30.2}, {200, 300, 400, 500}); } diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index 2a0c87fcaa..17d8bc0561 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -31,7 +31,7 @@ namespace metrics */ struct ScopeMetrics { - const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_; + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_ = nullptr; std::vector metric_data_; }; From d5f7309edb170d06b02802591fa2c03feefb23a4 Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Mon, 25 Sep 2023 23:59:49 +0000 Subject: [PATCH 2/3] try fixing --- exporters/prometheus/test/exporter_utils_test.cc | 6 +++--- .../opentelemetry/sdk/metrics/export/metric_producer.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index 0b5f062bcd..f24e5e3336 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -212,19 +212,19 @@ class AttributeCollisionTest : public ::testing::Test TEST_F(AttributeCollisionTest, SeparatesDistinctKeys) { CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}}, - {{"foo_a", "value1"}, {"foo_b", "value2"}}); + {{"foo_a", "value1"}, {"foo_b", "value2"}, {"otel_scope_name", "library_name"}, {"otel_scope_version", "1.2.0"}}); } TEST_F(AttributeCollisionTest, JoinsCollidingKeys) { CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, // - {{"foo_a", "value1;value2"}}); + {{"foo_a", "value1;value2"}, {"otel_scope_name", "library_name"}, {"otel_scope_version", "1.2.0"}}); } TEST_F(AttributeCollisionTest, DropsInvertedKeys) { CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}, {"foo__a", "value3"}}, - {{"foo_a", "value1"}, {"foo_b", "value2"}}); + {{"foo_a", "value1"}, {"foo_b", "value2"}, {"otel_scope_name", "library_name"}, {"otel_scope_version", "1.2.0"}}); } OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index 17d8bc0561..2a0c87fcaa 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -31,7 +31,7 @@ namespace metrics */ struct ScopeMetrics { - const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_ = nullptr; + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_; std::vector metric_data_; }; From afa90093618426fab856c6af7c0c6681dfcbde12 Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Tue, 26 Sep 2023 00:51:34 +0000 Subject: [PATCH 3/3] format --- .../exporters/prometheus/exporter_utils.h | 3 ++- exporters/prometheus/src/exporter_utils.cc | 12 ++++++++---- exporters/prometheus/test/exporter_utils_test.cc | 16 +++++++++++----- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index 21b83d675f..76c62d58ba 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -67,7 +67,8 @@ class PrometheusExporterUtils /** * Set time and labels to metric data */ - static void SetMetricBasic(::prometheus::ClientMetric &metric, + static void SetMetricBasic( + ::prometheus::ClientMetric &metric, const opentelemetry::sdk::metrics::PointAttributes &labels, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope); diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index eed158c1af..c0f034ffe5 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -164,14 +164,16 @@ std::vector PrometheusExporterUtils::TranslateT auto last_value_point_data = nostd::get(point_data_attr.point_data); std::vector values{last_value_point_data.value_}; - SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, &metric_family); + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, + &metric_family); } else if (nostd::holds_alternative(point_data_attr.point_data)) { auto sum_point_data = nostd::get(point_data_attr.point_data); std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, &metric_family); + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, + &metric_family); } else { @@ -187,7 +189,8 @@ std::vector PrometheusExporterUtils::TranslateT auto sum_point_data = nostd::get(point_data_attr.point_data); std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, &metric_family); + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, + &metric_family); } else { @@ -296,7 +299,8 @@ void PrometheusExporterUtils::SetData( /** * Set labels to metric data */ -void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &metric, +void PrometheusExporterUtils::SetMetricBasic( + prometheus_client::ClientMetric &metric, const metric_sdk::PointAttributes &labels, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope) { diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index f24e5e3336..3c945c6735 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -211,20 +211,26 @@ class AttributeCollisionTest : public ::testing::Test TEST_F(AttributeCollisionTest, SeparatesDistinctKeys) { - CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}}, - {{"foo_a", "value1"}, {"foo_b", "value2"}, {"otel_scope_name", "library_name"}, {"otel_scope_version", "1.2.0"}}); + CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}}, {{"foo_a", "value1"}, + {"foo_b", "value2"}, + {"otel_scope_name", "library_name"}, + {"otel_scope_version", "1.2.0"}}); } TEST_F(AttributeCollisionTest, JoinsCollidingKeys) { - CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, // - {{"foo_a", "value1;value2"}, {"otel_scope_name", "library_name"}, {"otel_scope_version", "1.2.0"}}); + CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, {{"foo_a", "value1;value2"}, + {"otel_scope_name", "library_name"}, + {"otel_scope_version", "1.2.0"}}); } TEST_F(AttributeCollisionTest, DropsInvertedKeys) { CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}, {"foo__a", "value3"}}, - {{"foo_a", "value1"}, {"foo_b", "value2"}, {"otel_scope_name", "library_name"}, {"otel_scope_version", "1.2.0"}}); + {{"foo_a", "value1"}, + {"foo_b", "value2"}, + {"otel_scope_name", "library_name"}, + {"otel_scope_version", "1.2.0"}}); } OPENTELEMETRY_END_NAMESPACE