From f17164798f923d93364582509763671a1e26ff18 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 19:02:46 -0400 Subject: [PATCH 01/32] add Prometheus Exporter Utils build files, headers, implementations, and unit test file --- WORKSPACE | 13 + exporters/CMakeLists.txt | 1 + exporters/prometheus/BUILD | 42 ++ exporters/prometheus/CMakeLists.txt | 22 + .../prometheus/prometheus_exporter_utils.h | 194 +++++++ .../src/prometheus_exporter_utils.cc | 526 ++++++++++++++++++ exporters/prometheus/test/CMakeLists.txt | 8 + .../test/prometheus_exporter_utils_test.cc | 475 ++++++++++++++++ 8 files changed, 1281 insertions(+) create mode 100644 exporters/prometheus/BUILD create mode 100644 exporters/prometheus/CMakeLists.txt create mode 100644 exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h create mode 100644 exporters/prometheus/src/prometheus_exporter_utils.cc create mode 100644 exporters/prometheus/test/CMakeLists.txt create mode 100644 exporters/prometheus/test/prometheus_exporter_utils_test.cc diff --git a/WORKSPACE b/WORKSPACE index 615d1d27ef..59d45f2d05 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -88,3 +88,16 @@ http_archive( "https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip", ], ) + +# C++ Prometheus Client library. +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") + +http_archive( + name = "com_github_jupp0r_prometheus_cpp", + strip_prefix = "prometheus-cpp-master", + urls = ["https://github.com/jupp0r/prometheus-cpp/archive/master.zip"], +) + +load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories") + +prometheus_cpp_repositories() diff --git a/exporters/CMakeLists.txt b/exporters/CMakeLists.txt index a5144a9a24..4090bd84a7 100644 --- a/exporters/CMakeLists.txt +++ b/exporters/CMakeLists.txt @@ -2,3 +2,4 @@ if(WITH_OTPROTOCOL) add_subdirectory(otlp) endif() add_subdirectory(ostream) +add_subdirectory(prometheus) diff --git a/exporters/prometheus/BUILD b/exporters/prometheus/BUILD new file mode 100644 index 0000000000..0852586ec4 --- /dev/null +++ b/exporters/prometheus/BUILD @@ -0,0 +1,42 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "prometheus_utils", + srcs = [ + "src/prometheus_exporter_utils.cc", + ], + hdrs = [ + "include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h", + ], + strip_include_prefix = "include", + deps = [ + "//api", + "//sdk:headers", + "@com_github_jupp0r_prometheus_cpp//core", + ], +) + +cc_test( + name = "prometheus_exporter_utils_test", + srcs = [ + "test/prometheus_exporter_utils_test.cc", + ], + deps = [ + ":prometheus_utils", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/exporters/prometheus/CMakeLists.txt b/exporters/prometheus/CMakeLists.txt new file mode 100644 index 0000000000..8a2658e97b --- /dev/null +++ b/exporters/prometheus/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_directories(include) + +find_package(prometheus-cpp CONFIG REQUIRED) +add_library(prometheus_exporter src/prometheus_exporter_utils.cc) + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h new file mode 100644 index 0000000000..c39c284833 --- /dev/null +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h @@ -0,0 +1,194 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include "opentelemetry/sdk/metrics/record.h" +#include "prometheus/metric_family.h" + +namespace prometheus_client = ::prometheus; +namespace metric_sdk = opentelemetry::sdk::metrics; + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace prometheus +{ +/** + * The Prometheus Utils contains utility functions for Prometheus Exporter + */ +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 TranslateToPrometheus( + std::vector &records); + +private: + /** + * Set value to metric family according to record + */ + static void SetMetricFamily(metric_sdk::Record &record, + prometheus_client::MetricFamily *metric_family); + + /** + * 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); + + /** + * Determine whether the input name is a valid OTel name or not + * + * From the spec: + * 1. They are non-empty strings + * 2. They are case-insensitive + * 3. The first character must be non-numeric, non-space, non-punctuation + * 4. Subsequent characters must belong to the alphanumeric characters, '_', '.', and '-'. + */ + static bool IsValidName(const std::string &name); + + /** + * Set value to metric family for different aggregator + */ + template + static void SetMetricFamilyByAggregator(std::shared_ptr> aggregator, + std::string labels_str, + prometheus_client::MetricFamily *metric_family); + + /** + * Translate the OTel metric type to Prometheus metric type + */ + static prometheus_client::MetricType TranslateType(metric_sdk::AggregatorKind kind); + + /** + * Set metric data for: + * Counter => Prometheus Counter + * Gauge => Prometheus Gauge + */ + template + static void SetData(std::vector values, + const std::string &labels, + prometheus_client::MetricType type, + std::chrono::nanoseconds time, + prometheus_client::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 std::string &labels, + std::chrono::nanoseconds time, + prometheus_client::MetricFamily *metric_family); + + /** + * Set metric data for: + * MinMaxSumCount => Prometheus Gauge + * Use Average (sum / count) as the gauge metric + */ + static void SetData(double value, + const std::string &labels, + std::chrono::nanoseconds time, + prometheus_client::MetricFamily *metric_family); + + /** + * Set metric data for: + * Exact => Prometheus Summary + * Sketch => Prometheus Summary + */ + template + static void SetData(std::vector values, + metric_sdk::AggregatorKind kind, + const std::vector &quantiles, + const std::string &labels, + std::chrono::nanoseconds time, + prometheus_client::MetricFamily *metric_family, + bool do_quantile, + std::vector quantile_points); + + /** + * Set time and labels to metric data + */ + static void SetMetricBasic(prometheus_client::ClientMetric &metric, + std::chrono::nanoseconds time, + const std::string &labels); + + /** + * Parse a string of labels (key:value) into a vector of pairs + * {,} + * {l1:v1,l2:v2,...,} + */ + static std::vector> ParseLabel(std::string labels); + + /** + * Build a quantiles vector from aggregator + */ + template + static std::vector GetQuantilesVector(std::shared_ptr> aggregator, + const std::vector &quantile_points); + + /** + * Handle Counter and Gauge. + */ + template + static void SetValue(std::vector values, + prometheus_client::MetricType type, + prometheus_client::ClientMetric *metric); + + /** + * Handle Gauge from MinMaxSumCount + */ + static void SetValue(double value, prometheus_client::ClientMetric *metric); + + /** + * Handle Histogram + */ + template + static void SetValue(std::vector values, + std::vector boundaries, + std::vector counts, + prometheus_client::ClientMetric *metric); + + /** + * Handle Exact and Sketch + */ + template + static void SetValue(std::vector values, + metric_sdk::AggregatorKind kind, + std::vector quantiles, + prometheus_client::ClientMetric *metric, + bool do_quantile, + const std::vector &quantile_points); +}; +} // namespace prometheus +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc new file mode 100644 index 0000000000..192f755f16 --- /dev/null +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -0,0 +1,526 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "opentelemetry/exporters/prometheus/prometheus_exporter_utils.h" +#include "opentelemetry/sdk/metrics/aggregator/aggregator.h" +#include "prometheus/metric_type.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace prometheus +{ +/** + * 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( + std::vector &records) +{ + if (records.empty()) + { + return {}; + } + + // initialize output vector + std::vector output(records.size()); + + // iterate through the vector and set result data into it + int i = 0; + for (auto r : records) + { + SetMetricFamily(r, &output[i]); + i++; + } + + return output; +} + +// ======================= private helper functions ========================= +/** + * Set value to metric family according to record + */ +void PrometheusExporterUtils::SetMetricFamily(metric_sdk::Record &record, + prometheus_client::MetricFamily *metric_family) +{ + try + { + auto origin_name = record.GetName(); + auto sanitized = SanitizeNames(origin_name); + if (origin_name != sanitized) + { + std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\"" + << std::endl; + } + metric_family->name = sanitized; + } + catch (std::invalid_argument &e) + { + metric_family->name = record.GetName(); + } + metric_family->help = record.GetDescription(); + + // unpack the variant and set the metric data to metric family struct + auto agg_var = record.GetAggregator(); + auto labels_str = record.GetLabels(); + if (nostd::holds_alternative>>(agg_var)) + { + auto aggregator = nostd::get>>(agg_var); + SetMetricFamilyByAggregator(aggregator, labels_str, metric_family); + } + else if (nostd::holds_alternative>>(agg_var)) + { + auto aggregator = nostd::get>>(agg_var); + SetMetricFamilyByAggregator(aggregator, labels_str, metric_family); + } + else if (nostd::holds_alternative>>( + record.GetAggregator())) + { + auto aggregator = nostd::get>>(agg_var); + SetMetricFamilyByAggregator(aggregator, labels_str, metric_family); + } + else if (nostd::holds_alternative>>( + record.GetAggregator())) + { + auto aggregator = nostd::get>>(agg_var); + SetMetricFamilyByAggregator(aggregator, labels_str, metric_family); + } +} + +/** + * 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) +{ + // name cannot be null or empty. + // a valid OTel name should only contain alphanumeric characters, + // '_', '.', or '-'. + if (!IsValidName(name)) + { + throw std::invalid_argument("Received an invalid OTel name.\n"); + } + + // replace all '.' and '-' with '_' + std::replace(name.begin(), name.end(), '.', '_'); + std::replace(name.begin(), name.end(), '-', '_'); + + // if the replaced name starts with '_', it's also invalid + if (name[0] == '_') + { + throw std::invalid_argument("Received an invalid OTel name.\n"); + } + + return name; +} + +/** + * Determine whether the input name is a valid OTel name or not + * + * From the spec: + * 1. They are non-empty strings + * 2. They are case-insensitive + * 3. The first character must be non-numeric, non-space, non-punctuation + * 4. Subsequent characters must belong to the alphanumeric characters, '_', '.', and '-'. + */ +bool PrometheusExporterUtils::IsValidName(const std::string &name) +{ + if (name.empty()) + { + return false; + } + + if (isnumber(name[0]) || isspace(name[0]) || ispunct(name[0])) + { + return false; + } + + for (std::string::size_type i = 1; i < name.size(); i++) + { + if (!isalnum(name[i]) && name[i] != '_' && name[i] != '.' && name[i] != '-') + { + return false; + } + } + + return true; +} + +/** + * Set value to metric family for different aggregator + */ +template +void PrometheusExporterUtils::SetMetricFamilyByAggregator( + std::shared_ptr> aggregator, + std::string labels_str, + prometheus_client::MetricFamily *metric_family) +{ + // get aggregator kind and translate to Prometheus metric type + auto kind = aggregator->get_aggregator_kind(); + const prometheus_client::MetricType type = TranslateType(kind); + metric_family->type = type; + // get check-pointed values, label string and check-pointed time + auto checkpointed_values = aggregator->get_checkpoint(); + auto time = aggregator->get_checkpoint_timestamp().time_since_epoch(); + + if (type == prometheus_client::MetricType::Histogram) // Histogram + { + auto boundaries = aggregator->get_boundaries(); + auto counts = aggregator->get_counts(); + SetData(checkpointed_values, boundaries, counts, labels_str, time, metric_family); + } + else if (type == prometheus_client::MetricType::Summary) // Sketch, Exact + { + std::vector quantile_points = {0, 0.5, 0.9, 0.95, 0.99, 1}; + if (kind == metric_sdk::AggregatorKind::Exact) + { + std::vector quantiles; + bool do_quantile = aggregator->get_quant_estimation(); + if (do_quantile) + { + quantiles = GetQuantilesVector(aggregator, quantile_points); + } + SetData(checkpointed_values, kind, quantiles, labels_str, time, metric_family, do_quantile, + quantile_points); + } + else if (kind == metric_sdk::AggregatorKind::Sketch) + { + auto quantiles = GetQuantilesVector(aggregator, quantile_points); + SetData(checkpointed_values, kind, quantiles, labels_str, time, metric_family, true, + quantile_points); + } + } + else // Counter, Gauge, MinMaxSumCount, Untyped + { + // Handle MinMaxSumCount: https://github.com/open-telemetry/opentelemetry-cpp/issues/228 + // Use sum/count is ok. + if (kind == metric_sdk::AggregatorKind::MinMaxSumCount) + { + double avg = (double)checkpointed_values[2] / checkpointed_values[3]; + SetData(avg, labels_str, time, metric_family); + } + else + { + SetData(checkpointed_values, labels_str, type, time, metric_family); + } + } +} + +/** + * Translate the OTel metric type to Prometheus metric type + */ +prometheus_client::MetricType PrometheusExporterUtils::TranslateType( + metric_sdk::AggregatorKind kind) +{ + switch (kind) + { + case metric_sdk::AggregatorKind::Counter: + return prometheus_client::MetricType::Counter; + case metric_sdk::AggregatorKind::Gauge: + case metric_sdk::AggregatorKind::MinMaxSumCount: + return prometheus_client::MetricType::Gauge; + case metric_sdk::AggregatorKind::Histogram: + return prometheus_client::MetricType::Histogram; + case metric_sdk::AggregatorKind::Sketch: + case metric_sdk::AggregatorKind::Exact: + return prometheus_client::MetricType::Summary; + default: + return prometheus_client::MetricType::Untyped; + } +} + +/** + * Set metric data for: + * Counter => Prometheus Counter + * Gauge => Prometheus Gauge + */ +template +void PrometheusExporterUtils::SetData(std::vector values, + const std::string &labels, + prometheus_client::MetricType type, + std::chrono::nanoseconds time, + prometheus_client::MetricFamily *metric_family) +{ + metric_family->metric.emplace_back(); + prometheus_client::ClientMetric &metric = metric_family->metric.back(); + SetMetricBasic(metric, time, 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 std::string &labels, + std::chrono::nanoseconds time, + prometheus_client::MetricFamily *metric_family) +{ + metric_family->metric.emplace_back(); + prometheus_client::ClientMetric &metric = metric_family->metric.back(); + SetMetricBasic(metric, time, labels); + SetValue(values, boundaries, counts, &metric); +} + +/** + * Set metric data for: + * MinMaxSumCount => Prometheus Gauge + * Use Average (sum / count) as the gauge metric + */ +void PrometheusExporterUtils::SetData(double value, + const std::string &labels, + std::chrono::nanoseconds time, + prometheus_client::MetricFamily *metric_family) +{ + metric_family->metric.emplace_back(); + prometheus_client::ClientMetric &metric = metric_family->metric.back(); + SetMetricBasic(metric, time, labels); + SetValue(value, &metric); +} + +/** + * Set metric data for: + * Exact => Prometheus Summary + * Sketch => Prometheus Summary + */ +template +void PrometheusExporterUtils::SetData(std::vector values, + metric_sdk::AggregatorKind kind, + const std::vector &quantiles, + const std::string &labels, + std::chrono::nanoseconds time, + prometheus_client::MetricFamily *metric_family, + bool do_quantile, + std::vector quantile_points) +{ + metric_family->metric.emplace_back(); + prometheus_client::ClientMetric &metric = metric_family->metric.back(); + SetMetricBasic(metric, time, labels); + SetValue(values, kind, quantiles, &metric, do_quantile, quantile_points); +} + +/** + * Set time and labels to metric data + */ +void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &metric, + std::chrono::nanoseconds time, + const std::string &labels) +{ + metric.timestamp_ms = time.count() / 1000; + + auto label_pairs = ParseLabel(labels); + if (!label_pairs.empty()) + { + metric.label.resize(label_pairs.size()); + for (int i = 0; i < label_pairs.size(); ++i) + { + try + { + auto origin_name = label_pairs[i].first; + auto sanitized = SanitizeNames(origin_name); + if (origin_name != sanitized) + { + std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\"" + << std::endl; + } + metric.label[i].name = sanitized; + } + catch (std::invalid_argument &e) + { + metric.label[i].name = label_pairs[i].first; + } + metric.label[i].value = label_pairs[i].second; + } + } +}; + +/** + * Parse a string of labels (key:value) into a vector of pairs + * {,} + * {l1:v1,l2:v2,...,} + */ +std::vector> PrometheusExporterUtils::ParseLabel( + std::string labels) +{ + labels = labels.substr(1, labels.size() - 2); + + std::vector paired_labels; + std::stringstream s_stream(labels); + while (s_stream.good()) + { + std::string substr; + getline(s_stream, substr, ','); // get first string delimited by comma + if (!substr.empty()) + { + paired_labels.push_back(substr); + } + } + + std::vector> result; + for (auto &paired : paired_labels) + { + std::size_t split_index = paired.find(':'); + std::string label = paired.substr(0, split_index); + std::string value = paired.substr(split_index + 1); + result.emplace_back(std::pair(label, value)); + } + + return result; +} + +/** + * Build a quantiles vector from aggregator + */ +template +std::vector PrometheusExporterUtils::GetQuantilesVector( + std::shared_ptr> aggregator, + const std::vector &quantile_points) +{ + std::vector quantiles; + for (double q : quantile_points) + { + T quantile = aggregator->get_quantiles(q); + quantiles.emplace_back(quantile); + } + return quantiles; +} + +/** + * Handle Counter and Gauge. + */ +template +void PrometheusExporterUtils::SetValue(std::vector values, + prometheus_client::MetricType type, + prometheus_client::ClientMetric *metric) +{ + switch (type) + { + case prometheus_client::MetricType::Counter: + { + metric->counter.value = values[0]; + break; + } + case prometheus_client::MetricType::Gauge: + { + metric->gauge.value = values[0]; + break; + } + case prometheus_client::MetricType::Untyped: + { + metric->untyped.value = values[0]; + break; + } + default: + return; + } +} + +/** + * Handle Gauge from MinMaxSumCount + */ +void PrometheusExporterUtils::SetValue(double value, prometheus_client::ClientMetric *metric) +{ + metric->gauge.value = value; +} + +/** + * Handle Histogram + */ +template +void PrometheusExporterUtils::SetValue(std::vector values, + std::vector boundaries, + 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; + for (int i = 0; i < boundaries.size() + 1; i++) + { + prometheus_client::ClientMetric::Bucket bucket; + cumulative += counts[i]; + bucket.cumulative_count = cumulative; + if (i != boundaries.size()) + { + bucket.upper_bound = boundaries[i]; + } + else + { + bucket.upper_bound = std::numeric_limits::infinity(); + } + buckets.emplace_back(bucket); + } + metric->histogram.bucket = buckets; +} + +/** + * Handle Exact and Sketch + */ +template +void PrometheusExporterUtils::SetValue(std::vector values, + metric_sdk::AggregatorKind kind, + std::vector quantiles, + prometheus_client::ClientMetric *metric, + bool do_quantile, + const std::vector &quantile_points) +{ + if (kind == metric_sdk::AggregatorKind::Exact) + { + metric->summary.sample_count = values.size(); + auto sum = 0; + for (auto val : values) + { + sum += val; + } + metric->summary.sample_sum = sum; + } + else if (kind == metric_sdk::AggregatorKind::Sketch) + { + metric->summary.sample_sum = values[0]; + metric->summary.sample_count = values[1]; + } + + if (do_quantile) + { + std::vector prometheus_quantiles; + for (int i = 0; i < quantiles.size(); i++) + { + prometheus_client::ClientMetric::Quantile quantile; + quantile.quantile = quantile_points[i]; + quantile.value = quantiles[i]; + prometheus_quantiles.emplace_back(quantile); + } + metric->summary.quantile = prometheus_quantiles; + } +} +} // namespace prometheus +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/CMakeLists.txt b/exporters/prometheus/test/CMakeLists.txt new file mode 100644 index 0000000000..a42feed797 --- /dev/null +++ b/exporters/prometheus/test/CMakeLists.txt @@ -0,0 +1,8 @@ +foreach(testname prometheus_exporter_utils_test) + add_executable(${testname} "${testname}.cc") + target_link_libraries( + ${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} + prometheus_exporter prometheus-cpp::pull) + gtest_add_tests(TARGET ${testname} TEST_PREFIX exporter. TEST_LIST + ${testname}) +endforeach() diff --git a/exporters/prometheus/test/prometheus_exporter_utils_test.cc b/exporters/prometheus/test/prometheus_exporter_utils_test.cc new file mode 100644 index 0000000000..f3b5004088 --- /dev/null +++ b/exporters/prometheus/test/prometheus_exporter_utils_test.cc @@ -0,0 +1,475 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include "opentelemetry/exporters/prometheus/prometheus_exporter_utils.h" +#include "opentelemetry/sdk/metrics/aggregator/counter_aggregator.h" +#include "opentelemetry/sdk/metrics/aggregator/exact_aggregator.h" +#include "opentelemetry/sdk/metrics/aggregator/gauge_aggregator.h" +#include "opentelemetry/sdk/metrics/aggregator/histogram_aggregator.h" +#include "opentelemetry/sdk/metrics/aggregator/min_max_sum_count_aggregator.h" +#include "opentelemetry/sdk/metrics/aggregator/sketch_aggregator.h" + +using opentelemetry::exporter::prometheus::PrometheusExporterUtils; +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace metric_api = opentelemetry::metrics; + +OPENTELEMETRY_BEGIN_NAMESPACE + +template +void assert_basic(prometheus_client::MetricFamily &metric, + const std::string &sanitized_name, + const std::string &description, + prometheus_client::MetricType type, + int label_num, + std::vector vals) +{ + ASSERT_EQ(metric.name, sanitized_name); // name sanitized + ASSERT_EQ(metric.help, description); // description not changed + ASSERT_EQ(metric.type, type); // type translated + + auto metric_data = metric.metric[0]; + ASSERT_EQ(metric_data.label.size(), label_num); + + switch (type) + { + case prometheus_client::MetricType::Counter: + { + ASSERT_DOUBLE_EQ(metric_data.counter.value, vals[0]); + break; + } + case prometheus_client::MetricType::Gauge: + { + ASSERT_EQ(metric_data.gauge.value, vals[0]); + break; + } + case prometheus_client::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::Summary: + { + ASSERT_DOUBLE_EQ(metric_data.summary.sample_count, vals[0]); + ASSERT_DOUBLE_EQ(metric_data.summary.sample_sum, vals[1]); + break; + } + case prometheus::MetricType::Untyped: + break; + } +} + +void assert_histogram(prometheus_client::MetricFamily &metric, + std::vector boundaries, + std::vector correct) +{ + int cumulative_count = 0; + auto buckets = metric.metric[0].histogram.bucket; + for (int i = 0; i < buckets.size(); i++) + { + auto bucket = buckets[i]; + if (i != buckets.size() - 1) + { + ASSERT_DOUBLE_EQ(boundaries[i], bucket.upper_bound); + } + else + { + ASSERT_DOUBLE_EQ(std::numeric_limits::infinity(), bucket.upper_bound); + } + cumulative_count += correct[i]; + ASSERT_EQ(cumulative_count, bucket.cumulative_count); + } +} + +template +metric_sdk::Record get_record(const std::string &type, + int version, + const std::string &label, + std::shared_ptr> aggregator) +{ + std::string name = "test-" + type + "-metric-record-v_" + std::to_string(version) + ".0"; + std::string desc = "this is a test " + type + " metric record"; + metric_sdk::Record record(name, desc, label, aggregator); + return record; +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusEmptyInputReturnsEmptyCollection) +{ + std::vector collection; + auto translated2 = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated2.size(), 0); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::CounterAggregator(metric_api::InstrumentKind::Counter)); + + std::vector collection; + + auto record1 = get_record("int-counter", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + aggregator->update(10); + aggregator->checkpoint(); + collection.emplace_back(record1); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric1 = translated[0]; + std::vector vals = {10}; + assert_basic(metric1, "test_int_counter_metric_record_v_1_0", record1.GetDescription(), + prometheus_client::MetricType::Counter, 3, vals); + + auto record2 = get_record("int-counter", 2, "{,}", aggregator); + aggregator->update(20); + aggregator->update(30); + aggregator->checkpoint(); + collection.emplace_back(record2); + + translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric2 = translated[1]; + vals = {50}; + assert_basic(metric2, "test_int_counter_metric_record_v_2_0", record2.GetDescription(), + prometheus_client::MetricType::Counter, 0, vals); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusDoubleCounter) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::CounterAggregator(metric_api::InstrumentKind::Counter)); + + std::vector collection; + aggregator->update(10.5); + aggregator->checkpoint(); + auto record1 = get_record("double-counter", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + aggregator->update(22.4); + aggregator->update(31.2); + aggregator->checkpoint(); + auto record2 = get_record("double-counter", 2, "{,}", aggregator); + collection.emplace_back(record1); + collection.emplace_back(record2); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric1 = translated[0]; + std::vector vals = {53.6}; + assert_basic(metric1, "test_double_counter_metric_record_v_1_0", record1.GetDescription(), + prometheus_client::MetricType::Counter, 3, vals); + auto metric2 = translated[1]; + assert_basic(metric2, "test_double_counter_metric_record_v_2_0", record2.GetDescription(), + prometheus_client::MetricType::Counter, 0, vals); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusShortCounter) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::CounterAggregator(metric_api::InstrumentKind::Counter)); + + std::vector collection; + aggregator->update(10); + aggregator->checkpoint(); + auto record1 = get_record("short-counter", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + aggregator->update(20); + aggregator->update(30); + aggregator->checkpoint(); + auto record2 = get_record("short-counter", 2, "{,}", aggregator); + collection.emplace_back(record1); + collection.emplace_back(record2); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric1 = translated[0]; + std::vector vals = {50}; + assert_basic(metric1, "test_short_counter_metric_record_v_1_0", record1.GetDescription(), + prometheus_client::MetricType::Counter, 3, vals); + auto metric2 = translated[1]; + assert_basic(metric2, "test_short_counter_metric_record_v_2_0", record2.GetDescription(), + prometheus_client::MetricType::Counter, 0, vals); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusFloatCounter) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::CounterAggregator(metric_api::InstrumentKind::Counter)); + + std::vector collection; + aggregator->update(10.5f); + aggregator->checkpoint(); + auto record1 = get_record("float-counter", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + aggregator->update(22.4f); + aggregator->update(31.2f); + aggregator->checkpoint(); + auto record2 = get_record("float-counter", 2, "{,}", aggregator); + collection.emplace_back(record1); + collection.emplace_back(record2); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric1 = translated[0]; + std::vector vals = {53.6f}; + assert_basic(metric1, "test_float_counter_metric_record_v_1_0", record1.GetDescription(), + prometheus_client::MetricType::Counter, 3, vals); + auto metric2 = translated[1]; + assert_basic(metric2, "test_float_counter_metric_record_v_2_0", record2.GetDescription(), + prometheus_client::MetricType::Counter, 0, vals); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusGauge) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::GaugeAggregator(metric_api::InstrumentKind::Counter)); + + std::vector collection; + aggregator->update(10); + aggregator->checkpoint(); + auto record1 = get_record("gauge", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + aggregator->update(20); + aggregator->update(30); + aggregator->checkpoint(); + auto record2 = get_record("gauge", 2, "{,}", aggregator); + collection.emplace_back(record1); + collection.emplace_back(record2); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric1 = translated[0]; + std::vector vals = {30}; + assert_basic(metric1, "test_gauge_metric_record_v_1_0", record1.GetDescription(), + prometheus_client::MetricType::Gauge, 3, vals); + auto metric2 = translated[1]; + assert_basic(metric2, "test_gauge_metric_record_v_2_0", record2.GetDescription(), + prometheus_client::MetricType::Gauge, 0, vals); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramUniform) +{ + std::vector boundaries{10, 20, 30, 40, 50}; + auto aggregator = std::shared_ptr>( + new metric_sdk::HistogramAggregator(metric_api::InstrumentKind::Counter, boundaries)); + + std::vector collection; + auto record = get_record("histogram-uniform", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + int count_num = 60; + for (int i = 0; i < count_num; i++) + { + aggregator->update(i); + } + aggregator->checkpoint(); + collection.emplace_back(record); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric = translated[0]; + std::vector vals = {aggregator->get_checkpoint()[1], aggregator->get_checkpoint()[0], + (int)boundaries.size() + 1}; + assert_basic(metric, "test_histogram_uniform_metric_record_v_1_0", record.GetDescription(), + prometheus_client::MetricType::Histogram, 3, vals); + std::vector correct = aggregator->get_counts(); + assert_histogram(metric, boundaries, correct); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) +{ + std::vector boundaries{2, 4, 6, 8, 10, 12}; + auto aggregator = std::shared_ptr>( + new metric_sdk::HistogramAggregator(metric_api::InstrumentKind::Counter, boundaries)); + + std::vector collection; + auto record = get_record("histogram-normal", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + std::vector values{1, 3, 3, 5, 5, 5, 7, 7, 7, 7, 9, 9, 9, 11, 11, 13}; + for (int i : values) + { + aggregator->update(i); + } + aggregator->checkpoint(); + collection.emplace_back(record); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric = translated[0]; + std::vector vals = {aggregator->get_checkpoint()[1], aggregator->get_checkpoint()[0], + (int)boundaries.size() + 1}; + assert_basic(metric, "test_histogram_normal_metric_record_v_1_0", record.GetDescription(), + prometheus_client::MetricType::Histogram, 3, vals); + std::vector correct = aggregator->get_counts(); + assert_histogram(metric, boundaries, correct); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusExact) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::ExactAggregator(metric_api::InstrumentKind::Counter, true)); + + std::vector collection; + int count_num = 100; + for (int i = 0; i <= count_num; i++) + { + aggregator->update(i); + } + aggregator->checkpoint(); + auto record = get_record("exact", 1, "{label-1:v1,label_2:v2,label3:v3,}", aggregator); + collection.emplace_back(record); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric = translated[0]; + std::vector vals = {101, 5050}; + assert_basic(metric, "test_exact_metric_record_v_1_0", record.GetDescription(), + prometheus_client::MetricType::Summary, 3, vals); + auto quantile = metric.metric[0].summary.quantile; + ASSERT_EQ(quantile.size(), 6); + ASSERT_DOUBLE_EQ(quantile[0].value, 0); + ASSERT_DOUBLE_EQ(quantile[1].value, 50); + ASSERT_DOUBLE_EQ(quantile[2].value, 90); + ASSERT_DOUBLE_EQ(quantile[3].value, 95); + ASSERT_DOUBLE_EQ(quantile[4].value, 99); + ASSERT_DOUBLE_EQ(quantile[5].value, 100); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusExactNoQuantile) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::ExactAggregator(metric_api::InstrumentKind::Counter, false)); + + std::vector collection; + int count_num = 10; + for (int i = 0; i < count_num; i++) + { + aggregator->update(i); + } + aggregator->checkpoint(); + auto record = get_record("exact-no-quantile", 1, "{label1:v1,label2:v2,}", aggregator); + collection.emplace_back(record); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric = translated[0]; + std::vector vals = {count_num, 45}; + assert_basic(metric, "test_exact_no_quantile_metric_record_v_1_0", record.GetDescription(), + prometheus_client::MetricType::Summary, 2, vals); + auto quantile = metric.metric[0].summary.quantile; + ASSERT_EQ(quantile.size(), 0); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusMinMaxSumCount) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::MinMaxSumCountAggregator(metric_api::InstrumentKind::Counter)); + + std::vector collection; + // min: 1, max: 10, sum: 55, count: 10 + for (int i = 1; i <= 10; i++) + { + aggregator->update(i); + } + aggregator->checkpoint(); + auto record = get_record("mmsc", 1, "{label1:v1,label2:v2,label3:v3,}", aggregator); + collection.emplace_back(record); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric = translated[0]; + // in this version of implementation, we use the sum/count as a gauge + std::vector vals = {5.5}; + assert_basic(metric, "test_mmsc_metric_record_v_1_0", record.GetDescription(), + prometheus_client::MetricType::Gauge, 3, vals); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusSketch) +{ + auto aggregator = std::shared_ptr>( + new metric_sdk::SketchAggregator(metric_api::InstrumentKind::Counter, 0.0005)); + + std::vector collection; + for (int i = 0; i <= 100; i++) + { + aggregator->update(i); + } + aggregator->checkpoint(); + auto record = get_record("sketch", 1, "{label1:v1,label2:v2,}", aggregator); + collection.emplace_back(record); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric = translated[0]; + std::vector vals = {aggregator->get_checkpoint()[1], aggregator->get_checkpoint()[0]}; + assert_basic(metric, "test_sketch_metric_record_v_1_0", record.GetDescription(), + prometheus_client::MetricType::Summary, 2, vals); + + auto quantile = metric.metric[0].summary.quantile; + ASSERT_EQ(quantile.size(), 6); + ASSERT_DOUBLE_EQ(quantile[0].value, 0); + ASSERT_DOUBLE_EQ(quantile[1].value, 49); + ASSERT_DOUBLE_EQ(quantile[2].value, 89); + ASSERT_DOUBLE_EQ(quantile[3].value, 94); + ASSERT_DOUBLE_EQ(quantile[4].value, 98); + ASSERT_DOUBLE_EQ(quantile[5].value, 99); +} + +TEST(PrometheusExporterUtils, TranslateToPrometheusMultipleAggregators) +{ + auto counter_aggregator = std::shared_ptr>( + new metric_sdk::CounterAggregator(metric_api::InstrumentKind::Counter)); + auto gauge_aggregator = std::shared_ptr>( + new metric_sdk::GaugeAggregator(metric_api::InstrumentKind::Counter)); + + std::vector collection; + counter_aggregator->update(10); + counter_aggregator->update(20); + counter_aggregator->checkpoint(); + auto record1 = get_record("counter", 1, "{label1:v1,label2:v2,label3:v3,}", counter_aggregator); + gauge_aggregator->update(10); + gauge_aggregator->update(30); + gauge_aggregator->update(20); + gauge_aggregator->checkpoint(); + auto record2 = get_record("gauge", 1, "{label1:v1,}", gauge_aggregator); + collection.emplace_back(record1); + collection.emplace_back(record2); + + auto translated = PrometheusExporterUtils::TranslateToPrometheus(collection); + ASSERT_EQ(translated.size(), collection.size()); + + auto metric1 = translated[0]; + std::vector vals = {30}; + assert_basic(metric1, "test_counter_metric_record_v_1_0", record1.GetDescription(), + prometheus_client::MetricType::Counter, 3, vals); + auto metric2 = translated[1]; + vals = {20}; + assert_basic(metric2, "test_gauge_metric_record_v_1_0", record2.GetDescription(), + prometheus_client::MetricType::Gauge, 1, vals); +} +OPENTELEMETRY_END_NAMESPACE From 75df0a8128d978eab258886e379cf550be1cc6e0 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 22:35:01 -0400 Subject: [PATCH 02/32] remove helper of validating name because it's guaranteed in sdk --- .../prometheus/prometheus_exporter_utils.h | 11 ---- .../src/prometheus_exporter_utils.cc | 55 +------------------ 2 files changed, 3 insertions(+), 63 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h index c39c284833..c617f4548f 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h @@ -62,17 +62,6 @@ class PrometheusExporterUtils */ static std::string SanitizeNames(std::string name); - /** - * Determine whether the input name is a valid OTel name or not - * - * From the spec: - * 1. They are non-empty strings - * 2. They are case-insensitive - * 3. The first character must be non-numeric, non-space, non-punctuation - * 4. Subsequent characters must belong to the alphanumeric characters, '_', '.', and '-'. - */ - static bool IsValidName(const std::string &name); - /** * Set value to metric family for different aggregator */ diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index 192f755f16..5708b9d0ed 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -117,59 +117,13 @@ void PrometheusExporterUtils::SetMetricFamily(metric_sdk::Record &record, */ std::string PrometheusExporterUtils::SanitizeNames(std::string name) { - // name cannot be null or empty. - // a valid OTel name should only contain alphanumeric characters, - // '_', '.', or '-'. - if (!IsValidName(name)) - { - throw std::invalid_argument("Received an invalid OTel name.\n"); - } - // replace all '.' and '-' with '_' std::replace(name.begin(), name.end(), '.', '_'); std::replace(name.begin(), name.end(), '-', '_'); - // if the replaced name starts with '_', it's also invalid - if (name[0] == '_') - { - throw std::invalid_argument("Received an invalid OTel name.\n"); - } - return name; } -/** - * Determine whether the input name is a valid OTel name or not - * - * From the spec: - * 1. They are non-empty strings - * 2. They are case-insensitive - * 3. The first character must be non-numeric, non-space, non-punctuation - * 4. Subsequent characters must belong to the alphanumeric characters, '_', '.', and '-'. - */ -bool PrometheusExporterUtils::IsValidName(const std::string &name) -{ - if (name.empty()) - { - return false; - } - - if (isnumber(name[0]) || isspace(name[0]) || ispunct(name[0])) - { - return false; - } - - for (std::string::size_type i = 1; i < name.size(); i++) - { - if (!isalnum(name[i]) && name[i] != '_' && name[i] != '.' && name[i] != '-') - { - return false; - } - } - - return true; -} - /** * Set value to metric family for different aggregator */ @@ -422,18 +376,15 @@ void PrometheusExporterUtils::SetValue(std::vector values, { switch (type) { - case prometheus_client::MetricType::Counter: - { + case prometheus_client::MetricType::Counter: { metric->counter.value = values[0]; break; } - case prometheus_client::MetricType::Gauge: - { + case prometheus_client::MetricType::Gauge: { metric->gauge.value = values[0]; break; } - case prometheus_client::MetricType::Untyped: - { + case prometheus_client::MetricType::Untyped: { metric->untyped.value = values[0]; break; } From 9c74f41fad946a25e206f9295eac39e87046a8d2 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 22:40:34 -0400 Subject: [PATCH 03/32] format code --- exporters/prometheus/src/prometheus_exporter_utils.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index 5708b9d0ed..30ce7c5d82 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -376,15 +376,18 @@ void PrometheusExporterUtils::SetValue(std::vector values, { switch (type) { - case prometheus_client::MetricType::Counter: { + case prometheus_client::MetricType::Counter: + { metric->counter.value = values[0]; break; } - case prometheus_client::MetricType::Gauge: { + case prometheus_client::MetricType::Gauge: + { metric->gauge.value = values[0]; break; } - case prometheus_client::MetricType::Untyped: { + case prometheus_client::MetricType::Untyped: + { metric->untyped.value = values[0]; break; } From 91f382a85cd120603adcb5f459c2b6b0ac6792ef Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 22:51:36 -0400 Subject: [PATCH 04/32] delete useless try catch --- .../src/prometheus_exporter_utils.cc | 48 +++++++------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index 30ce7c5d82..4a6bd70c35 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -64,21 +64,15 @@ std::vector PrometheusExporterUtils::TranslateT void PrometheusExporterUtils::SetMetricFamily(metric_sdk::Record &record, prometheus_client::MetricFamily *metric_family) { - try - { - auto origin_name = record.GetName(); - auto sanitized = SanitizeNames(origin_name); - if (origin_name != sanitized) - { - std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\"" - << std::endl; - } - metric_family->name = sanitized; - } - catch (std::invalid_argument &e) + + auto origin_name = record.GetName(); + auto sanitized = SanitizeNames(origin_name); + if (origin_name != sanitized) { - metric_family->name = record.GetName(); + std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\"" + << std::endl; } + metric_family->name = sanitized; metric_family->help = record.GetDescription(); // unpack the variant and set the metric data to metric family struct @@ -295,21 +289,14 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me metric.label.resize(label_pairs.size()); for (int i = 0; i < label_pairs.size(); ++i) { - try + auto origin_name = label_pairs[i].first; + auto sanitized = SanitizeNames(origin_name); + if (origin_name != sanitized) { - auto origin_name = label_pairs[i].first; - auto sanitized = SanitizeNames(origin_name); - if (origin_name != sanitized) - { - std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\"" - << std::endl; - } - metric.label[i].name = sanitized; - } - catch (std::invalid_argument &e) - { - metric.label[i].name = label_pairs[i].first; + std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\"" + << std::endl; } + metric.label[i].name = sanitized; metric.label[i].value = label_pairs[i].second; } } @@ -376,18 +363,15 @@ void PrometheusExporterUtils::SetValue(std::vector values, { switch (type) { - case prometheus_client::MetricType::Counter: - { + case prometheus_client::MetricType::Counter: { metric->counter.value = values[0]; break; } - case prometheus_client::MetricType::Gauge: - { + case prometheus_client::MetricType::Gauge: { metric->gauge.value = values[0]; break; } - case prometheus_client::MetricType::Untyped: - { + case prometheus_client::MetricType::Untyped: { metric->untyped.value = values[0]; break; } From b826383cc9867eeab2ea6b554eb6c22a6f88c0b6 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 22:53:31 -0400 Subject: [PATCH 05/32] delete useless try catch --- exporters/prometheus/src/prometheus_exporter_utils.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index 4a6bd70c35..271be027d1 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -363,15 +363,18 @@ void PrometheusExporterUtils::SetValue(std::vector values, { switch (type) { - case prometheus_client::MetricType::Counter: { + case prometheus_client::MetricType::Counter: + { metric->counter.value = values[0]; break; } - case prometheus_client::MetricType::Gauge: { + case prometheus_client::MetricType::Gauge: + { metric->gauge.value = values[0]; break; } - case prometheus_client::MetricType::Untyped: { + case prometheus_client::MetricType::Untyped: + { metric->untyped.value = values[0]; break; } From d98baf50301f85dcfc6b647eff561604bd7384c4 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 23:24:33 -0400 Subject: [PATCH 06/32] try to add promethues client to ci --- ci/setup_cmake.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index 0ab9be37fd..63e7b40264 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -14,3 +14,16 @@ cmake CMakeLists.txt make cp *.a /usr/lib || cp lib/*.a /usr/lib popd + +# Prometheus client +git clone https://github.com/jupp0r/prometheus-cpp.git +cd prometheus-cpp +git submodule init +git submodule update +mkdir _build +cd _build +cmake .. -DBUILD_SHARED_LIBS=ON +make -j 4 +mkdir -p deploy +make DESTDIR=`pwd`/deploy install +make install \ No newline at end of file From deb2d4b633500aecaab3c5b71888710e863cf77f Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 23:30:22 -0400 Subject: [PATCH 07/32] try to add promethues client to ci --- ci/setup_ci_environment.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/setup_ci_environment.sh b/ci/setup_ci_environment.sh index 66b3d73d67..8d1a887872 100755 --- a/ci/setup_ci_environment.sh +++ b/ci/setup_ci_environment.sh @@ -8,4 +8,5 @@ apt-get install --no-install-recommends --no-install-suggests -y \ wget \ git \ valgrind \ - lcov + lcov \ + curl From c099a760b220f5694e00fd2d9875839b58680840 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 23:34:08 -0400 Subject: [PATCH 08/32] try to add promethues client to ci --- ci/setup_ci_environment.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/setup_ci_environment.sh b/ci/setup_ci_environment.sh index 8d1a887872..28fbf30715 100755 --- a/ci/setup_ci_environment.sh +++ b/ci/setup_ci_environment.sh @@ -9,4 +9,4 @@ apt-get install --no-install-recommends --no-install-suggests -y \ git \ valgrind \ lcov \ - curl + libcurl4-openssl-dev From 215a9380448d4600d19bcc1feddfbfc054337943 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 17 Aug 2020 23:43:33 -0400 Subject: [PATCH 09/32] try to add promethues client to ci --- ci/setup_ci_environment.sh | 3 +-- ci/setup_cmake.sh | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/setup_ci_environment.sh b/ci/setup_ci_environment.sh index 28fbf30715..66b3d73d67 100755 --- a/ci/setup_ci_environment.sh +++ b/ci/setup_ci_environment.sh @@ -8,5 +8,4 @@ apt-get install --no-install-recommends --no-install-suggests -y \ wget \ git \ valgrind \ - lcov \ - libcurl4-openssl-dev + lcov diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index 63e7b40264..d3c58a43f7 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -5,7 +5,8 @@ set -e apt-get install --no-install-recommends --no-install-suggests -y \ cmake \ libbenchmark-dev \ - libgtest-dev + libgtest-dev \ + libcurl4-openssl-dev # Follows these instructions for setting up gtest # https://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/ From eee7fac5845f13a0309b35abf3cf491129ea28c8 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Tue, 18 Aug 2020 11:17:36 -0400 Subject: [PATCH 10/32] modify prometheus client build --- ci/setup_cmake.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index d3c58a43f7..6a4fb86e51 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -25,6 +25,4 @@ mkdir _build cd _build cmake .. -DBUILD_SHARED_LIBS=ON make -j 4 -mkdir -p deploy -make DESTDIR=`pwd`/deploy install make install \ No newline at end of file From eb4957e02cd298ad0d4fa4d45ada351d142177ef Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Tue, 18 Aug 2020 11:48:45 -0400 Subject: [PATCH 11/32] extract prometheus client instalation to a separate script --- ci/Dockerfile | 4 +++- ci/install_prometheus_client.sh | 10 ++++++++++ ci/setup_cmake.sh | 11 ----------- 3 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 ci/install_prometheus_client.sh diff --git a/ci/Dockerfile b/ci/Dockerfile index a1f43af928..a9a053a598 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -8,10 +8,12 @@ ADD install_gcc48.sh /setup-ci ADD install_bazelisk.sh /setup-ci ADD install_protobuf.sh /setup-ci ADD install_format_tools.sh /setup-ci +ADD install_prometheus_client.sh /setup-ci RUN /setup-ci/setup_ci_environment.sh \ && /setup-ci/setup_cmake.sh \ && /setup-ci/install_gcc48.sh \ && /setup-ci/install_bazelisk.sh \ && /setup-ci/install_protobuf.sh \ - && /setup-ci/install_format_tools.sh + && /setup-ci/install_format_tools.sh \ + && /setup-ci/install_prometheus_client.sh diff --git a/ci/install_prometheus_client.sh b/ci/install_prometheus_client.sh new file mode 100644 index 0000000000..8c98f0b572 --- /dev/null +++ b/ci/install_prometheus_client.sh @@ -0,0 +1,10 @@ +# Prometheus client +git clone https://github.com/jupp0r/prometheus-cpp.git +cd prometheus-cpp +git submodule init +git submodule update +mkdir _build +cd _build +cmake .. -DBUILD_SHARED_LIBS=ON +make -j 4 +make install diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index 6a4fb86e51..c6bff6d308 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -15,14 +15,3 @@ cmake CMakeLists.txt make cp *.a /usr/lib || cp lib/*.a /usr/lib popd - -# Prometheus client -git clone https://github.com/jupp0r/prometheus-cpp.git -cd prometheus-cpp -git submodule init -git submodule update -mkdir _build -cd _build -cmake .. -DBUILD_SHARED_LIBS=ON -make -j 4 -make install \ No newline at end of file From c1e1da3944968c996f8965e7cbe92840002051c5 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Tue, 18 Aug 2020 14:13:38 -0400 Subject: [PATCH 12/32] change script to use prometheus client 0.9.0 release --- ci/install_prometheus_client.sh | 12 ++++++------ ci/setup_cmake.sh | 10 ++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/ci/install_prometheus_client.sh b/ci/install_prometheus_client.sh index 8c98f0b572..b1747f19cd 100644 --- a/ci/install_prometheus_client.sh +++ b/ci/install_prometheus_client.sh @@ -1,10 +1,10 @@ -# Prometheus client -git clone https://github.com/jupp0r/prometheus-cpp.git +#!/bin/bash + +git clone https://github.com/jupp0r/prometheus-cpp cd prometheus-cpp +git checkout v0.9.0 git submodule init git submodule update -mkdir _build -cd _build +mkdir _build && cd _build cmake .. -DBUILD_SHARED_LIBS=ON -make -j 4 -make install +make && make install diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index c6bff6d308..5dc6c45961 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -15,3 +15,13 @@ cmake CMakeLists.txt make cp *.a /usr/lib || cp lib/*.a /usr/lib popd + +# Prometheus client +git clone https://github.com/jupp0r/prometheus-cpp +cd prometheus-cpp +git checkout v0.9.0 +git submodule init +git submodule update +mkdir _build && cd _build +cmake .. -DBUILD_SHARED_LIBS=ON +make && make install From 942714e8f82a70d67d74a6161f6bd6ff1083b373 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Wed, 19 Aug 2020 15:22:51 -0400 Subject: [PATCH 13/32] try to add prom-client git submodule; try to add script to install on windows with vcpkg --- .gitmodules | 3 ++ ci/install_windows_prometheus_client.ps1 | 6 ++++ ci/ports/prometheus-cpp/CONTROL | 20 +++++++++++ ci/ports/prometheus-cpp/portfile.cmake | 43 ++++++++++++++++++++++++ ci/setup_cmake.sh | 10 ------ third_party/prometheus-cpp | 1 + 6 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 .gitmodules create mode 100644 ci/install_windows_prometheus_client.ps1 create mode 100644 ci/ports/prometheus-cpp/CONTROL create mode 100644 ci/ports/prometheus-cpp/portfile.cmake create mode 160000 third_party/prometheus-cpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..94dac0ba74 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/prometheus-cpp"] + path = third_party/prometheus-cpp + url = https://github.com/jupp0r/prometheus-cpp.git diff --git a/ci/install_windows_prometheus_client.ps1 b/ci/install_windows_prometheus_client.ps1 new file mode 100644 index 0000000000..4c7b8f97d1 --- /dev/null +++ b/ci/install_windows_prometheus_client.ps1 @@ -0,0 +1,6 @@ +$ErrorActionPreference = "Stop" +trap { $host.SetShouldExit(1) } + +cd vcpkg +# Lock to specific version of Protobuf port file to avoid build break +./vcpkg install --overlay-ports="$PSScriptRoot\ports" prometheus-cpp:x86-windows diff --git a/ci/ports/prometheus-cpp/CONTROL b/ci/ports/prometheus-cpp/CONTROL new file mode 100644 index 0000000000..99b84715cc --- /dev/null +++ b/ci/ports/prometheus-cpp/CONTROL @@ -0,0 +1,20 @@ +Source: prometheus-cpp +Version: 0.9.0 +Description: Prometheus Client Library for Modern C++ +Default-Features: compression, pull + +Feature: compression +Build-Depends: zlib +Description: Enable zlib compression + +Feature: tests +Build-Depends: gtest +Description: Additional testing support + +Feature: pull +Build-Depends: civetweb +Description: Support for regular pull mode + +Feature: push +Build-Depends: curl +Description: Support push gateway diff --git a/ci/ports/prometheus-cpp/portfile.cmake b/ci/ports/prometheus-cpp/portfile.cmake new file mode 100644 index 0000000000..01dbfe91a2 --- /dev/null +++ b/ci/ports/prometheus-cpp/portfile.cmake @@ -0,0 +1,43 @@ +include(vcpkg_common_functions) + +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO jupp0r/prometheus-cpp + REF v0.9.0 + SHA512 d9d5fbbd8c8aad5dd6a5e872275324d689a0c57199e4158d74e13ea62b286fa71dee01bb4197b906b79792bf1ca4e67a46b5c04621d7070241ac32876f6de891 + HEAD_REF master +) + +macro(feature FEATURENAME OPTIONNAME) + if ("${FEATURENAME}" IN_LIST FEATURES) + list(APPEND FEATURE_OPTIONS -D${OPTIONNAME}=TRUE) + else () + list(APPEND FEATURE_OPTIONS -D${OPTIONNAME}=FALSE) + endif () +endmacro() + +feature(compression ENABLE_COMPRESSION) +feature(pull ENABLE_PULL) +feature(push ENABLE_PUSH) +feature(tests ENABLE_TESTING) + +vcpkg_configure_cmake( + SOURCE_PATH ${SOURCE_PATH} + PREFER_NINJA + OPTIONS + -DUSE_THIRDPARTY_LIBRARIES=OFF # use vcpkg packages + ${FEATURE_OPTIONS} +) + +vcpkg_install_cmake() + +vcpkg_copy_pdbs() + +vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/prometheus-cpp) + +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) + +# Handle copyright +configure_file(${SOURCE_PATH}/LICENSE ${CURRENT_PACKAGES_DIR}/share/prometheus-cpp/copyright COPYONLY) diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index 5dc6c45961..c6bff6d308 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -15,13 +15,3 @@ cmake CMakeLists.txt make cp *.a /usr/lib || cp lib/*.a /usr/lib popd - -# Prometheus client -git clone https://github.com/jupp0r/prometheus-cpp -cd prometheus-cpp -git checkout v0.9.0 -git submodule init -git submodule update -mkdir _build && cd _build -cmake .. -DBUILD_SHARED_LIBS=ON -make && make install diff --git a/third_party/prometheus-cpp b/third_party/prometheus-cpp new file mode 160000 index 0000000000..de66b57c42 --- /dev/null +++ b/third_party/prometheus-cpp @@ -0,0 +1 @@ +Subproject commit de66b57c42cc23b5b412ef4ae01697dbda259da4 From a13bf69f8c54c687ac40b61e8161a3fb31d21eeb Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Wed, 19 Aug 2020 15:45:57 -0400 Subject: [PATCH 14/32] add prometheus-client as subdirectory in main cmake file --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94b6c44354..425bc2ca25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,8 @@ if(BUILD_TESTING) include_directories(SYSTEM ${GTEST_INCLUDE_DIRS}) endif() +add_subdirectory(third_party/prometheus-cpp) + include_directories(api/include) add_subdirectory(api) include_directories(sdk/include) From 7f8f2f5f7409dad8403fca6c6cefee168d36aa07 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Wed, 19 Aug 2020 16:20:16 -0400 Subject: [PATCH 15/32] Removed submodule --- .gitmodules | 3 --- third_party/prometheus-cpp | 1 - 2 files changed, 4 deletions(-) delete mode 160000 third_party/prometheus-cpp diff --git a/.gitmodules b/.gitmodules index 94dac0ba74..e69de29bb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "third_party/prometheus-cpp"] - path = third_party/prometheus-cpp - url = https://github.com/jupp0r/prometheus-cpp.git diff --git a/third_party/prometheus-cpp b/third_party/prometheus-cpp deleted file mode 160000 index de66b57c42..0000000000 --- a/third_party/prometheus-cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit de66b57c42cc23b5b412ef4ae01697dbda259da4 From 26c735a612b1f67471ca5645254dafc378573004 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Wed, 19 Aug 2020 23:36:19 -0400 Subject: [PATCH 16/32] try to install prometheus client with vcpkg --- .gitmodules | 3 +++ CMakeLists.txt | 2 -- ci/install_windows_prometheus_client.ps1 | 1 - ci/setup_windows_ci_environment.ps1 | 2 ++ third_party/prometheus-cpp | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) create mode 160000 third_party/prometheus-cpp diff --git a/.gitmodules b/.gitmodules index e69de29bb2..94dac0ba74 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/prometheus-cpp"] + path = third_party/prometheus-cpp + url = https://github.com/jupp0r/prometheus-cpp.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 425bc2ca25..94b6c44354 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,8 +48,6 @@ if(BUILD_TESTING) include_directories(SYSTEM ${GTEST_INCLUDE_DIRS}) endif() -add_subdirectory(third_party/prometheus-cpp) - include_directories(api/include) add_subdirectory(api) include_directories(sdk/include) diff --git a/ci/install_windows_prometheus_client.ps1 b/ci/install_windows_prometheus_client.ps1 index 4c7b8f97d1..81a9192108 100644 --- a/ci/install_windows_prometheus_client.ps1 +++ b/ci/install_windows_prometheus_client.ps1 @@ -2,5 +2,4 @@ $ErrorActionPreference = "Stop" trap { $host.SetShouldExit(1) } cd vcpkg -# Lock to specific version of Protobuf port file to avoid build break ./vcpkg install --overlay-ports="$PSScriptRoot\ports" prometheus-cpp:x86-windows diff --git a/ci/setup_windows_ci_environment.ps1 b/ci/setup_windows_ci_environment.ps1 index 6e2c91e467..2791d0cdb3 100755 --- a/ci/setup_windows_ci_environment.ps1 +++ b/ci/setup_windows_ci_environment.ps1 @@ -12,4 +12,6 @@ $VCPKG_DIR=(Get-Item -Path ".\").FullName ./vcpkg install --overlay-ports="$PSScriptRoot\ports" benchmark:x64-windows ./vcpkg install gtest:x64-windows + +./vcpkg install --overlay-ports="$PSScriptRoot\ports" prometheus-cpp:x86-windows Pop-Location diff --git a/third_party/prometheus-cpp b/third_party/prometheus-cpp new file mode 160000 index 0000000000..de66b57c42 --- /dev/null +++ b/third_party/prometheus-cpp @@ -0,0 +1 @@ +Subproject commit de66b57c42cc23b5b412ef4ae01697dbda259da4 From c083771d897660cb68091050aa9ddd0977c57ba7 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Fri, 21 Aug 2020 11:11:03 -0400 Subject: [PATCH 17/32] add windows prometheus client installation --- ci/setup_windows_ci_environment.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/setup_windows_ci_environment.ps1 b/ci/setup_windows_ci_environment.ps1 index 2791d0cdb3..084bea4934 100755 --- a/ci/setup_windows_ci_environment.ps1 +++ b/ci/setup_windows_ci_environment.ps1 @@ -13,5 +13,5 @@ $VCPKG_DIR=(Get-Item -Path ".\").FullName ./vcpkg install gtest:x64-windows -./vcpkg install --overlay-ports="$PSScriptRoot\ports" prometheus-cpp:x86-windows +./vcpkg install --overlay-ports="$PSScriptRoot\ports" prometheus-cpp:x64-windows Pop-Location From 140c73df2af9f53c48128b07ee6e666d9f9f9f66 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Sun, 23 Aug 2020 23:48:12 -0400 Subject: [PATCH 18/32] modify prometheus client command --- ci/install_prometheus_client.sh | 2 +- ci/install_windows_prometheus_client.ps1 | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 ci/install_windows_prometheus_client.ps1 diff --git a/ci/install_prometheus_client.sh b/ci/install_prometheus_client.sh index b1747f19cd..9a7dcb801a 100644 --- a/ci/install_prometheus_client.sh +++ b/ci/install_prometheus_client.sh @@ -1,6 +1,6 @@ #!/bin/bash -git clone https://github.com/jupp0r/prometheus-cpp +git clone https://github.com/jupp0r/prometheus-cpp.git cd prometheus-cpp git checkout v0.9.0 git submodule init diff --git a/ci/install_windows_prometheus_client.ps1 b/ci/install_windows_prometheus_client.ps1 deleted file mode 100644 index 81a9192108..0000000000 --- a/ci/install_windows_prometheus_client.ps1 +++ /dev/null @@ -1,5 +0,0 @@ -$ErrorActionPreference = "Stop" -trap { $host.SetShouldExit(1) } - -cd vcpkg -./vcpkg install --overlay-ports="$PSScriptRoot\ports" prometheus-cpp:x86-windows From 5e7453f0ceb9fbd8d5ccb5f7fb33a8b6810b2234 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 09:24:07 -0400 Subject: [PATCH 19/32] stick prometheus client to v0.9.0 and added sha256 --- WORKSPACE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 59d45f2d05..ef2c9611be 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -94,8 +94,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file" http_archive( name = "com_github_jupp0r_prometheus_cpp", - strip_prefix = "prometheus-cpp-master", - urls = ["https://github.com/jupp0r/prometheus-cpp/archive/master.zip"], + sha256 = "85ad6fea0f0dcb413104366b7d6109acdb015aff8767945511c5cad8202a28a6", + strip_prefix = "prometheus-cpp-0.9.0", + urls = ["https://github.com/jupp0r/prometheus-cpp/archive/v0.9.0.tar.gz"], ) load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories") From 0383028da00573818dadad766c4deedb90d2c635 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 09:24:34 -0400 Subject: [PATCH 20/32] fix problems from review comments --- .../prometheus/prometheus_exporter_utils.h | 35 +++++++++---------- .../src/prometheus_exporter_utils.cc | 21 +++++------ .../test/prometheus_exporter_utils_test.cc | 18 ++++------ 3 files changed, 33 insertions(+), 41 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h index c617f4548f..de63b4d88e 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h @@ -22,8 +22,7 @@ #include "opentelemetry/sdk/metrics/record.h" #include "prometheus/metric_family.h" -namespace prometheus_client = ::prometheus; -namespace metric_sdk = opentelemetry::sdk::metrics; +namespace metric_sdk = opentelemetry::sdk::metrics; OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -43,15 +42,15 @@ class PrometheusExporterUtils * @param records a collection of metrics in OpenTelemetry * @return a collection of translated metrics that is acceptable by Prometheus */ - static std::vector TranslateToPrometheus( - std::vector &records); + static std::vector<::prometheus::MetricFamily> TranslateToPrometheus( + const std::vector &records); private: /** * Set value to metric family according to record */ static void SetMetricFamily(metric_sdk::Record &record, - prometheus_client::MetricFamily *metric_family); + ::prometheus::MetricFamily *metric_family); /** * Sanitize the given metric name or label according to Prometheus rule. @@ -68,12 +67,12 @@ class PrometheusExporterUtils template static void SetMetricFamilyByAggregator(std::shared_ptr> aggregator, std::string labels_str, - prometheus_client::MetricFamily *metric_family); + ::prometheus::MetricFamily *metric_family); /** * Translate the OTel metric type to Prometheus metric type */ - static prometheus_client::MetricType TranslateType(metric_sdk::AggregatorKind kind); + static ::prometheus::MetricType TranslateType(metric_sdk::AggregatorKind kind); /** * Set metric data for: @@ -83,9 +82,9 @@ class PrometheusExporterUtils template static void SetData(std::vector values, const std::string &labels, - prometheus_client::MetricType type, + ::prometheus::MetricType type, std::chrono::nanoseconds time, - prometheus_client::MetricFamily *metric_family); + ::prometheus::MetricFamily *metric_family); /** * Set metric data for: @@ -97,7 +96,7 @@ class PrometheusExporterUtils const std::vector &counts, const std::string &labels, std::chrono::nanoseconds time, - prometheus_client::MetricFamily *metric_family); + ::prometheus::MetricFamily *metric_family); /** * Set metric data for: @@ -107,7 +106,7 @@ class PrometheusExporterUtils static void SetData(double value, const std::string &labels, std::chrono::nanoseconds time, - prometheus_client::MetricFamily *metric_family); + ::prometheus::MetricFamily *metric_family); /** * Set metric data for: @@ -120,14 +119,14 @@ class PrometheusExporterUtils const std::vector &quantiles, const std::string &labels, std::chrono::nanoseconds time, - prometheus_client::MetricFamily *metric_family, + ::prometheus::MetricFamily *metric_family, bool do_quantile, std::vector quantile_points); /** * Set time and labels to metric data */ - static void SetMetricBasic(prometheus_client::ClientMetric &metric, + static void SetMetricBasic(::prometheus::ClientMetric &metric, std::chrono::nanoseconds time, const std::string &labels); @@ -150,13 +149,13 @@ class PrometheusExporterUtils */ template static void SetValue(std::vector values, - prometheus_client::MetricType type, - prometheus_client::ClientMetric *metric); + ::prometheus::MetricType type, + ::prometheus::ClientMetric *metric); /** * Handle Gauge from MinMaxSumCount */ - static void SetValue(double value, prometheus_client::ClientMetric *metric); + static void SetValue(double value, ::prometheus::ClientMetric *metric); /** * Handle Histogram @@ -165,7 +164,7 @@ class PrometheusExporterUtils static void SetValue(std::vector values, std::vector boundaries, std::vector counts, - prometheus_client::ClientMetric *metric); + ::prometheus::ClientMetric *metric); /** * Handle Exact and Sketch @@ -174,7 +173,7 @@ class PrometheusExporterUtils static void SetValue(std::vector values, metric_sdk::AggregatorKind kind, std::vector quantiles, - prometheus_client::ClientMetric *metric, + ::prometheus::ClientMetric *metric, bool do_quantile, const std::vector &quantile_points); }; diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index 271be027d1..2ac3af3b24 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -23,6 +23,8 @@ #include "opentelemetry/sdk/metrics/aggregator/aggregator.h" #include "prometheus/metric_type.h" +namespace prometheus_client = ::prometheus; + OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { @@ -36,7 +38,7 @@ namespace prometheus * @return a collection of translated metrics that is acceptable by Prometheus */ std::vector PrometheusExporterUtils::TranslateToPrometheus( - std::vector &records) + const std::vector &records) { if (records.empty()) { @@ -69,8 +71,7 @@ void PrometheusExporterUtils::SetMetricFamily(metric_sdk::Record &record, auto sanitized = SanitizeNames(origin_name); if (origin_name != sanitized) { - std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\"" - << std::endl; + std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\"\n"; } metric_family->name = sanitized; metric_family->help = record.GetDescription(); @@ -281,7 +282,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me std::chrono::nanoseconds time, const std::string &labels) { - metric.timestamp_ms = time.count() / 1000; + metric.timestamp_ms = time.count() / 1000000; auto label_pairs = ParseLabel(labels); if (!label_pairs.empty()) @@ -293,8 +294,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me auto sanitized = SanitizeNames(origin_name); if (origin_name != sanitized) { - std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\"" - << std::endl; + std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\"\n"; } metric.label[i].name = sanitized; metric.label[i].value = label_pairs[i].second; @@ -363,18 +363,15 @@ void PrometheusExporterUtils::SetValue(std::vector values, { switch (type) { - case prometheus_client::MetricType::Counter: - { + case prometheus_client::MetricType::Counter: { metric->counter.value = values[0]; break; } - case prometheus_client::MetricType::Gauge: - { + case prometheus_client::MetricType::Gauge: { metric->gauge.value = values[0]; break; } - case prometheus_client::MetricType::Untyped: - { + case prometheus_client::MetricType::Untyped: { metric->untyped.value = values[0]; break; } diff --git a/exporters/prometheus/test/prometheus_exporter_utils_test.cc b/exporters/prometheus/test/prometheus_exporter_utils_test.cc index f3b5004088..5de04a02ee 100644 --- a/exporters/prometheus/test/prometheus_exporter_utils_test.cc +++ b/exporters/prometheus/test/prometheus_exporter_utils_test.cc @@ -30,11 +30,11 @@ #include "opentelemetry/sdk/metrics/aggregator/sketch_aggregator.h" using opentelemetry::exporter::prometheus::PrometheusExporterUtils; -namespace metric_sdk = opentelemetry::sdk::metrics; -namespace metric_api = opentelemetry::metrics; +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace metric_api = opentelemetry::metrics; +namespace prometheus_client = ::prometheus; OPENTELEMETRY_BEGIN_NAMESPACE - template void assert_basic(prometheus_client::MetricFamily &metric, const std::string &sanitized_name, @@ -52,26 +52,22 @@ void assert_basic(prometheus_client::MetricFamily &metric, switch (type) { - case prometheus_client::MetricType::Counter: - { + case prometheus_client::MetricType::Counter: { ASSERT_DOUBLE_EQ(metric_data.counter.value, vals[0]); break; } - case prometheus_client::MetricType::Gauge: - { + case prometheus_client::MetricType::Gauge: { ASSERT_EQ(metric_data.gauge.value, vals[0]); break; } - case prometheus_client::MetricType::Histogram: - { + case prometheus_client::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::Summary: - { + case prometheus_client::MetricType::Summary: { ASSERT_DOUBLE_EQ(metric_data.summary.sample_count, vals[0]); ASSERT_DOUBLE_EQ(metric_data.summary.sample_sum, vals[1]); break; From 645da3936fe91c63c3dac0f25eade34e5318167d Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 11:42:22 -0400 Subject: [PATCH 21/32] change CMakefile to conditional build prometheus --- CMakeLists.txt | 3 +++ ci/install_prometheus_client.sh | 10 ---------- exporters/CMakeLists.txt | 6 +++++- third_party/prometheus-cpp | 1 - 4 files changed, 8 insertions(+), 12 deletions(-) delete mode 100644 ci/install_prometheus_client.sh delete mode 160000 third_party/prometheus-cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 94b6c44354..d8ed3468b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,9 @@ endif() option(WITH_OTPROTOCOL "Whether to include the OpenTelemetry Protocol in the SDK" OFF) +option(WITH_PROMETHEUS + "Whether to include the Prometheus Client in the SDK" OFF) + set(WITH_PROTOBUF OFF) if(WITH_OTPROTOCOL) set(WITH_PROTOBUF ON) diff --git a/ci/install_prometheus_client.sh b/ci/install_prometheus_client.sh deleted file mode 100644 index 9a7dcb801a..0000000000 --- a/ci/install_prometheus_client.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -git clone https://github.com/jupp0r/prometheus-cpp.git -cd prometheus-cpp -git checkout v0.9.0 -git submodule init -git submodule update -mkdir _build && cd _build -cmake .. -DBUILD_SHARED_LIBS=ON -make && make install diff --git a/exporters/CMakeLists.txt b/exporters/CMakeLists.txt index 4090bd84a7..18fb6808ed 100644 --- a/exporters/CMakeLists.txt +++ b/exporters/CMakeLists.txt @@ -1,5 +1,9 @@ if(WITH_OTPROTOCOL) add_subdirectory(otlp) endif() + add_subdirectory(ostream) -add_subdirectory(prometheus) + +if(WITH_PROMETHEUS) + add_subdirectory(prometheus) +endif() \ No newline at end of file diff --git a/third_party/prometheus-cpp b/third_party/prometheus-cpp deleted file mode 160000 index de66b57c42..0000000000 --- a/third_party/prometheus-cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit de66b57c42cc23b5b412ef4ae01697dbda259da4 From 22237b457a7a8be928612e1545b9aa9225eb793d Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 12:23:41 -0400 Subject: [PATCH 22/32] modify CI bazel config so that prometheus is excluded for noexcept test --- ci/Dockerfile | 4 +--- ci/do_ci.sh | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ci/Dockerfile b/ci/Dockerfile index a9a053a598..a1f43af928 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -8,12 +8,10 @@ ADD install_gcc48.sh /setup-ci ADD install_bazelisk.sh /setup-ci ADD install_protobuf.sh /setup-ci ADD install_format_tools.sh /setup-ci -ADD install_prometheus_client.sh /setup-ci RUN /setup-ci/setup_ci_environment.sh \ && /setup-ci/setup_cmake.sh \ && /setup-ci/install_gcc48.sh \ && /setup-ci/install_bazelisk.sh \ && /setup-ci/install_protobuf.sh \ - && /setup-ci/install_format_tools.sh \ - && /setup-ci/install_prometheus_client.sh + && /setup-ci/install_format_tools.sh diff --git a/ci/do_ci.sh b/ci/do_ci.sh index fb641aa701..feea0f29c9 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -83,8 +83,8 @@ elif [[ "$1" == "bazel.legacy.test" ]]; then bazel test $BAZEL_TEST_OPTIONS -- //... -//exporters/otlp/... exit 0 elif [[ "$1" == "bazel.noexcept" ]]; then - bazel build --copt=-fno-exceptions $BAZEL_OPTIONS //... - bazel test --copt=-fno-exceptions $BAZEL_TEST_OPTIONS //... + bazel build --copt=-fno-exceptions $BAZEL_OPTIONS -- //... -//exporters/prometheus/... + bazel test --copt=-fno-exceptions $BAZEL_TEST_OPTIONS -- //... -//exporters/prometheus/... exit 0 elif [[ "$1" == "bazel.asan" ]]; then bazel test --config=asan $BAZEL_TEST_OPTIONS //... From 1d2930ec2856fa1055a300b5369ef4d9aaf602c3 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 15:07:01 -0400 Subject: [PATCH 23/32] try to fix 404 not found problem in setup cmake --- ci/ports/prometheus-cpp/CONTROL | 20 ------------ ci/ports/prometheus-cpp/portfile.cmake | 43 -------------------------- ci/setup_cmake.sh | 1 + ci/setup_windows_ci_environment.ps1 | 2 -- 4 files changed, 1 insertion(+), 65 deletions(-) delete mode 100644 ci/ports/prometheus-cpp/CONTROL delete mode 100644 ci/ports/prometheus-cpp/portfile.cmake diff --git a/ci/ports/prometheus-cpp/CONTROL b/ci/ports/prometheus-cpp/CONTROL deleted file mode 100644 index 99b84715cc..0000000000 --- a/ci/ports/prometheus-cpp/CONTROL +++ /dev/null @@ -1,20 +0,0 @@ -Source: prometheus-cpp -Version: 0.9.0 -Description: Prometheus Client Library for Modern C++ -Default-Features: compression, pull - -Feature: compression -Build-Depends: zlib -Description: Enable zlib compression - -Feature: tests -Build-Depends: gtest -Description: Additional testing support - -Feature: pull -Build-Depends: civetweb -Description: Support for regular pull mode - -Feature: push -Build-Depends: curl -Description: Support push gateway diff --git a/ci/ports/prometheus-cpp/portfile.cmake b/ci/ports/prometheus-cpp/portfile.cmake deleted file mode 100644 index 01dbfe91a2..0000000000 --- a/ci/ports/prometheus-cpp/portfile.cmake +++ /dev/null @@ -1,43 +0,0 @@ -include(vcpkg_common_functions) - -vcpkg_check_linkage(ONLY_STATIC_LIBRARY) - -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO jupp0r/prometheus-cpp - REF v0.9.0 - SHA512 d9d5fbbd8c8aad5dd6a5e872275324d689a0c57199e4158d74e13ea62b286fa71dee01bb4197b906b79792bf1ca4e67a46b5c04621d7070241ac32876f6de891 - HEAD_REF master -) - -macro(feature FEATURENAME OPTIONNAME) - if ("${FEATURENAME}" IN_LIST FEATURES) - list(APPEND FEATURE_OPTIONS -D${OPTIONNAME}=TRUE) - else () - list(APPEND FEATURE_OPTIONS -D${OPTIONNAME}=FALSE) - endif () -endmacro() - -feature(compression ENABLE_COMPRESSION) -feature(pull ENABLE_PULL) -feature(push ENABLE_PUSH) -feature(tests ENABLE_TESTING) - -vcpkg_configure_cmake( - SOURCE_PATH ${SOURCE_PATH} - PREFER_NINJA - OPTIONS - -DUSE_THIRDPARTY_LIBRARIES=OFF # use vcpkg packages - ${FEATURE_OPTIONS} -) - -vcpkg_install_cmake() - -vcpkg_copy_pdbs() - -vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/prometheus-cpp) - -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) - -# Handle copyright -configure_file(${SOURCE_PATH}/LICENSE ${CURRENT_PACKAGES_DIR}/share/prometheus-cpp/copyright COPYONLY) diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index c6bff6d308..54ee3987ce 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -2,6 +2,7 @@ set -e +apt update apt-get install --no-install-recommends --no-install-suggests -y \ cmake \ libbenchmark-dev \ diff --git a/ci/setup_windows_ci_environment.ps1 b/ci/setup_windows_ci_environment.ps1 index 084bea4934..6e2c91e467 100755 --- a/ci/setup_windows_ci_environment.ps1 +++ b/ci/setup_windows_ci_environment.ps1 @@ -12,6 +12,4 @@ $VCPKG_DIR=(Get-Item -Path ".\").FullName ./vcpkg install --overlay-ports="$PSScriptRoot\ports" benchmark:x64-windows ./vcpkg install gtest:x64-windows - -./vcpkg install --overlay-ports="$PSScriptRoot\ports" prometheus-cpp:x64-windows Pop-Location From 09eb665cbd71721c3eeae1c008e5e0d6bb659ced Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 15:25:30 -0400 Subject: [PATCH 24/32] format code --- CMakeLists.txt | 4 ++-- exporters/CMakeLists.txt | 2 +- .../prometheus/src/prometheus_exporter_utils.cc | 9 ++++++--- .../test/prometheus_exporter_utils_test.cc | 12 ++++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8ed3468b9..78ff1b5c89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ endif() option(WITH_OTPROTOCOL "Whether to include the OpenTelemetry Protocol in the SDK" OFF) -option(WITH_PROMETHEUS - "Whether to include the Prometheus Client in the SDK" OFF) +option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK" + OFF) set(WITH_PROTOBUF OFF) if(WITH_OTPROTOCOL) diff --git a/exporters/CMakeLists.txt b/exporters/CMakeLists.txt index 18fb6808ed..227c0f7f1f 100644 --- a/exporters/CMakeLists.txt +++ b/exporters/CMakeLists.txt @@ -6,4 +6,4 @@ add_subdirectory(ostream) if(WITH_PROMETHEUS) add_subdirectory(prometheus) -endif() \ No newline at end of file +endif() diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index 2ac3af3b24..b1d87ef89e 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -363,15 +363,18 @@ void PrometheusExporterUtils::SetValue(std::vector values, { switch (type) { - case prometheus_client::MetricType::Counter: { + case prometheus_client::MetricType::Counter: + { metric->counter.value = values[0]; break; } - case prometheus_client::MetricType::Gauge: { + case prometheus_client::MetricType::Gauge: + { metric->gauge.value = values[0]; break; } - case prometheus_client::MetricType::Untyped: { + case prometheus_client::MetricType::Untyped: + { metric->untyped.value = values[0]; break; } diff --git a/exporters/prometheus/test/prometheus_exporter_utils_test.cc b/exporters/prometheus/test/prometheus_exporter_utils_test.cc index 5de04a02ee..ed8f921265 100644 --- a/exporters/prometheus/test/prometheus_exporter_utils_test.cc +++ b/exporters/prometheus/test/prometheus_exporter_utils_test.cc @@ -52,22 +52,26 @@ void assert_basic(prometheus_client::MetricFamily &metric, switch (type) { - case prometheus_client::MetricType::Counter: { + case prometheus_client::MetricType::Counter: + { ASSERT_DOUBLE_EQ(metric_data.counter.value, vals[0]); break; } - case prometheus_client::MetricType::Gauge: { + case prometheus_client::MetricType::Gauge: + { ASSERT_EQ(metric_data.gauge.value, vals[0]); break; } - case prometheus_client::MetricType::Histogram: { + case prometheus_client::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::Summary: { + case prometheus_client::MetricType::Summary: + { ASSERT_DOUBLE_EQ(metric_data.summary.sample_count, vals[0]); ASSERT_DOUBLE_EQ(metric_data.summary.sample_sum, vals[1]); break; From 6e525d932eb3e5f95beaae4c99ebdb424a741f36 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 15:51:30 -0400 Subject: [PATCH 25/32] restore setup cmake file --- ci/setup_cmake.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index 54ee3987ce..0ab9be37fd 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -2,12 +2,10 @@ set -e -apt update apt-get install --no-install-recommends --no-install-suggests -y \ cmake \ libbenchmark-dev \ - libgtest-dev \ - libcurl4-openssl-dev + libgtest-dev # Follows these instructions for setting up gtest # https://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/ From e5f63c9555f407d4fe691190e2d806128331a495 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 17:19:11 -0400 Subject: [PATCH 26/32] add prometheus exporter tests to ci workflow --- .github/workflows/ci.yml | 2 ++ ci/do_ci.sh | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fb971743d..e4fab212f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,8 @@ jobs: sudo ./ci/setup_ci_environment.sh - name: run tests run: ./ci/do_ci.sh cmake.test + - name: run prometheus exporter tests + run: ./ci/do_ci.sh cmake.exporter.prometheus.test cmake_test_cxx20: name: CMake C++20 test diff --git a/ci/do_ci.sh b/ci/do_ci.sh index feea0f29c9..ab86e1219b 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -40,6 +40,33 @@ elif [[ "$1" == "cmake.exporter.otprotocol.test" ]]; then make make test exit 0 +elif [[ "$1" == "cmake.exporter.prometheus.test" ]]; then + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install zlib1g-dev + apt-get -y install libcurl4-openssl-dev + + cd third_party + git clone https://github.com/jupp0r/prometheus-cpp + cd prometheus-cpp + git checkout v0.9.0 + git submodule init + git submodule update + mkdir _build && cd _build + cmake .. -DBUILD_SHARED_LIBS=ON + make -j 4 + make install + + cd "${BUILD_DIR}" + rm -rf * + + cmake -DCMAKE_BUILD_TYPE=Debug \ + -DWITH_PROMETHEUS=ON \ + -DCMAKE_CXX_FLAGS="-Werror" \ + "${SRC_DIR}" + make + make test + exit 0 elif [[ "$1" == "cmake.test_example_plugin" ]]; then # Build the plugin cd "${BUILD_DIR}" From 17639bc01f5e636b1b8bca1582bdda7feede5e55 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 17:41:30 -0400 Subject: [PATCH 27/32] install dependencies in setup_cmake --- ci/do_ci.sh | 9 ++++----- ci/setup_cmake.sh | 6 +++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index ab86e1219b..9911719b5f 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -41,11 +41,10 @@ elif [[ "$1" == "cmake.exporter.otprotocol.test" ]]; then make test exit 0 elif [[ "$1" == "cmake.exporter.prometheus.test" ]]; then - export DEBIAN_FRONTEND=noninteractive - apt-get update - apt-get install zlib1g-dev - apt-get -y install libcurl4-openssl-dev - +# export DEBIAN_FRONTEND=noninteractive +# sudo apt-get update +# sudo apt-get install zlib1g-dev +# sudo apt-get -y install libcurl4-openssl-dev cd third_party git clone https://github.com/jupp0r/prometheus-cpp cd prometheus-cpp diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index 0ab9be37fd..8751d375ec 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -2,10 +2,14 @@ set -e +export DEBIAN_FRONTEND=noninteractive +apt-get update apt-get install --no-install-recommends --no-install-suggests -y \ cmake \ libbenchmark-dev \ - libgtest-dev + libgtest-dev \ + zlib1g-dev \ + libcurl4-openssl-dev # Follows these instructions for setting up gtest # https://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/ From 7c6b3083f93abbb4ec30a6baef27c28530085961 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Mon, 24 Aug 2020 18:01:47 -0400 Subject: [PATCH 28/32] try to figure out install permission problem --- ci/do_ci.sh | 9 +++++---- ci/setup_cmake.sh | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 9911719b5f..fecba4dc90 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -42,9 +42,10 @@ elif [[ "$1" == "cmake.exporter.otprotocol.test" ]]; then exit 0 elif [[ "$1" == "cmake.exporter.prometheus.test" ]]; then # export DEBIAN_FRONTEND=noninteractive -# sudo apt-get update -# sudo apt-get install zlib1g-dev -# sudo apt-get -y install libcurl4-openssl-dev +# apt-get update +# apt-get install sudo +# apt-get install zlib1g-dev +# apt-get -y install libcurl4-openssl-dev cd third_party git clone https://github.com/jupp0r/prometheus-cpp cd prometheus-cpp @@ -54,7 +55,7 @@ elif [[ "$1" == "cmake.exporter.prometheus.test" ]]; then mkdir _build && cd _build cmake .. -DBUILD_SHARED_LIBS=ON make -j 4 - make install + sudo make install cd "${BUILD_DIR}" rm -rf * diff --git a/ci/setup_cmake.sh b/ci/setup_cmake.sh index 8751d375ec..34097dbaa3 100755 --- a/ci/setup_cmake.sh +++ b/ci/setup_cmake.sh @@ -9,6 +9,7 @@ apt-get install --no-install-recommends --no-install-suggests -y \ libbenchmark-dev \ libgtest-dev \ zlib1g-dev \ + sudo \ libcurl4-openssl-dev # Follows these instructions for setting up gtest From fda7664862d2c0d0093673b4cc7d32fcdcff2d25 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Tue, 25 Aug 2020 16:05:08 -0400 Subject: [PATCH 29/32] remove printing for sanitize names --- exporters/prometheus/src/prometheus_exporter_utils.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index b1d87ef89e..9035a4def9 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -69,10 +69,6 @@ void PrometheusExporterUtils::SetMetricFamily(metric_sdk::Record &record, auto origin_name = record.GetName(); auto sanitized = SanitizeNames(origin_name); - if (origin_name != sanitized) - { - std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\"\n"; - } metric_family->name = sanitized; metric_family->help = record.GetDescription(); @@ -292,10 +288,6 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me { auto origin_name = label_pairs[i].first; auto sanitized = SanitizeNames(origin_name); - if (origin_name != sanitized) - { - std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\"\n"; - } metric.label[i].name = sanitized; metric.label[i].value = label_pairs[i].second; } From 6569d3e6a75b8fd3fe574960b8e5def2c758433e Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Tue, 25 Aug 2020 16:05:51 -0400 Subject: [PATCH 30/32] add comment for ignoring Prometheus Exporter in noexcept test --- ci/do_ci.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index fecba4dc90..54e84b9e92 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -110,6 +110,8 @@ elif [[ "$1" == "bazel.legacy.test" ]]; then bazel test $BAZEL_TEST_OPTIONS -- //... -//exporters/otlp/... exit 0 elif [[ "$1" == "bazel.noexcept" ]]; then + # there are some exceptions and error handling code from the Prometheus Client + # that make this test always fail. ignore Prometheus exporter in the noexcept here. bazel build --copt=-fno-exceptions $BAZEL_OPTIONS -- //... -//exporters/prometheus/... bazel test --copt=-fno-exceptions $BAZEL_TEST_OPTIONS -- //... -//exporters/prometheus/... exit 0 From 781277d5740b4f2d87d8dde1b05b2f47d34d91a2 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Tue, 25 Aug 2020 16:28:45 -0400 Subject: [PATCH 31/32] format code --- exporters/prometheus/src/prometheus_exporter_utils.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index 9035a4def9..d9f1ef9498 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -67,8 +67,8 @@ void PrometheusExporterUtils::SetMetricFamily(metric_sdk::Record &record, prometheus_client::MetricFamily *metric_family) { - auto origin_name = record.GetName(); - auto sanitized = SanitizeNames(origin_name); + auto origin_name = record.GetName(); + auto sanitized = SanitizeNames(origin_name); metric_family->name = sanitized; metric_family->help = record.GetDescription(); @@ -280,14 +280,14 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me { metric.timestamp_ms = time.count() / 1000000; - auto label_pairs = ParseLabel(labels); + auto label_pairs = Parse Label(labels); if (!label_pairs.empty()) { metric.label.resize(label_pairs.size()); for (int i = 0; i < label_pairs.size(); ++i) { - auto origin_name = label_pairs[i].first; - auto sanitized = SanitizeNames(origin_name); + auto origin_name = label_pairs[i].first; + auto sanitized = SanitizeNames(origin_name); metric.label[i].name = sanitized; metric.label[i].value = label_pairs[i].second; } From c370218a45ac311a326a77a0e58a3c71120283d9 Mon Sep 17 00:00:00 2001 From: Cunjun Wang Date: Tue, 25 Aug 2020 16:41:56 -0400 Subject: [PATCH 32/32] format code --- exporters/prometheus/src/prometheus_exporter_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/prometheus/src/prometheus_exporter_utils.cc b/exporters/prometheus/src/prometheus_exporter_utils.cc index d9f1ef9498..de2a233fa8 100644 --- a/exporters/prometheus/src/prometheus_exporter_utils.cc +++ b/exporters/prometheus/src/prometheus_exporter_utils.cc @@ -280,7 +280,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me { metric.timestamp_ms = time.count() / 1000000; - auto label_pairs = Parse Label(labels); + auto label_pairs = ParseLabel(labels); if (!label_pairs.empty()) { metric.label.resize(label_pairs.size());