kudu-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ale...@apache.org
Subject [kudu] branch master updated: [metrics] Add a metric to count merged entities when merge metrics
Date Tue, 10 Sep 2019 20:46:47 GMT
This is an automated email from the ASF dual-hosted git repository.

alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/master by this push:
     new 59c2de4  [metrics] Add a metric to count merged entities when merge metrics
59c2de4 is described below

commit 59c2de495a16f6c252196e91a9b4beeba28ed969
Author: Yingchun Lai <405403881@qq.com>
AuthorDate: Mon Aug 26 16:27:18 2019 +0800

    [metrics] Add a metric to count merged entities when merge metrics
    
    When metric entities merged to a new entity, we don't know how many
    entities it's merged from.
    This patch adds a new metric 'merged_entities_count_of_<entity>' to
    entity and set value to 1, then the new merged entity will have the
    same metric with value merged.
    In Kudu, when we want to check whether tables are balanced or not on
    tservers, and how many replicas distributed on each tserver, though
    we can use CLI tool like 'kudu cluster rebalance' to check per-table
    balance status of a cluster, but we have to fetch balance info table
    by table (by add --tables=xx flag), and also we have to "run command"
    in thirdparty monitor system and this tool seems not fast enough
    because it will call functions like RetrieveAllTablets.
    Now we can use this new feature to check whether a table is balanced
    or not by thirdparty monitor system efficiently. For example, when
    we fetch metrics from tserver by:
    http://<host>:<port>/metrics?merge_rules=tablet|table|table_name
    we can get merged metrics of table entity from each tserver as
    mentioned in commit fe6e5cc0c9c1573de174d1ce7838b449373ae36e, and now
    we can get an extra size type gauge metric
    "merged_entities_count_of_tablet" that indicate how many replicas this
    tserver hold of a table, then compare this metric of each tserver and
    judge whether this table is balanced or not.
    
    Change-Id: I652b457a2df73414f95f5d1d5efaa003cc262bd1
    Reviewed-on: http://gerrit.cloudera.org:8080/14128
    Tested-by: Kudu Jenkins
    Reviewed-by: Adar Dembo <adar@cloudera.com>
---
 build-support/iwyu.py              |  1 +
 src/kudu/master/catalog_manager.cc |  1 +
 src/kudu/server/server_base.cc     |  4 ++++
 src/kudu/tablet/tablet.cc          |  1 +
 src/kudu/util/metrics-test.cc      | 10 +++++++---
 src/kudu/util/metrics.cc           | 13 +++++++++----
 src/kudu/util/metrics.h            | 30 ++++++++++++++++++++++++++----
 7 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/build-support/iwyu.py b/build-support/iwyu.py
index e74a112..6091ad7 100755
--- a/build-support/iwyu.py
+++ b/build-support/iwyu.py
@@ -78,6 +78,7 @@ _MUTED_FILES = set([
   "src/kudu/server/webserver.cc",
   "src/kudu/util/bit-util-test.cc",
   "src/kudu/util/group_varint-test.cc",
+  "src/kudu/util/metrics.h",
   "src/kudu/util/minidump.cc",
   "src/kudu/util/mt-metrics-test.cc",
   "src/kudu/util/process_memory.cc",
diff --git a/src/kudu/master/catalog_manager.cc b/src/kudu/master/catalog_manager.cc
index d9cd3ab..08e435c 100644
--- a/src/kudu/master/catalog_manager.cc
+++ b/src/kudu/master/catalog_manager.cc
@@ -5546,6 +5546,7 @@ void TableInfo::RegisterMetrics(MetricRegistry* metric_registry, const
string& t
     attrs["table_name"] = table_name;
     metric_entity_ = METRIC_ENTITY_table.Instantiate(metric_registry, table_id_, attrs);
     metrics_.reset(new TableMetrics(metric_entity_));
+    METRIC_merged_entities_count_of_table.InstantiateHidden(metric_entity_, 1);
   }
 }
 
diff --git a/src/kudu/server/server_base.cc b/src/kudu/server/server_base.cc
index 636cde2..02294fc 100644
--- a/src/kudu/server/server_base.cc
+++ b/src/kudu/server/server_base.cc
@@ -218,6 +218,8 @@ DECLARE_int32(dns_resolver_max_threads_num);
 DECLARE_uint32(dns_resolver_cache_capacity_mb);
 DECLARE_uint32(dns_resolver_cache_ttl_sec);
 
+METRIC_DECLARE_gauge_size(merged_entities_count_of_server);
+
 using kudu::security::RpcAuthentication;
 using kudu::security::RpcEncryption;
 using std::ostringstream;
@@ -372,6 +374,8 @@ ServerBase::ServerBase(string name, const ServerBaseOptions& options,
           MonoDelta::FromSeconds(FLAGS_dns_resolver_cache_ttl_sec))),
       options_(options),
       stop_background_threads_latch_(1) {
+  METRIC_merged_entities_count_of_server.InstantiateHidden(metric_entity_, 1);
+
   FsManagerOpts fs_opts;
   fs_opts.metric_entity = metric_entity_;
   fs_opts.parent_mem_tracker = mem_tracker_;
diff --git a/src/kudu/tablet/tablet.cc b/src/kudu/tablet/tablet.cc
index 2e43ddc..78eff66 100644
--- a/src/kudu/tablet/tablet.cc
+++ b/src/kudu/tablet/tablet.cc
@@ -231,6 +231,7 @@ Tablet::Tablet(scoped_refptr<TabletMetadata> metadata,
     METRIC_num_rowsets_on_disk.InstantiateFunctionGauge(
       metric_entity_, Bind(&Tablet::num_rowsets, Unretained(this)))
       ->AutoDetach(&metric_detacher_);
+    METRIC_merged_entities_count_of_tablet.InstantiateHidden(metric_entity_, 1);
   }
 
   if (FLAGS_tablet_throttler_rpc_per_sec > 0 || FLAGS_tablet_throttler_bytes_per_sec >
0) {
diff --git a/src/kudu/util/metrics-test.cc b/src/kudu/util/metrics-test.cc
index 4b23214..6e8e4c8 100644
--- a/src/kudu/util/metrics-test.cc
+++ b/src/kudu/util/metrics-test.cc
@@ -705,14 +705,19 @@ TEST_F(MetricsTest, TestDumpOnlyChanged) {
   };
 
   scoped_refptr<Counter> test_counter = METRIC_test_counter.Instantiate(entity_);
+  test_counter->InvalidateEpoch();
 
-  int64_t epoch_when_modified = Metric::current_epoch();
+  // It's not visible before it changed.
+  int64_t epoch_before_modified = Metric::current_epoch();
+  ASSERT_STR_NOT_CONTAINS(GetJson(epoch_before_modified), "test_counter");
+
+  // Increment() will make it visible.
   test_counter->Increment();
 
   // If we pass a "since dirty" epoch from before we incremented it, we should
   // see the metric.
   for (int i = 0; i < 2; i++) {
-    ASSERT_STR_CONTAINS(GetJson(epoch_when_modified), "{\"name\":\"test_counter\",\"value\":1}");
+    ASSERT_STR_CONTAINS(GetJson(epoch_before_modified), "{\"name\":\"test_counter\",\"value\":1}");
     Metric::IncrementEpoch();
   }
 
@@ -724,7 +729,6 @@ TEST_F(MetricsTest, TestDumpOnlyChanged) {
   ASSERT_STR_CONTAINS(GetJson(new_epoch), "{\"name\":\"test_counter\",\"value\":2}");
 }
 
-
 // Test that 'include_untouched_metrics=false' prevents dumping counters and histograms
 // which have never been incremented.
 TEST_F(MetricsTest, TestDontDumpUntouched) {
diff --git a/src/kudu/util/metrics.cc b/src/kudu/util/metrics.cc
index 4df2874..8f1f0c8 100644
--- a/src/kudu/util/metrics.cc
+++ b/src/kudu/util/metrics.cc
@@ -354,19 +354,24 @@ Status MetricEntity::CollectTo(MergedEntityMetrics* collections,
   auto* merge_rule = ::FindOrNull(merge_rules, prototype_->name());
   if (merge_rule) {
     entity_type = merge_rule->merge_to;
-    entity_id = attrs[merge_rule->attribute_to_merge_by];
+    auto entity_id_ptr = ::FindOrNull(attrs, merge_rule->attribute_to_merge_by);
+    if (!entity_id_ptr) {
+      return Status::NotFound(Substitute("attribute $0 not found in entity $1",
+                                         merge_rule->attribute_to_merge_by, entity_id));
+    }
+    entity_id = *entity_id_ptr;
   }
 
   MergedEntity e(entity_type, entity_id);
-  auto& table_collection = collections->emplace(std::make_pair(e, MergedMetrics())).first->second;
+  auto& entity_collection = collections->emplace(std::make_pair(e, MergedMetrics())).first->second;
   for (const auto& val : metrics) {
     const MetricPrototype* prototype = val.first;
     const scoped_refptr<Metric>& metric = val.second;
 
-    scoped_refptr<Metric> entry = FindPtrOrNull(table_collection, prototype);
+    scoped_refptr<Metric> entry = FindPtrOrNull(entity_collection, prototype);
     if (!entry) {
       scoped_refptr<Metric> new_metric = metric->snapshot();
-      InsertOrDie(&table_collection, new_metric->prototype(), new_metric);
+      InsertOrDie(&entity_collection, new_metric->prototype(), new_metric);
     } else {
       entry->MergeFrom(metric);
     }
diff --git a/src/kudu/util/metrics.h b/src/kudu/util/metrics.h
index a64a735..82b46a9 100644
--- a/src/kudu/util/metrics.h
+++ b/src/kudu/util/metrics.h
@@ -223,11 +223,10 @@
 //
 /////////////////////////////////////////////////////
 
-#include <cstring>
-
 #include <atomic>
 #include <cstddef>
 #include <cstdint>
+#include <cstring>
 #include <limits>
 #include <mutex>
 #include <string>
@@ -258,8 +257,13 @@
 //
 // The metrics subsystem itself defines the entity type 'server', but other
 // entity types can be registered using this macro.
-#define METRIC_DEFINE_entity(name)                               \
-  ::kudu::MetricEntityPrototype METRIC_ENTITY_##name(#name)
+#define METRIC_DEFINE_entity(name)                                                  \
+  ::kudu::MetricEntityPrototype METRIC_ENTITY_##name(#name);                        \
+  METRIC_DEFINE_gauge_size(name, merged_entities_count_of_##name,                   \
+                           "Entities Count Merged From",                            \
+                           kudu::MetricUnit::kEntries,                              \
+                           "Count of entities merged together when entities are "   \
+                           "merged by common attribute value.");
 
 // Convenience macros to define metric prototypes.
 // See the documentation at the top of this file for example usage.
@@ -761,6 +765,11 @@ class Metric : public RefCountedThreadSafe<Metric> {
     }
   }
 
+  // Invalidate 'm_epoch_', causing this metric to be invisible until its value changes.
+  void InvalidateEpoch() {
+    m_epoch_ = -1;
+  }
+
   // The last metrics epoch in which this metric was modified.
   // We use epochs instead of timestamps since we can ensure that epochs
   // only change rarely. Thus this member is read-mostly and doesn't cause
@@ -773,6 +782,9 @@ class Metric : public RefCountedThreadSafe<Metric> {
 
   friend class MetricEntity;
   friend class RefCountedThreadSafe<Metric>;
+  template<typename T>
+  friend class GaugePrototype;
+  FRIEND_TEST(MetricsTest, TestDumpOnlyChanged);
 
   // The time at which we should retire this metric if it is still un-referenced outside
   // of the metrics subsystem. If this metric is not due for retirement, this member is
@@ -891,6 +903,16 @@ class GaugePrototype : public MetricPrototype {
     return entity->FindOrCreateFunctionGauge(this, function);
   }
 
+  // Instantiate a "manual" gauge and hide it. It will appear
+  // when its value is updated, or when its entity is merged.
+  scoped_refptr<AtomicGauge<T> > InstantiateHidden(
+      const scoped_refptr<MetricEntity>& entity,
+      const T& initial_value) const {
+    auto gauge = Instantiate(entity, initial_value);
+    gauge->InvalidateEpoch();
+    return gauge;
+  }
+
   virtual MetricType::Type type() const OVERRIDE {
     if (args_.flags_ & EXPOSE_AS_COUNTER) {
       return MetricType::kCounter;


Mime
View raw message