From: Pere Diaz Bou Date: Thu, 10 Mar 2022 15:42:23 +0000 (+0100) Subject: exporter: parse perfcounters X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=5a861b4e4f67a46b8b9e6f80b727ea07f18da971;p=ceph.git exporter: parse perfcounters Signed-off-by: Pere Diaz Bou --- diff --git a/src/mgr/DaemonMetricCollector.cc b/src/mgr/DaemonMetricCollector.cc index 4718f36d97545..2823f2084d004 100644 --- a/src/mgr/DaemonMetricCollector.cc +++ b/src/mgr/DaemonMetricCollector.cc @@ -1,49 +1,138 @@ #include "DaemonMetricCollector.h" #include "common/admin_socket_client.h" +#include "include/common_fwd.h" +#include "common/perf_counters.h" -#include #include -#include - - #include -#include #include +#include +#include + +using json_object = boost::json::object; +using json_value = boost::json::value; +using json_array = boost::json::array; void DaemonMetricCollector::main() { std::cout << "metric" << std::endl; - while (1) { + // start server + int times = 1; + while (times--) { update_sockets(); + send_requests(); } } -void update_sockets() { - for (const auto &entry : fs::recursive_directory_iterator(socketdir)) { - if (entry.path().extension() == ".asok") { - if (clients.find(entry.path()) == clients.end()) { - AdminSocketClient sock(entry.path()); - clients[entry.path()] = sock; - } - } +template +void add_metric(std::stringstream &ss, T value, std::string name, std::string description, + std::string mtype, std::string labels) { + ss << "# HELP " << name << " " << description << "\n"; + ss << "# TYPE " << name << " " << mtype << "\n"; + ss << name << "{" << labels << "} " << value << "\n"; +} + +void add_double_or_int_metric(std::stringstream &ss, json_value value, std::string name, std::string description, + std::string mtype, std::string labels) { + if (value.is_int64()) { + int64_t v = value.as_int64(); + add_metric(ss, v, name, description, mtype, labels); + } + else if (value.is_double()) { + double v = value.as_double(); + add_metric(ss, v, name, description, mtype, labels); } } -void DaemonMetricCollector::send_request_per_client() { - AdminSocketClient mgr_sock_client("/var/run/ceph/whatever"); - std::string request("{\"prefix\":\"perf dump\"}"); - std::string path = "/run/" - for (const auto & entry : std::filesystem::directory_iterator(path)) { - if (clients.find(entry.path()) == clients.end()) { - AdminSocketClient sock(entry.path()); - clients[entry.path()] = sock; +std::string boost_string_to_std(boost::json::string js) { + std::string res(js.data()); + return res; +} + +void DaemonMetricCollector::send_requests() { + for(auto client : clients) { + AdminSocketClient &sock_client = client.second; + std::string daemon_name = client.first; + std::string request("{\"prefix\":\"perf dump\"}"); + std::string response; + sock_client.do_request(request, &response); + std::cout << client.first << std::endl; + std::cout << response << std::endl; + if (response.size() > 0) { + json_object dump = boost::json::parse(response).as_object(); + request = "{\"prefix\":\"perf schema\"}"; + response = ""; + sock_client.do_request(request, &response); + std::cout << response << std::endl; + json_object schema = boost::json::parse(response).as_object(); + for (auto perf : schema) { + std::string perf_group = perf.key().to_string(); + json_object perf_group_object = perf.value().as_object(); + for (auto perf_counter : perf_group_object) { + std::string perf_name = perf_counter.key().to_string(); + json_object perf_info = perf_counter.value().as_object(); + if (perf_info["priority"].as_int64() < PerfCountersBuilder::PRIO_USEFUL) { + continue; + } + int64_t type = perf_info["type"].as_int64(); + std::string mtype = boost_string_to_std(perf_info["metric_type"].as_string()); + std::string description = boost_string_to_std(perf_info["description"].as_string()); + std::stringstream ss; + std::string name = "ceph_" + perf_group + "_" + perf_name; + + std::string labels; + // Labels + // FIXME: test this, based on mgr_module perfpath_to_path_labels + if (daemon_name.substr(0, 4) == "rgw.") { + labels = "instance_id=" + daemon_name.substr(4, std::string::npos); + } else { + labels = "ceph_daemon=" + daemon_name; + if (daemon_name.substr(0, 11) == "rbd-mirror.") { + std::regex re("^rbd_mirror_image_([^/]+)/(?:(?:([^/]+)/)?)(.*)\\.(replay(?:_bytes|_latency)?)$"); + std::smatch match; + if (std::regex_search(daemon_name, match, re) == true) { + name = "ceph_rbd_mirror_image_" + match.str(4); + labels += ",pool=" + match.str(1); + labels += ",namespace=" + match.str(2); + labels += ",image=" + match.str(3); + } + } + } + + // value and add_metric + json_value perf_values = dump[perf_group].as_object()[perf_name]; + if (type & PERFCOUNTER_LONGRUNAVG) { + int64_t count = perf_values.as_object()["avgcount"].as_int64(); + add_metric(ss, count, name + "_count", description, mtype, labels); + json_value sum_value = perf_values.as_object()["sum"]; + add_double_or_int_metric(ss, sum_value, name + "_sum", description, mtype, labels); + } else if(type & PERFCOUNTER_TIME) { + if (perf_values.is_int64()) { + double value = perf_values.as_int64() / 1000000000.0f; + add_metric(ss, value, name, description, mtype, labels); + } + else if (perf_values.is_double()) { + double value = perf_values.as_double() / 1000000000.0f; + add_metric(ss, value, name, description, mtype, labels); + } + } else { + add_double_or_int_metric(ss, perf_values, name, description, mtype, labels); + } + std::cout << ss.str() << std::endl; + } + } } } } -void DaemonMetricCollector::start_mgr_connection() { - AdminSocketClient mgr_sock_client("/var/run/ceph/whatever"); - std::string request("{\"prefix\":\"help\"}"); - std::string response; - mgr_sock_client.do_request(request, &response); - std::cout << response << std::endl; +void DaemonMetricCollector::update_sockets() { + std::string path = "/tmp/ceph-asok.YY0Vnr/"; + for (const auto & entry : std::filesystem::directory_iterator(path)) { + std::string daemon_socket_name = entry.path().filename().string(); + // remove .asok + std::string daemon_name = daemon_socket_name.substr(0, daemon_socket_name.size() - 5); + if (clients.find(daemon_name) == clients.end()) { + AdminSocketClient sock(entry.path().string()); + clients.insert({daemon_name, std::move(sock)}); + } + } } diff --git a/src/mgr/DaemonMetricCollector.h b/src/mgr/DaemonMetricCollector.h index e51af8e739abd..fa397d6c699f8 100644 --- a/src/mgr/DaemonMetricCollector.h +++ b/src/mgr/DaemonMetricCollector.h @@ -1,4 +1,5 @@ #pragma once + #include "common/admin_socket_client.h" #include #include @@ -19,5 +20,6 @@ private: // list dir of sockets std::map clients; void update_sockets(); + void send_requests(); void start_mgr_connection(); };