in src/meta/meta_http_service.cpp [76:206]
void meta_http_service::get_app_handler(const http_request &req, http_response &resp)
{
std::string app_name;
bool detailed = false;
for (const auto &p : req.query_args) {
if (p.first == "name") {
app_name = p.second;
} else if (p.first == "detail") {
detailed = true;
} else {
resp.status_code = http_status_code::bad_request;
return;
}
}
if (!redirect_if_not_primary(req, resp))
return;
query_cfg_request request;
query_cfg_response response;
request.app_name = app_name;
_service->_state->query_configuration_by_index(request, response);
if (response.err == ERR_OBJECT_NOT_FOUND) {
resp.status_code = http_status_code::not_found;
resp.body = fmt::format("table not found: \"{}\"", app_name);
return;
}
if (response.err != dsn::ERR_OK) {
resp.body = response.err.to_string();
resp.status_code = http_status_code::internal_server_error;
return;
}
// output as json format
dsn::utils::multi_table_printer mtp;
std::ostringstream out;
dsn::utils::table_printer tp_general("general");
tp_general.add_row_name_and_data("app_name", app_name);
tp_general.add_row_name_and_data("app_id", response.app_id);
tp_general.add_row_name_and_data("partition_count", response.partition_count);
if (!response.partitions.empty()) {
tp_general.add_row_name_and_data("max_replica_count",
response.partitions[0].max_replica_count);
} else {
tp_general.add_row_name_and_data("max_replica_count", 0);
}
mtp.add(std::move(tp_general));
if (detailed) {
dsn::utils::table_printer tp_details("replicas");
tp_details.add_title("pidx");
tp_details.add_column("ballot");
tp_details.add_column("replica_count");
tp_details.add_column("primary");
tp_details.add_column("secondaries");
std::map<rpc_address, std::pair<int, int>> node_stat;
int total_prim_count = 0;
int total_sec_count = 0;
int fully_healthy = 0;
int write_unhealthy = 0;
int read_unhealthy = 0;
for (const auto &p : response.partitions) {
int replica_count = 0;
if (!p.primary.is_invalid()) {
replica_count++;
node_stat[p.primary].first++;
total_prim_count++;
}
replica_count += p.secondaries.size();
total_sec_count += p.secondaries.size();
if (!p.primary.is_invalid()) {
if (replica_count >= p.max_replica_count)
fully_healthy++;
else if (replica_count < 2)
write_unhealthy++;
} else {
write_unhealthy++;
read_unhealthy++;
}
tp_details.add_row(p.pid.get_partition_index());
tp_details.append_data(p.ballot);
std::stringstream oss;
oss << replica_count << "/" << p.max_replica_count;
tp_details.append_data(oss.str());
tp_details.append_data((p.primary.is_invalid() ? "-" : p.primary.to_std_string()));
oss.str("");
oss << "[";
for (int j = 0; j < p.secondaries.size(); j++) {
if (j != 0)
oss << ",";
oss << p.secondaries[j].to_std_string();
node_stat[p.secondaries[j]].second++;
}
oss << "]";
tp_details.append_data(oss.str());
}
mtp.add(std::move(tp_details));
// 'node' section.
dsn::utils::table_printer tp_nodes("nodes");
tp_nodes.add_title("node");
tp_nodes.add_column("primary");
tp_nodes.add_column("secondary");
tp_nodes.add_column("total");
for (auto &kv : node_stat) {
tp_nodes.add_row(kv.first.to_std_string());
tp_nodes.append_data(kv.second.first);
tp_nodes.append_data(kv.second.second);
tp_nodes.append_data(kv.second.first + kv.second.second);
}
tp_nodes.add_row("total");
tp_nodes.append_data(total_prim_count);
tp_nodes.append_data(total_sec_count);
tp_nodes.append_data(total_prim_count + total_sec_count);
mtp.add(std::move(tp_nodes));
// healthy partition count section.
dsn::utils::table_printer tp_hpc("healthy");
tp_hpc.add_row_name_and_data("fully_healthy_partition_count", fully_healthy);
tp_hpc.add_row_name_and_data("unhealthy_partition_count",
response.partition_count - fully_healthy);
tp_hpc.add_row_name_and_data("write_unhealthy_partition_count", write_unhealthy);
tp_hpc.add_row_name_and_data("read_unhealthy_partition_count", read_unhealthy);
mtp.add(std::move(tp_hpc));
}
mtp.output(out, dsn::utils::table_printer::output_format::kJsonCompact);
resp.body = out.str();
resp.status_code = http_status_code::ok;
}