in src/meta/meta_http_service.cpp [208:371]
void meta_http_service::list_app_handler(const http_request &req, http_response &resp)
{
bool detailed = false;
for (const auto &p : req.query_args) {
if (p.first == "detail") {
detailed = true;
} else {
resp.status_code = http_status_code::bad_request;
return;
}
}
if (!redirect_if_not_primary(req, resp))
return;
configuration_list_apps_response response;
configuration_list_apps_request request;
request.status = dsn::app_status::AS_INVALID;
_service->_state->list_apps(request, response);
if (response.err != dsn::ERR_OK) {
resp.body = response.err.to_string();
resp.status_code = http_status_code::internal_server_error;
return;
}
std::vector<::dsn::app_info> &apps = response.infos;
// output as json format
std::ostringstream out;
dsn::utils::multi_table_printer mtp;
int available_app_count = 0;
dsn::utils::table_printer tp_general("general_info");
tp_general.add_title("app_id");
tp_general.add_column("status");
tp_general.add_column("app_name");
tp_general.add_column("app_type");
tp_general.add_column("partition_count");
tp_general.add_column("replica_count");
tp_general.add_column("is_stateful");
tp_general.add_column("create_time");
tp_general.add_column("drop_time");
tp_general.add_column("drop_expire");
tp_general.add_column("envs_count");
for (const auto &app : apps) {
if (app.status != dsn::app_status::AS_AVAILABLE) {
continue;
}
std::string status_str = enum_to_string(app.status);
status_str = status_str.substr(status_str.find("AS_") + 3);
std::string create_time = "-";
if (app.create_second > 0) {
char buf[24] = {0};
dsn::utils::time_ms_to_string((uint64_t)app.create_second * 1000, buf);
create_time = buf;
}
std::string drop_time = "-";
std::string drop_expire_time = "-";
if (app.status == app_status::AS_AVAILABLE) {
available_app_count++;
} else if (app.status == app_status::AS_DROPPED && app.expire_second > 0) {
if (app.drop_second > 0) {
char buf[24] = {0};
dsn::utils::time_ms_to_string((uint64_t)app.drop_second * 1000, buf);
drop_time = buf;
}
if (app.expire_second > 0) {
char buf[24] = {0};
dsn::utils::time_ms_to_string((uint64_t)app.expire_second * 1000, buf);
drop_expire_time = buf;
}
}
tp_general.add_row(app.app_id);
tp_general.append_data(status_str);
tp_general.append_data(app.app_name);
tp_general.append_data(app.app_type);
tp_general.append_data(app.partition_count);
tp_general.append_data(app.max_replica_count);
tp_general.append_data(app.is_stateful);
tp_general.append_data(create_time);
tp_general.append_data(drop_time);
tp_general.append_data(drop_expire_time);
tp_general.append_data(app.envs.size());
}
mtp.add(std::move(tp_general));
int total_fully_healthy_app_count = 0;
int total_unhealthy_app_count = 0;
int total_write_unhealthy_app_count = 0;
int total_read_unhealthy_app_count = 0;
if (detailed && available_app_count > 0) {
dsn::utils::table_printer tp_health("healthy_info");
tp_health.add_title("app_id");
tp_health.add_column("app_name");
tp_health.add_column("partition_count");
tp_health.add_column("fully_healthy");
tp_health.add_column("unhealthy");
tp_health.add_column("write_unhealthy");
tp_health.add_column("read_unhealthy");
for (auto &info : apps) {
if (info.status != app_status::AS_AVAILABLE) {
continue;
}
query_cfg_request request;
query_cfg_response response;
request.app_name = info.app_name;
_service->_state->query_configuration_by_index(request, response);
CHECK_EQ(info.app_id, response.app_id);
CHECK_EQ(info.partition_count, response.partition_count);
int fully_healthy = 0;
int write_unhealthy = 0;
int read_unhealthy = 0;
for (int i = 0; i < response.partitions.size(); i++) {
const dsn::partition_configuration &p = response.partitions[i];
int replica_count = 0;
if (!p.primary.is_invalid()) {
replica_count++;
}
replica_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_health.add_row(info.app_id);
tp_health.append_data(info.app_name);
tp_health.append_data(info.partition_count);
tp_health.append_data(fully_healthy);
tp_health.append_data(info.partition_count - fully_healthy);
tp_health.append_data(write_unhealthy);
tp_health.append_data(read_unhealthy);
if (fully_healthy == info.partition_count)
total_fully_healthy_app_count++;
else
total_unhealthy_app_count++;
if (write_unhealthy > 0)
total_write_unhealthy_app_count++;
if (read_unhealthy > 0)
total_read_unhealthy_app_count++;
}
mtp.add(std::move(tp_health));
}
dsn::utils::table_printer tp_count("summary");
tp_count.add_row_name_and_data("total_app_count", available_app_count);
if (detailed && available_app_count > 0) {
tp_count.add_row_name_and_data("fully_healthy_app_count", total_fully_healthy_app_count);
tp_count.add_row_name_and_data("unhealthy_app_count", total_unhealthy_app_count);
tp_count.add_row_name_and_data("write_unhealthy_app_count",
total_write_unhealthy_app_count);
tp_count.add_row_name_and_data("read_unhealthy_app_count", total_read_unhealthy_app_count);
}
mtp.add(std::move(tp_count));
mtp.output(out, dsn::utils::table_printer::output_format::kJsonCompact);
resp.body = out.str();
resp.status_code = http_status_code::ok;
}