From 4782e2e498fd70eb2e37007d4b05017bd4dd1333 Mon Sep 17 00:00:00 2001 From: erichsueh3 Date: Thu, 6 Aug 2020 17:59:52 -0700 Subject: [PATCH 1/3] Prometheus Collector implementation: header and source files --- .../prometheus/prometheus_collector.h | 84 ++++++++++ .../prometheus/src/prometheus_collector.cc | 152 ++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h create mode 100644 exporters/prometheus/src/prometheus_collector.cc diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h new file mode 100644 index 0000000000..18bfa61800 --- /dev/null +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include + +#include "prometheus_exporter_utils.h" +#include "opentelemetry/sdk/metrics/record.h" +#include "prometheus/collectable.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 Collector maintains the intermediate collection in Prometheus Exporter + */ +class PrometheusCollector : public prometheus_client::Collectable +{ +public: + /** + * Default Constructor. + * + * This constructor initializes the collection for metrics to export + * in this class with default capacity + */ + explicit PrometheusCollector(int max_collection_size = 2048); + + /** + * Collects all metrics data from metricsToCollect collection. + * + * @return all metrics in the metricsToCollect snapshot + */ + std::vector Collect() const override; + + /** + * This function is called by export() function and add the collection of + * records to the metricsToCollect collection + * + * @param records a collection of records to add to the metricsToCollect collection + */ + void AddMetricData(const std::vector &records); + + /** + * Get the current collection in the collector. + * + * @return the current metricsToCollect collection + */ + std::vector GetCollection(); + + /** + * Gets the maximum size of the collection. + * + * @return max collection size + */ + int GetMaxCollectionSize() const; + +private: + /** + * Collection of metrics data from the export() function, and to be export + * to user when they send a pull request. This collection is a pointer + * to a collection so Collect() is able to clear the collection, even + * though it is a const function. + */ + std::unique_ptr> metrics_to_collect_; + + /** + * Maximum size of the metricsToCollect collection. + */ + int max_collection_size_; + + /* + * Lock when operating the metricsToCollect collection + */ + mutable std::mutex collection_lock_; +}; +} // namespace prometheus +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/src/prometheus_collector.cc b/exporters/prometheus/src/prometheus_collector.cc new file mode 100644 index 0000000000..f3eb092f6e --- /dev/null +++ b/exporters/prometheus/src/prometheus_collector.cc @@ -0,0 +1,152 @@ +#include + +#include "opentelemetry/exporters/prometheus/prometheus_collector.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace prometheus +{ +/** + * Default Constructor. + * + * This constructor initializes the collection for metrics to export + * in this class with default capacity + */ +PrometheusCollector::PrometheusCollector(int max_collection_size) + : max_collection_size_(max_collection_size) +{ + metrics_to_collect_ = + std::unique_ptr>(new std::vector); +} + +/** + * Collects all metrics data from metricsToCollect collection. + * + * @return all metrics in the metricsToCollect snapshot + */ +std::vector PrometheusCollector::Collect() const +{ + if (metrics_to_collect_->empty()) + { + return {}; + } + + std::vector result; + + // copy the intermediate collection, and then clear it + std::vector copied_data; + + collection_lock_.lock(); + copied_data = std::vector(*metrics_to_collect_); + metrics_to_collect_->clear(); + collection_lock_.unlock(); + + result = PrometheusExporterUtils::TranslateToPrometheus(copied_data); + return result; +} + +/** + * This function is called by export() function and add the collection of + * records to the metricsToCollect collection + * + * @param records a collection of records to add to the metricsToCollect collection + */ +void PrometheusCollector::AddMetricData(const std::vector &records) +{ + if (metrics_to_collect_->size() + records.size() <= max_collection_size_ && !records.empty()) + { + /** + * ValidAggregator is a lambda that checks a Record to see if its + * Aggregator is a valid nostd::shared_ptr and not a nullptr. + */ + auto ValidAggregator = [](sdk::metrics::Record record) { + auto aggregator_variant = record.GetAggregator(); + if (nostd::holds_alternative>>( + aggregator_variant)) + { + auto aggregator = + nostd::get>>(aggregator_variant); + if (!aggregator) + { + return false; + } + } + else if (nostd::holds_alternative>>( + aggregator_variant)) + { + auto aggregator = + nostd::get>>(aggregator_variant); + if (!aggregator) + { + return false; + } + } + else if (nostd::holds_alternative>>( + aggregator_variant)) + { + auto aggregator = + nostd::get>>(aggregator_variant); + if (!aggregator) + { + return false; + } + } + else if (nostd::holds_alternative>>( + aggregator_variant)) + { + auto aggregator = + nostd::get>>(aggregator_variant); + if (!aggregator) + { + return false; + } + } + + return true; + }; + + collection_lock_.lock(); + + for (auto &r : records) + { + if (ValidAggregator(r)) + { + metrics_to_collect_->push_back(r); + } + // Drop the record and write to std::cout + else + { + // Cannot call non const functions on const Record r + sdk::metrics::Record c = r; + std::cout << "Dropped Record containing invalid aggregator with name: " + c.GetName() << std::endl; + } + } + + collection_lock_.unlock(); + } +} + +/** + * Get the current collection in the collector. + * + * @return the current metrics_to_collect collection + */ +std::vector PrometheusCollector::GetCollection() +{ + return *metrics_to_collect_; +} + +/** + * Gets the maximum size of the collection. + * + * @return max collection size + */ +int PrometheusCollector::GetMaxCollectionSize() const +{ + return max_collection_size_; +} + +} // namespace prometheus +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE From 9019032028369a2d44311263dace28a5e4778a93 Mon Sep 17 00:00:00 2001 From: erichsueh3 Date: Fri, 7 Aug 2020 10:41:56 -0700 Subject: [PATCH 2/3] CI formatting, added copyright header --- .../prometheus/prometheus_collector.h | 18 +++++++++++++++++- .../prometheus/src/prometheus_collector.cc | 19 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h index 18bfa61800..71aad4d59b 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/prometheus_collector.h @@ -1,13 +1,29 @@ +/* + * 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 -#include "prometheus_exporter_utils.h" #include "opentelemetry/sdk/metrics/record.h" #include "prometheus/collectable.h" #include "prometheus/metric_family.h" +#include "prometheus_exporter_utils.h" namespace prometheus_client = ::prometheus; namespace metric_sdk = opentelemetry::sdk::metrics; diff --git a/exporters/prometheus/src/prometheus_collector.cc b/exporters/prometheus/src/prometheus_collector.cc index f3eb092f6e..bd3908ff85 100644 --- a/exporters/prometheus/src/prometheus_collector.cc +++ b/exporters/prometheus/src/prometheus_collector.cc @@ -1,3 +1,19 @@ +/* + * 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 "opentelemetry/exporters/prometheus/prometheus_collector.h" @@ -119,7 +135,8 @@ void PrometheusCollector::AddMetricData(const std::vector { // Cannot call non const functions on const Record r sdk::metrics::Record c = r; - std::cout << "Dropped Record containing invalid aggregator with name: " + c.GetName() << std::endl; + std::cout << "Dropped Record containing invalid aggregator with name: " + c.GetName() + << std::endl; } } From 6d47f844597ccd732ac7bf11d5846114caf1cf28 Mon Sep 17 00:00:00 2001 From: erichsueh3 Date: Fri, 14 Aug 2020 22:31:07 -0700 Subject: [PATCH 3/3] fixed ValidAggregator lambda to use std::shared_ptrs instead of nostd::shared_ptrs --- .../prometheus/src/prometheus_collector.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/exporters/prometheus/src/prometheus_collector.cc b/exporters/prometheus/src/prometheus_collector.cc index bd3908ff85..3851296209 100644 --- a/exporters/prometheus/src/prometheus_collector.cc +++ b/exporters/prometheus/src/prometheus_collector.cc @@ -74,45 +74,45 @@ void PrometheusCollector::AddMetricData(const std::vector { /** * ValidAggregator is a lambda that checks a Record to see if its - * Aggregator is a valid nostd::shared_ptr and not a nullptr. + * Aggregator is a valid std::shared_ptr and not a nullptr. */ auto ValidAggregator = [](sdk::metrics::Record record) { auto aggregator_variant = record.GetAggregator(); - if (nostd::holds_alternative>>( + if (nostd::holds_alternative>>( aggregator_variant)) { auto aggregator = - nostd::get>>(aggregator_variant); + nostd::get>>(aggregator_variant); if (!aggregator) { return false; } } - else if (nostd::holds_alternative>>( + else if (nostd::holds_alternative>>( aggregator_variant)) { auto aggregator = - nostd::get>>(aggregator_variant); + nostd::get>>(aggregator_variant); if (!aggregator) { return false; } } - else if (nostd::holds_alternative>>( + else if (nostd::holds_alternative>>( aggregator_variant)) { auto aggregator = - nostd::get>>(aggregator_variant); + nostd::get>>(aggregator_variant); if (!aggregator) { return false; } } - else if (nostd::holds_alternative>>( + else if (nostd::holds_alternative>>( aggregator_variant)) { auto aggregator = - nostd::get>>(aggregator_variant); + nostd::get>>(aggregator_variant); if (!aggregator) { return false;