From dfefb44dcd6f5cc4052c247ccedceaf3b8ca0a33 Mon Sep 17 00:00:00 2001 From: owent Date: Sat, 9 Sep 2023 00:25:50 +0800 Subject: [PATCH 01/25] Export resource for prometheus --- .../exporters/prometheus/exporter_utils.h | 27 +++- exporters/prometheus/src/exporter_utils.cc | 122 +++++++++++++++--- .../prometheus/test/exporter_utils_test.cc | 65 +++++++++- 3 files changed, 191 insertions(+), 23 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index ce7f0a1191..c6eea5265d 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -41,6 +41,24 @@ class PrometheusExporterUtils */ static std::string SanitizeNames(std::string name); + /** + * Some attributes should be ignored when converting resource attributes to + * prometheus labels. + * + * @param name resource attribnuet name + * @return true if the attribute should be ignored, false otherwise. + */ + static bool ShouldIgnoreResourceAttribute(const std::string &name); + + /** + * Some attributes should be renamed when converting resource attributes to + * prometheus labels. + * + * @param name resource attribnuet name + * @return const std::string& + */ + static const std::string &GetPrometheusAttributeName(const std::string &name); + static opentelemetry::sdk::metrics::AggregationType getAggregationType( const opentelemetry::sdk::metrics::PointType &point_type); @@ -59,7 +77,8 @@ class PrometheusExporterUtils const opentelemetry::sdk::metrics::PointAttributes &labels, ::prometheus::MetricType type, std::chrono::nanoseconds time, - ::prometheus::MetricFamily *metric_family); + ::prometheus::MetricFamily *metric_family, + const opentelemetry::sdk::resource::Resource *resource); /** * Set metric data for: @@ -71,14 +90,16 @@ class PrometheusExporterUtils const std::vector &counts, const opentelemetry::sdk::metrics::PointAttributes &labels, std::chrono::nanoseconds time, - ::prometheus::MetricFamily *metric_family); + ::prometheus::MetricFamily *metric_family, + const opentelemetry::sdk::resource::Resource *resource); /** * Set time and labels to metric data */ static void SetMetricBasic(::prometheus::ClientMetric &metric, std::chrono::nanoseconds time, - const opentelemetry::sdk::metrics::PointAttributes &labels); + const opentelemetry::sdk::metrics::PointAttributes &labels, + const opentelemetry::sdk::resource::Resource *resource); /** * Convert attribute value to string diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 966d665df6..fe61250bec 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -2,13 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 #include +#include +#include +#include #include #include +#include "opentelemetry/sdk/resource/resource.h" #include "prometheus/metric_family.h" #include #include "opentelemetry/exporters/prometheus/exporter_utils.h" #include "opentelemetry/sdk/metrics/export/metric_producer.h" +#include "opentelemetry/sdk/resource/semantic_conventions.h" +#include "opentelemetry/trace/semantic_conventions.h" #include "opentelemetry/sdk/common/global_log_handler.h" @@ -20,6 +26,7 @@ namespace exporter { namespace metrics { + /** * Helper function to convert OpenTelemetry metrics data collection * to Prometheus metrics data collection @@ -72,7 +79,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, time, &metric_family); + point_data_attr.attributes, time, &metric_family, data.resource_); } else if (type == prometheus_client::MetricType::Gauge) { @@ -82,14 +89,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, time, &metric_family); + SetData(values, point_data_attr.attributes, type, time, &metric_family, data.resource_); } 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, time, &metric_family); + SetData(values, point_data_attr.attributes, type, time, &metric_family, data.resource_); } else { @@ -105,7 +112,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, time, &metric_family); + SetData(values, point_data_attr.attributes, type, time, &metric_family, data.resource_); } else { @@ -167,6 +174,30 @@ std::string PrometheusExporterUtils::SanitizeNames(std::string name) return name; } +bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &name) +{ + static std::unordered_set ignores{ + opentelemetry::sdk::resource::SemanticConventions::kServiceName, + opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace, + opentelemetry::trace::SemanticConventions::kServerAddress, + opentelemetry::trace::SemanticConventions::kServerPort, + opentelemetry::trace::SemanticConventions::kUrlScheme}; + return ignores.end() == ignores.find(name); +} + +const std::string &PrometheusExporterUtils::GetPrometheusAttributeName(const std::string &name) +{ + static std::unordered_map name_mappings{ + {opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, "instance"}}; + std::unordered_map::const_iterator it = name_mappings.find(name); + if (it == name_mappings.end()) + { + return name; + } + + return it->second; +} + metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType( const metric_sdk::PointType &point_type) { @@ -229,11 +260,12 @@ void PrometheusExporterUtils::SetData(std::vector values, const metric_sdk::PointAttributes &labels, prometheus_client::MetricType type, std::chrono::nanoseconds time, - prometheus_client::MetricFamily *metric_family) + prometheus_client::MetricFamily *metric_family, + const opentelemetry::sdk::resource::Resource *resource) { metric_family->metric.emplace_back(); prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, time, labels); + SetMetricBasic(metric, time, labels, resource); SetValue(values, type, &metric); } @@ -247,11 +279,12 @@ void PrometheusExporterUtils::SetData(std::vector values, const std::vector &counts, const metric_sdk::PointAttributes &labels, std::chrono::nanoseconds time, - prometheus_client::MetricFamily *metric_family) + prometheus_client::MetricFamily *metric_family, + const opentelemetry::sdk::resource::Resource *resource) { metric_family->metric.emplace_back(); prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, time, labels); + SetMetricBasic(metric, time, labels, resource); SetValue(values, boundaries, counts, &metric); } @@ -260,20 +293,79 @@ void PrometheusExporterUtils::SetData(std::vector values, */ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &metric, std::chrono::nanoseconds time, - const metric_sdk::PointAttributes &labels) + const metric_sdk::PointAttributes &labels, + const opentelemetry::sdk::resource::Resource *resource) { metric.timestamp_ms = time.count() / 1000000; + std::size_t label_size = 0; + if (nullptr != resource) + { + label_size += resource->GetAttributes().size(); + } + if (!labels.empty()) + { + label_size += labels.size(); + } + metric.label.resize(label_size); + + // Convert resource to prometheus labels + if (nullptr != resource) + { + opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it = + resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceName); + opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_namespace_it = + resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace); + + if (service_namespace_it != resource->GetAttributes().end() && + service_name_it != resource->GetAttributes().end()) + { + prometheus_client::ClientMetric::Label prometheus_label; + prometheus_label.name = "job"; + prometheus_label.value = AttributeValueToString(service_namespace_it->second) + "/" + + AttributeValueToString(service_name_it->second); + metric.label.emplace_back(std::move(prometheus_label)); + } + else if (service_name_it != resource->GetAttributes().end()) + { + prometheus_client::ClientMetric::Label prometheus_label; + prometheus_label.name = "job"; + prometheus_label.value = AttributeValueToString(service_name_it->second); + metric.label.emplace_back(std::move(prometheus_label)); + } + else if (service_namespace_it != resource->GetAttributes().end()) + { + prometheus_client::ClientMetric::Label prometheus_label; + prometheus_label.name = "job"; + prometheus_label.value = AttributeValueToString(service_namespace_it->second); + metric.label.emplace_back(std::move(prometheus_label)); + } + + for (auto &label : resource->GetAttributes()) + { + if (ShouldIgnoreResourceAttribute(label.first)) + { + continue; + } + + prometheus_client::ClientMetric::Label prometheus_label; + prometheus_label.name = SanitizeNames(GetPrometheusAttributeName(label.first)); + prometheus_label.value = AttributeValueToString(label.second); + metric.label.emplace_back(std::move(prometheus_label)); + } + } + // auto label_pairs = ParseLabel(labels); if (!labels.empty()) { - metric.label.resize(labels.size()); - size_t i = 0; - for (auto const &label : labels) + for (auto &label : labels) { - auto sanitized = SanitizeNames(label.first); - metric.label[i].name = sanitized; - metric.label[i++].value = AttributeValueToString(label.second); + prometheus_client::ClientMetric::Label prometheus_label; + prometheus_label.name = SanitizeNames(label.first); + prometheus_label.value = AttributeValueToString(label.second); + metric.label.emplace_back(std::move(prometheus_label)); } } } diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index 2eac7a6d8b..6e852fe6b8 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -6,6 +6,7 @@ #include "prometheus/metric_type.h" #include "opentelemetry/exporters/prometheus/exporter_utils.h" +#include "opentelemetry/sdk/resource/resource.h" #include "prometheus_test_helper.h" using opentelemetry::exporter::metrics::PrometheusExporterUtils; @@ -35,7 +36,7 @@ void assert_basic(prometheus_client::MetricFamily &metric, const std::string &sanitized_name, const std::string &description, prometheus_client::MetricType type, - int label_num, + size_t label_num, std::vector vals) { ASSERT_EQ(metric.name, sanitized_name + "_unit"); // name sanitized @@ -107,28 +108,82 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusEmptyInputReturnsEmptyCollect TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) { + opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create( + {{"service.name", "test_service"}, + {"service.namespace", "test_namespace"}, + {"service.instance.id", "localhost:8000"}, + {"custom_resource_attr", "custom_resource_value"}}); metric_sdk::ResourceMetrics metrics_data = CreateSumPointData(); + metrics_data.resource_ = &resource; auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); ASSERT_EQ(translated.size(), 1); 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", "description", prometheus_client::MetricType::Counter, + resource.GetAttributes().size(), vals); + + int checked_label_num = 0; + for (auto &label : metric1.metric[0].label) + { + if (label.name == "job") + { + ASSERT_EQ(label.value, "test_namespace/test_service"); + checked_label_num++; + } + else if (label.name == "instance") + { + ASSERT_EQ(label.value, "localhost:8000"); + checked_label_num++; + } + else if (label.name == "custom_resource_attr") + { + ASSERT_EQ(label.value, "custom_resource_value"); + checked_label_num++; + } + } + ASSERT_EQ(checked_label_num, 3); } TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) { + opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create( + {{"service.name", "test_service"}, + {"service.instance.id", "localhost:8000"}, + {"custom_resource_attr", "custom_resource_value"}}); metric_sdk::ResourceMetrics metrics_data = CreateLastValuePointData(); + metrics_data.resource_ = &resource; auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); ASSERT_EQ(translated.size(), 1); auto metric1 = translated[0]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 1, - vals); + assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, + resource.GetAttributes().size() + 1, vals); + + int checked_label_num = 0; + for (auto &label : metric1.metric[0].label) + { + if (label.name == "job") + { + ASSERT_EQ(label.value, "test_service"); + checked_label_num++; + } + else if (label.name == "instance") + { + ASSERT_EQ(label.value, "localhost:8000"); + checked_label_num++; + } + else if (label.name == "custom_resource_attr") + { + ASSERT_EQ(label.value, "custom_resource_value"); + checked_label_num++; + } + } + ASSERT_EQ(checked_label_num, 3); } TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) From ca3286ac7a0fb6ec189cfc7d0ac72d2aaebd2e55 Mon Sep 17 00:00:00 2001 From: owent Date: Sat, 9 Sep 2023 17:37:19 +0800 Subject: [PATCH 02/25] Fix unit test in prometheus, fix resouce exporting for prometheus exporter --- CHANGELOG.md | 2 ++ exporters/prometheus/src/exporter_utils.cc | 4 ++-- exporters/prometheus/test/exporter_utils_test.cc | 4 ++-- exporters/prometheus/test/prometheus_test_helper.h | 6 +++--- .../opentelemetry/sdk/metrics/export/metric_producer.h | 8 ++++++-- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f09553ce70..a5dbff8cda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ Increment the: * [DEPRECATION] Deprecate ZPAGES [#2291](https://github.com/open-telemetry/opentelemetry-cpp/pull/2291) +* [EXPORTER] Prometheus exporter emit resource attributes + [#2301](https://github.com/open-telemetry/opentelemetry-cpp/pull/2301) ## [1.11.0] 2023-08-21 diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index fe61250bec..14a69d053d 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -182,7 +182,7 @@ bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &n opentelemetry::trace::SemanticConventions::kServerAddress, opentelemetry::trace::SemanticConventions::kServerPort, opentelemetry::trace::SemanticConventions::kUrlScheme}; - return ignores.end() == ignores.find(name); + return ignores.end() != ignores.find(name); } const std::string &PrometheusExporterUtils::GetPrometheusAttributeName(const std::string &name) @@ -307,7 +307,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me { label_size += labels.size(); } - metric.label.resize(label_size); + metric.label.reserve(label_size); // Convert resource to prometheus labels if (nullptr != resource) diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index 6e852fe6b8..a2591b103d 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -195,8 +195,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", "description", prometheus_client::MetricType::Histogram, + metrics_data.resource_->GetAttributes().size() + 1, vals); assert_histogram(metric, std::list{10.1, 20.2, 30.2}, {200, 300, 400, 500}); } diff --git a/exporters/prometheus/test/prometheus_test_helper.h b/exporters/prometheus/test/prometheus_test_helper.h index 4743e032bd..8fc7a3cb3b 100644 --- a/exporters/prometheus/test/prometheus_test_helper.h +++ b/exporters/prometheus/test/prometheus_test_helper.h @@ -54,7 +54,7 @@ inline metric_sdk::ResourceMetrics CreateHistogramPointData() histogram_point_data2.counts_ = {200, 300, 400, 500}; histogram_point_data2.sum_ = (int64_t)900; metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create( + static auto resource = opentelemetry::sdk::resource::Resource::Create( opentelemetry::sdk::resource::ResourceAttributes{}); data.resource_ = &resource; auto instrumentation_scope = @@ -77,7 +77,7 @@ inline metric_sdk::ResourceMetrics CreateHistogramPointData() inline metric_sdk::ResourceMetrics CreateLastValuePointData() { metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create( + static auto resource = opentelemetry::sdk::resource::Resource::Create( opentelemetry::sdk::resource::ResourceAttributes{}); data.resource_ = &resource; auto instrumentation_scope = @@ -108,7 +108,7 @@ inline metric_sdk::ResourceMetrics CreateLastValuePointData() inline metric_sdk::ResourceMetrics CreateDropPointData() { metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create( + static auto resource = opentelemetry::sdk::resource::Resource::Create( opentelemetry::sdk::resource::ResourceAttributes{}); data.resource_ = &resource; auto instrumentation_scope = diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index 2a0c87fcaa..e70eaebce2 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -31,14 +31,18 @@ namespace metrics */ struct ScopeMetrics { - const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_; + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_ = nullptr; std::vector metric_data_; + + ScopeMetrics() = default; }; struct ResourceMetrics { - const opentelemetry::sdk::resource::Resource *resource_; + const opentelemetry::sdk::resource::Resource *resource_ = nullptr; std::vector scope_metric_data_; + + ResourceMetrics() = default; }; /** From 14363681abc82efe0c4bb996c38a7061dece349c Mon Sep 17 00:00:00 2001 From: owent Date: Sat, 9 Sep 2023 19:28:18 +0800 Subject: [PATCH 03/25] Fix constructor --- .../sdk/metrics/export/metric_producer.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index e70eaebce2..b54ba9ebe1 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -34,7 +34,11 @@ struct ScopeMetrics const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_ = nullptr; std::vector metric_data_; - ScopeMetrics() = default; + ScopeMetrics() = default; + ScopeMetrics(const ScopeMetrics &) = default; + ScopeMetrics(ScopeMetrics &&) = default; + ScopeMetrics &operator=(const ScopeMetrics &) = default; + ScopeMetrics &operator=(ScopeMetrics &&) = default; }; struct ResourceMetrics @@ -42,7 +46,11 @@ struct ResourceMetrics const opentelemetry::sdk::resource::Resource *resource_ = nullptr; std::vector scope_metric_data_; - ResourceMetrics() = default; + ResourceMetrics() = default; + ResourceMetrics(const ResourceMetrics &) = default; + ResourceMetrics(ResourceMetrics &&) = default; + ResourceMetrics &operator=(const ResourceMetrics &) = default; + ResourceMetrics &operator=(ResourceMetrics &&) = default; }; /** From 22b8c94878118903b841d584adddf23785eab220 Mon Sep 17 00:00:00 2001 From: owent Date: Sat, 9 Sep 2023 21:25:12 +0800 Subject: [PATCH 04/25] Fix compiling problem --- exporters/prometheus/src/exporter_utils.cc | 5 +-- .../sdk/metrics/export/metric_producer.h | 33 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 14a69d053d..41d0637a19 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -7,12 +7,13 @@ #include #include #include -#include "opentelemetry/sdk/resource/resource.h" + #include "prometheus/metric_family.h" +#include "prometheus/metric_type.h" -#include #include "opentelemetry/exporters/prometheus/exporter_utils.h" #include "opentelemetry/sdk/metrics/export/metric_producer.h" +#include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/sdk/resource/semantic_conventions.h" #include "opentelemetry/trace/semantic_conventions.h" diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index b54ba9ebe1..0d74d90400 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include "opentelemetry/nostd/function_ref.h" @@ -34,11 +35,17 @@ struct ScopeMetrics const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope_ = nullptr; std::vector metric_data_; - ScopeMetrics() = default; - ScopeMetrics(const ScopeMetrics &) = default; - ScopeMetrics(ScopeMetrics &&) = default; - ScopeMetrics &operator=(const ScopeMetrics &) = default; - ScopeMetrics &operator=(ScopeMetrics &&) = default; + template + inline ScopeMetrics(ScopePtr &&scope, MetricDataType &&metric) + : scope_{std::move(scope)}, metric_data_{std::move(metric)} + {} + + inline ScopeMetrics() = default; + inline ScopeMetrics(const ScopeMetrics &) = default; + inline ScopeMetrics(ScopeMetrics &&) = default; + + inline ScopeMetrics &operator=(const ScopeMetrics &) = default; + inline ScopeMetrics &operator=(ScopeMetrics &&) = default; }; struct ResourceMetrics @@ -46,11 +53,17 @@ struct ResourceMetrics const opentelemetry::sdk::resource::Resource *resource_ = nullptr; std::vector scope_metric_data_; - ResourceMetrics() = default; - ResourceMetrics(const ResourceMetrics &) = default; - ResourceMetrics(ResourceMetrics &&) = default; - ResourceMetrics &operator=(const ResourceMetrics &) = default; - ResourceMetrics &operator=(ResourceMetrics &&) = default; + template + inline ResourceMetrics(ResourcePtr &&resource, ScopeMetricsType &&scope_metric_data) + : resource_{std::move(resource)}, scope_metric_data_{std::move(scope_metric_data)} + {} + + inline ResourceMetrics() = default; + inline ResourceMetrics(const ResourceMetrics &) = default; + inline ResourceMetrics(ResourceMetrics &&) = default; + + inline ResourceMetrics &operator=(const ResourceMetrics &) = default; + inline ResourceMetrics &operator=(ResourceMetrics &&) = default; }; /** From 3b15502e6ad0da66747dc102996cdd6b6cc5648b Mon Sep 17 00:00:00 2001 From: owent Date: Sat, 9 Sep 2023 22:00:15 +0800 Subject: [PATCH 05/25] Fix invalid resource pointer in unit test of prometheus --- .../prometheus/test/prometheus_test_helper.h | 24 +++++++++---------- .../sdk/metrics/export/metric_producer.h | 6 +++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/exporters/prometheus/test/prometheus_test_helper.h b/exporters/prometheus/test/prometheus_test_helper.h index 8fc7a3cb3b..b4b478ef25 100644 --- a/exporters/prometheus/test/prometheus_test_helper.h +++ b/exporters/prometheus/test/prometheus_test_helper.h @@ -11,6 +11,14 @@ namespace exportermetrics = opentelemetry::exporter::metrics; namespace { + +inline opentelemetry::sdk::resource::Resource &GetEmptyResource() +{ + static auto resource = opentelemetry::sdk::resource::Resource::Create( + opentelemetry::sdk::resource::ResourceAttributes{}); + return resource; +} + /** * Helper function to create ResourceMetrics */ @@ -21,9 +29,7 @@ inline metric_sdk::ResourceMetrics CreateSumPointData() metric_sdk::SumPointData sum_point_data2{}; sum_point_data2.value_ = 20.0; metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create( - opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); @@ -54,9 +60,7 @@ inline metric_sdk::ResourceMetrics CreateHistogramPointData() histogram_point_data2.counts_ = {200, 300, 400, 500}; histogram_point_data2.sum_ = (int64_t)900; metric_sdk::ResourceMetrics data; - static auto resource = opentelemetry::sdk::resource::Resource::Create( - opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); @@ -77,9 +81,7 @@ inline metric_sdk::ResourceMetrics CreateHistogramPointData() inline metric_sdk::ResourceMetrics CreateLastValuePointData() { metric_sdk::ResourceMetrics data; - static auto resource = opentelemetry::sdk::resource::Resource::Create( - opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); @@ -108,9 +110,7 @@ inline metric_sdk::ResourceMetrics CreateLastValuePointData() inline metric_sdk::ResourceMetrics CreateDropPointData() { metric_sdk::ResourceMetrics data; - static auto resource = opentelemetry::sdk::resource::Resource::Create( - opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index 0d74d90400..2bef6f7a2c 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -45,7 +45,8 @@ struct ScopeMetrics inline ScopeMetrics(ScopeMetrics &&) = default; inline ScopeMetrics &operator=(const ScopeMetrics &) = default; - inline ScopeMetrics &operator=(ScopeMetrics &&) = default; + + inline ScopeMetrics &operator=(ScopeMetrics &&) = default; }; struct ResourceMetrics @@ -63,7 +64,8 @@ struct ResourceMetrics inline ResourceMetrics(ResourceMetrics &&) = default; inline ResourceMetrics &operator=(const ResourceMetrics &) = default; - inline ResourceMetrics &operator=(ResourceMetrics &&) = default; + + inline ResourceMetrics &operator=(ResourceMetrics &&) = default; }; /** From 1ffba54775c767f990399cd046f6993853d4f83e Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 12 Sep 2023 16:00:26 +0800 Subject: [PATCH 06/25] Fix "default member initializer" problem --- .../opentelemetry/sdk/metrics/export/metric_producer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index 2bef6f7a2c..4bd5b131fb 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -40,7 +40,7 @@ struct ScopeMetrics : scope_{std::move(scope)}, metric_data_{std::move(metric)} {} - inline ScopeMetrics() = default; + inline ScopeMetrics() {} inline ScopeMetrics(const ScopeMetrics &) = default; inline ScopeMetrics(ScopeMetrics &&) = default; @@ -59,7 +59,7 @@ struct ResourceMetrics : resource_{std::move(resource)}, scope_metric_data_{std::move(scope_metric_data)} {} - inline ResourceMetrics() = default; + inline ResourceMetrics() {} inline ResourceMetrics(const ResourceMetrics &) = default; inline ResourceMetrics(ResourceMetrics &&) = default; From d2e144a1e6bee173d80aba6b3e0b30cc5d37577b Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 14 Sep 2023 17:37:00 +0800 Subject: [PATCH 07/25] Add `target_info` metric. --- .../exporters/prometheus/exporter_utils.h | 23 +++- exporters/prometheus/src/exporter_utils.cc | 125 ++++++++++++++---- 2 files changed, 118 insertions(+), 30 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index c6eea5265d..b7024aa701 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -41,11 +41,24 @@ class PrometheusExporterUtils */ static std::string SanitizeNames(std::string name); + /** + * Append key-value pair to prometheus labels. + * + * @param name label name + * @param value label value + * @param labels target labels + * + * @return true if the attribute should be ignored, false otherwise. + */ + static void AddPrometheusLabel(std::string name, + std::string value, + std::vector<::prometheus::ClientMetric::Label> *labels); + /** * Some attributes should be ignored when converting resource attributes to * prometheus labels. * - * @param name resource attribnuet name + * @param name resource attribute name * @return true if the attribute should be ignored, false otherwise. */ static bool ShouldIgnoreResourceAttribute(const std::string &name); @@ -54,7 +67,7 @@ class PrometheusExporterUtils * Some attributes should be renamed when converting resource attributes to * prometheus labels. * - * @param name resource attribnuet name + * @param name resource attribute name * @return const std::string& */ static const std::string &GetPrometheusAttributeName(const std::string &name); @@ -68,6 +81,12 @@ class PrometheusExporterUtils static ::prometheus::MetricType TranslateType(opentelemetry::sdk::metrics::AggregationType kind, bool is_monotonic = true); + /** + * Add a target_info metric to collect resource attributes + */ + static void SetTarget(const sdk::metrics::ResourceMetrics &data, + std::vector<::prometheus::MetricFamily> *output); + /** * Set metric data for: * Counter => Prometheus Counter diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 41d0637a19..b09410d31e 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -28,6 +28,8 @@ namespace exporter namespace metrics { +static constexpr const char *kPrometheusInstance = "instance"; + /** * Helper function to convert OpenTelemetry metrics data collection * to Prometheus metrics data collection @@ -40,7 +42,17 @@ std::vector PrometheusExporterUtils::TranslateT { // initialize output vector + std::size_t reserve_size = 1; + for (const auto &instrumentation_info : data.scope_metric_data_) + { + reserve_size += instrumentation_info.metric_data_.size(); + } + std::vector output; + output.reserve(reserve_size); + + // Append target_info as the first metric + SetTarget(data, &output); for (const auto &instrumentation_info : data.scope_metric_data_) { @@ -175,6 +187,17 @@ std::string PrometheusExporterUtils::SanitizeNames(std::string name) return name; } +void PrometheusExporterUtils::AddPrometheusLabel( + std::string name, + std::string value, + std::vector<::prometheus::ClientMetric::Label> *labels) +{ + prometheus_client::ClientMetric::Label prometheus_label; + prometheus_label.name = std::move(name); + prometheus_label.value = std::move(value); + labels->emplace_back(std::move(prometheus_label)); +} + bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &name) { static std::unordered_set ignores{ @@ -189,7 +212,7 @@ bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &n const std::string &PrometheusExporterUtils::GetPrometheusAttributeName(const std::string &name) { static std::unordered_map name_mappings{ - {opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, "instance"}}; + {opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, kPrometheusInstance}}; std::unordered_map::const_iterator it = name_mappings.find(name); if (it == name_mappings.end()) { @@ -252,6 +275,57 @@ prometheus_client::MetricType PrometheusExporterUtils::TranslateType( } } +void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &data, + std::vector<::prometheus::MetricFamily> *output) +{ + if (output == nullptr || data.resource_ == nullptr) + { + return; + } + if (data.scope_metric_data_.empty()) + { + return; + } + if ((*data.scope_metric_data_.begin()).metric_data_.empty()) + { + return; + } + + prometheus_client::MetricFamily metric_family; + metric_family.name = "target_info"; + metric_family.help = "Target metadata"; + metric_family.type = prometheus_client::MetricType::Info; + metric_family.metric.emplace_back(); + + prometheus_client::ClientMetric &metric = metric_family.metric.back(); + metric.info.value = 1.0; + + std::chrono::nanoseconds time; + for (const auto &instrumentation_info : data.scope_metric_data_) + { + for (const auto &metric_data : instrumentation_info.metric_data_) + { + time = metric_data.end_ts.time_since_epoch(); + break; + } + break; + } + + metric_sdk::PointAttributes empty_attributes; + SetMetricBasic(metric, time, empty_attributes, data.resource_); + + for (auto &label : data.resource_->GetAttributes()) + { + if (ShouldIgnoreResourceAttribute(label.first)) + { + continue; + } + + AddPrometheusLabel(SanitizeNames(GetPrometheusAttributeName(label.first)), + AttributeValueToString(label.second), &metric.label); + } +} + /** * Set metric data for: * sum => Prometheus Counter @@ -311,6 +385,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me metric.label.reserve(label_size); // Convert resource to prometheus labels + bool has_instance_label = false; if (nullptr != resource) { opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it = @@ -323,51 +398,45 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me if (service_namespace_it != resource->GetAttributes().end() && service_name_it != resource->GetAttributes().end()) { - prometheus_client::ClientMetric::Label prometheus_label; - prometheus_label.name = "job"; - prometheus_label.value = AttributeValueToString(service_namespace_it->second) + "/" + - AttributeValueToString(service_name_it->second); - metric.label.emplace_back(std::move(prometheus_label)); + AddPrometheusLabel("job", + AttributeValueToString(service_namespace_it->second) + "/" + + AttributeValueToString(service_name_it->second), + &metric.label); } else if (service_name_it != resource->GetAttributes().end()) { - prometheus_client::ClientMetric::Label prometheus_label; - prometheus_label.name = "job"; - prometheus_label.value = AttributeValueToString(service_name_it->second); - metric.label.emplace_back(std::move(prometheus_label)); + AddPrometheusLabel("job", AttributeValueToString(service_name_it->second), &metric.label); } else if (service_namespace_it != resource->GetAttributes().end()) { - prometheus_client::ClientMetric::Label prometheus_label; - prometheus_label.name = "job"; - prometheus_label.value = AttributeValueToString(service_namespace_it->second); - metric.label.emplace_back(std::move(prometheus_label)); + AddPrometheusLabel("job", AttributeValueToString(service_namespace_it->second), + &metric.label); } + } - for (auto &label : resource->GetAttributes()) + // auto label_pairs = ParseLabel(labels); + if (!labels.empty()) + { + for (auto &label : labels) { if (ShouldIgnoreResourceAttribute(label.first)) { continue; } - prometheus_client::ClientMetric::Label prometheus_label; - prometheus_label.name = SanitizeNames(GetPrometheusAttributeName(label.first)); - prometheus_label.value = AttributeValueToString(label.second); - metric.label.emplace_back(std::move(prometheus_label)); + std::string label_name = SanitizeNames(GetPrometheusAttributeName(label.first)); + if (label_name == kPrometheusInstance) + { + has_instance_label = true; + } + AddPrometheusLabel(std::move(label_name), AttributeValueToString(label.second), + &metric.label); } } - // auto label_pairs = ParseLabel(labels); - if (!labels.empty()) + if (!has_instance_label) { - for (auto &label : labels) - { - prometheus_client::ClientMetric::Label prometheus_label; - prometheus_label.name = SanitizeNames(label.first); - prometheus_label.value = AttributeValueToString(label.second); - metric.label.emplace_back(std::move(prometheus_label)); - } + AddPrometheusLabel(kPrometheusInstance, "", &metric.label); } } From 02f4d042c9e33e86b9a90bee7f5acafc315220ca Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 14 Sep 2023 20:14:01 +0800 Subject: [PATCH 08/25] Fix instance and job exporting --- .../exporters/prometheus/exporter_utils.h | 9 -- exporters/prometheus/src/exporter_utils.cc | 129 +++++++++++------- exporters/prometheus/test/collector_test.cc | 2 +- .../prometheus/test/exporter_utils_test.cc | 98 +++++++++++-- 4 files changed, 169 insertions(+), 69 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index b7024aa701..67b1535968 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -63,15 +63,6 @@ class PrometheusExporterUtils */ static bool ShouldIgnoreResourceAttribute(const std::string &name); - /** - * Some attributes should be renamed when converting resource attributes to - * prometheus labels. - * - * @param name resource attribute name - * @return const std::string& - */ - static const std::string &GetPrometheusAttributeName(const std::string &name); - static opentelemetry::sdk::metrics::AggregationType getAggregationType( const opentelemetry::sdk::metrics::PointType &point_type); diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index b09410d31e..0e76421a80 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -29,6 +29,7 @@ namespace metrics { static constexpr const char *kPrometheusInstance = "instance"; +static constexpr const char *kPrometheusJob = "job"; /** * Helper function to convert OpenTelemetry metrics data collection @@ -205,23 +206,13 @@ bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &n opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace, opentelemetry::trace::SemanticConventions::kServerAddress, opentelemetry::trace::SemanticConventions::kServerPort, - opentelemetry::trace::SemanticConventions::kUrlScheme}; + opentelemetry::trace::SemanticConventions::kUrlScheme, + opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, + kPrometheusJob, + kPrometheusInstance}; return ignores.end() != ignores.find(name); } -const std::string &PrometheusExporterUtils::GetPrometheusAttributeName(const std::string &name) -{ - static std::unordered_map name_mappings{ - {opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, kPrometheusInstance}}; - std::unordered_map::const_iterator it = name_mappings.find(name); - if (it == name_mappings.end()) - { - return name; - } - - return it->second; -} - metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType( const metric_sdk::PointType &point_type) { @@ -321,9 +312,11 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat continue; } - AddPrometheusLabel(SanitizeNames(GetPrometheusAttributeName(label.first)), - AttributeValueToString(label.second), &metric.label); + AddPrometheusLabel(SanitizeNames(label.first), AttributeValueToString(label.second), + &metric.label); } + + output->emplace_back(std::move(metric_family)); } /** @@ -384,37 +377,9 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me } metric.label.reserve(label_size); - // Convert resource to prometheus labels - bool has_instance_label = false; - if (nullptr != resource) - { - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it = - resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceName); - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_namespace_it = - resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace); - - if (service_namespace_it != resource->GetAttributes().end() && - service_name_it != resource->GetAttributes().end()) - { - AddPrometheusLabel("job", - AttributeValueToString(service_namespace_it->second) + "/" + - AttributeValueToString(service_name_it->second), - &metric.label); - } - else if (service_name_it != resource->GetAttributes().end()) - { - AddPrometheusLabel("job", AttributeValueToString(service_name_it->second), &metric.label); - } - else if (service_namespace_it != resource->GetAttributes().end()) - { - AddPrometheusLabel("job", AttributeValueToString(service_namespace_it->second), - &metric.label); - } - } - // auto label_pairs = ParseLabel(labels); + bool has_instance_label = false; + bool has_job_label = false; if (!labels.empty()) { for (auto &label : labels) @@ -424,16 +389,86 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me continue; } - std::string label_name = SanitizeNames(GetPrometheusAttributeName(label.first)); + std::string label_name = SanitizeNames(label.first); if (label_name == kPrometheusInstance) { has_instance_label = true; } + else if (label_name == kPrometheusJob) + { + has_job_label = true; + } AddPrometheusLabel(std::move(label_name), AttributeValueToString(label.second), &metric.label); } } + // Convert resource to prometheus labels + if (nullptr != resource) + { + do + { + if (has_job_label) + { + break; + } + + opentelemetry::sdk::resource::ResourceAttributes::const_iterator prometheus_job_it = + resource->GetAttributes().find(kPrometheusJob); + if (prometheus_job_it != resource->GetAttributes().end()) + { + AddPrometheusLabel(kPrometheusJob, AttributeValueToString(prometheus_job_it->second), + &metric.label); + break; + } + + opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it = + resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceName); + opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_namespace_it = + resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace); + + if (service_namespace_it != resource->GetAttributes().end() && + service_name_it != resource->GetAttributes().end()) + { + AddPrometheusLabel(kPrometheusJob, + AttributeValueToString(service_namespace_it->second) + "/" + + AttributeValueToString(service_name_it->second), + &metric.label); + } + else if (service_name_it != resource->GetAttributes().end()) + { + AddPrometheusLabel(kPrometheusJob, AttributeValueToString(service_name_it->second), + &metric.label); + } + else if (service_namespace_it != resource->GetAttributes().end()) + { + AddPrometheusLabel(kPrometheusJob, + AttributeValueToString(service_namespace_it->second) + "/", + &metric.label); + } + } while (false); + + if (!has_instance_label) + { + opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_instance_id_it = + resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); + if (service_instance_id_it == resource->GetAttributes().end()) + { + service_instance_id_it = resource->GetAttributes().find(kPrometheusInstance); + } + if (service_instance_id_it != resource->GetAttributes().end()) + { + has_instance_label = true; + AddPrometheusLabel(kPrometheusInstance, + AttributeValueToString(service_instance_id_it->second), &metric.label); + } + } + } + + // Add a empty instance label if it's not exist if (!has_instance_label) { AddPrometheusLabel(kPrometheusInstance, "", &metric.label); diff --git a/exporters/prometheus/test/collector_test.cc b/exporters/prometheus/test/collector_test.cc index d422c45c5b..e711e8bdc7 100644 --- a/exporters/prometheus/test/collector_test.cc +++ b/exporters/prometheus/test/collector_test.cc @@ -76,7 +76,7 @@ TEST(PrometheusCollector, BasicTests) // Collection size should be the same as the size // of the records collection produced by MetricProducer. - ASSERT_EQ(data.size(), 1); + ASSERT_EQ(data.size(), 2); delete reader; delete producer; } diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index a2591b103d..d603743475 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -117,16 +117,32 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) metrics_data.resource_ = &resource; auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); - ASSERT_EQ(translated.size(), 1); + ASSERT_EQ(translated.size(), 2); - auto metric1 = translated[0]; + auto metric1 = translated[1]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, - resource.GetAttributes().size(), vals); + assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 3, + vals); int checked_label_num = 0; for (auto &label : metric1.metric[0].label) + { + if (label.name == "job") + { + ASSERT_EQ(label.value, "test_namespace/test_service"); + checked_label_num++; + } + else if (label.name == "instance") + { + ASSERT_EQ(label.value, "localhost:8000"); + checked_label_num++; + } + } + ASSERT_EQ(checked_label_num, 2); + + checked_label_num = 0; + for (auto &label : translated[0].metric[0].label) { if (label.name == "job") { @@ -157,15 +173,31 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) metrics_data.resource_ = &resource; auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); - ASSERT_EQ(translated.size(), 1); + ASSERT_EQ(translated.size(), 2); - auto metric1 = translated[0]; + auto metric1 = translated[1]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, - resource.GetAttributes().size() + 1, vals); + assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 3, + vals); int checked_label_num = 0; for (auto &label : metric1.metric[0].label) + { + if (label.name == "job") + { + ASSERT_EQ(label.value, "test_service"); + checked_label_num++; + } + else if (label.name == "instance") + { + ASSERT_EQ(label.value, "localhost:8000"); + checked_label_num++; + } + } + ASSERT_EQ(checked_label_num, 2); + + checked_label_num = 0; + for (auto &label : translated[0].metric[0].label) { if (label.name == "job") { @@ -188,16 +220,58 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) { + opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create( + {{"job", "test_service2"}, + {"instance", "localhost:8001"}, + {"custom_resource_attr", "custom_resource_value"}}); metric_sdk::ResourceMetrics metrics_data = CreateHistogramPointData(); + metrics_data.resource_ = &resource; auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); - ASSERT_EQ(translated.size(), 1); + ASSERT_EQ(translated.size(), 2); - auto metric = translated[0]; + auto metric = translated[1]; std::vector vals = {3, 900.5, 4}; - assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, - metrics_data.resource_->GetAttributes().size() + 1, vals); + 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}); + + int checked_label_num = 0; + for (auto &label : metric.metric[0].label) + { + if (label.name == "job") + { + ASSERT_EQ(label.value, "test_service2"); + checked_label_num++; + } + else if (label.name == "instance") + { + ASSERT_EQ(label.value, "localhost:8001"); + checked_label_num++; + } + } + ASSERT_EQ(checked_label_num, 2); + + checked_label_num = 0; + for (auto &label : translated[0].metric[0].label) + { + if (label.name == "job") + { + ASSERT_EQ(label.value, "test_service2"); + checked_label_num++; + } + else if (label.name == "instance") + { + ASSERT_EQ(label.value, "localhost:8001"); + checked_label_num++; + } + else if (label.name == "custom_resource_attr") + { + ASSERT_EQ(label.value, "custom_resource_value"); + checked_label_num++; + } + } + ASSERT_EQ(checked_label_num, 3); } TEST(PrometheusExporterUtils, SanitizeName) From 72ed7516fada5ef63ceae21157112aefd646f120 Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 19 Sep 2023 23:09:31 +0800 Subject: [PATCH 09/25] Add options to let user to decide whether to populate target_info --- .../exporters/prometheus/collector.h | 3 +- .../exporters/prometheus/exporter_options.h | 3 ++ .../exporters/prometheus/exporter_utils.h | 6 ++-- exporters/prometheus/src/collector.cc | 17 ++++++++-- exporters/prometheus/src/exporter.cc | 3 +- exporters/prometheus/src/exporter_utils.cc | 32 +++++++------------ exporters/prometheus/test/collector_test.cc | 2 +- 7 files changed, 37 insertions(+), 29 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h index 46d270905b..5dfa983088 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h @@ -31,7 +31,7 @@ class PrometheusCollector : public prometheus_client::Collectable * This constructor initializes the collection for metrics to export * in this class with default capacity */ - explicit PrometheusCollector(sdk::metrics::MetricReader *reader); + explicit PrometheusCollector(sdk::metrics::MetricReader *reader, bool populate_target_info); /** * Collects all metrics data from metricsToCollect collection. @@ -42,6 +42,7 @@ class PrometheusCollector : public prometheus_client::Collectable private: sdk::metrics::MetricReader *reader_; + bool populate_target_info_; /* * Lock when operating the metricsToCollect collection diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_options.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_options.h index 76a08d2a4a..3f36d780ee 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_options.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_options.h @@ -22,6 +22,9 @@ struct PrometheusExporterOptions // The endpoint the Prometheus backend can collect metrics from std::string url; + + // Populating target_info + bool populate_target_info = true; }; } // namespace metrics diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index 67b1535968..6a4163f740 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -26,10 +26,12 @@ class PrometheusExporterUtils * to Prometheus metrics data collection * * @param records a collection of metrics in OpenTelemetry + * @param populate_target_info whether to populate target_info * @return a collection of translated metrics that is acceptable by Prometheus */ static std::vector<::prometheus::MetricFamily> TranslateToPrometheus( - const sdk::metrics::ResourceMetrics &data); + const sdk::metrics::ResourceMetrics &data, + bool populate_target_info = true); private: /** @@ -47,8 +49,6 @@ class PrometheusExporterUtils * @param name label name * @param value label value * @param labels target labels - * - * @return true if the attribute should be ignored, false otherwise. */ static void AddPrometheusLabel(std::string name, std::string value, diff --git a/exporters/prometheus/src/collector.cc b/exporters/prometheus/src/collector.cc index 29c0bc8db2..3dde2beaee 100644 --- a/exporters/prometheus/src/collector.cc +++ b/exporters/prometheus/src/collector.cc @@ -17,7 +17,10 @@ namespace metrics * This constructor initializes the collection for metrics to export * in this class with default capacity */ -PrometheusCollector::PrometheusCollector(sdk::metrics::MetricReader *reader) : reader_(reader) {} +PrometheusCollector::PrometheusCollector(sdk::metrics::MetricReader *reader, + bool populate_target_info) + : reader_(reader), populate_target_info_(populate_target_info) +{} /** * Collects all metrics data from metricsToCollect collection. @@ -36,7 +39,17 @@ std::vector PrometheusCollector::Collect() cons collection_lock_.lock(); std::vector result; - reader_->Collect([&result](sdk::metrics::ResourceMetrics &metric_data) { + + // If populate_target_info_ is true, populate target_info once. + bool populate_target_info = false; + if (populate_target_info_) + { + populate_target_info = true; + + const_cast(this)->populate_target_info_ = false; + } + + reader_->Collect([&result, populate_target_info](sdk::metrics::ResourceMetrics &metric_data) { auto prometheus_metric_data = PrometheusExporterUtils::TranslateToPrometheus(metric_data); for (auto &data : prometheus_metric_data) result.emplace_back(data); diff --git a/exporters/prometheus/src/exporter.cc b/exporters/prometheus/src/exporter.cc index 7691e32f39..6022c2c33b 100644 --- a/exporters/prometheus/src/exporter.cc +++ b/exporters/prometheus/src/exporter.cc @@ -30,7 +30,8 @@ PrometheusExporter::PrometheusExporter(const PrometheusExporterOptions &options) Shutdown(); // set MetricReader in shutdown state. return; } - collector_ = std::shared_ptr(new PrometheusCollector(this)); + collector_ = std::shared_ptr( + new PrometheusCollector(this, options_.populate_target_info)); exposer_->RegisterCollectable(collector_); } diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 0e76421a80..997374be85 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -39,7 +39,8 @@ static constexpr const char *kPrometheusJob = "job"; * @return a collection of translated metrics that is acceptable by Prometheus */ std::vector PrometheusExporterUtils::TranslateToPrometheus( - const sdk::metrics::ResourceMetrics &data) + const sdk::metrics::ResourceMetrics &data, + bool populate_target_info) { // initialize output vector @@ -53,7 +54,10 @@ std::vector PrometheusExporterUtils::TranslateT output.reserve(reserve_size); // Append target_info as the first metric - SetTarget(data, &output); + if (populate_target_info) + { + SetTarget(data, &output); + } for (const auto &instrumentation_info : data.scope_metric_data_) { @@ -291,16 +295,8 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat prometheus_client::ClientMetric &metric = metric_family.metric.back(); metric.info.value = 1.0; - std::chrono::nanoseconds time; - for (const auto &instrumentation_info : data.scope_metric_data_) - { - for (const auto &metric_data : instrumentation_info.metric_data_) - { - time = metric_data.end_ts.time_since_epoch(); - break; - } - break; - } + std::chrono::nanoseconds time = + (*data.scope_metric_data_.begin()).metric_data_.begin()->end_ts.time_since_epoch(); metric_sdk::PointAttributes empty_attributes; SetMetricBasic(metric, time, empty_attributes, data.resource_); @@ -442,22 +438,16 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me AddPrometheusLabel(kPrometheusJob, AttributeValueToString(service_name_it->second), &metric.label); } - else if (service_namespace_it != resource->GetAttributes().end()) - { - AddPrometheusLabel(kPrometheusJob, - AttributeValueToString(service_namespace_it->second) + "/", - &metric.label); - } } while (false); if (!has_instance_label) { opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_instance_id_it = - resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); + resource->GetAttributes().find(kPrometheusInstance); if (service_instance_id_it == resource->GetAttributes().end()) { - service_instance_id_it = resource->GetAttributes().find(kPrometheusInstance); + service_instance_id_it = resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); } if (service_instance_id_it != resource->GetAttributes().end()) { diff --git a/exporters/prometheus/test/collector_test.cc b/exporters/prometheus/test/collector_test.cc index e711e8bdc7..4d1147aa2f 100644 --- a/exporters/prometheus/test/collector_test.cc +++ b/exporters/prometheus/test/collector_test.cc @@ -71,7 +71,7 @@ TEST(PrometheusCollector, BasicTests) MockMetricReader *reader = new MockMetricReader(); MockMetricProducer *producer = new MockMetricProducer(); reader->SetMetricProducer(producer); - PrometheusCollector collector(reader); + PrometheusCollector collector(reader, true); auto data = collector.Collect(); // Collection size should be the same as the size From 00b0b6673a047ead45f9b19befe62553fdb1ba1e Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 19 Sep 2023 23:56:07 +0800 Subject: [PATCH 10/25] Fix warnings --- exporters/prometheus/src/collector.cc | 3 ++- exporters/prometheus/src/exporter_utils.cc | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/exporters/prometheus/src/collector.cc b/exporters/prometheus/src/collector.cc index 3dde2beaee..b066f3eb7b 100644 --- a/exporters/prometheus/src/collector.cc +++ b/exporters/prometheus/src/collector.cc @@ -50,7 +50,8 @@ std::vector PrometheusCollector::Collect() cons } reader_->Collect([&result, populate_target_info](sdk::metrics::ResourceMetrics &metric_data) { - auto prometheus_metric_data = PrometheusExporterUtils::TranslateToPrometheus(metric_data); + auto prometheus_metric_data = + PrometheusExporterUtils::TranslateToPrometheus(metric_data, populate_target_info); for (auto &data : prometheus_metric_data) result.emplace_back(data); return true; diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 997374be85..e8ef83aca9 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include @@ -94,7 +95,7 @@ std::vector PrometheusExporterUtils::TranslateT } else { - sum = nostd::get(histogram_point_data.sum_); + sum = static_cast(nostd::get(histogram_point_data.sum_)); } SetData(std::vector{sum, (double)histogram_point_data.count_}, boundaries, counts, point_data_attr.attributes, time, &metric_family, data.resource_); @@ -518,7 +519,7 @@ void PrometheusExporterUtils::SetValue(std::vector values, const auto &value_var = values[0]; if (nostd::holds_alternative(value_var)) { - value = nostd::get(value_var); + value = static_cast(nostd::get(value_var)); } else { @@ -553,9 +554,9 @@ void PrometheusExporterUtils::SetValue(std::vector values, const std::vector &counts, prometheus_client::ClientMetric *metric) { - metric->histogram.sample_sum = values[0]; - metric->histogram.sample_count = values[1]; - int cumulative = 0; + metric->histogram.sample_sum = static_cast(values[0]); + metric->histogram.sample_count = static_cast(values[1]); + std::uint64_t cumulative = 0; std::vector buckets; uint32_t idx = 0; for (const auto &boundary : boundaries) From 9f01fd4cc4e5a5db736111fc58f8958cfdaf7e84 Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 21 Sep 2023 21:22:15 +0800 Subject: [PATCH 11/25] Fix priority of conflict labels. --- exporters/prometheus/src/exporter_utils.cc | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index e8ef83aca9..71007b3f54 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -410,15 +410,6 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me break; } - opentelemetry::sdk::resource::ResourceAttributes::const_iterator prometheus_job_it = - resource->GetAttributes().find(kPrometheusJob); - if (prometheus_job_it != resource->GetAttributes().end()) - { - AddPrometheusLabel(kPrometheusJob, AttributeValueToString(prometheus_job_it->second), - &metric.label); - break; - } - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it = resource->GetAttributes().find( opentelemetry::sdk::resource::SemanticConventions::kServiceName); @@ -433,22 +424,32 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me AttributeValueToString(service_namespace_it->second) + "/" + AttributeValueToString(service_name_it->second), &metric.label); + break; } else if (service_name_it != resource->GetAttributes().end()) { AddPrometheusLabel(kPrometheusJob, AttributeValueToString(service_name_it->second), &metric.label); + break; + } + + opentelemetry::sdk::resource::ResourceAttributes::const_iterator prometheus_job_it = + resource->GetAttributes().find(kPrometheusJob); + if (prometheus_job_it != resource->GetAttributes().end()) + { + AddPrometheusLabel(kPrometheusJob, AttributeValueToString(prometheus_job_it->second), + &metric.label); } } while (false); if (!has_instance_label) { opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_instance_id_it = - resource->GetAttributes().find(kPrometheusInstance); + resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); if (service_instance_id_it == resource->GetAttributes().end()) { - service_instance_id_it = resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); + service_instance_id_it = resource->GetAttributes().find(kPrometheusInstance); } if (service_instance_id_it != resource->GetAttributes().end()) { From 5d24d88c64d89ffffbd2ca09c1b5db4d04306cc2 Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 21 Sep 2023 21:54:04 +0800 Subject: [PATCH 12/25] Fix unit test --- exporters/prometheus/test/exporter_utils_test.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index d603743475..e24c546848 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -241,7 +241,8 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) { if (label.name == "job") { - ASSERT_EQ(label.value, "test_service2"); + // job label should be ignored when service.name exist + ASSERT_EQ(label.value, "unknown_service"); checked_label_num++; } else if (label.name == "instance") From e50a3d6ccfcabc0157e3b7b63275bfb830eff7db Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 21 Sep 2023 22:43:22 +0800 Subject: [PATCH 13/25] Allow some attributes in resource attributes but not in metric attributes --- .../exporters/prometheus/exporter_utils.h | 9 +++++++++ exporters/prometheus/src/exporter_utils.cc | 13 +++++++++++-- exporters/prometheus/test/exporter_utils_test.cc | 3 ++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index 6a4163f740..ff2fc9faa9 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -63,6 +63,15 @@ class PrometheusExporterUtils */ static bool ShouldIgnoreResourceAttribute(const std::string &name); + /** + * Some attributes should be ignored when converting metric attributes to + * prometheus labels. + * + * @param name attribute name + * @return true if the attribute should be ignored, false otherwise. + */ + static bool ShouldIgnoreMetricAttribute(const std::string &name); + static opentelemetry::sdk::metrics::AggregationType getAggregationType( const opentelemetry::sdk::metrics::PointType &point_type); diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 71007b3f54..a6ba93ea6f 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -209,10 +209,19 @@ bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &n static std::unordered_set ignores{ opentelemetry::sdk::resource::SemanticConventions::kServiceName, opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace, + opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, kPrometheusJob, + kPrometheusInstance}; + return ignores.end() != ignores.find(name); +} + +bool PrometheusExporterUtils::ShouldIgnoreMetricAttribute(const std::string &name) +{ + static std::unordered_set ignores{ + opentelemetry::sdk::resource::SemanticConventions::kServiceName, + opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, opentelemetry::trace::SemanticConventions::kServerAddress, opentelemetry::trace::SemanticConventions::kServerPort, opentelemetry::trace::SemanticConventions::kUrlScheme, - opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, kPrometheusJob, kPrometheusInstance}; return ignores.end() != ignores.find(name); @@ -381,7 +390,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me { for (auto &label : labels) { - if (ShouldIgnoreResourceAttribute(label.first)) + if (ShouldIgnoreMetricAttribute(label.first)) { continue; } diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index e24c546848..fb30c13d46 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -258,7 +258,8 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) { if (label.name == "job") { - ASSERT_EQ(label.value, "test_service2"); + // job label should be ignored when service.name exist + ASSERT_EQ(label.value, "unknown_service"); checked_label_num++; } else if (label.name == "instance") From 88e98572059ecb3742f239746367c7a0d776bdb8 Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 21 Sep 2023 23:36:02 +0800 Subject: [PATCH 14/25] Change the info-typed target metric. --- exporters/prometheus/src/exporter_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index a6ba93ea6f..bb84f0c4c4 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -297,7 +297,7 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat } prometheus_client::MetricFamily metric_family; - metric_family.name = "target_info"; + metric_family.name = "target"; metric_family.help = "Target metadata"; metric_family.type = prometheus_client::MetricType::Info; metric_family.metric.emplace_back(); From a0b322bf0fce6597b80eab7e3a983c080b1fc269 Mon Sep 17 00:00:00 2001 From: owent Date: Fri, 22 Sep 2023 00:06:30 +0800 Subject: [PATCH 15/25] Do not ignore metric attributes. --- .../exporters/prometheus/exporter_utils.h | 9 --------- exporters/prometheus/src/exporter_utils.cc | 18 ------------------ 2 files changed, 27 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index ff2fc9faa9..6a4163f740 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -63,15 +63,6 @@ class PrometheusExporterUtils */ static bool ShouldIgnoreResourceAttribute(const std::string &name); - /** - * Some attributes should be ignored when converting metric attributes to - * prometheus labels. - * - * @param name attribute name - * @return true if the attribute should be ignored, false otherwise. - */ - static bool ShouldIgnoreMetricAttribute(const std::string &name); - static opentelemetry::sdk::metrics::AggregationType getAggregationType( const opentelemetry::sdk::metrics::PointType &point_type); diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index bb84f0c4c4..53cdeca9f4 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -214,19 +214,6 @@ bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &n return ignores.end() != ignores.find(name); } -bool PrometheusExporterUtils::ShouldIgnoreMetricAttribute(const std::string &name) -{ - static std::unordered_set ignores{ - opentelemetry::sdk::resource::SemanticConventions::kServiceName, - opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, - opentelemetry::trace::SemanticConventions::kServerAddress, - opentelemetry::trace::SemanticConventions::kServerPort, - opentelemetry::trace::SemanticConventions::kUrlScheme, - kPrometheusJob, - kPrometheusInstance}; - return ignores.end() != ignores.find(name); -} - metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType( const metric_sdk::PointType &point_type) { @@ -390,11 +377,6 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me { for (auto &label : labels) { - if (ShouldIgnoreMetricAttribute(label.first)) - { - continue; - } - std::string label_name = SanitizeNames(label.first); if (label_name == kPrometheusInstance) { From fcc397f13534b3a264074cf708bac61ee63ee98c Mon Sep 17 00:00:00 2001 From: owent Date: Wed, 27 Sep 2023 16:02:31 +0800 Subject: [PATCH 16/25] Fix unit tests after merged. --- .../prometheus/test/exporter_utils_test.cc | 26 ++++++++++++++++--- .../sdk/metrics/export/metric_producer.h | 5 ++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index 4b9733c316..dc719b0b44 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -283,7 +283,11 @@ class SanitizeNameTest : public ::testing::Test metric_sdk::InstrumentValueType::kDouble}; std::vector result = PrometheusExporterUtils::TranslateToPrometheus( {&resource_, - {{instrumentation_scope_.get(), {{instrument_descriptor_, {}, {}, {}, {{{}, {}}}}}}}}); + std::vector{ + {instrumentation_scope_.get(), + std::vector{ + {instrument_descriptor_, {}, {}, {}, {{{}, {}}}}}}}}, + false); EXPECT_EQ(result.begin()->name, sanitized + "_unit"); } }; @@ -313,8 +317,24 @@ class AttributeCollisionTest : public ::testing::Test { std::vector result = PrometheusExporterUtils::TranslateToPrometheus( {&resource_, - {{instrumentation_scope_.get(), {{instrument_descriptor_, {}, {}, {}, {{attrs, {}}}}}}}}); - EXPECT_EQ(result.begin()->metric.begin()->label, expected); + std::vector{ + {instrumentation_scope_.get(), + std::vector{ + {instrument_descriptor_, {}, {}, {}, {{attrs, {}}}}}}}}, + false); + for (auto &expected_kv : expected) + { + bool found = false; + for (auto &found_kv : result.begin()->metric.begin()->label) + { + if (found_kv.name == expected_kv.name) + { + EXPECT_EQ(found_kv.value, expected_kv.value); + found = true; + } + } + EXPECT_TRUE(found); + } } }; diff --git a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h index 4bd5b131fb..11eb113e1e 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -37,7 +37,7 @@ struct ScopeMetrics template inline ScopeMetrics(ScopePtr &&scope, MetricDataType &&metric) - : scope_{std::move(scope)}, metric_data_{std::move(metric)} + : scope_{std::forward(scope)}, metric_data_{std::forward(metric)} {} inline ScopeMetrics() {} @@ -56,7 +56,8 @@ struct ResourceMetrics template inline ResourceMetrics(ResourcePtr &&resource, ScopeMetricsType &&scope_metric_data) - : resource_{std::move(resource)}, scope_metric_data_{std::move(scope_metric_data)} + : resource_{std::forward(resource)}, + scope_metric_data_{std::forward(scope_metric_data)} {} inline ResourceMetrics() {} From 765eb99d1ee4891a98903b47cad0f503a9b7aea4 Mon Sep 17 00:00:00 2001 From: owent Date: Wed, 27 Sep 2023 16:43:31 +0800 Subject: [PATCH 17/25] Merge SanitizeName changes --- exporters/prometheus/src/exporter_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 55c4017876..62e3997825 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -334,7 +334,7 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat continue; } - AddPrometheusLabel(SanitizeNames(label.first), AttributeValueToString(label.second), + AddPrometheusLabel(SanitizeName(label.first), AttributeValueToString(label.second), &metric.label); } From c47693935883defa7e1991ea58048ec47c0ac4f7 Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 28 Sep 2023 16:22:23 +0800 Subject: [PATCH 18/25] Remove ignores in resource attributes --- .../exporters/prometheus/exporter_utils.h | 9 --- exporters/prometheus/src/exporter_utils.cc | 71 ++++--------------- .../prometheus/test/exporter_utils_test.cc | 3 +- 3 files changed, 13 insertions(+), 70 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index 3ff0e58b0a..0b60639995 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -45,15 +45,6 @@ class PrometheusExporterUtils std::string value, std::vector<::prometheus::ClientMetric::Label> *labels); - /** - * Some attributes should be ignored when converting resource attributes to - * prometheus labels. - * - * @param name resource attribute name - * @return true if the attribute should be ignored, false otherwise. - */ - static bool ShouldIgnoreResourceAttribute(const std::string &name); - static opentelemetry::sdk::metrics::AggregationType getAggregationType( const opentelemetry::sdk::metrics::PointType &point_type); diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 62e3997825..e784f23211 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -236,16 +236,6 @@ void PrometheusExporterUtils::AddPrometheusLabel( labels->emplace_back(std::move(prometheus_label)); } -bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &name) -{ - static std::unordered_set ignores{ - opentelemetry::sdk::resource::SemanticConventions::kServiceName, - opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace, - opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, kPrometheusJob, - kPrometheusInstance}; - return ignores.end() != ignores.find(name); -} - metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType( const metric_sdk::PointType &point_type) { @@ -329,11 +319,6 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat for (auto &label : data.resource_->GetAttributes()) { - if (ShouldIgnoreResourceAttribute(label.first)) - { - continue; - } - AddPrometheusLabel(SanitizeName(label.first), AttributeValueToString(label.second), &metric.label); } @@ -394,20 +379,9 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me // in this hot code path. Instead, we ignore out-of-order keys and emit a warning. metric.label.reserve(labels.size() + 2); std::string previous_key; - bool has_instance_label = false; - bool has_job_label = false; for (auto const &label : labels) { auto sanitized = SanitizeLabel(label.first); - if (!has_instance_label && sanitized == kPrometheusInstance) - { - has_instance_label = true; - } - else if (!has_job_label && sanitized == kPrometheusJob) - { - has_job_label = true; - } - int comparison = previous_key.compare(sanitized); if (metric.label.empty() || comparison < 0) // new key { @@ -433,11 +407,6 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me { do { - if (has_job_label) - { - break; - } - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it = resource->GetAttributes().find( opentelemetry::sdk::resource::SemanticConventions::kServiceName); @@ -460,38 +429,22 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me &metric.label); break; } - - opentelemetry::sdk::resource::ResourceAttributes::const_iterator prometheus_job_it = - resource->GetAttributes().find(kPrometheusJob); - if (prometheus_job_it != resource->GetAttributes().end()) - { - AddPrometheusLabel(kPrometheusJob, AttributeValueToString(prometheus_job_it->second), - &metric.label); - } } while (false); - if (!has_instance_label) + opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_instance_id_it = + resource->GetAttributes().find( + opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); + + if (service_instance_id_it != resource->GetAttributes().end()) { - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_instance_id_it = - resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); - if (service_instance_id_it == resource->GetAttributes().end()) - { - service_instance_id_it = resource->GetAttributes().find(kPrometheusInstance); - } - if (service_instance_id_it != resource->GetAttributes().end()) - { - has_instance_label = true; - AddPrometheusLabel(kPrometheusInstance, - AttributeValueToString(service_instance_id_it->second), &metric.label); - } + AddPrometheusLabel(kPrometheusInstance, + AttributeValueToString(service_instance_id_it->second), &metric.label); + } + else + { + // Add a empty instance label if it's not exist + AddPrometheusLabel(kPrometheusInstance, "", &metric.label); } - } - - // Add a empty instance label if it's not exist - if (!has_instance_label) - { - AddPrometheusLabel(kPrometheusInstance, "", &metric.label); } } diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index a269d71556..df6fdde7d7 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -213,8 +213,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) { opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create( - {{"job", "test_service2"}, - {"instance", "localhost:8001"}, + {{"service.instance.id", "localhost:8001"}, {"custom_resource_attr", "custom_resource_value"}}); TestDataPoints dp; metric_sdk::ResourceMetrics metrics_data = dp.CreateHistogramPointData(); From 422bca272dd984086ef82410a7901f1ff6414cca Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Fri, 29 Sep 2023 13:49:56 +0800 Subject: [PATCH 19/25] Remove labels conversations that should only be in target info. Signed-off-by: WenTao Ou --- exporters/prometheus/src/exporter_utils.cc | 53 ------------- .../prometheus/test/exporter_utils_test.cc | 74 ++++--------------- 2 files changed, 15 insertions(+), 112 deletions(-) diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index e784f23211..4e5b75707a 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -296,14 +296,6 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat { return; } - if (data.scope_metric_data_.empty()) - { - return; - } - if ((*data.scope_metric_data_.begin()).metric_data_.empty()) - { - return; - } prometheus_client::MetricFamily metric_family; metric_family.name = "target"; @@ -401,51 +393,6 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me << "'. Ignoring this label."); } } - - // Convert resource to job and instance labels - if (nullptr != resource) - { - do - { - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it = - resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceName); - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_namespace_it = - resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace); - - if (service_namespace_it != resource->GetAttributes().end() && - service_name_it != resource->GetAttributes().end()) - { - AddPrometheusLabel(kPrometheusJob, - AttributeValueToString(service_namespace_it->second) + "/" + - AttributeValueToString(service_name_it->second), - &metric.label); - break; - } - else if (service_name_it != resource->GetAttributes().end()) - { - AddPrometheusLabel(kPrometheusJob, AttributeValueToString(service_name_it->second), - &metric.label); - break; - } - } while (false); - - opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_instance_id_it = - resource->GetAttributes().find( - opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId); - - if (service_instance_id_it != resource->GetAttributes().end()) - { - AddPrometheusLabel(kPrometheusInstance, - AttributeValueToString(service_instance_id_it->second), &metric.label); - } - else - { - // Add a empty instance label if it's not exist - AddPrometheusLabel(kPrometheusInstance, "", &metric.label); - } - } } std::string PrometheusExporterUtils::AttributeValueToString( diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index df6fdde7d7..64f3b8ddf4 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -113,34 +113,23 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) auto metric1 = translated[1]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 3, + assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 1, vals); int checked_label_num = 0; - for (auto &label : metric1.metric[0].label) + for (auto &label : translated[0].metric[0].label) { - if (label.name == "job") + if (label.name == "service_namespace") { - ASSERT_EQ(label.value, "test_namespace/test_service"); - checked_label_num++; - } - else if (label.name == "instance") - { - ASSERT_EQ(label.value, "localhost:8000"); + ASSERT_EQ(label.value, "test_namespace"); checked_label_num++; } - } - ASSERT_EQ(checked_label_num, 2); - - checked_label_num = 0; - for (auto &label : translated[0].metric[0].label) - { - if (label.name == "job") + else if (label.name == "service_name") { - ASSERT_EQ(label.value, "test_namespace/test_service"); + ASSERT_EQ(label.value, "test_service"); checked_label_num++; } - else if (label.name == "instance") + else if (label.name == "service_instance_id") { ASSERT_EQ(label.value, "localhost:8000"); checked_label_num++; @@ -151,7 +140,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) checked_label_num++; } } - ASSERT_EQ(checked_label_num, 3); + ASSERT_EQ(checked_label_num, 4); } TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) @@ -169,34 +158,18 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) auto metric1 = translated[1]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 3, + assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 1, vals); int checked_label_num = 0; - for (auto &label : metric1.metric[0].label) - { - if (label.name == "job") - { - ASSERT_EQ(label.value, "test_service"); - checked_label_num++; - } - else if (label.name == "instance") - { - ASSERT_EQ(label.value, "localhost:8000"); - checked_label_num++; - } - } - ASSERT_EQ(checked_label_num, 2); - - checked_label_num = 0; for (auto &label : translated[0].metric[0].label) { - if (label.name == "job") + if (label.name == "service_name") { ASSERT_EQ(label.value, "test_service"); checked_label_num++; } - else if (label.name == "instance") + else if (label.name == "service_instance_id") { ASSERT_EQ(label.value, "localhost:8000"); checked_label_num++; @@ -224,37 +197,20 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) auto metric = translated[1]; std::vector vals = {3, 900.5, 4}; - assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, 3, + assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, 1, vals); assert_histogram(metric, std::list{10.1, 20.2, 30.2}, {200, 300, 400, 500}); int checked_label_num = 0; - for (auto &label : metric.metric[0].label) - { - if (label.name == "job") - { - // job label should be ignored when service.name exist - ASSERT_EQ(label.value, "unknown_service"); - checked_label_num++; - } - else if (label.name == "instance") - { - ASSERT_EQ(label.value, "localhost:8001"); - checked_label_num++; - } - } - ASSERT_EQ(checked_label_num, 2); - - checked_label_num = 0; for (auto &label : translated[0].metric[0].label) { - if (label.name == "job") + if (label.name == "service_name") { - // job label should be ignored when service.name exist + // default service name is "unknown_service" ASSERT_EQ(label.value, "unknown_service"); checked_label_num++; } - else if (label.name == "instance") + else if (label.name == "service_instance_id") { ASSERT_EQ(label.value, "localhost:8001"); checked_label_num++; From d0f15f2754517cf13b85bd8233ee3905f0c2e901 Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Fri, 29 Sep 2023 16:53:47 +0800 Subject: [PATCH 20/25] Remove unused variables. Signed-off-by: WenTao Ou --- exporters/prometheus/src/exporter_utils.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 4e5b75707a..a54fb3e429 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -31,9 +31,6 @@ namespace metrics namespace { -static constexpr const char *kPrometheusInstance = "instance"; -static constexpr const char *kPrometheusJob = "job"; - /** * Sanitize the given metric name by replacing invalid characters with _, * ensuring that multiple consecutive _ characters are collapsed to a single _. From bb62f0a5c6b7d88a24ebc4d1c0f33f9b82998aed Mon Sep 17 00:00:00 2001 From: owent Date: Sun, 1 Oct 2023 21:35:06 +0800 Subject: [PATCH 21/25] Populate target_info with every scrape Signed-off-by: owent --- exporters/prometheus/src/collector.cc | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/exporters/prometheus/src/collector.cc b/exporters/prometheus/src/collector.cc index b066f3eb7b..f0937b6f4d 100644 --- a/exporters/prometheus/src/collector.cc +++ b/exporters/prometheus/src/collector.cc @@ -39,16 +39,8 @@ std::vector PrometheusCollector::Collect() cons collection_lock_.lock(); std::vector result; - - // If populate_target_info_ is true, populate target_info once. - bool populate_target_info = false; - if (populate_target_info_) - { - populate_target_info = true; - - const_cast(this)->populate_target_info_ = false; - } - + + bool populate_target_info = populate_target_info_; reader_->Collect([&result, populate_target_info](sdk::metrics::ResourceMetrics &metric_data) { auto prometheus_metric_data = PrometheusExporterUtils::TranslateToPrometheus(metric_data, populate_target_info); From db783e20f09e2219e5a61a66d1cc5c685216fa67 Mon Sep 17 00:00:00 2001 From: owent Date: Sun, 1 Oct 2023 21:47:42 +0800 Subject: [PATCH 22/25] Fix style Signed-off-by: owent --- exporters/prometheus/src/collector.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/prometheus/src/collector.cc b/exporters/prometheus/src/collector.cc index f0937b6f4d..9082f49f6f 100644 --- a/exporters/prometheus/src/collector.cc +++ b/exporters/prometheus/src/collector.cc @@ -39,7 +39,7 @@ std::vector PrometheusCollector::Collect() cons collection_lock_.lock(); std::vector result; - + bool populate_target_info = populate_target_info_; reader_->Collect([&result, populate_target_info](sdk::metrics::ResourceMetrics &metric_data) { auto prometheus_metric_data = From dd737e3cf2a6b92577dfa8fe85fd265d8dcf7c9f Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 3 Oct 2023 22:42:29 +0800 Subject: [PATCH 23/25] Fix some legacy issues to remove `job` and `instance` labels. Signed-off-by: owent --- exporters/prometheus/src/collector.cc | 5 ++--- exporters/prometheus/src/exporter_utils.cc | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/exporters/prometheus/src/collector.cc b/exporters/prometheus/src/collector.cc index 9082f49f6f..33b9a9b8c8 100644 --- a/exporters/prometheus/src/collector.cc +++ b/exporters/prometheus/src/collector.cc @@ -40,10 +40,9 @@ std::vector PrometheusCollector::Collect() cons std::vector result; - bool populate_target_info = populate_target_info_; - reader_->Collect([&result, populate_target_info](sdk::metrics::ResourceMetrics &metric_data) { + reader_->Collect([&result, this](sdk::metrics::ResourceMetrics &metric_data) { auto prometheus_metric_data = - PrometheusExporterUtils::TranslateToPrometheus(metric_data, populate_target_info); + PrometheusExporterUtils::TranslateToPrometheus(metric_data, this->populate_target_info_); for (auto &data : prometheus_metric_data) result.emplace_back(data); return true; diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 5b834f8176..0ecabc3983 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -379,7 +379,7 @@ void PrometheusExporterUtils::SetMetricBasic( // 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() + 2); + metric.label.reserve(labels.size()); std::string previous_key; for (auto const &label : labels) { From b6ca2f2b22c36e0fbd437c7b3d596cffad2286bf Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 3 Oct 2023 23:02:02 +0800 Subject: [PATCH 24/25] Add scope for target-info Signed-off-by: owent --- .../exporters/prometheus/exporter_utils.h | 1 + exporters/prometheus/src/exporter_utils.cc | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index c0cb85c62f..96c7ac8826 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -58,6 +58,7 @@ class PrometheusExporterUtils * Add a target_info metric to collect resource attributes */ static void SetTarget(const sdk::metrics::ResourceMetrics &data, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, std::vector<::prometheus::MetricFamily> *output); /** diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 0ecabc3983..49ece800a5 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -134,9 +134,9 @@ std::vector PrometheusExporterUtils::TranslateT output.reserve(reserve_size); // Append target_info as the first metric - if (populate_target_info) + if (populate_target_info && !data.scope_metric_data_.empty()) { - SetTarget(data, &output); + SetTarget(data, (*data.scope_metric_data_.begin()).scope_, &output); } for (const auto &instrumentation_info : data.scope_metric_data_) @@ -293,8 +293,10 @@ prometheus_client::MetricType PrometheusExporterUtils::TranslateType( } } -void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &data, - std::vector<::prometheus::MetricFamily> *output) +void PrometheusExporterUtils::SetTarget( + const sdk::metrics::ResourceMetrics &data, + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, + std::vector<::prometheus::MetricFamily> *output) { if (output == nullptr || data.resource_ == nullptr) { @@ -311,7 +313,7 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat metric.info.value = 1.0; metric_sdk::PointAttributes empty_attributes; - SetMetricBasic(metric, empty_attributes, data.resource_); + SetMetricBasic(metric, empty_attributes, scope, data.resource_); for (auto &label : data.resource_->GetAttributes()) { From 0149d5ccdfe3c83812e2edaaa6350c5463da8c4b Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 3 Oct 2023 23:27:38 +0800 Subject: [PATCH 25/25] Restore `+2` when reserve space for vector. Signed-off-by: owent --- exporters/prometheus/src/exporter_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 49ece800a5..42fafc6336 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -381,7 +381,7 @@ void PrometheusExporterUtils::SetMetricBasic( // 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) {