You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/deps/prometheus-cpp/serial_exposer.patch

262 lines
7.8 KiB

diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h
index 93e0b2b..0e83a7a 100644
--- a/pull/include/prometheus/exposer.h
+++ b/pull/include/prometheus/exposer.h
@@ -6,9 +6,12 @@
#include <mutex>
#include <string>
#include <vector>
+#include <functional>
+#include <map>
#include "prometheus/collectable.h"
#include "prometheus/detail/pull_export.h"
+#include "prometheus/registry.h"
class CivetServer;
struct CivetCallbacks;
@@ -17,6 +20,7 @@ namespace prometheus {
namespace detail {
class Endpoint;
+class SerialMetricsHandler;
} // namespace detail
class PROMETHEUS_CPP_PULL_EXPORT Exposer {
@@ -53,4 +57,18 @@ class PROMETHEUS_CPP_PULL_EXPORT Exposer {
std::mutex mutex_;
};
+class SerialExposer {
+ public:
+ explicit SerialExposer(const std::function<void()> update_callback = std::function<void()> {});
+ std::pair<std::map<std::string, std::string>, std::string>
+ operator()(const std::map<std::string, std::string>& req_headers);
+ void RegisterCollectable(const std::weak_ptr<Collectable>& collectable);
+ ~SerialExposer();
+
+ private:
+ std::vector<std::weak_ptr<Collectable>> collectables_;
+ std::shared_ptr<Registry> exposer_registry_;
+ std::unique_ptr<detail::SerialMetricsHandler> metrics_handler_;
+};
+
} // namespace prometheus
diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc
index 38a28e0..0d62bf3 100644
--- a/pull/src/exposer.cc
+++ b/pull/src/exposer.cc
@@ -1,4 +1,5 @@
#include "prometheus/exposer.h"
+#include "handler.h"
#include <algorithm>
#include <iterator>
@@ -63,4 +64,28 @@ detail::Endpoint& Exposer::GetEndpointForUri(const std::string& uri) {
return *endpoints_.back().get();
}
+SerialExposer::SerialExposer(
+ const std::function<void()> update_callback
+) :
+ exposer_registry_(std::make_shared<Registry>()),
+ metrics_handler_(new detail::SerialMetricsHandler {
+ collectables_, *exposer_registry_, update_callback
+ })
+{
+ RegisterCollectable(exposer_registry_);
+}
+
+SerialExposer::~SerialExposer() {}
+
+std::pair<std::map<std::string, std::string>, std::string>
+SerialExposer::operator()(const std::map<std::string, std::string>& req_headers) {
+ return (*this->metrics_handler_)(req_headers);
+}
+
+void SerialExposer::RegisterCollectable(
+ const std::weak_ptr<Collectable>& collectable
+) {
+ collectables_.push_back(collectable);
+}
+
} // namespace prometheus
diff --git a/pull/src/handler.cc b/pull/src/handler.cc
index 5a55001..b6ffa85 100644
--- a/pull/src/handler.cc
+++ b/pull/src/handler.cc
@@ -172,5 +172,124 @@ void MetricsHandler::CleanupStalePointers(
}),
std::end(collectables));
}
+
+//////////////////////////////////////////////////////
+/// Serial Metrics Handler ///
+//////////////////////////////////////////////////////
+
+SerialMetricsHandler::SerialMetricsHandler(
+ const std::vector<std::weak_ptr<Collectable>>& collectables,
+ Registry& registry,
+ const std::function<void()> update_callback)
+:
+ collectables_(collectables),
+ bytes_transferred_family_(
+ BuildCounter()
+ .Name("exposer_transferred_bytes_total")
+ .Help("Transferred bytes to metrics services")
+ .Register(registry)),
+ bytes_transferred_(bytes_transferred_family_.Add({})),
+ num_scrapes_family_(BuildCounter()
+ .Name("exposer_scrapes_total")
+ .Help("Number of times metrics were scraped")
+ .Register(registry)),
+ num_scrapes_(num_scrapes_family_.Add({})),
+ request_latencies_family_(
+ BuildSummary()
+ .Name("exposer_request_latencies")
+ .Help("Latencies of serving scrape requests, in microseconds")
+ .Register(registry)),
+ request_latencies_(request_latencies_family_.Add(
+ {}, Summary::Quantiles{{0.5, 0.05}, {0.9, 0.01}, {0.99, 0.001}})),
+ update_callback_(update_callback)
+{}
+
+std::vector<MetricFamily> SerialMetricsHandler::CollectMetrics() const {
+ auto collected_metrics = std::vector<MetricFamily>{};
+
+ for (auto&& wcollectable : collectables_) {
+ auto collectable = wcollectable.lock();
+ if (!collectable) {
+ continue;
+ }
+
+ auto&& metrics = collectable->Collect();
+ collected_metrics.insert(collected_metrics.end(),
+ std::make_move_iterator(metrics.begin()),
+ std::make_move_iterator(metrics.end()));
+ }
+
+ return collected_metrics;
+}
+
+using std::pair;
+using std::vector;
+using std::string;
+using std::map;
+
+#ifdef HAVE_ZLIB
+static bool IsEncodingAccepted(const map<string, string>& headers, string encoding) {
+ auto accept_encoding = headers.find("Accept-Encoding");
+ if (accept_encoding == headers.end()) {
+ return false;
+ }
+ return accept_encoding->second == encoding;
+}
+#endif
+
+static pair<map<string, string>, std::string> WriteResponse(
+ const std::map<std::string, std::string>& req_headers,
+ const std::string& body
+) {
+ map<string, string> headers {};
+
+ headers.insert({ "Content-Type", "text/plain" });
+
+#ifdef HAVE_ZLIB
+ auto acceptsGzip = IsEncodingAccepted(req_headers, "gzip");
+
+ if (acceptsGzip) {
+ auto compressed = GZipCompress(body);
+
+ if (!compressed.empty()) {
+ headers.insert({"Content-Encoding", "gzip"});
+ headers.insert({"Content-Length", std::to_string(static_cast<unsigned long>(compressed.size()))});
+
+ // Convert the vector<BYTE> into std::string
+ std::string res_body { compressed.begin(), compressed.end() };
+
+ return { headers, res_body };
+ }
+ }
+#endif
+ headers.insert({"Content-Length", std::to_string(static_cast<unsigned long>(body.size()))});
+
+ return { headers, body };
+}
+
+pair<map<string, string>, string> SerialMetricsHandler::operator()(
+ const map<string, string>& req_headers
+) {
+ auto start_time_of_request = std::chrono::steady_clock::now();
+
+ // Execute the callback updating the metrics
+ this->update_callback_();
+
+ auto metrics = CollectMetrics();
+ auto serializer = std::unique_ptr<Serializer>{ new TextSerializer() };
+ auto headers_body = WriteResponse(req_headers, serializer->Serialize(metrics));
+
+ auto stop_time_of_request = std::chrono::steady_clock::now();
+ auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
+ stop_time_of_request - start_time_of_request
+ );
+
+ request_latencies_.Observe(duration.count());
+ bytes_transferred_.Increment(headers_body.second.size());
+ num_scrapes_.Increment();
+
+ return headers_body;
+}
+
} // namespace detail
} // namespace prometheus
diff --git a/pull/src/handler.h b/pull/src/handler.h
index 10c90f9..8b62aab 100644
--- a/pull/src/handler.h
+++ b/pull/src/handler.h
@@ -3,6 +3,7 @@
#include <memory>
#include <mutex>
#include <vector>
+#include <functional>
#include "CivetServer.h"
#include "prometheus/collectable.h"
@@ -34,6 +35,36 @@ class MetricsHandler : public CivetHandler {
Counter& num_scrapes_;
Family<Summary>& request_latencies_family_;
Summary& request_latencies_;
+ std::function<void()> update_callback_ {};
};
+
+//////////////////////////////////////////////////////
+/// Serial Metrics Handler ///
+//////////////////////////////////////////////////////
+
+class SerialMetricsHandler {
+ public:
+ SerialMetricsHandler(
+ const std::vector<std::weak_ptr<Collectable>>& collectables,
+ Registry& registry,
+ const std::function<void()> update_callback = std::function<void()> {}
+ );
+
+ std::pair<std::map<std::string, std::string>, std::string>
+ operator()(const std::map<std::string, std::string>& req_headers);
+
+ private:
+ std::vector<MetricFamily> CollectMetrics() const;
+
+ const std::vector<std::weak_ptr<Collectable>>& collectables_;
+ Family<Counter>& bytes_transferred_family_;
+ Counter& bytes_transferred_;
+ Family<Counter>& num_scrapes_family_;
+ Counter& num_scrapes_;
+ Family<Summary>& request_latencies_family_;
+ Summary& request_latencies_;
+ std::function<void()> update_callback_ {};
+};
+
} // namespace detail
} // namespace prometheus