This is an automated email from the ASF dual-hosted git repository.
laiyingchun 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 e7b9b831e refactor(HTTP): Improve the help description of HTTP APIs
(#1959)
e7b9b831e is described below
commit e7b9b831e4b999236e2ebced370090321b5dbf28
Author: Yingchun Lai <[email protected]>
AuthorDate: Mon Apr 8 15:23:39 2024 +0800
refactor(HTTP): Improve the help description of HTTP APIs (#1959)
This patch improves the help description of HTTP APIs.
Before this patch, the path and parameters are output. The path is duplicate
because we can obtain all the paths directly (e.g. `curl 127.0.0.1:34601/`).
After this patch, the help description is more readable and we don't have to
maintain the website docs, e.g.
```
$ curl 127.0.0.1:34601/
{
"/": "List all supported calls.",
"/config": "name=<config_name>. Gets the details of a specified config.
Only the configs which are registered by DSN_DEFINE_xxx macro can be queried.",
"/configs": "List all configs. Only the configs which are registered by
DSN_DEFINE_xxx macro can be queried.",
"/meta/app": "name=<app_name>[&detail]. Query app info.",
"/meta/app/duplication": "name=<app_name>. Query app duplication info.",
"/meta/app/query_bulk_load": "name=<app_name>. Query app bulk load
info.",
"/meta/app/start_bulk_load": "A JSON format of start_bulk_load_request
structure. Start bulk load on an app.",
"/meta/app/start_compaction": "A JSON format of manual_compaction_info
structure. Start compaction for an app.",
"/meta/app/usage_scenario": "A JSON format of usage_scenario_info
structure. Update usage scenario of an app.",
"/meta/app_envs": "name=<app_name>. Query app environments.",
"/meta/apps": "[detail]. List all apps in the cluster.",
"/meta/backup_policy": "name=<app_name1>&name=<app_name2>. Query backup
policy by policy names.",
"/meta/cluster": "Query the cluster info.",
"/meta/nodes": "[detail]. Query the replica servers info.",
"/metrics":
"[with_metric_fields=field1,field2,...][&types=type1,type2,...][&ids=id1,id2,...][&attributes=attr1,value1,attr2,value2,...][&metrics=metric1,metric2,...][&detail=true|false]Query
the node metrics.",
"/pprof/cmdline": "Query the process' cmdline.",
"/pprof/growth": "Query the stack traces that caused growth in the
address space size.",
"/pprof/heap": "[seconds=<heap_profile_seconds>]. Query a sample of
live objects and the stack traces that allocated these objects (an environment
variable TCMALLOC_SAMPLE_PARAMETER should set to a positive value, such as
524288), or the current heap profiling information if 'seconds' parameter is
specified.",
"/pprof/profile": "[seconds=<cpu_profile_seconds>]. Query the CPU
profile. 'seconds' is 60 if not specified.",
"/pprof/symbol": "[symbol_address]. Query the process' symbols. Return
the symbol count of the process if using GET, return the symbol of the
'symbol_address' if using POST.",
"/recentStartTime": "Get the server start time.",
"/updateConfig": "<key>=<new_value>. Update the config to the new
value.",
"/version": "Get the server version."
}
```
or
```
$ curl 127.0.0.1:34801/
{
"/": "List all supported calls.",
"/config": "name=<config_name>. Gets the details of a specified config.
Only the configs which are registered by DSN_DEFINE_xxx macro can be queried.",
"/configs": "List all configs. Only the configs which are registered by
DSN_DEFINE_xxx macro can be queried.",
"/metrics":
"[with_metric_fields=field1,field2,...][&types=type1,type2,...][&ids=id1,id2,...][&attributes=attr1,value1,attr2,value2,...][&metrics=metric1,metric2,...][&detail=true|false]Query
the node metrics.",
"/pprof/cmdline": "Query the process' cmdline.",
"/pprof/growth": "Query the stack traces that caused growth in the
address space size.",
"/pprof/heap": "[seconds=<heap_profile_seconds>]. Query a sample of
live objects and the stack traces that allocated these objects (an environment
variable TCMALLOC_SAMPLE_PARAMETER should set to a positive value, such as
524288), or the current heap profiling information if 'seconds' parameter is
specified.",
"/pprof/profile": "[seconds=<cpu_profile_seconds>]. Query the CPU
profile. 'seconds' is 60 if not specified.",
"/pprof/symbol": "[symbol_address]. Query the process' symbols. Return
the symbol count of the process if using GET, return the symbol of the
'symbol_address' if using POST.",
"/recentStartTime": "Get the server start time.",
"/replica/data_version": "app_id=<app_id>. Query the data version of an
app.",
"/replica/duplication": "appid=<appid>. Query the duplication status of
an app.",
"/replica/manual_compaction": "app_id=<app_id>. Query the manual
compaction status of an app.",
"/updateConfig": "<key>=<new_value>. Update the config to the new
value.",
"/version": "Get the server version."
}
```
---
src/http/builtin_http_calls.cpp | 14 +++++++++-----
src/http/config_http_service.cpp | 6 ++++++
src/http/http_server.cpp | 11 +++++++++--
src/http/http_server.h | 16 ++++++++++++----
src/http/pprof_http_service.cpp | 10 +++++-----
src/http/pprof_http_service.h | 17 ++++++++++++-----
src/http/test/http_server_test.cpp | 9 +++++----
src/http/test/main.cpp | 4 ++--
src/meta/meta_http_service.cpp | 9 ++++++++-
src/meta/meta_http_service.h | 32 +++++++++++++++++++++-----------
src/replica/replica_http_service.h | 9 ++++++---
src/utils/flags.cpp | 2 +-
src/utils/metrics.cpp | 5 ++++-
13 files changed, 100 insertions(+), 44 deletions(-)
diff --git a/src/http/builtin_http_calls.cpp b/src/http/builtin_http_calls.cpp
index 6cdb87159..d42c95d68 100644
--- a/src/http/builtin_http_calls.cpp
+++ b/src/http/builtin_http_calls.cpp
@@ -80,27 +80,31 @@ namespace dsn {
register_http_call("")
.with_callback(
[](const http_request &req, http_response &resp) {
get_help_handler(req, resp); })
- .with_help("Lists all supported calls");
+ .with_help("List all supported calls.");
register_http_call("version")
.with_callback(
[](const http_request &req, http_response &resp) {
get_version_handler(req, resp); })
- .with_help("Gets the server version.");
+ .with_help("Get the server version.");
register_http_call("recentStartTime")
.with_callback([](const http_request &req, http_response &resp) {
get_recent_start_time_handler(req, resp);
})
- .with_help("Gets the server start time.");
+ .with_help("Get the server start time.");
register_http_call("config")
.with_callback([](const http_request &req, http_response &resp) {
get_config(req, resp); })
- .with_help("get the details of a specified config");
+ .with_help("name=<config_name>",
+ "Gets the details of a specified config. Only the configs "
+ "which are registered by DSN_DEFINE_xxx macro can be "
+ "queried.");
register_http_call("configs")
.with_callback(
[](const http_request &req, http_response &resp) {
list_all_configs(req, resp); })
- .with_help("list all configs");
+ .with_help("List all configs. Only the configs which are registered by
DSN_DEFINE_xxx "
+ "macro can be queried.");
}
} // namespace dsn
diff --git a/src/http/config_http_service.cpp b/src/http/config_http_service.cpp
index 68fd8be36..c13db7a5d 100644
--- a/src/http/config_http_service.cpp
+++ b/src/http/config_http_service.cpp
@@ -48,6 +48,12 @@ void get_config(const http_request &req, http_response &resp)
}
}
+ if (config_name.empty()) {
+ resp.status_code = http_status_code::kBadRequest;
+ resp.body = "name shouldn't be empty";
+ return;
+ }
+
auto res = get_flag_str(config_name);
if (res.is_ok()) {
resp.body = res.get_value();
diff --git a/src/http/http_server.cpp b/src/http/http_server.cpp
index d8e38cf53..cbd214bba 100644
--- a/src/http/http_server.cpp
+++ b/src/http/http_server.cpp
@@ -89,6 +89,14 @@ std::string http_service::get_rel_path(const std::string
&sub_path) const
}
void http_service::register_handler(std::string sub_path, http_callback cb,
std::string help) const
+{
+ register_handler(std::move(sub_path), std::move(cb), "", std::move(help));
+}
+
+void http_service::register_handler(std::string sub_path,
+ http_callback cb,
+ std::string parameters,
+ std::string help) const
{
CHECK_FALSE(sub_path.empty());
if (!FLAGS_enable_http_server) {
@@ -97,8 +105,7 @@ void http_service::register_handler(std::string sub_path,
http_callback cb, std:
auto call = std::make_unique<http_call>();
call->path = get_rel_path(sub_path);
- call->callback = std::move(cb);
- call->help = std::move(help);
+ call->with_callback(std::move(cb)).with_help(parameters, help);
http_call_registry::instance().add(std::move(call));
}
diff --git a/src/http/http_server.h b/src/http/http_server.h
index 0f600ec4f..a9cf668b2 100644
--- a/src/http/http_server.h
+++ b/src/http/http_server.h
@@ -25,6 +25,7 @@
#include <unordered_map>
#include <utility>
+#include "fmt/core.h"
#include "http/http_method.h"
#include "http/http_status_code.h"
#include "runtime/task/task_code.h"
@@ -76,9 +77,10 @@ struct http_call
callback = std::move(cb);
return *this;
}
- http_call &with_help(std::string hp)
+ http_call &with_help(std::string hp) { return with_help("",
std::move(hp)); }
+ http_call &with_help(std::string parameters, std::string hp)
{
- help = std::move(hp);
+ help = fmt::format("{}{}{}", parameters, parameters.empty() ? "" : ".
", hp);
return *this;
}
};
@@ -96,6 +98,11 @@ public:
void register_handler(std::string sub_path, http_callback cb, std::string
help) const;
+ void register_handler(std::string sub_path,
+ http_callback cb,
+ std::string parameters,
+ std::string help) const;
+
private:
// If sub_path is 'app/duplication', the built path would be
'<root_path>/app/duplication',
// where path() would be called as root_path.
@@ -114,7 +121,8 @@ public:
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/updateConfig?<key>=<value>");
+ "<key>=<new_value>",
+ "Update the config to the new value.");
});
}
@@ -134,7 +142,7 @@ protected:
// this,
// std::placeholders::_1,
// std::placeholders::_2))
-// .with_help("Gets the app information")
+// .with_help("Gets the app information.")
// .add_argument("app_name", HTTP_ARG_STRING);
// ```
extern http_call ®ister_http_call(std::string full_path);
diff --git a/src/http/pprof_http_service.cpp b/src/http/pprof_http_service.cpp
index 8d9757fe9..d7246ae69 100644
--- a/src/http/pprof_http_service.cpp
+++ b/src/http/pprof_http_service.cpp
@@ -481,12 +481,12 @@ void pprof_http_service::growth_handler(const
http_request &req, http_response &
// //
// == ip:port/pprof/profile == //
// //
-static bool get_cpu_profile(std::string &result, useconds_t seconds)
+static bool get_cpu_profile(std::string &result, useconds_t micro_seconds)
{
const char *file_name = "cpu.prof";
ProfilerStart(file_name);
- usleep(seconds);
+ usleep(micro_seconds);
ProfilerStop();
std::ifstream in(file_name);
@@ -514,7 +514,7 @@ void pprof_http_service::profile_handler(const http_request
&req, http_response
return;
}
- useconds_t seconds = 60000000;
+ useconds_t micro_seconds = 60000000;
std::string req_url = req.full_url.to_string();
size_t len = req.full_url.length();
@@ -526,7 +526,7 @@ void pprof_http_service::profile_handler(const http_request
&req, http_response
std::string key(kv_sp.field(), kv_sp.length());
if (kv_sp != NULL && key == "seconds" && ++kv_sp != NULL) {
char *end_ptr;
- seconds = strtoul(kv_sp.field(), &end_ptr, 10) * 1000000;
+ micro_seconds = strtoul(kv_sp.field(), &end_ptr, 10) * 1000000;
break;
}
param_sp++;
@@ -535,7 +535,7 @@ void pprof_http_service::profile_handler(const http_request
&req, http_response
resp.status_code = http_status_code::kOk;
- get_cpu_profile(resp.body, seconds);
+ get_cpu_profile(resp.body, micro_seconds);
_in_pprof_action.store(false);
}
diff --git a/src/http/pprof_http_service.h b/src/http/pprof_http_service.h
index c10f3c719..56659d0bf 100644
--- a/src/http/pprof_http_service.h
+++ b/src/http/pprof_http_service.h
@@ -37,31 +37,38 @@ public:
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/pprof/heap");
+ "[seconds=<heap_profile_seconds>]",
+ "Query a sample of live objects and the stack traces
that allocated these "
+ "objects (an environment variable
TCMALLOC_SAMPLE_PARAMETER should set to "
+ "a positive value, such as 524288), or the current
heap profiling "
+ "information if 'seconds' parameter is specified.");
register_handler("symbol",
std::bind(&pprof_http_service::symbol_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/pprof/symbol");
+ "[symbol_address]",
+ "Query the process' symbols. Return the symbol count
of the process if "
+ "using GET, return the symbol of the 'symbol_address'
if using POST.");
register_handler("cmdline",
std::bind(&pprof_http_service::cmdline_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/pprof/cmdline");
+ "Query the process' cmdline.");
register_handler("growth",
std::bind(&pprof_http_service::growth_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/pprof/growth");
+ "Query the stack traces that caused growth in the
address space size.");
register_handler("profile",
std::bind(&pprof_http_service::profile_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/pprof/profile");
+ "[seconds=<cpu_profile_seconds>]",
+ "Query the CPU profile. 'seconds' is 60 if not
specified.");
}
std::string path() const override { return "pprof"; }
diff --git a/src/http/test/http_server_test.cpp
b/src/http/test/http_server_test.cpp
index 01d854b07..dc7f0bce7 100644
--- a/src/http/test/http_server_test.cpp
+++ b/src/http/test/http_server_test.cpp
@@ -99,22 +99,23 @@ TEST(bultin_http_calls_test, get_help)
register_http_call("")
.with_callback(
[](const http_request &req, http_response &resp) {
get_help_handler(req, resp); })
- .with_help("ip:port/");
+ .with_help("Empty test");
http_request req;
http_response resp;
get_help_handler(req, resp);
ASSERT_EQ(resp.status_code, http_status_code::kOk);
- ASSERT_EQ(resp.body, "{\"/\":\"ip:port/\"}\n");
+ ASSERT_EQ(resp.body, "{\"/\":\"Empty test\"}\n");
register_http_call("recentStartTime")
.with_callback([](const http_request &req, http_response &resp) {
get_recent_start_time_handler(req, resp);
})
- .with_help("ip:port/recentStartTime");
+ .with_help("Gets recentStartTime test");
get_help_handler(req, resp);
- ASSERT_EQ(resp.body,
"{\"/\":\"ip:port/\",\"/recentStartTime\":\"ip:port/recentStartTime\"}\n");
+ ASSERT_EQ(resp.body,
+ "{\"/\":\"Empty test\",\"/recentStartTime\":\"Gets
recentStartTime test\"}\n");
// Remove all http calls, especially `recentStartTime`.
for (const auto &call : http_call_registry::instance().list_all_calls()) {
diff --git a/src/http/test/main.cpp b/src/http/test/main.cpp
index bde70c9d0..7f950b99b 100644
--- a/src/http/test/main.cpp
+++ b/src/http/test/main.cpp
@@ -46,14 +46,14 @@ public:
dsn::http_method::GET,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/test/get");
+ "Test GET.");
register_handler("post",
std::bind(&test_http_service::method_handler,
this,
dsn::http_method::POST,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/test/post");
+ "Test POST.");
}
~test_http_service() = default;
diff --git a/src/meta/meta_http_service.cpp b/src/meta/meta_http_service.cpp
index ba5bc9b7e..4ae299bb8 100644
--- a/src/meta/meta_http_service.cpp
+++ b/src/meta/meta_http_service.cpp
@@ -90,6 +90,12 @@ void meta_http_service::get_app_handler(const http_request
&req, http_response &
if (!redirect_if_not_primary(req, resp))
return;
+ if (app_name.empty()) {
+ resp.status_code = http_status_code::kBadRequest;
+ resp.body = "app name shouldn't be empty";
+ return;
+ }
+
query_cfg_request request;
query_cfg_response response;
@@ -674,6 +680,7 @@ void meta_http_service::start_bulk_load_handler(const
http_request &req, http_re
resp.status_code = http_status_code::kBadRequest;
return;
}
+ // TODO(yingchun): Also deal the 'ingest_behind' parameter.
auto rpc_req = std::make_unique<start_bulk_load_request>(request);
start_bulk_load_rpc rpc(std::move(rpc_req), LPC_META_CALLBACK);
@@ -799,7 +806,7 @@ void meta_http_service::update_scenario_handler(const
http_request &req, http_re
return;
}
- // validate paramters
+ // validate parameters
usage_scenario_info info;
bool ret = json::json_forwarder<usage_scenario_info>::decode(req.body,
info);
if (!ret) {
diff --git a/src/meta/meta_http_service.h b/src/meta/meta_http_service.h
index 3c4d1c0a3..e603a4517 100644
--- a/src/meta/meta_http_service.h
+++ b/src/meta/meta_http_service.h
@@ -67,70 +67,80 @@ public:
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/app?app_name=temp");
+ "name=<app_name>[&detail]",
+ "Query app info.");
register_handler("app/duplication",
std::bind(&meta_http_service::query_duplication_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/app/duplication?name=<app_name>");
+ "name=<app_name>",
+ "Query app duplication info.");
register_handler("apps",
std::bind(&meta_http_service::list_app_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/apps");
+ "[detail]",
+ "List all apps in the cluster.");
register_handler("nodes",
std::bind(&meta_http_service::list_node_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/nodes");
+ "[detail]",
+ "Query the replica servers info.");
register_handler("cluster",
std::bind(&meta_http_service::get_cluster_info_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/cluster");
+ "Query the cluster info.");
register_handler("app_envs",
std::bind(&meta_http_service::get_app_envs_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/app_envs?name=temp");
+ "name=<app_name>",
+ "Query app environments.");
register_handler("backup_policy",
std::bind(&meta_http_service::query_backup_policy_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/backup_policy");
+ "name=<app_name1>&name=<app_name2>",
+ "Query backup policy by policy names.");
// request body should be start_bulk_load_request
register_handler("app/start_bulk_load",
std::bind(&meta_http_service::start_bulk_load_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/start_bulk_load");
+ "A JSON format of start_bulk_load_request structure",
+ "Start bulk load on an app.");
register_handler("app/query_bulk_load",
std::bind(&meta_http_service::query_bulk_load_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/query_bulk_load?name=temp");
+ "name=<app_name>",
+ "Query app bulk load info.");
// request body should be manual_compaction_info
register_handler("app/start_compaction",
std::bind(&meta_http_service::start_compaction_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/start_compaction");
+ "A JSON format of manual_compaction_info structure",
+ "Start compaction for an app.");
// request body should be usage_scenario_info
register_handler("app/usage_scenario",
std::bind(&meta_http_service::update_scenario_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/meta/app/usage_scenario");
+ "A JSON format of usage_scenario_info structure",
+ "Update usage scenario of an app.");
}
std::string path() const override { return "meta"; }
diff --git a/src/replica/replica_http_service.h
b/src/replica/replica_http_service.h
index 8fed6c6da..84f652d81 100644
--- a/src/replica/replica_http_service.h
+++ b/src/replica/replica_http_service.h
@@ -37,19 +37,22 @@ public:
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/replica/duplication?appid=<appid>");
+ "appid=<appid>",
+ "Query the duplication status of an app.");
register_handler("data_version",
std::bind(&replica_http_service::query_app_data_version_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/replica/data_version?app_id=<app_id>");
+ "app_id=<app_id>",
+ "Query the data version of an app.");
register_handler("manual_compaction",
std::bind(&replica_http_service::query_manual_compaction_handler,
this,
std::placeholders::_1,
std::placeholders::_2),
- "ip:port/replica/manual_compaction?app_id=<app_id>");
+ "app_id=<app_id>",
+ "Query the manual compaction status of an app.");
}
~replica_http_service()
diff --git a/src/utils/flags.cpp b/src/utils/flags.cpp
index b49526280..0eaf13806 100644
--- a/src/utils/flags.cpp
+++ b/src/utils/flags.cpp
@@ -322,7 +322,7 @@ public:
{
const auto iter = _flags.find(name);
if (iter == _flags.end()) {
- return error_s::make(ERR_OBJECT_NOT_FOUND, fmt::format("{} is not
found", name));
+ return error_s::make(ERR_OBJECT_NOT_FOUND, fmt::format("'{}' is
not found", name));
}
return iter->second.to_json();
diff --git a/src/utils/metrics.cpp b/src/utils/metrics.cpp
index d7ca3b503..1677584be 100644
--- a/src/utils/metrics.cpp
+++ b/src/utils/metrics.cpp
@@ -285,7 +285,10 @@ metrics_http_service::metrics_http_service(metric_registry
*registry) : _registr
this,
std::placeholders::_1,
std::placeholders::_2),
- fmt::format("ip:port{}", kMetricsQueryPath));
+
"[with_metric_fields=field1,field2,...][&types=type1,type2,...][&ids=id1,id2,."
+
"..][&attributes=attr1,value1,attr2,value2,...][&metrics=metric1,metric2,...]["
+ "&detail=true|false]"
+ "Query the node metrics.");
}
namespace {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]