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 363d78988 feat(new_metrics): add some basic fields to the response to
metrics query (#1827)
363d78988 is described below
commit 363d7898828bebbb562c6de2ccabf982b98e4fe6
Author: Dan Wang <[email protected]>
AuthorDate: Fri Jan 5 17:31:22 2024 +0800
feat(new_metrics): add some basic fields to the response to metrics query
(#1827)
https://github.com/apache/incubator-pegasus/issues/1820
Labels are needed by metric models like Prometheus Data Model.
Therefore, cluster name, role name, host name and port should be
provided in the response to metrics query as the labels. All of these
fields would be added in the form of name/value pairs of json object.
Original entity array would be the value of a json object with name
"entities".
---
src/runtime/task/task.h | 6 +++
src/utils/CMakeLists.txt | 3 +-
src/utils/metrics.cpp | 94 ++++++++++++++++++++++++++++++++++++-----
src/utils/metrics.h | 8 ++++
src/utils/test/metrics_test.cpp | 30 ++++++++++---
5 files changed, 124 insertions(+), 17 deletions(-)
diff --git a/src/runtime/task/task.h b/src/runtime/task/task.h
index 4e2f70ed6..9fbe022dd 100644
--- a/src/runtime/task/task.h
+++ b/src/runtime/task/task.h
@@ -243,6 +243,7 @@ public:
static int get_current_worker_index();
static const char *get_current_node_name();
static rpc_engine *get_current_rpc();
+ static rpc_engine *get_current_rpc2();
static env_provider *get_current_env();
static void set_tls_dsn_context(
@@ -594,6 +595,11 @@ __inline /*static*/ rpc_engine *task::get_current_rpc()
return tls_dsn.rpc;
}
+__inline /*static*/ rpc_engine *task::get_current_rpc2()
+{
+ return tls_dsn.magic == 0xdeadbeef ? tls_dsn.rpc : nullptr;
+}
+
__inline /*static*/ env_provider *task::get_current_env()
{
check_tls_dsn();
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
index 38390f0ed..1c1c7d0c4 100644
--- a/src/utils/CMakeLists.txt
+++ b/src/utils/CMakeLists.txt
@@ -43,9 +43,10 @@ set(MY_BINPLACES "")
if (APPLE)
dsn_add_static_library()
- target_link_libraries(${MY_PROJ_NAME} PRIVATE dsn_http)
+ target_link_libraries(${MY_PROJ_NAME} PRIVATE dsn_http
dsn_replication_common)
else()
dsn_add_shared_library()
+ target_link_libraries(${MY_PROJ_NAME} PRIVATE dsn_replication_common)
endif()
add_subdirectory(long_adder_bench)
diff --git a/src/utils/metrics.cpp b/src/utils/metrics.cpp
index 3d2ad00b8..2cd8e70d0 100644
--- a/src/utils/metrics.cpp
+++ b/src/utils/metrics.cpp
@@ -22,11 +22,17 @@
#include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <boost/system/error_code.hpp>
#include <fmt/core.h>
+#include <unistd.h>
#include <new>
#include "http/http_method.h"
#include "http/http_status_code.h"
#include "runtime/api_layer1.h"
+#include "runtime/rpc/rpc_address.h"
+#include "runtime/rpc/rpc_engine.h"
+#include "runtime/service_app.h"
+#include "runtime/service_engine.h"
+#include "runtime/task/task.h"
#include "utils/flags.h"
#include "utils/rand.h"
#include "utils/shared_io_service.h"
@@ -410,17 +416,6 @@ 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)
@@ -449,6 +444,83 @@ metric_entity_ptr
metric_registry::find_or_create_entity(const metric_entity_pro
return entity;
}
+DSN_DECLARE_string(cluster_name);
+
+namespace {
+
+#define ENCODE_OBJ_VAL(cond, val)
\
+ do {
\
+ if (dsn_likely(cond)) {
\
+ dsn::json::json_encode(writer, val);
\
+ } else {
\
+ dsn::json::json_encode(writer, "unknown");
\
+ }
\
+ } while (0)
+
+void encode_cluster(dsn::metric_json_writer &writer)
+{
+ writer.Key(dsn::kMetricClusterField.c_str());
+
+ ENCODE_OBJ_VAL(!utils::is_empty(dsn::FLAGS_cluster_name),
dsn::FLAGS_cluster_name);
+}
+
+void encode_role(dsn::metric_json_writer &writer)
+{
+ writer.Key(dsn::kMetricRoleField.c_str());
+
+ const auto *const node = dsn::task::get_current_node2();
+ ENCODE_OBJ_VAL(node != nullptr, node->get_service_app_info().full_name);
+}
+
+void encode_host(dsn::metric_json_writer &writer)
+{
+ writer.Key(dsn::kMetricHostField.c_str());
+
+ char hostname[1024];
+ ENCODE_OBJ_VAL(gethostname(hostname, sizeof(hostname)) == 0, hostname);
+}
+
+void encode_port(dsn::metric_json_writer &writer)
+{
+ writer.Key(dsn::kMetricPortField.c_str());
+
+ const auto *const rpc = dsn::task::get_current_rpc2();
+ ENCODE_OBJ_VAL(rpc != nullptr, rpc->primary_address().port());
+}
+
+#undef ENCODE_OBJ_VAL
+
+} // anonymous namespace
+
+void metric_registry::encode_entities(metric_json_writer &writer,
+ const metric_filters &filters) const
+{
+ writer.Key(dsn::kMetricEntitiesField.c_str());
+
+ writer.StartArray();
+
+ {
+ utils::auto_read_lock l(_lock);
+
+ for (const auto &entity : _entities) {
+ entity.second->take_snapshot(writer, filters);
+ }
+ }
+
+ writer.EndArray();
+}
+
+void metric_registry::take_snapshot(metric_json_writer &writer, const
metric_filters &filters) const
+{
+ writer.StartObject();
+ encode_cluster(writer);
+ encode_role(writer);
+ encode_host(writer);
+ encode_port(writer);
+ encode_entities(writer, filters);
+ writer.EndObject();
+}
+
metric_registry::collected_entities_info
metric_registry::collect_stale_entities() const
{
collected_entities_info collected_info;
diff --git a/src/utils/metrics.h b/src/utils/metrics.h
index 93ed703e7..abd7d5ef2 100644
--- a/src/utils/metrics.h
+++ b/src/utils/metrics.h
@@ -348,6 +348,12 @@ const std::string kMetricEntityIdField = "id";
const std::string kMetricEntityAttrsField = "attributes";
const std::string kMetricEntityMetricsField = "metrics";
+const std::string kMetricClusterField = "cluster";
+const std::string kMetricRoleField = "role";
+const std::string kMetricHostField = "host";
+const std::string kMetricPortField = "port";
+const std::string kMetricEntitiesField = "entities";
+
class metric_entity : public ref_counter
{
public:
@@ -687,6 +693,8 @@ private:
const std::string &id,
const metric_entity::attr_map
&attrs);
+ void encode_entities(metric_json_writer &writer, const metric_filters
&filters) const;
+
// These functions are used to retire stale entities.
//
// Since retirement is infrequent, there tend to be no entity that should
be retired.
diff --git a/src/utils/test/metrics_test.cpp b/src/utils/test/metrics_test.cpp
index 9e6b51066..144466b4f 100644
--- a/src/utils/test/metrics_test.cpp
+++ b/src/utils/test/metrics_test.cpp
@@ -2267,22 +2267,35 @@ TEST(metrics_test, take_snapshot_entity)
}
}
+const std::unordered_set<std::string> kAllMetricQueryFields =
{kMetricClusterField,
+
kMetricRoleField,
+
kMetricHostField,
+
kMetricPortField,
+
kMetricEntitiesField};
+
void check_entity_ids_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 "[]".
+ // Even if there is not any entity selected, `json_string` should not be
empty.
ASSERT_FALSE(json_string.empty());
rapidjson::Document doc;
rapidjson::ParseResult result = doc.Parse(json_string.c_str());
ASSERT_FALSE(result.IsError());
+ // The root struct should be an object.
+ ASSERT_TRUE(doc.IsObject());
+ for (const auto &field : kAllMetricQueryFields) {
+ ASSERT_TRUE(doc.HasMember(field.c_str()));
+ }
+
// Actual entity ids parsed from json string.
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()) {
+ const auto &entities = doc.FindMember(kMetricEntitiesField.c_str())->value;
+ ASSERT_TRUE(entities.IsArray());
+ for (const auto &entity : entities.GetArray()) {
// The json format for each entity should be an object.
ASSERT_TRUE(entity.IsObject());
@@ -2429,12 +2442,19 @@ void check_entities_from_json_string(const std::string
&json_string,
return;
}
+ // The successful response should be an object.
+ ASSERT_TRUE(doc.IsObject());
+ for (const auto &field : kAllMetricQueryFields) {
+ ASSERT_TRUE(doc.HasMember(field.c_str()));
+ }
+
// Actual entities parsed from json string.
entity_container actual_entities;
// The json format for entities should be an array.
- ASSERT_TRUE(doc.IsArray());
- for (const auto &entity : doc.GetArray()) {
+ const auto &entities = doc.FindMember(kMetricEntitiesField.c_str())->value;
+ ASSERT_TRUE(entities.IsArray());
+ for (const auto &entity : entities.GetArray()) {
// The json format for each entity should be an object.
ASSERT_TRUE(entity.IsObject());
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]