This is an automated email from the ASF dual-hosted git repository. mzhu pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 6d77d7784c41cc13eb856e337a2f7a77cf3d2554 Author: Andrei Sekretenko <asekrete...@mesosphere.io> AuthorDate: Fri Oct 4 18:14:56 2019 -0400 Replaced removal+adding of quota metrics with updating them. This patch factor out the common code for updating quota guarantee and quota limit metrics, and replaces pairs of `process::metrics::remove()`/`process::metrics::add()` called for the same metric with calling `PushGauge::operator = ()`. This is a perequisite for adding PushGauge-based quota consumption metrics. Review: https://reviews.apache.org/r/71489/ --- src/master/allocator/mesos/metrics.cpp | 107 ++++++++++++++++----------------- src/master/allocator/mesos/metrics.hpp | 25 ++++++++ 2 files changed, 78 insertions(+), 54 deletions(-) diff --git a/src/master/allocator/mesos/metrics.cpp b/src/master/allocator/mesos/metrics.cpp index ba95dc4..6a8d369 100644 --- a/src/master/allocator/mesos/metrics.cpp +++ b/src/master/allocator/mesos/metrics.cpp @@ -43,6 +43,53 @@ namespace master { namespace allocator { namespace internal { + +template<class Quantities> +void QuotaMetrics::update(const string& role, const Quantities& quantities) +{ + hashmap<string, PushGauge>& gauges = metrics[role]; + + hashset<string> namesToRemove = gauges.keys(); + + for (const auto& quantity : quantities) { + const string& name = quantity.first; + const double value = quantity.second.value(); + + namesToRemove.erase(name); + + if (gauges.contains(name)) { + gauges.at(name) = value; + continue; + } + + PushGauge newGauge( + "allocator/mesos/quota/roles/" + role + "/resources/" + name + suffix); + + newGauge = value; + process::metrics::add(newGauge); + gauges.put(name, newGauge); + } + + for (const string& name : namesToRemove) { + process::metrics::remove(gauges.at(name)); + gauges.erase(name); + } + + if (gauges.empty()) { + metrics.erase(role); + } +} + + +QuotaMetrics::~QuotaMetrics() { + foreachkey(const string& role, metrics) { + foreachvalue(const PushGauge& gauge, metrics.at(role)) { + process::metrics::remove(gauge); + } + } +} + + Metrics::Metrics(const HierarchicalAllocatorProcess& _allocator) : allocator(_allocator.self()), event_queue_dispatches( @@ -116,18 +163,6 @@ Metrics::~Metrics() } } - foreachkey (const string& role, quota_guarantee) { - foreachvalue (const PushGauge& gauge, quota_guarantee.at(role)) { - process::metrics::remove(gauge); - } - } - - foreachkey (const string& role, quota_limit) { - foreachvalue (const PushGauge& gauge, quota_limit.at(role)) { - process::metrics::remove(gauge); - } - } - foreachvalue (const PullGauge& gauge, offer_filters_active) { process::metrics::remove(gauge); } @@ -136,63 +171,27 @@ Metrics::~Metrics() void Metrics::updateQuota(const string& role, const Quota& quota) { + quotaGuarantees.update(role, quota.guarantees); + quotaLimits.update(role, quota.limits); + // First remove the existing metrics. foreachvalue (const PullGauge& gauge, quota_allocated[role]) { process::metrics::remove(gauge); } quota_allocated.erase(role); - foreachvalue (const PushGauge& gauge, quota_guarantee[role]) { - process::metrics::remove(gauge); - } - quota_guarantee.erase(role); - - foreachvalue (const PushGauge& gauge, quota_limit[role]) { - process::metrics::remove(gauge); - } - quota_limit.erase(role); - // This is the original quota "remove" case where the // role's quota is set to the default. We used to not // show the quota allocated_or_offered metric in this // case, so we keep this behavior for now. // - // TODO(mzhu): always expose the allocated gauge even - // if a role only has default quota. + // TODO(asekretenko): move offered_or_allocated to PushGauge-based + // QuotaMetrics. This also solves the problem of exposing consumption of + // roles with a default quota. if (quota == DEFAULT_QUOTA) { return; } - // Now add the new metrics. - - foreach (auto& quantity, quota.guarantees) { - PushGauge guarantee( - "allocator/mesos/quota" - "/roles/" + role + - "/resources/" + quantity.first + - "/guarantee"); - - guarantee = quantity.second.value(); - - process::metrics::add(guarantee); - - quota_guarantee[role].put(quantity.first, guarantee); - } - - foreach (auto& quantity, quota.limits) { - PushGauge limit( - "allocator/mesos/quota" - "/roles/" + role + - "/resources/" + quantity.first + - "/limit"); - - limit = quantity.second.value(); - - process::metrics::add(limit); - - quota_limit[role].put(quantity.first, limit); - } - hashset<string> names; foreach (auto& quantity, quota.guarantees) { diff --git a/src/master/allocator/mesos/metrics.hpp b/src/master/allocator/mesos/metrics.hpp index adb9515..d2cb41b 100644 --- a/src/master/allocator/mesos/metrics.hpp +++ b/src/master/allocator/mesos/metrics.hpp @@ -23,6 +23,7 @@ #include <mesos/quota/quota.hpp> #include <process/metrics/counter.hpp> +#include <process/metrics/metrics.hpp> #include <process/metrics/pull_gauge.hpp> #include <process/metrics/push_gauge.hpp> #include <process/metrics/timer.hpp> @@ -40,6 +41,24 @@ namespace internal { // Forward declarations. class HierarchicalAllocatorProcess; + +class QuotaMetrics +{ +public: + explicit QuotaMetrics(const std::string& suffix_) : suffix(suffix_){}; + ~QuotaMetrics(); + + template <class Quantities> + void update(const std::string& role, const Quantities& quantities); + +private: + const std::string suffix; + + hashmap<std::string, hashmap<std::string, process::metrics::PushGauge>> + metrics; +}; + + // Collection of metrics for the allocator; these begin // with the following prefix: `allocator/mesos/`. struct Metrics @@ -92,6 +111,12 @@ struct Metrics // PullGauges for the per-role count of active offer filters. hashmap<std::string, process::metrics::PullGauge> offer_filters_active; + +private: + // NOTE: Quota metrics should have a suffix in singilar. + // (Example of a name: allocator/mesos/quota/roles/roleA/resources/cpu/limit.) + QuotaMetrics quotaGuarantees {"/guarantee"}; + QuotaMetrics quotaLimits {"/limit"}; };