]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
exporter: parse perfcounters
authorPere Diaz Bou <pdiazbou@redhat.com>
Thu, 10 Mar 2022 15:42:23 +0000 (16:42 +0100)
committerAvan Thakkar <athakkar@redhat.com>
Mon, 20 Jun 2022 18:20:46 +0000 (23:50 +0530)
Signed-off-by: Pere Diaz Bou <pdiazbou@redhat.com>
src/mgr/DaemonMetricCollector.cc
src/mgr/DaemonMetricCollector.h

index 4718f36d9754537e7473ebbf9a7669c19f319128..2823f2084d00425f3aa41c5325d6e4f1bde45dab 100644 (file)
 #include "DaemonMetricCollector.h"
 #include "common/admin_socket_client.h"
+#include "include/common_fwd.h"
+#include "common/perf_counters.h"
 
-#include <iostream>
 #include <string>
-#include <filesystem>
-
-
 #include <iostream>
-#include <string>
 #include <filesystem>
+#include <regex>
+#include <boost/json/src.hpp>
+
+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 <class T>
+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)});
+    }
+  }
 }
index e51af8e739abd7950d89506278d7c858d8c1e02d..fa397d6c699f833f9ce839d630f081725bd3d1ee 100644 (file)
@@ -1,4 +1,5 @@
 #pragma once
+
 #include "common/admin_socket_client.h"
 #include <string>
 #include <map>
@@ -19,5 +20,6 @@ private:
   //       list dir of sockets
   std::map<std::string, AdminSocketClient> clients;
   void update_sockets();
+  void send_requests();
   void start_mgr_connection();
 };