You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pegasus.apache.org by wa...@apache.org on 2022/12/06 17:06:23 UTC

[incubator-pegasus] branch master updated: feat(new_metrics): traverse the whole registry to choose entities and metrics according to the filters (#1285)

This is an automated email from the ASF dual-hosted git repository.

wangdan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pegasus.git


The following commit(s) were added to refs/heads/master by this push:
     new 06b2033ea feat(new_metrics): traverse the whole registry to choose entities and metrics according to the filters (#1285)
06b2033ea is described below

commit 06b2033ea0b8a4249d652b8bb0bab3ff75ee8b30
Author: Dan Wang <wa...@apache.org>
AuthorDate: Wed Dec 7 01:06:16 2022 +0800

    feat(new_metrics): traverse the whole registry to choose entities and metrics according to the filters (#1285)
---
 src/utils/metrics.cpp           |  11 ++++
 src/utils/metrics.h             |   2 +
 src/utils/test/metrics_test.cpp | 110 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 123 insertions(+)

diff --git a/src/utils/metrics.cpp b/src/utils/metrics.cpp
index e5522d9b6..0d25ba6cc 100644
--- a/src/utils/metrics.cpp
+++ b/src/utils/metrics.cpp
@@ -243,6 +243,17 @@ metric_registry::entity_map metric_registry::entities() const
     return _entities;
 }
 
+void metric_registry::take_snapshot(metric_json_writer &writer, const metric_filters &filters) const
+{
+    utils::auto_read_lock l(_lock);
+
+    writer.StartArray();
+    for (const auto &entity : _entities) {
+        entity.second->take_snapshot(writer, filters);
+    }
+    writer.EndArray();
+}
+
 metric_entity_ptr metric_registry::find_or_create_entity(const metric_entity_prototype *prototype,
                                                          const std::string &id,
                                                          const metric_entity::attr_map &attrs)
diff --git a/src/utils/metrics.h b/src/utils/metrics.h
index d130da5bf..d52228bd5 100644
--- a/src/utils/metrics.h
+++ b/src/utils/metrics.h
@@ -334,6 +334,8 @@ public:
 
     entity_map entities() const;
 
+    void take_snapshot(metric_json_writer &writer, const metric_filters &filters) const;
+
 private:
     friend class metric_entity_prototype;
     friend class utils::singleton<metric_registry>;
diff --git a/src/utils/test/metrics_test.cpp b/src/utils/test/metrics_test.cpp
index acfb7cda0..67f3d50d3 100644
--- a/src/utils/test/metrics_test.cpp
+++ b/src/utils/test/metrics_test.cpp
@@ -2178,4 +2178,114 @@ TEST(metrics_test, take_snapshot_entity)
     }
 }
 
+void check_entities_from_json_string(const std::string &json_string,
+                                     const std::unordered_set<std::string> &expected_entity_ids)
+{
+    // Even if there is not any entity selected, `json_string` should be "{}".
+    ASSERT_FALSE(json_string.empty());
+
+    rapidjson::Document doc;
+    rapidjson::ParseResult result = doc.Parse(json_string.c_str());
+    ASSERT_FALSE(result.IsError());
+
+    // Actual entity ids parsed from json string for entities.
+    std::unordered_set<std::string> actual_entity_ids;
+
+    // The json format for entities should be an array.
+    ASSERT_TRUE(doc.IsArray());
+    for (const auto &entity : doc.GetArray()) {
+        // The json format for each entity should be an object.
+        ASSERT_TRUE(entity.IsObject());
+
+        for (const auto &elem : entity.GetObject()) {
+            // Each name must be a string.
+            ASSERT_TRUE(elem.name.IsString());
+
+            if (kMetricEntityTypeField == elem.name.GetString()) {
+                ASSERT_STREQ("my_server", elem.value.GetString());
+            } else if (kMetricEntityIdField == elem.name.GetString()) {
+                actual_entity_ids.emplace(elem.value.GetString());
+            } else if (kMetricEntityAttrsField == elem.name.GetString()) {
+                ASSERT_TRUE(elem.value.ObjectEmpty());
+            } else if (kMetricEntityMetricsField == elem.name.GetString()) {
+                ASSERT_TRUE(elem.value.IsArray());
+
+                std::unordered_set<std::string> actual_entity_metrics;
+                for (const auto &m : elem.value.GetArray()) {
+                    ASSERT_TRUE(m.IsObject());
+
+                    for (const auto &field : m.GetObject()) {
+                        // Each name must be a string.
+                        ASSERT_TRUE(field.name.IsString());
+                        if (kMetricNameField == field.name.GetString()) {
+                            ASSERT_TRUE(field.value.IsString());
+                            actual_entity_metrics.emplace(field.value.GetString());
+                        }
+                    }
+                }
+
+                static const std::unordered_set<std::string> kExpectedEntityMetrics = {
+                    "test_gauge_int64", "test_counter"};
+                ASSERT_EQ(kExpectedEntityMetrics, actual_entity_metrics);
+            } else {
+                ASSERT_TRUE(false) << "invalid field name: " << elem.name.GetString();
+            }
+        }
+    }
+
+    ASSERT_EQ(expected_entity_ids, actual_entity_ids);
+}
+
+void check_registry_json_string(const std::unordered_set<std::string> &entity_ids,
+                                const metric_filters::entity_ids_type &filter_entity_ids,
+                                const std::unordered_set<std::string> &expected_entity_ids)
+{
+    for (const auto &id : entity_ids) {
+        auto my_entity = METRIC_ENTITY_my_server.instantiate(id);
+
+        auto my_gauge_int64 = METRIC_test_gauge_int64.instantiate(my_entity);
+        my_gauge_int64->set(5);
+
+        auto my_counter = METRIC_test_counter.instantiate(my_entity);
+        my_counter->increment();
+    }
+
+    metric_filters filters;
+    filters.entity_ids = filter_entity_ids;
+
+    auto &registery = metric_registry::instance();
+    auto json_string = take_snapshot_and_get_json_string(&registery, filters);
+    check_entities_from_json_string(json_string, expected_entity_ids);
+}
+
+TEST(metrics_test, take_snapshot_registry)
+{
+    // Test cases:
+    // - filter an entity that does not exist in registery
+    // - filter 2 entities both of which do not exist in registery
+    // - filter an entity that exists in registery
+    // - filter 2 entities one of which does not exist in registery
+    // - filter 2 entities both of which exist in registery
+    // - filter 3 entities one of which does not exist in registery
+    struct test_case
+    {
+        std::unordered_set<std::string> entity_ids;
+        metric_filters::entity_ids_type filter_entity_ids;
+        std::unordered_set<std::string> expected_entity_ids;
+    } tests[] = {
+        {{}, {"server_109"}, {}},
+        {{}, {"server_109", "server_110"}, {}},
+        {{"server_109"}, {"server_109"}, {"server_109"}},
+        {{"server_110"}, {"server_110", "server_111"}, {"server_110"}},
+        {{"server_111", "server_112"}, {"server_111", "server_112"}, {"server_111", "server_112"}},
+        {{"server_113", "server_114"},
+         {"server_113", "server_114", "server_115"},
+         {"server_113", "server_114"}},
+    };
+    for (const auto &test : tests) {
+        check_registry_json_string(
+            test.entity_ids, test.filter_entity_ids, test.expected_entity_ids);
+    }
+}
+
 } // namespace dsn


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pegasus.apache.org
For additional commands, e-mail: commits-help@pegasus.apache.org