diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h index 46d270905b..4759b96669 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/collector.h @@ -12,8 +12,6 @@ #include "opentelemetry/exporters/prometheus/exporter_utils.h" #include "opentelemetry/sdk/metrics/metric_reader.h" -namespace prometheus_client = ::prometheus; - OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { @@ -22,7 +20,7 @@ namespace metrics /** * The Prometheus Collector maintains the intermediate collection in Prometheus Exporter */ -class PrometheusCollector : public prometheus_client::Collectable +class PrometheusCollector : public ::prometheus::Collectable { public: /** @@ -38,7 +36,7 @@ class PrometheusCollector : public prometheus_client::Collectable * * @return all metrics in the metricsToCollect snapshot */ - std::vector Collect() const override; + std::vector<::prometheus::MetricFamily> Collect() const override; private: sdk::metrics::MetricReader *reader_; diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index cb7da0b2b5..7cd3bfed50 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -16,98 +16,13 @@ namespace exporter namespace metrics { /** - * The Prometheus Utils contains utility functions for Prometheus Exporter + * Convert OpenTelemetry metrics data collection to Prometheus metrics data collection + * + * @param data a collection of metrics in OpenTelemetry + * @return a collection of translated metrics that is acceptable by Prometheus */ -class PrometheusExporterUtils -{ -public: - /** - * Helper function to convert OpenTelemetry metrics data collection - * to Prometheus metrics data collection - * - * @param records a collection of metrics in OpenTelemetry - * @return a collection of translated metrics that is acceptable by Prometheus - */ - static std::vector<::prometheus::MetricFamily> TranslateToPrometheus( - const sdk::metrics::ResourceMetrics &data); - -private: - /** - * Sanitize the given metric name or label according to Prometheus rule. - * - * This function is needed because names in OpenTelemetry can contain - * alphanumeric characters, '_', '.', and '-', whereas in Prometheus the - * name should only contain alphanumeric characters and '_'. - */ - static std::string SanitizeNames(std::string name); - - static opentelemetry::sdk::metrics::AggregationType getAggregationType( - const opentelemetry::sdk::metrics::PointType &point_type); - - /** - * Translate the OTel metric type to Prometheus metric type - */ - static ::prometheus::MetricType TranslateType(opentelemetry::sdk::metrics::AggregationType kind, - bool is_monotonic = true); - - /** - * Set metric data for: - * Counter => Prometheus Counter - */ - template - static void SetData(std::vector values, - const opentelemetry::sdk::metrics::PointAttributes &labels, - ::prometheus::MetricType type, - ::prometheus::MetricFamily *metric_family); - - /** - * Set metric data for: - * Histogram => Prometheus Histogram - */ - template - static void SetData(std::vector values, - const std::vector &boundaries, - const std::vector &counts, - const opentelemetry::sdk::metrics::PointAttributes &labels, - ::prometheus::MetricFamily *metric_family); - - /** - * Set time and labels to metric data - */ - static void SetMetricBasic(::prometheus::ClientMetric &metric, - const opentelemetry::sdk::metrics::PointAttributes &labels); - - /** - * Convert attribute value to string - */ - static std::string AttributeValueToString( - const opentelemetry::sdk::common::OwnedAttributeValue &value); - - /** - * Handle Counter and Gauge. - */ - template - static void SetValue(std::vector values, - ::prometheus::MetricType type, - ::prometheus::ClientMetric *metric); - - /** - * Handle Gauge from MinMaxSumCount - */ - static void SetValue(double value, ::prometheus::ClientMetric *metric); - - /** - * Handle Histogram - */ - template - static void SetValue(std::vector values, - const std::vector &boundaries, - const std::vector &counts, - ::prometheus::ClientMetric *metric); - - // For testing - friend class SanitizeNameTester; -}; +std::vector<::prometheus::MetricFamily> TranslateToPrometheus( + const sdk::metrics::ResourceMetrics &data); } // namespace metrics } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/src/collector.cc b/exporters/prometheus/src/collector.cc index 29c0bc8db2..d0ef9b0fc6 100644 --- a/exporters/prometheus/src/collector.cc +++ b/exporters/prometheus/src/collector.cc @@ -4,9 +4,10 @@ #include "opentelemetry/exporters/prometheus/collector.h" #include "opentelemetry/sdk/common/global_log_handler.h" -namespace metric_sdk = opentelemetry::sdk::metrics; - OPENTELEMETRY_BEGIN_NAMESPACE + +namespace metric_sdk = sdk::metrics; + namespace exporter { namespace metrics @@ -24,7 +25,7 @@ PrometheusCollector::PrometheusCollector(sdk::metrics::MetricReader *reader) : r * * @return all metrics in the metricsToCollect snapshot */ -std::vector PrometheusCollector::Collect() const +std::vector<::prometheus::MetricFamily> PrometheusCollector::Collect() const { if (reader_->IsShutdown()) { @@ -35,9 +36,9 @@ std::vector PrometheusCollector::Collect() cons } collection_lock_.lock(); - std::vector result; + std::vector<::prometheus::MetricFamily> result; reader_->Collect([&result](sdk::metrics::ResourceMetrics &metric_data) { - auto prometheus_metric_data = PrometheusExporterUtils::TranslateToPrometheus(metric_data); + auto prometheus_metric_data = TranslateToPrometheus(metric_data); 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 e912256e4f..c15f44d233 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -12,164 +12,19 @@ #include "opentelemetry/sdk/common/global_log_handler.h" -namespace prometheus_client = ::prometheus; -namespace metric_sdk = opentelemetry::sdk::metrics; - OPENTELEMETRY_BEGIN_NAMESPACE + +namespace metric_sdk = sdk::metrics; + namespace exporter { namespace metrics { -/** - * Helper function to convert OpenTelemetry metrics data collection - * to Prometheus metrics data collection - * - * @param records a collection of metrics in OpenTelemetry - * @return a collection of translated metrics that is acceptable by Prometheus - */ -std::vector PrometheusExporterUtils::TranslateToPrometheus( - const sdk::metrics::ResourceMetrics &data) +namespace { - // initialize output vector - std::vector output; - - for (const auto &instrumentation_info : data.scope_metric_data_) - { - for (const auto &metric_data : instrumentation_info.metric_data_) - { - auto origin_name = metric_data.instrument_descriptor.name_; - auto unit = metric_data.instrument_descriptor.unit_; - auto sanitized = SanitizeNames(origin_name); - prometheus_client::MetricFamily metric_family; - metric_family.name = sanitized + "_" + unit; - metric_family.help = metric_data.instrument_descriptor.description_; - for (const auto &point_data_attr : metric_data.point_data_attr_) - { - auto kind = getAggregationType(point_data_attr.point_data); - bool is_monotonic = true; - if (kind == sdk::metrics::AggregationType::kSum) - { - is_monotonic = - nostd::get(point_data_attr.point_data).is_monotonic_; - } - const prometheus_client::MetricType type = TranslateType(kind, is_monotonic); - metric_family.type = type; - if (type == prometheus_client::MetricType::Histogram) // Histogram - { - auto histogram_point_data = - nostd::get(point_data_attr.point_data); - auto boundaries = histogram_point_data.boundaries_; - auto counts = histogram_point_data.counts_; - double sum = 0.0; - if (nostd::holds_alternative(histogram_point_data.sum_)) - { - sum = nostd::get(histogram_point_data.sum_); - } - else - { - sum = nostd::get(histogram_point_data.sum_); - } - SetData(std::vector{sum, (double)histogram_point_data.count_}, boundaries, counts, - point_data_attr.attributes, &metric_family); - } - else if (type == prometheus_client::MetricType::Gauge) - { - if (nostd::holds_alternative( - point_data_attr.point_data)) - { - auto last_value_point_data = - nostd::get(point_data_attr.point_data); - std::vector values{last_value_point_data.value_}; - SetData(values, point_data_attr.attributes, type, &metric_family); - } - else if (nostd::holds_alternative(point_data_attr.point_data)) - { - auto sum_point_data = - nostd::get(point_data_attr.point_data); - std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, type, &metric_family); - } - else - { - OTEL_INTERNAL_LOG_WARN( - "[Prometheus Exporter] TranslateToPrometheus - " - "invalid LastValuePointData type"); - } - } - else // Counter, Untyped - { - if (nostd::holds_alternative(point_data_attr.point_data)) - { - auto sum_point_data = - nostd::get(point_data_attr.point_data); - std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, type, &metric_family); - } - else - { - OTEL_INTERNAL_LOG_WARN( - "[Prometheus Exporter] TranslateToPrometheus - " - "invalid SumPointData type"); - } - } - } - output.emplace_back(metric_family); - } - } - return output; -} - -/** - * Sanitize the given metric name or label according to Prometheus rule. - * - * This function is needed because names in OpenTelemetry can contain - * alphanumeric characters, '_', '.', and '-', whereas in Prometheus the - * name should only contain alphanumeric characters and '_'. - */ -std::string PrometheusExporterUtils::SanitizeNames(std::string name) -{ - constexpr const auto replacement = '_'; - constexpr const auto replacement_dup = '='; - - auto valid = [](int i, char c) { - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == ':' || - (c >= '0' && c <= '9' && i > 0)) - { - return true; - } - return false; - }; - - bool has_dup = false; - for (int i = 0; i < (int)name.size(); ++i) - { - if (valid(i, name[i])) - { - continue; - } - if (i > 0 && (name[i - 1] == replacement || name[i - 1] == replacement_dup)) - { - has_dup = true; - name[i] = replacement_dup; - } - else - { - name[i] = replacement; - } - } - if (has_dup) - { - auto end = std::remove(name.begin(), name.end(), replacement_dup); - return std::string{name.begin(), end}; - } - return name; -} - -metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType( - const metric_sdk::PointType &point_type) +metric_sdk::AggregationType getAggregationType(const metric_sdk::PointType &point_type) { - if (nostd::holds_alternative(point_type)) { return metric_sdk::AggregationType::kSum; @@ -192,88 +47,32 @@ metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType( /** * Translate the OTel metric type to Prometheus metric type */ -prometheus_client::MetricType PrometheusExporterUtils::TranslateType( - metric_sdk::AggregationType kind, - bool is_monotonic) +::prometheus::MetricType TranslateType(metric_sdk::AggregationType kind, bool is_monotonic) { switch (kind) { case metric_sdk::AggregationType::kSum: if (!is_monotonic) { - return prometheus_client::MetricType::Gauge; + return ::prometheus::MetricType::Gauge; } else { - return prometheus_client::MetricType::Counter; + return ::prometheus::MetricType::Counter; } break; case metric_sdk::AggregationType::kHistogram: - return prometheus_client::MetricType::Histogram; + return ::prometheus::MetricType::Histogram; break; case metric_sdk::AggregationType::kLastValue: - return prometheus_client::MetricType::Gauge; + return ::prometheus::MetricType::Gauge; break; default: - return prometheus_client::MetricType::Untyped; + return ::prometheus::MetricType::Untyped; } } -/** - * Set metric data for: - * sum => Prometheus Counter - */ -template -void PrometheusExporterUtils::SetData(std::vector values, - const metric_sdk::PointAttributes &labels, - prometheus_client::MetricType type, - prometheus_client::MetricFamily *metric_family) -{ - metric_family->metric.emplace_back(); - prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, labels); - SetValue(values, type, &metric); -} - -/** - * Set metric data for: - * Histogram => Prometheus Histogram - */ -template -void PrometheusExporterUtils::SetData(std::vector values, - const std::vector &boundaries, - const std::vector &counts, - const metric_sdk::PointAttributes &labels, - prometheus_client::MetricFamily *metric_family) -{ - metric_family->metric.emplace_back(); - prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, labels); - SetValue(values, boundaries, counts, &metric); -} - -/** - * Set labels to metric data - */ -void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &metric, - const metric_sdk::PointAttributes &labels) -{ - // auto label_pairs = ParseLabel(labels); - if (!labels.empty()) - { - metric.label.resize(labels.size()); - size_t i = 0; - for (auto const &label : labels) - { - auto sanitized = SanitizeNames(label.first); - metric.label[i].name = sanitized; - metric.label[i++].value = AttributeValueToString(label.second); - } - } -} - -std::string PrometheusExporterUtils::AttributeValueToString( - const opentelemetry::sdk::common::OwnedAttributeValue &value) +std::string AttributeValueToString(const opentelemetry::sdk::common::OwnedAttributeValue &value) { std::string result; if (nostd::holds_alternative(value)) @@ -314,74 +113,255 @@ std::string PrometheusExporterUtils::AttributeValueToString( } /** - * Handle Counter. + * Sanitize the given metric name or label according to Prometheus rule. + * + * This function is needed because names in OpenTelemetry can contain + * alphanumeric characters, '_', '.', and '-', whereas in Prometheus the + * name should only contain alphanumeric characters and '_'. */ -template -void PrometheusExporterUtils::SetValue(std::vector values, - prometheus_client::MetricType type, - prometheus_client::ClientMetric *metric) +std::string SanitizeNames(std::string name) { - double value = 0.0; - const auto &value_var = values[0]; - if (nostd::holds_alternative(value_var)) + constexpr const auto replacement = '_'; + constexpr const auto replacement_dup = '='; + + auto valid = [](int i, char c) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == ':' || + (c >= '0' && c <= '9' && i > 0)) + { + return true; + } + return false; + }; + + bool has_dup = false; + for (int i = 0; i < (int)name.size(); ++i) { - value = nostd::get(value_var); + if (valid(i, name[i])) + { + continue; + } + if (i > 0 && (name[i - 1] == replacement || name[i - 1] == replacement_dup)) + { + has_dup = true; + name[i] = replacement_dup; + } + else + { + name[i] = replacement; + } } - else + if (has_dup) { - value = nostd::get(value_var); + auto end = std::remove(name.begin(), name.end(), replacement_dup); + return std::string{name.begin(), end}; } + return name; +} - switch (type) +struct ClientMetricWrapper +{ + ::prometheus::ClientMetric &metric; + + /** + * Set labels to metric data + */ + void SetLabels(const metric_sdk::PointAttributes &labels) { - case prometheus_client::MetricType::Counter: { - metric->counter.value = value; - break; + if (!labels.empty()) + { + metric.label.resize(labels.size()); + size_t i = 0; + for (auto const &label : labels) + { + auto sanitized = SanitizeNames(label.first); + metric.label[i].name = sanitized; + metric.label[i++].value = AttributeValueToString(label.second); + } } - case prometheus_client::MetricType::Gauge: { - metric->gauge.value = value; - break; + } + + /** + * Handle Counter. + */ + template + void SetValue(const std::vector &values, ::prometheus::MetricType type) + { + double value = 0.0; + const auto &value_var = values[0]; + if (nostd::holds_alternative(value_var)) + { + value = nostd::get(value_var); } - case prometheus_client::MetricType::Untyped: { - metric->untyped.value = value; - break; + else + { + value = nostd::get(value_var); + } + + switch (type) + { + case ::prometheus::MetricType::Counter: { + metric.counter.value = value; + break; + } + case ::prometheus::MetricType::Gauge: { + metric.gauge.value = value; + break; + } + case ::prometheus::MetricType::Untyped: { + metric.untyped.value = value; + break; + } + default: + return; } - default: - return; } -} -/** - * Handle Histogram - */ -template -void PrometheusExporterUtils::SetValue(std::vector values, - const std::vector &boundaries, - const std::vector &counts, - prometheus_client::ClientMetric *metric) -{ - metric->histogram.sample_sum = values[0]; - metric->histogram.sample_count = values[1]; - int cumulative = 0; - std::vector buckets; - uint32_t idx = 0; - for (const auto &boundary : boundaries) + /** + * Handle Histogram + */ + void SetValue(const std::vector &values, + const std::vector &boundaries, + const std::vector &counts) { - prometheus_client::ClientMetric::Bucket bucket; + metric.histogram.sample_sum = values[0]; + metric.histogram.sample_count = values[1]; + int cumulative = 0; + std::vector<::prometheus::ClientMetric::Bucket> buckets; + uint32_t idx = 0; + for (const auto &boundary : boundaries) + { + ::prometheus::ClientMetric::Bucket bucket; + cumulative += counts[idx]; + bucket.cumulative_count = cumulative; + bucket.upper_bound = boundary; + buckets.emplace_back(bucket); + ++idx; + } + ::prometheus::ClientMetric::Bucket bucket; cumulative += counts[idx]; bucket.cumulative_count = cumulative; - bucket.upper_bound = boundary; + bucket.upper_bound = std::numeric_limits::infinity(); buckets.emplace_back(bucket); - ++idx; + metric.histogram.bucket = buckets; } - prometheus_client::ClientMetric::Bucket bucket; - cumulative += counts[idx]; - bucket.cumulative_count = cumulative; - bucket.upper_bound = std::numeric_limits::infinity(); - buckets.emplace_back(bucket); - metric->histogram.bucket = buckets; -} +}; + +struct MetricFamilyWrapper +{ + ::prometheus::MetricFamily &metric_family; + + ClientMetricWrapper Add(const metric_sdk::PointAttributes &labels) + { + metric_family.metric.emplace_back(); + ClientMetricWrapper wrapper{metric_family.metric.back()}; + wrapper.SetLabels(labels); + return wrapper; + } +}; + +} // namespace + +/** + * Helper function to convert OpenTelemetry metrics data collection + * to Prometheus metrics data collection + * + * @param records a collection of metrics in OpenTelemetry + * @return a collection of translated metrics that is acceptable by Prometheus + */ +std::vector<::prometheus::MetricFamily> TranslateToPrometheus( + const sdk::metrics::ResourceMetrics &data) +{ + + // initialize output vector + std::vector<::prometheus::MetricFamily> output; + for (const auto &instrumentation_info : data.scope_metric_data_) + { + for (const auto &metric_data : instrumentation_info.metric_data_) + { + auto origin_name = metric_data.instrument_descriptor.name_; + auto unit = metric_data.instrument_descriptor.unit_; + auto sanitized = SanitizeNames(origin_name); + ::prometheus::MetricFamily metric_family; + metric_family.name = sanitized + "_" + unit; + metric_family.help = metric_data.instrument_descriptor.description_; + for (const auto &point_data_attr : metric_data.point_data_attr_) + { + auto kind = getAggregationType(point_data_attr.point_data); + bool is_monotonic = true; + if (kind == sdk::metrics::AggregationType::kSum) + { + is_monotonic = + nostd::get(point_data_attr.point_data).is_monotonic_; + } + const ::prometheus::MetricType type = TranslateType(kind, is_monotonic); + metric_family.type = type; + MetricFamilyWrapper wrapper{metric_family}; + if (type == ::prometheus::MetricType::Histogram) // Histogram + { + auto histogram_point_data = + nostd::get(point_data_attr.point_data); + auto boundaries = histogram_point_data.boundaries_; + auto counts = histogram_point_data.counts_; + double sum = 0.0; + if (nostd::holds_alternative(histogram_point_data.sum_)) + { + sum = nostd::get(histogram_point_data.sum_); + } + else + { + sum = nostd::get(histogram_point_data.sum_); + } + wrapper.Add(point_data_attr.attributes) + .SetValue(std::vector{sum, (double)histogram_point_data.count_}, boundaries, + counts); + } + else if (type == ::prometheus::MetricType::Gauge) + { + if (nostd::holds_alternative( + point_data_attr.point_data)) + { + auto last_value_point_data = + nostd::get(point_data_attr.point_data); + std::vector values{last_value_point_data.value_}; + wrapper.Add(point_data_attr.attributes).SetValue(values, type); + } + 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_}; + wrapper.Add(point_data_attr.attributes).SetValue(values, type); + } + else + { + OTEL_INTERNAL_LOG_WARN( + "[Prometheus Exporter] TranslateToPrometheus - " + "invalid LastValuePointData type"); + } + } + else // Counter, Untyped + { + 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_}; + wrapper.Add(point_data_attr.attributes).SetValue(values, type); + } + else + { + OTEL_INTERNAL_LOG_WARN( + "[Prometheus Exporter] TranslateToPrometheus - " + "invalid SumPointData type"); + } + } + } + output.emplace_back(metric_family); + } + } + return output; +} } // namespace metrics } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/collector_test.cc b/exporters/prometheus/test/collector_test.cc index 8947dcfd27..5b191e7d6c 100644 --- a/exporters/prometheus/test/collector_test.cc +++ b/exporters/prometheus/test/collector_test.cc @@ -11,11 +11,13 @@ #include #include -using opentelemetry::exporter::metrics::PrometheusCollector; -using opentelemetry::sdk::metrics::ResourceMetrics; -namespace metric_api = opentelemetry::metrics; -namespace metric_sdk = opentelemetry::sdk::metrics; -namespace metric_exporter = opentelemetry::exporter::metrics; +OPENTELEMETRY_BEGIN_NAMESPACE + +using exporter::metrics::PrometheusCollector; +using sdk::metrics::ResourceMetrics; +namespace metric_api = metrics; +namespace metric_sdk = sdk::metrics; +namespace metric_exporter = exporter::metrics; class MockMetricProducer : public opentelemetry::sdk::metrics::MetricProducer { @@ -82,3 +84,5 @@ TEST(PrometheusCollector, BasicTests) delete reader; delete producer; } + +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/exporter_test.cc b/exporters/prometheus/test/exporter_test.cc index 3bda4c3d7b..28ed1fd71b 100644 --- a/exporters/prometheus/test/exporter_test.cc +++ b/exporters/prometheus/test/exporter_test.cc @@ -9,6 +9,8 @@ #include "opentelemetry/version.h" #include "prometheus_test_helper.h" +OPENTELEMETRY_BEGIN_NAMESPACE + /** * PrometheusExporterTest is a friend class of PrometheusExporter. * It has access to a private constructor that does not take in @@ -16,11 +18,12 @@ * private constructor is only to be used here for testing */ -using opentelemetry::exporter::metrics::PrometheusCollector; -using opentelemetry::exporter::metrics::PrometheusExporter; -using opentelemetry::exporter::metrics::PrometheusExporterOptions; -using opentelemetry::sdk::metrics::AggregationTemporality; -using opentelemetry::sdk::metrics::InstrumentType; +using exporter::metrics::PrometheusCollector; +using exporter::metrics::PrometheusExporter; +using exporter::metrics::PrometheusExporterOptions; +using sdk::metrics::AggregationTemporality; +using sdk::metrics::InstrumentType; + /** * When a PrometheusExporter is initialized, * isShutdown should be false. @@ -77,3 +80,5 @@ TEST(PrometheusExporter, CheckAggregationTemporality) ASSERT_EQ(exporter.GetAggregationTemporality(InstrumentType::kUpDownCounter), AggregationTemporality::kCumulative); } + +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index ac9ed4545f..7d803c01e0 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -8,33 +8,17 @@ #include "opentelemetry/exporters/prometheus/exporter_utils.h" #include "prometheus_test_helper.h" -using opentelemetry::exporter::metrics::PrometheusExporterUtils; -namespace metric_sdk = opentelemetry::sdk::metrics; -namespace metric_api = opentelemetry::metrics; -namespace prometheus_client = ::prometheus; - OPENTELEMETRY_BEGIN_NAMESPACE -namespace exporter -{ -namespace metrics -{ -class SanitizeNameTester -{ -public: - static std::string sanitize(std::string name) - { - return PrometheusExporterUtils::SanitizeNames(name); - } -}; -} // namespace metrics -} // namespace exporter +using exporter::metrics::TranslateToPrometheus; +namespace metric_sdk = sdk::metrics; +namespace metric_api = metrics; template -void assert_basic(prometheus_client::MetricFamily &metric, +void assert_basic(::prometheus::MetricFamily &metric, const std::string &sanitized_name, const std::string &description, - prometheus_client::MetricType type, + ::prometheus::MetricType type, int label_num, std::vector vals) { @@ -53,23 +37,23 @@ void assert_basic(prometheus_client::MetricFamily &metric, switch (type) { - case prometheus_client::MetricType::Counter: { + case ::prometheus::MetricType::Counter: { ASSERT_DOUBLE_EQ(metric_data.counter.value, vals[0]); break; } - case prometheus_client::MetricType::Histogram: { + case ::prometheus::MetricType::Histogram: { ASSERT_DOUBLE_EQ(metric_data.histogram.sample_count, vals[0]); ASSERT_DOUBLE_EQ(metric_data.histogram.sample_sum, vals[1]); auto buckets = metric_data.histogram.bucket; ASSERT_EQ(buckets.size(), vals[2]); break; } - case prometheus_client::MetricType::Gauge: { + case ::prometheus::MetricType::Gauge: { ASSERT_DOUBLE_EQ(metric_data.gauge.value, vals[0]); break; } break; - case prometheus_client::MetricType::Summary: + case ::prometheus::MetricType::Summary: // Summary and Info type not supported ASSERT_TRUE(false); break; @@ -80,7 +64,7 @@ void assert_basic(prometheus_client::MetricFamily &metric, } } -void assert_histogram(prometheus_client::MetricFamily &metric, +void assert_histogram(::prometheus::MetricFamily &metric, std::list boundaries, std::vector correct) { @@ -106,7 +90,7 @@ void assert_histogram(prometheus_client::MetricFamily &metric, TEST(PrometheusExporterUtils, TranslateToPrometheusEmptyInputReturnsEmptyCollection) { metric_sdk::ResourceMetrics metrics_data = {}; - auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); + auto translated = TranslateToPrometheus(metrics_data); ASSERT_EQ(translated.size(), 0); } @@ -115,13 +99,12 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) TestDataPoints dp; metric_sdk::ResourceMetrics metrics_data = dp.CreateSumPointData(); - auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); + auto translated = 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::MetricType::Counter, 1, vals); } TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) @@ -129,13 +112,12 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) TestDataPoints dp; metric_sdk::ResourceMetrics metrics_data = dp.CreateLastValuePointData(); - auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); + auto translated = 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::MetricType::Gauge, 1, vals); } TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) @@ -143,24 +125,41 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) TestDataPoints dp; metric_sdk::ResourceMetrics metrics_data = dp.CreateHistogramPointData(); - auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); + auto translated = TranslateToPrometheus(metrics_data); ASSERT_EQ(translated.size(), 1); 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::MetricType::Histogram, 1, vals); assert_histogram(metric, std::list{10.1, 20.2, 30.2}, {200, 300, 400, 500}); } -TEST(PrometheusExporterUtils, SanitizeName) +class SanitizeNameTest : public ::testing::Test +{ + Resource resource_ = Resource::Create(ResourceAttributes{}); + nostd::unique_ptr instrumentation_scope_ = + InstrumentationScope::Create("library_name", "1.2.0"); + +protected: + void CheckSanitation(const std::string &original, const std::string &sanitized) + { + metric_sdk::InstrumentDescriptor instrument_descriptor{ + original, "description", "unit", metric_sdk::InstrumentType::kCounter, + metric_sdk::InstrumentValueType::kDouble}; + std::vector result = TranslateToPrometheus( + {&resource_, + {{instrumentation_scope_.get(), {{instrument_descriptor, {}, {}, {}, {{}}}}}}}); + EXPECT_EQ(result.begin()->name, sanitized + "_unit"); + } +}; + +TEST_F(SanitizeNameTest, SanitizeName) { - ASSERT_EQ(exporter::metrics::SanitizeNameTester::sanitize("name"), "name"); - ASSERT_EQ(exporter::metrics::SanitizeNameTester::sanitize("name?"), "name_"); - ASSERT_EQ(exporter::metrics::SanitizeNameTester::sanitize("name???"), "name_"); - ASSERT_EQ(exporter::metrics::SanitizeNameTester::sanitize("name?__"), "name_"); - ASSERT_EQ(exporter::metrics::SanitizeNameTester::sanitize("name?__name"), "name_name"); - ASSERT_EQ(exporter::metrics::SanitizeNameTester::sanitize("name?__name:"), "name_name:"); + CheckSanitation("name", "name"); + CheckSanitation("name?", "name_"); + CheckSanitation("name???", "name_"); + CheckSanitation("name?__name", "name_name"); + CheckSanitation("name?__name:", "name_name:"); } OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/prometheus_test_helper.h b/exporters/prometheus/test/prometheus_test_helper.h index d42f66c6eb..35b28ecaa3 100644 --- a/exporters/prometheus/test/prometheus_test_helper.h +++ b/exporters/prometheus/test/prometheus_test_helper.h @@ -5,16 +5,18 @@ #include "opentelemetry/version.h" -namespace metric_sdk = opentelemetry::sdk::metrics; -namespace nostd = opentelemetry::nostd; -namespace exportermetrics = opentelemetry::exporter::metrics; +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace metric_sdk = sdk::metrics; +namespace nostd = nostd; +namespace exportermetrics = exporter::metrics; namespace { -using opentelemetry::sdk::instrumentationscope::InstrumentationScope; -using opentelemetry::sdk::resource::Resource; -using opentelemetry::sdk::resource::ResourceAttributes; +using sdk::instrumentationscope::InstrumentationScope; +using sdk::resource::Resource; +using sdk::resource::ResourceAttributes; struct TestDataPoints { @@ -123,7 +125,6 @@ struct TestDataPoints }; } // namespace -OPENTELEMETRY_BEGIN_NAMESPACE namespace sdk { namespace metrics