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/02 06:11:26 UTC
[incubator-pegasus] branch master updated: feat(new_metrics): take snapshot of each entity as json format (#1258)
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 8205f245a feat(new_metrics): take snapshot of each entity as json format (#1258)
8205f245a is described below
commit 8205f245a11edc0f7298df632cdfad713be88a37
Author: Dan Wang <wa...@apache.org>
AuthorDate: Fri Dec 2 14:11:20 2022 +0800
feat(new_metrics): take snapshot of each entity as json format (#1258)
---
src/common/json_helper.h | 24 +-
src/utils/metrics.cpp | 136 ++++++-
src/utils/metrics.h | 176 ++++++---
src/utils/test/metrics_test.cpp | 856 ++++++++++++++++++++++++++++++++++++++--
4 files changed, 1102 insertions(+), 90 deletions(-)
diff --git a/src/common/json_helper.h b/src/common/json_helper.h
index 001ffb6bd..399052f89 100644
--- a/src/common/json_helper.h
+++ b/src/common/json_helper.h
@@ -252,7 +252,11 @@ void json_encode(Writer &out, const std::string &str)
{
out.String(str.c_str(), str.length(), true);
}
-inline void json_encode(JsonWriter &out, const char *str) { out.String(str, strlen(str), true); }
+template <typename Writer>
+inline void json_encode(Writer &out, const char *str)
+{
+ out.String(str, std::strlen(str), true);
+}
inline bool json_decode(const JsonObject &in, std::string &str)
{
dverify(in.IsString());
@@ -289,7 +293,11 @@ inline bool json_decode(const JsonObject &in, bool &t)
}
// json serialization for double types
-inline void json_encode(JsonWriter &out, double d) { out.Double(d); }
+template <typename Writer>
+inline void json_encode(Writer &out, double d)
+{
+ out.Double(d);
+}
inline bool json_decode(const JsonObject &in, double &t)
{
if (in.IsDouble()) {
@@ -307,7 +315,11 @@ inline bool json_decode(const JsonObject &in, double &t)
// json serialization for int types
#define INT_TYPE_SERIALIZATION(TName) \
- inline void json_encode(JsonWriter &out, TName t) { out.Int64((int64_t)t); } \
+ template <typename Writer> \
+ inline void json_encode(Writer &out, TName t) \
+ { \
+ out.Int64(static_cast<int64_t>(t)); \
+ } \
inline bool json_decode(const JsonObject &in, TName &t) \
{ \
dverify(in.IsInt64()); \
@@ -325,7 +337,11 @@ INT_TYPE_SERIALIZATION(int64_t)
// json serialization for uint types
#define UINT_TYPE_SERIALIZATION(TName) \
- inline void json_encode(JsonWriter &out, TName t) { out.Uint64((uint64_t)t); } \
+ template <typename Writer> \
+ inline void json_encode(Writer &out, TName t) \
+ { \
+ out.Uint64(static_cast<uint64_t>(t)); \
+ } \
inline bool json_decode(const JsonObject &in, TName &t) \
{ \
dverify(in.IsUint64()); \
diff --git a/src/utils/metrics.cpp b/src/utils/metrics.cpp
index 2036a135c..e5522d9b6 100644
--- a/src/utils/metrics.cpp
+++ b/src/utils/metrics.cpp
@@ -24,8 +24,10 @@
namespace dsn {
-metric_entity::metric_entity(const std::string &id, attr_map &&attrs)
- : _id(id), _lock(), _attrs(std::move(attrs)), _metrics()
+metric_entity::metric_entity(const metric_entity_prototype *prototype,
+ const std::string &id,
+ const attr_map &attrs)
+ : _prototype(prototype), _id(id), _attrs(attrs)
{
}
@@ -81,19 +83,119 @@ metric_entity::metric_map metric_entity::metrics() const
return _metrics;
}
-void metric_entity::set_attributes(attr_map &&attrs)
+void metric_entity::set_attributes(const attr_map &attrs)
{
utils::auto_write_lock l(_lock);
- _attrs = std::move(attrs);
+ _attrs = attrs;
}
-metric_entity_ptr metric_entity_prototype::instantiate(const std::string &id,
- metric_entity::attr_map attrs) const
+void metric_entity::encode_type(metric_json_writer &writer) const
+{
+ writer.Key(kMetricEntityTypeField.c_str());
+ json::json_encode(writer, _prototype->name());
+}
+
+void metric_entity::encode_id(metric_json_writer &writer) const
+{
+ writer.Key(kMetricEntityIdField.c_str());
+ json::json_encode(writer, _id);
+}
+
+namespace {
+
+void encode_attrs(dsn::metric_json_writer &writer, const dsn::metric_entity::attr_map &attrs)
+{
+ // Empty attributes are allowed and will just be encoded as {}.
+
+ writer.Key(dsn::kMetricEntityAttrsField.c_str());
+
+ writer.StartObject();
+ for (const auto &attr : attrs) {
+ writer.Key(attr.first.c_str());
+ dsn::json::json_encode(writer, attr.second);
+ }
+ writer.EndObject();
+}
+
+void encode_metrics(dsn::metric_json_writer &writer,
+ const dsn::metric_entity::metric_map &metrics,
+ const dsn::metric_filters &filters)
+{
+ // We shouldn't reach here if no metric is chosen, thus just mark an assertion.
+ CHECK(!metrics.empty(),
+ "this entity should not be encoded into the response since no metric is chosen");
+
+ writer.Key(dsn::kMetricEntityMetricsField.c_str());
+
+ writer.StartArray();
+ for (const auto &m : metrics) {
+ m.second->take_snapshot(writer, filters);
+ }
+ writer.EndArray();
+}
+
+} // anonymous namespace
+
+void metric_entity::take_snapshot(metric_json_writer &writer, const metric_filters &filters) const
+{
+ if (!filters.match_entity_type(_prototype->name())) {
+ return;
+ }
+
+ if (!filters.match_entity_id(_id)) {
+ return;
+ }
+
+ attr_map my_attrs;
+ metric_map target_metrics;
+
+ {
+ utils::auto_read_lock l(_lock);
+
+ if (!filters.match_entity_attrs(_attrs)) {
+ return;
+ }
+
+ filters.extract_entity_metrics(_metrics, target_metrics);
+ if (target_metrics.empty()) {
+ // None of metrics is chosen, there is no need to take snapshot for
+ // this entity.
+ return;
+ }
+
+ my_attrs = _attrs;
+ }
+
+ // At least one metric of this entity has been chosen, thus take snapshot and encode
+ // this entity as json format.
+ writer.StartObject();
+ encode_type(writer);
+ encode_id(writer);
+ encode_attrs(writer, my_attrs);
+ encode_metrics(writer, target_metrics, filters);
+ writer.EndObject();
+}
+
+void metric_filters::extract_entity_metrics(const metric_entity::metric_map &candidates,
+ metric_entity::metric_map &target_metrics) const
{
- CHECK(attrs.find("entity") == attrs.end(), "{}'s attribute \"entity\" is reserved", id);
+ if (entity_metrics.empty()) {
+ target_metrics = candidates;
+ return;
+ }
- attrs["entity"] = _name;
- return metric_registry::instance().find_or_create_entity(id, std::move(attrs));
+ target_metrics.clear();
+ for (const auto &candidate : candidates) {
+ if (match(candidate.first->name().data(), entity_metrics)) {
+ target_metrics.emplace(candidate.first, candidate.second);
+ }
+ }
+}
+
+metric_entity_ptr metric_entity_prototype::instantiate(const std::string &id,
+ const metric_entity::attr_map &attrs) const
+{
+ return metric_registry::instance().find_or_create_entity(this, id, attrs);
}
metric_entity_ptr metric_entity_prototype::instantiate(const std::string &id) const
@@ -141,8 +243,9 @@ metric_registry::entity_map metric_registry::entities() const
return _entities;
}
-metric_entity_ptr metric_registry::find_or_create_entity(const std::string &id,
- metric_entity::attr_map &&attrs)
+metric_entity_ptr metric_registry::find_or_create_entity(const metric_entity_prototype *prototype,
+ const std::string &id,
+ const metric_entity::attr_map &attrs)
{
utils::auto_write_lock l(_lock);
@@ -150,10 +253,17 @@ metric_entity_ptr metric_registry::find_or_create_entity(const std::string &id,
metric_entity_ptr entity;
if (iter == _entities.end()) {
- entity = new metric_entity(id, std::move(attrs));
+ entity = new metric_entity(prototype, id, attrs);
_entities[id] = entity;
} else {
- iter->second->set_attributes(std::move(attrs));
+ CHECK_EQ_MSG(std::strcmp(prototype->name(), iter->second->prototype()->name()),
+ 0,
+ "new prototype '{}' is inconsistent with old prototype '{}' for entity '{}'",
+ prototype->name(),
+ iter->second->prototype()->name(),
+ id);
+
+ iter->second->set_attributes(attrs);
entity = iter->second;
}
diff --git a/src/utils/metrics.h b/src/utils/metrics.h
index e9490ead2..d130da5bf 100644
--- a/src/utils/metrics.h
+++ b/src/utils/metrics.h
@@ -132,32 +132,18 @@
namespace dsn {
-using metric_fields_type = std::unordered_set<std::string>;
-
-// This struct includes a set of filters for both entities and metrics requested by client.
-struct metric_filters
-{
- // According to the parameters requested by client, this function will filter metric
- // fields that will be put in the response.
- bool include_metric_field(const std::string &field_name) const
- {
- // NOTICE: empty `with_metric_fields` means every field is required by client.
- if (with_metric_fields.empty()) {
- return true;
- }
-
- return with_metric_fields.find(field_name) != with_metric_fields.end();
- }
-
- // `with_metric_fields` includes all the metric fields that are wanted by client. If it
- // is empty, there will be no restriction: in other words, all fields owned by the metric
- // will be put in the response.
- metric_fields_type with_metric_fields;
-};
-
class metric_prototype;
class metric;
using metric_ptr = ref_ptr<metric>;
+struct metric_filters;
+class metric_entity_prototype;
+
+using metric_json_writer = dsn::json::PrettyJsonWriter;
+
+const std::string kMetricEntityTypeField = "type";
+const std::string kMetricEntityIdField = "id";
+const std::string kMetricEntityAttrsField = "attributes";
+const std::string kMetricEntityMetricsField = "metrics";
class metric_entity : public ref_counter
{
@@ -165,6 +151,8 @@ public:
using attr_map = std::unordered_map<std::string, std::string>;
using metric_map = std::unordered_map<const metric_prototype *, metric_ptr>;
+ const metric_entity_prototype *prototype() const { return _prototype; }
+
const std::string &id() const { return _id; }
attr_map attributes() const;
@@ -188,11 +176,15 @@ public:
return ptr;
}
+ void take_snapshot(metric_json_writer &writer, const metric_filters &filters) const;
+
private:
friend class metric_registry;
friend class ref_ptr<metric_entity>;
- metric_entity(const std::string &id, attr_map &&attrs);
+ metric_entity(const metric_entity_prototype *prototype,
+ const std::string &id,
+ const attr_map &attrs);
~metric_entity();
@@ -209,8 +201,13 @@ private:
};
void close(close_option option);
- void set_attributes(attr_map &&attrs);
+ void set_attributes(const attr_map &attrs);
+
+ void encode_type(metric_json_writer &writer) const;
+ void encode_id(metric_json_writer &writer) const;
+
+ const metric_entity_prototype *const _prototype;
const std::string _id;
mutable utils::rw_lock_nr _lock;
@@ -222,6 +219,95 @@ private:
using metric_entity_ptr = ref_ptr<metric_entity>;
+// This struct includes a set of filters for both entities and metrics requested by client.
+struct metric_filters
+{
+ using metric_fields_type = std::unordered_set<std::string>;
+ using entity_types_type = std::vector<std::string>;
+ using entity_ids_type = std::unordered_set<std::string>;
+ using entity_attrs_type = std::vector<std::string>;
+ using entity_metrics_type = std::vector<std::string>;
+
+// NOTICE: empty `white_list` means every field is required by client.
+#define RETURN_MATCHED_WITH_EMPTY_WHITE_LIST(white_list) \
+ do { \
+ if (white_list.empty()) { \
+ return true; \
+ } \
+ } while (0)
+
+#define DEFINE_SIMPLE_MATCHER(name) \
+ template <typename T> \
+ inline bool match_##name(const T &candidate) const \
+ { \
+ return match(candidate, name##s); \
+ }
+
+ static inline bool match(const char *candidate, const std::vector<std::string> &white_list)
+ {
+ RETURN_MATCHED_WITH_EMPTY_WHITE_LIST(white_list);
+ // Will use `bool operator==(const string &lhs, const char *rhs);` to compare each element
+ // in `white_list` with `candidate`.
+ return std::find(white_list.begin(), white_list.end(), candidate) != white_list.end();
+ }
+
+ static inline bool match(const std::string &candidate,
+ const std::unordered_set<std::string> &white_list)
+ {
+ RETURN_MATCHED_WITH_EMPTY_WHITE_LIST(white_list);
+ return white_list.find(candidate) != white_list.end();
+ }
+
+ // According to the parameters requested by client, this function will filter metric
+ // fields that will be put in the response.
+ DEFINE_SIMPLE_MATCHER(with_metric_field)
+
+ DEFINE_SIMPLE_MATCHER(entity_type)
+
+ DEFINE_SIMPLE_MATCHER(entity_id)
+
+ bool match_entity_attrs(const metric_entity::attr_map &candidates) const
+ {
+ RETURN_MATCHED_WITH_EMPTY_WHITE_LIST(entity_attrs);
+
+ // The size of container must be divisible by 2, since attribute name always pairs
+ // with value in it.
+ CHECK_EQ(entity_attrs.size() & 1, 0);
+
+ for (entity_attrs_type::size_type i = 0; i < entity_attrs.size(); i += 2) {
+ const auto &iter = candidates.find(entity_attrs[i]);
+ if (iter == candidates.end()) {
+ continue;
+ }
+ if (iter->second == entity_attrs[i + 1]) {
+ // It will be considered as matched once any attribute is matched
+ // for both name and value.
+ return true;
+ }
+ }
+ return false;
+ }
+
+#undef DEFINE_SIMPLE_MATCHER
+#undef RETURN_MATCHED_WITH_EMPTY_WHITE_LIST
+
+ void extract_entity_metrics(const metric_entity::metric_map &candidates,
+ metric_entity::metric_map &target_metrics) const;
+
+ // `with_metric_fields` includes all the metric fields that are wanted by client. If it
+ // is empty, there will be no restriction: in other words, all fields owned by the metric
+ // will be put in the response.
+ metric_fields_type with_metric_fields;
+
+ entity_types_type entity_types;
+
+ entity_ids_type entity_ids;
+
+ entity_attrs_type entity_attrs;
+
+ entity_metrics_type entity_metrics;
+};
+
class metric_entity_prototype
{
public:
@@ -231,7 +317,8 @@ public:
const char *name() const { return _name; }
// Create an entity with the given ID and attributes, if any.
- metric_entity_ptr instantiate(const std::string &id, metric_entity::attr_map attrs) const;
+ metric_entity_ptr instantiate(const std::string &id,
+ const metric_entity::attr_map &attrs) const;
metric_entity_ptr instantiate(const std::string &id) const;
private:
@@ -254,7 +341,9 @@ private:
metric_registry();
~metric_registry();
- metric_entity_ptr find_or_create_entity(const std::string &id, metric_entity::attr_map &&attrs);
+ metric_entity_ptr find_or_create_entity(const metric_entity_prototype *prototype,
+ const std::string &id,
+ const metric_entity::attr_map &attrs);
mutable utils::rw_lock_nr _lock;
entity_map _entities;
@@ -378,7 +467,7 @@ public:
// Take snapshot of each metric to collect current values as json format with fields chosen
// by `filters`.
- virtual void take_snapshot(dsn::json::JsonWriter &writer, const metric_filters &filters) = 0;
+ virtual void take_snapshot(metric_json_writer &writer, const metric_filters &filters) = 0;
protected:
explicit metric(const metric_prototype *prototype);
@@ -387,12 +476,12 @@ protected:
// Encode a metric field specified by `field_name` as json format. However, once the field
// are not chosen by `filters`, this function will do nothing.
template <typename T>
- inline void encode(dsn::json::JsonWriter &writer,
- const std::string &field_name,
- const T &value,
- const metric_filters &filters) const
+ static inline void encode(metric_json_writer &writer,
+ const std::string &field_name,
+ const T &value,
+ const metric_filters &filters)
{
- if (!filters.include_metric_field(field_name)) {
+ if (!filters.match_with_metric_field(field_name)) {
return;
}
@@ -401,31 +490,31 @@ protected:
}
// Encode the metric type as json format, if it is chosen by `filters`.
- inline void encode_type(dsn::json::JsonWriter &writer, const metric_filters &filters) const
+ inline void encode_type(metric_json_writer &writer, const metric_filters &filters) const
{
encode(writer, kMetricTypeField, enum_to_string(prototype()->type()), filters);
}
// Encode the metric name as json format, if it is chosen by `filters`.
- inline void encode_name(dsn::json::JsonWriter &writer, const metric_filters &filters) const
+ inline void encode_name(metric_json_writer &writer, const metric_filters &filters) const
{
encode(writer, kMetricNameField, prototype()->name().data(), filters);
}
// Encode the metric unit as json format, if it is chosen by `filters`.
- inline void encode_unit(dsn::json::JsonWriter &writer, const metric_filters &filters) const
+ inline void encode_unit(metric_json_writer &writer, const metric_filters &filters) const
{
encode(writer, kMetricUnitField, enum_to_string(prototype()->unit()), filters);
}
// Encode the metric description as json format, if it is chosen by `filters`.
- inline void encode_desc(dsn::json::JsonWriter &writer, const metric_filters &filters) const
+ inline void encode_desc(metric_json_writer &writer, const metric_filters &filters) const
{
encode(writer, kMetricDescField, prototype()->description().data(), filters);
}
// Encode the metric prototype as json format, if some attributes in it are chosen by `filters`.
- inline void encode_prototype(dsn::json::JsonWriter &writer, const metric_filters &filters) const
+ inline void encode_prototype(metric_json_writer &writer, const metric_filters &filters) const
{
encode_type(writer, filters);
encode_name(writer, filters);
@@ -436,9 +525,8 @@ protected:
// Encode the unique value of a metric as json format, if it is chosen by `filters`. Notice
// that the metric should have only one value. like gauge and counter.
template <typename T>
- inline void encode_single_value(dsn::json::JsonWriter &writer,
- const T &value,
- const metric_filters &filters) const
+ static inline void
+ encode_single_value(metric_json_writer &writer, const T &value, const metric_filters &filters)
{
encode(writer, kMetricSingleValueField, value, filters);
}
@@ -496,7 +584,7 @@ public:
// where "name" is the name of the gauge in string type, and "value" is just current value
// of the gauge fetched by `value()`, in numeric types (i.e. integral or floating-point type,
// determined by `value_type`).
- void take_snapshot(json::JsonWriter &writer, const metric_filters &filters) override
+ void take_snapshot(metric_json_writer &writer, const metric_filters &filters) override
{
writer.StartObject();
@@ -613,7 +701,7 @@ public:
// }
// where "name" is the name of the counter in string type, and "value" is just current value
// of the counter fetched by `value()`, in integral type (namely int64_t).
- void take_snapshot(json::JsonWriter &writer, const metric_filters &filters) override
+ void take_snapshot(metric_json_writer &writer, const metric_filters &filters) override
{
writer.StartObject();
@@ -845,7 +933,7 @@ public:
// where "name" is the name of the percentile in string type, with each configured kth
// percentile followed, such as "p50", "p90", "p95", etc. All of them are in numeric types
// (i.e. integral or floating-point type, determined by `value_type`).
- void take_snapshot(json::JsonWriter &writer, const metric_filters &filters) override
+ void take_snapshot(metric_json_writer &writer, const metric_filters &filters) override
{
writer.StartObject();
diff --git a/src/utils/test/metrics_test.cpp b/src/utils/test/metrics_test.cpp
index 36bf79f78..acfb7cda0 100644
--- a/src/utils/test/metrics_test.cpp
+++ b/src/utils/test/metrics_test.cpp
@@ -34,7 +34,7 @@ class my_gauge : public metric
public:
int64_t value() { return _value; }
- void take_snapshot(json::JsonWriter &, const metric_filters &) override {}
+ void take_snapshot(metric_json_writer &, const metric_filters &) override {}
protected:
explicit my_gauge(const metric_prototype *prototype) : metric(prototype), _value(0) {}
@@ -158,7 +158,7 @@ TEST(metrics_test, create_entity)
metric_registry::entity_map entities;
for (const auto &test : tests) {
- ASSERT_EQ(test.prototype->name(), test.type_name);
+ ASSERT_STREQ(test.prototype->name(), test.type_name.c_str());
metric_entity_ptr entity;
if (test.entity_attrs.empty() && !test.use_attrs_arg_if_empty) {
@@ -171,10 +171,6 @@ TEST(metrics_test, create_entity)
ASSERT_EQ(id, test.entity_id);
auto attrs = entity->attributes();
- ASSERT_NE(attrs.find("entity"), attrs.end());
- ASSERT_EQ(attrs["entity"], test.type_name);
- ASSERT_EQ(attrs.size(), test.entity_attrs.size() + 1);
- ASSERT_EQ(attrs.erase("entity"), 1);
ASSERT_EQ(attrs, test.entity_attrs);
ASSERT_EQ(entities.find(test.entity_id), entities.end());
@@ -207,7 +203,6 @@ TEST(metrics_test, recreate_entity)
// the attributes will be updated
auto attrs = entity->attributes();
- ASSERT_EQ(attrs.erase("entity"), 1);
ASSERT_EQ(attrs, test.entity_attrs);
}
}
@@ -906,15 +901,24 @@ TEST(metrics_test, percentile_double)
floating_checker<value_type>>(METRIC_test_percentile_double);
}
-std::string take_snapshot_and_get_json_string(metric *m, const metric_filters &filters)
+template <typename T>
+std::string take_snapshot_and_get_json_string(T *m, const metric_filters &filters)
{
std::stringstream out;
rapidjson::OStreamWrapper wrapper(out);
- json::JsonWriter writer(wrapper);
+ metric_json_writer writer(wrapper);
m->take_snapshot(writer, filters);
- return out.str();
+ auto out_str = out.str();
+ if (out_str.empty()) {
+ std::cout << "The json string is empty." << std::endl;
+ } else {
+ std::cout << "The json string is: " << std::endl;
+ std::cout << out_str << std::endl;
+ }
+
+ return out_str;
}
template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
@@ -925,35 +929,35 @@ void check_prototype_and_extract_value_map_from_json_string(
metric *my_metric,
const std::string &json_string,
const bool is_integral,
- const metric_fields_type &expected_metric_fields,
+ const metric_filters::metric_fields_type &expected_metric_fields,
metric_value_map<T> &value_map)
{
rapidjson::Document doc;
rapidjson::ParseResult result = doc.Parse(json_string.c_str());
ASSERT_FALSE(result.IsError());
- metric_fields_type actual_metric_fields;
+ metric_filters::metric_fields_type actual_metric_fields;
// The json format for each metric should be an object.
ASSERT_TRUE(doc.IsObject());
for (const auto &elem : doc.GetObject()) {
- // Each metric name must be a string.
+ // Each name must be a string.
ASSERT_TRUE(elem.name.IsString());
if (elem.value.IsString()) {
// Must be a field of metric prototype.
- if (std::strcmp(elem.name.GetString(), kMetricTypeField.c_str()) == 0) {
+ if (kMetricTypeField == elem.name.GetString()) {
ASSERT_STREQ(elem.value.GetString(),
enum_to_string(my_metric->prototype()->type()));
- } else if (std::strcmp(elem.name.GetString(), kMetricNameField.c_str()) == 0) {
+ } else if (kMetricNameField == elem.name.GetString()) {
ASSERT_STREQ(elem.value.GetString(), my_metric->prototype()->name().data());
- } else if (std::strcmp(elem.name.GetString(), kMetricUnitField.c_str()) == 0) {
+ } else if (kMetricUnitField == elem.name.GetString()) {
ASSERT_STREQ(elem.value.GetString(),
enum_to_string(my_metric->prototype()->unit()));
- } else if (std::strcmp(elem.name.GetString(), kMetricDescField.c_str()) == 0) {
+ } else if (kMetricDescField == elem.name.GetString()) {
ASSERT_STREQ(elem.value.GetString(), my_metric->prototype()->description().data());
} else {
- ASSERT_TRUE(false);
+ ASSERT_TRUE(false) << "invalid field name: " << elem.name.GetString();
}
} else {
// Must be a field of metric value.
@@ -980,7 +984,7 @@ template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::
void generate_metric_value_map(metric *my_metric,
const bool is_integral,
const metric_filters &filters,
- const metric_fields_type &expected_metric_fields,
+ const metric_filters::metric_fields_type &expected_metric_fields,
metric_value_map<T> &value_map)
{
auto json_string = take_snapshot_and_get_json_string(my_metric, filters);
@@ -1038,10 +1042,10 @@ void compare_floating_metric_value_map(const metric_value_map<T> &actual_value_m
value_map_comparator(actual_value_map, expected_value_map); \
} while (0)
-const metric_fields_type kAllPrototypeMetricFields = {
+const metric_filters::metric_fields_type kAllPrototypeMetricFields = {
kMetricTypeField, kMetricNameField, kMetricUnitField, kMetricDescField};
-metric_fields_type get_all_single_value_metric_fields()
+metric_filters::metric_fields_type get_all_single_value_metric_fields()
{
auto fields = kAllPrototypeMetricFields;
fields.insert(kMetricSingleValueField);
@@ -1074,14 +1078,14 @@ metric_fields_type get_all_single_value_metric_fields()
#define RUN_CASES_WITH_SINGLE_VALUE_SNAPSHOT( \
metric_prototype, updater, value_type, is_integral, value, value_map_comparator) \
do { \
- static const metric_fields_type kAllSingleValueMetricFields = \
+ static const metric_filters::metric_fields_type kAllSingleValueMetricFields = \
get_all_single_value_metric_fields(); \
struct test_case \
{ \
std::string entity_id; \
value_type expected_value; \
- metric_fields_type with_metric_fields; \
- metric_fields_type expected_metric_fields; \
+ metric_filters::metric_fields_type with_metric_fields; \
+ metric_filters::metric_fields_type expected_metric_fields; \
} tests[] = { \
{"server_60", value, {}, kAllSingleValueMetricFields}, \
{"server_61", value, {kMetricNameField}, {kMetricNameField}}, \
@@ -1184,7 +1188,7 @@ void generate_metric_value_map(MetricType *my_metric,
const uint64_t interval_ms,
const uint64_t exec_ms,
const std::set<kth_percentile_type> &kth_percentiles,
- const metric_fields_type &expected_metric_fields,
+ const metric_filters::metric_fields_type &expected_metric_fields,
metric_value_map<typename MetricType::value_type> &value_map)
{
using value_type = typename MetricType::value_type;
@@ -1254,7 +1258,7 @@ void generate_metric_value_map(MetricType *my_metric,
value_map_comparator(actual_value_map, expected_value_map); \
} while (0)
-metric_fields_type get_all_kth_percentile_fields()
+metric_filters::metric_fields_type get_all_kth_percentile_fields()
{
auto fields = kAllPrototypeMetricFields;
for (const auto &kth : kAllKthPercentiles) {
@@ -1301,13 +1305,14 @@ metric_fields_type get_all_kth_percentile_fields()
#define RUN_CASES_WITH_PERCENTILE_SNAPSHOT( \
metric_prototype, case_generator, is_integral, value_map_comparator) \
do { \
- static const metric_fields_type kAllKthPercentileFields = get_all_kth_percentile_fields(); \
+ static const metric_filters::metric_fields_type kAllKthPercentileFields = \
+ get_all_kth_percentile_fields(); \
\
struct test_case \
{ \
std::string entity_id; \
- metric_fields_type with_metric_fields; \
- metric_fields_type expected_metric_fields; \
+ metric_filters::metric_fields_type with_metric_fields; \
+ metric_filters::metric_fields_type expected_metric_fields; \
} tests[] = { \
{"server_60", {}, kAllKthPercentileFields}, \
{"server_61", {kMetricNameField}, {kMetricNameField}}, \
@@ -1380,4 +1385,797 @@ TEST(metrics_test, take_snapshot_percentile_double)
compare_floating_metric_value_map);
}
+void check_entity_from_json_string(metric_entity *my_entity,
+ const std::string &json_string,
+ const std::string &expected_entity_type,
+ const std::string &expected_entity_id,
+ const metric_entity::attr_map &expected_entity_attrs,
+ const std::unordered_set<std::string> &expected_entity_metrics)
+{
+ // `json_string` and `expected_entity_metrics` should be empty or non-empty simultaneously;
+ // empty `json_string` means this entity is not selected by the filters.
+ ASSERT_EQ(json_string.empty(), expected_entity_metrics.empty());
+ if (json_string.empty()) {
+ std::cout << "Empty json string means this entity is not selected by the filters."
+ << std::endl;
+ return;
+ }
+
+ rapidjson::Document doc;
+ rapidjson::ParseResult result = doc.Parse(json_string.c_str());
+ ASSERT_FALSE(result.IsError());
+
+ // Actual fields parsed from json string for each entity.
+ std::unordered_set<std::string> actual_fields;
+
+ // The json format for each entity should be an object.
+ ASSERT_TRUE(doc.IsObject());
+ for (const auto &elem : doc.GetObject()) {
+ // Each name must be a string.
+ ASSERT_TRUE(elem.name.IsString());
+
+ if (kMetricEntityTypeField == elem.name.GetString()) {
+ ASSERT_STREQ(elem.value.GetString(), expected_entity_type.c_str());
+ ASSERT_STREQ(elem.value.GetString(), my_entity->prototype()->name());
+ } else if (kMetricEntityIdField == elem.name.GetString()) {
+ ASSERT_STREQ(elem.value.GetString(), expected_entity_id.c_str());
+ ASSERT_STREQ(elem.value.GetString(), my_entity->id().c_str());
+ } else if (kMetricEntityAttrsField == elem.name.GetString()) {
+ ASSERT_TRUE(elem.value.IsObject());
+
+ metric_entity::attr_map actual_entity_attrs;
+ for (const auto &attr : elem.value.GetObject()) {
+ // Each name must be a string.
+ ASSERT_TRUE(attr.name.IsString());
+ ASSERT_TRUE(attr.value.IsString());
+ actual_entity_attrs.emplace(attr.name.GetString(), attr.value.GetString());
+ }
+ ASSERT_EQ(actual_entity_attrs, expected_entity_attrs);
+ ASSERT_EQ(actual_entity_attrs, my_entity->attributes());
+ } 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());
+ }
+ }
+ }
+
+ ASSERT_EQ(actual_entity_metrics, expected_entity_metrics);
+ } else {
+ ASSERT_TRUE(false) << "invalid field name: " << elem.name.GetString();
+ }
+
+ actual_fields.emplace(elem.name.GetString());
+ }
+
+ static const std::unordered_set<std::string> kAllMetricEntityFields = {
+ kMetricEntityTypeField,
+ kMetricEntityIdField,
+ kMetricEntityAttrsField,
+ kMetricEntityMetricsField};
+ ASSERT_EQ(actual_fields, kAllMetricEntityFields);
+}
+
+TEST(metrics_test, take_snapshot_entity)
+{
+ static const std::unordered_set<std::string> kAllEntityMetrics = {"test_gauge_int64",
+ "test_counter"};
+
+ // Test cases:
+ // - both attributes and filters are empty
+ // - entity has an attribute while filters are empty
+ // - entity has 2 attributes while filters are empty
+ // - entity has 2 attributes while filters are empty and metrics are empty
+ // - filter has one matched entity type
+ // - filter has one mismatched entity type
+ // - filter has 2 entity types one of which is matched
+ // - filter has 2 mismatched entity types
+ // - filter has one matched entity id
+ // - filter has one mismatched entity id
+ // - filter has 2 entity ids one of which is matched
+ // - filter has 2 mismatched entity ids
+ // - entity has no attribute while filter has one mismatched entity attribute
+ // - entity has no attribute while filter has 2 mismatched entity attributes
+ // - entity has an attribute while filter has one matched entity attribute
+ // - entity has an attribute while filter has one entity attribute whose key is mismatched
+ // - entity has an attribute while filter has one entity attribute whose value is mismatched
+ // - entity has an attribute while filter has one entity attribute whose key and value are
+ // both mismatched
+ // - entity has an attribute while filter has 2 entity attributes one of which is matched
+ // - entity has an attribute while filter has 2 mismatched entity attributes
+ // - entity has 2 attributes while filter has one matched entity attribute
+ // - entity has 2 attributes while filter has one entity attribute whose key is mismatched
+ // - entity has 2 attributes while filter has one entity attribute whose value is mismatched
+ // - entity has 2 attributes while filter has one entity attribute whose key and value are
+ // both mismatched
+ // - entity has 2 attributes while filter has 2 matched entity attributes
+ // - entity has 2 attributes while filter has 2 entity attributes one of which is matched
+ // - entity has 2 attributes while filter has 2 mismatched entity attributes
+ // - entity has no metrics while filter has one mismatched entity metrics
+ // - entity has no metrics while filter has 2 mismatched entity metrics
+ // - entity has an metric while filter has one matched entity metric
+ // - entity has an metric while filter has one mismatched entity metric
+ // - entity has an metric while filter has 2 entity metrics one of which is matched
+ // - entity has an metric while filter has 2 mismatched entity metrics
+ // - entity has 2 metrics while filter has one matched entity metric
+ // - entity has 2 metrics while filter has one mismatched entity metric
+ // - entity has 2 metrics while filter has 2 matched entity metrics
+ // - entity has 2 metrics while filter has 2 entity metrics one of which is matched
+ // - entity has 2 metrics while filter has 2 mismatched entity metrics
+ // - matched for entity types and ids
+ // - mismatched for entity types and ids
+ // - matched for entity types and attributes
+ // - mismatched for entity types and attributes
+ // - matched for entity types and metrics
+ // - mismatched for entity types and metrics
+ // - matched for entity ids and attributes
+ // - mismatched for entity ids and attributes
+ // - matched for entity ids and metrics
+ // - mismatched for entity ids and metrics
+ // - matched for entity attributes and metrics
+ // - mismatched for entity attributes and metrics
+ // - matched for entity types, ids and attributes
+ // - mismatched for entity types, ids and attributes
+ // - matched for entity types, ids and metrics
+ // - mismatched for entity types, ids and metrics
+ // - matched for entity types, attributes and metrics
+ // - mismatched for entity types, attributes and metrics
+ // - matched for entity ids, attributes and metrics
+ // - mismatched for entity ids, attributes and metrics
+ // - matched for entity types, ids, attributes and metrics
+ // - mismatched for entity types, ids, attributes and metrics
+ struct test_case
+ {
+ metric_entity_prototype *entity_prototype;
+ std::unordered_set<std::string> entity_metrics;
+ std::string expected_entity_type;
+ std::string expected_entity_id;
+ metric_entity::attr_map expected_entity_attrs;
+ std::unordered_set<std::string> expected_entity_metrics;
+ metric_filters::entity_types_type filter_entity_types;
+ metric_filters::entity_ids_type filter_entity_ids;
+ metric_filters::entity_attrs_type filter_entity_attrs;
+ metric_filters::entity_metrics_type filter_entity_metrics;
+ } tests[] = {
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_81",
+ {},
+ kAllEntityMetrics,
+ {},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_table,
+ kAllEntityMetrics,
+ "my_table",
+ "table_1",
+ {{"table", "test_table_1"}},
+ kAllEntityMetrics,
+ {},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_1.0",
+ {{"table", "test_table_1"}, {"partition", "0"}},
+ kAllEntityMetrics,
+ {},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ {},
+ "my_replica",
+ "replica_1.1",
+ {{"table", "test_table_1"}, {"partition", "1"}},
+ {},
+ {},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_82",
+ {},
+ kAllEntityMetrics,
+ {"my_server"},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_83",
+ {},
+ {},
+ {"another_server"},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_84",
+ {},
+ kAllEntityMetrics,
+ {"another_server", "my_server"},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_85",
+ {},
+ {},
+ {"another_server", "another_another_server"},
+ {},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_86",
+ {},
+ kAllEntityMetrics,
+ {},
+ {"server_86"},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_87",
+ {},
+ {},
+ {},
+ {"another_server_87"},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_88",
+ {},
+ kAllEntityMetrics,
+ {},
+ {"another_server_88", "server_88"},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_89",
+ {},
+ {},
+ {},
+ {"another_server_89", "another_another_server_89"},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_90",
+ {},
+ {},
+ {},
+ {},
+ {"attr_name_1", "attr_value_1"},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_91",
+ {},
+ {},
+ {},
+ {},
+ {"attr_name_1", "attr_value_1", "attr_name_2", "attr_value_2"},
+ {}},
+ {&METRIC_ENTITY_my_table,
+ kAllEntityMetrics,
+ "my_table",
+ "table_2",
+ {{"table", "test_table_2"}},
+ kAllEntityMetrics,
+ {},
+ {},
+ {"table", "test_table_2"},
+ {}},
+ {&METRIC_ENTITY_my_table,
+ kAllEntityMetrics,
+ "my_table",
+ "table_3",
+ {{"table", "test_table_3"}},
+ {},
+ {},
+ {},
+ {"another_table", "test_table_3"},
+ {}},
+ {&METRIC_ENTITY_my_table,
+ kAllEntityMetrics,
+ "my_table",
+ "table_4",
+ {{"table", "test_table_4"}},
+ {},
+ {},
+ {},
+ {"table", "another_test_table_4"},
+ {}},
+ {&METRIC_ENTITY_my_table,
+ kAllEntityMetrics,
+ "my_table",
+ "table_5",
+ {{"table", "test_table_5"}},
+ {},
+ {},
+ {},
+ {"another_table", "another_test_table_5"},
+ {}},
+ {&METRIC_ENTITY_my_table,
+ kAllEntityMetrics,
+ "my_table",
+ "table_6",
+ {{"table", "test_table_6"}},
+ kAllEntityMetrics,
+ {},
+ {},
+ {"another_table", "another_test_table_6", "table", "test_table_6"},
+ {}},
+ {&METRIC_ENTITY_my_table,
+ kAllEntityMetrics,
+ "my_table",
+ "table_7",
+ {{"table", "test_table_7"}},
+ {},
+ {},
+ {},
+ {"another_table", "test_table_7", "table", "another_test_table_7"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_1.2",
+ {{"table", "test_table_1"}, {"partition", "2"}},
+ kAllEntityMetrics,
+ {},
+ {},
+ {"table", "test_table_1"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_1.3",
+ {{"table", "test_table_1"}, {"partition", "3"}},
+ {},
+ {},
+ {},
+ {"another_partition", "3"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_1.4",
+ {{"table", "test_table_1"}, {"partition", "4"}},
+ {},
+ {},
+ {},
+ {"table", "another_test_table_1"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_1.5",
+ {{"table", "test_table_1"}, {"partition", "5"}},
+ {},
+ {},
+ {},
+ {"another_table", "another_test_table_1"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_1.6",
+ {{"table", "test_table_1"}, {"partition", "6"}},
+ kAllEntityMetrics,
+ {},
+ {},
+ {"table", "test_table_1", "partition", "6"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_1.7",
+ {{"table", "test_table_1"}, {"partition", "7"}},
+ kAllEntityMetrics,
+ {},
+ {},
+ {"another_table", "another_test_table_1", "partition", "7"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.0",
+ {{"table", "test_table_2"}, {"partition", "0"}},
+ {},
+ {},
+ {},
+ {"table", "another_test_table_2", "partition", "1"},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ {},
+ "my_server",
+ "server_92",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {"test_gauge_int64"}},
+ {&METRIC_ENTITY_my_server,
+ {},
+ "my_server",
+ "server_93",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {"test_gauge_int64", "test_counter"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64"},
+ "my_server",
+ "server_94",
+ {},
+ {"test_gauge_int64"},
+ {},
+ {},
+ {},
+ {"test_gauge_int64"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64"},
+ "my_server",
+ "server_95",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {"test_counter"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64"},
+ "my_server",
+ "server_96",
+ {},
+ {"test_gauge_int64"},
+ {},
+ {},
+ {},
+ {"test_gauge_int64", "test_counter"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64"},
+ "my_server",
+ "server_97",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {"test_gauge_double", "test_counter"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64", "test_counter"},
+ "my_server",
+ "server_98",
+ {},
+ {"test_counter"},
+ {},
+ {},
+ {},
+ {"test_counter"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64", "test_counter"},
+ "my_server",
+ "server_99",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {"test_gauge_double"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64", "test_counter"},
+ "my_server",
+ "server_100",
+ {},
+ {"test_gauge_int64", "test_counter"},
+ {},
+ {},
+ {},
+ {"test_gauge_int64", "test_counter"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64", "test_counter"},
+ "my_server",
+ "server_101",
+ {},
+ {"test_gauge_int64"},
+ {},
+ {},
+ {},
+ {"test_gauge_int64", "test_gauge_double"}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64", "test_counter"},
+ "my_server",
+ "server_102",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {"test_gauge_double", "test_concurrent_counter"}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_103",
+ {},
+ kAllEntityMetrics,
+ {"another_server", "my_server"},
+ {"another_server_103", "server_103"},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_104",
+ {},
+ {},
+ {"another_server", "my_server"},
+ {"another_server_104"},
+ {},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.1",
+ {{"table", "test_table_2"}, {"partition", "1"}},
+ kAllEntityMetrics,
+ {"another_replica", "my_replica"},
+ {},
+ {"table", "test_table_2", "partition", "1"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.2",
+ {{"table", "test_table_2"}, {"partition", "2"}},
+ {},
+ {"another_replica", "my_replica"},
+ {},
+ {"table", "another_test_table_2", "another_partition", "2"},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ {"test_gauge_int64", "test_counter"},
+ "my_server",
+ "server_105",
+ {},
+ {"test_gauge_int64", "test_counter"},
+ {"another_server", "my_server"},
+ {},
+ {},
+ {"test_gauge_int64", "test_counter"}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_106",
+ {},
+ {"test_counter"},
+ {"another_server", "my_server"},
+ {},
+ {},
+ {"test_gauge_double", "test_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.3",
+ {{"table", "test_table_2"}, {"partition", "3"}},
+ kAllEntityMetrics,
+ {},
+ {"another_replica_2.3", "replica_2.3"},
+ {"table", "another_test_table_2", "partition", "3"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.4",
+ {{"table", "test_table_2"}, {"partition", "4"}},
+ {},
+ {},
+ {"another_replica_2.4", "replica_2.4"},
+ {"table", "another_test_table_2", "another_partition", "4"},
+ {}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_107",
+ {},
+ {"test_gauge_int64"},
+ {},
+ {"another_server_107", "server_107"},
+ {},
+ {"test_gauge_int64", "test_gauge_double"}},
+ {&METRIC_ENTITY_my_server,
+ kAllEntityMetrics,
+ "my_server",
+ "server_108",
+ {},
+ {},
+ {},
+ {"another_server_108", "server_108"},
+ {},
+ {"test_gauge_double", "test_concurrent_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.5",
+ {{"table", "test_table_2"}, {"partition", "5"}},
+ {"test_gauge_int64"},
+ {},
+ {},
+ {"table", "another_test_table_2", "partition", "5"},
+ {"test_gauge_int64", "test_gauge_double"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.6",
+ {{"table", "test_table_2"}, {"partition", "6"}},
+ {},
+ {},
+ {},
+ {"table", "test_table_2", "partition", "6"},
+ {"test_gauge_double", "test_concurrent_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_2.7",
+ {{"table", "test_table_2"}, {"partition", "7"}},
+ kAllEntityMetrics,
+ {"another_replica", "my_replica"},
+ {"another_replica_2.7", "replica_2.7"},
+ {"table", "another_test_table_2", "partition", "7"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.0",
+ {{"table", "test_table_3"}, {"partition", "0"}},
+ {},
+ {"another_replica", "my_replica"},
+ {"another_replica_3.0", "replica_3.0"},
+ {"table", "another_test_table_3", "another_partition", "0"},
+ {}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.1",
+ {},
+ {"test_counter"},
+ {"another_replica", "my_replica"},
+ {"another_replica_3.1", "replica_3.1"},
+ {},
+ {"test_gauge_double", "test_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.2",
+ {},
+ {},
+ {"another_replica", "my_replica"},
+ {"another_replica_3.2", "replica_3.2"},
+ {},
+ {"test_gauge_double", "test_concurrent_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.3",
+ {{"table", "test_table_3"}, {"partition", "3"}},
+ {"test_gauge_int64"},
+ {"another_replica", "my_replica"},
+ {},
+ {"table", "test_table_3", "another_partition", "3"},
+ {"test_gauge_int64", "test_gauge_double"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.4",
+ {{"table", "test_table_3"}, {"partition", "4"}},
+ {},
+ {"another_replica", "my_replica"},
+ {},
+ {"table", "another_test_table_3", "partition", "4"},
+ {"test_gauge_double", "test_concurrent_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.5",
+ {{"table", "test_table_3"}, {"partition", "5"}},
+ {"test_counter"},
+ {},
+ {"another_replica_3.5", "replica_3.5"},
+ {"table", "test_table_3", "another_partition", "5"},
+ {"test_gauge_double", "test_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.6",
+ {{"table", "test_table_3"}, {"partition", "6"}},
+ {},
+ {},
+ {"another_replica_3.6", "replica_3.6"},
+ {"table", "another_test_table_3", "partition", "6"},
+ {"test_gauge_double", "test_concurrent_counter"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_3.7",
+ {{"table", "test_table_3"}, {"partition", "7"}},
+ {"test_gauge_int64"},
+ {"another_replica", "my_replica"},
+ {"another_replica_3.7", "replica_3.7"},
+ {"table", "test_table_3", "another_partition", "7"},
+ {"test_gauge_int64", "test_gauge_double"}},
+ {&METRIC_ENTITY_my_replica,
+ kAllEntityMetrics,
+ "my_replica",
+ "replica_4.0",
+ {{"table", "test_table_4"}, {"partition", "0"}},
+ {},
+ {"another_replica", "my_replica"},
+ {"another_replica_4.0", "replica_4.0"},
+ {"table", "another_test_table_4", "partition", "0"},
+ {"test_gauge_double", "test_concurrent_counter"}},
+ };
+
+ for (const auto &test : tests) {
+ auto my_entity =
+ test.entity_prototype->instantiate(test.expected_entity_id, test.expected_entity_attrs);
+
+ if (test.entity_metrics.find("test_gauge_int64") != test.entity_metrics.end()) {
+ auto my_gauge_int64 = METRIC_test_gauge_int64.instantiate(my_entity);
+ my_gauge_int64->set(5);
+ }
+
+ if (test.entity_metrics.find("test_counter") != test.entity_metrics.end()) {
+ auto my_counter = METRIC_test_counter.instantiate(my_entity);
+ my_counter->increment();
+ }
+
+ metric_filters filters;
+ filters.entity_types = test.filter_entity_types;
+ filters.entity_ids = test.filter_entity_ids;
+ filters.entity_attrs = test.filter_entity_attrs;
+ filters.entity_metrics = test.filter_entity_metrics;
+
+ auto json_string = take_snapshot_and_get_json_string(my_entity.get(), filters);
+ check_entity_from_json_string(my_entity,
+ json_string,
+ test.expected_entity_type,
+ test.expected_entity_id,
+ test.expected_entity_attrs,
+ test.expected_entity_metrics);
+ }
+}
+
} // namespace dsn
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pegasus.apache.org
For additional commands, e-mail: commits-help@pegasus.apache.org