]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/tools/rbd_mirror/image_replayer/journal/ReplayStatusFormatter.cc
import 15.2.2 octopus source
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / journal / ReplayStatusFormatter.cc
index 79b4b365671665648cc5245a33428a8a2e5074db..216a2fa2caf96b0e9511bd5bdfa49dd284352b3e 100644 (file)
@@ -6,6 +6,7 @@
 #include "common/dout.h"
 #include "common/errno.h"
 #include "journal/Journaler.h"
+#include "json_spirit/json_spirit.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/Journal.h"
 #include "librbd/Utils.h"
@@ -24,6 +25,25 @@ namespace journal {
 
 using librbd::util::unique_lock_name;
 
+namespace {
+
+double round_to_two_places(double value) {
+  return abs(round(value * 100) / 100);
+}
+
+json_spirit::mObject to_json_object(
+    const cls::journal::ObjectPosition& position) {
+  json_spirit::mObject object;
+  if (position != cls::journal::ObjectPosition{}) {
+    object["object_number"] = position.object_number;
+    object["tag_tid"] = position.tag_tid;
+    object["entry_tid"] = position.entry_tid;
+  }
+  return object;
+}
+
+} // anonymous namespace
+
 template <typename I>
 ReplayStatusFormatter<I>::ReplayStatusFormatter(Journaler *journaler,
                                                const std::string &mirror_uuid)
@@ -32,6 +52,14 @@ ReplayStatusFormatter<I>::ReplayStatusFormatter(Journaler *journaler,
     m_lock(ceph::make_mutex(unique_lock_name("ReplayStatusFormatter::m_lock", this))) {
 }
 
+template <typename I>
+void ReplayStatusFormatter<I>::handle_entry_processed(uint32_t bytes) {
+  dout(20) << dendl;
+
+  m_bytes_per_second(bytes);
+  m_entries_per_second(1);
+}
+
 template <typename I>
 bool ReplayStatusFormatter<I>::get_or_send_update(std::string *description,
                                                  Context *on_finish) {
@@ -216,28 +244,37 @@ void ReplayStatusFormatter<I>::handle_update_tag_cache(uint64_t master_tag_tid,
 
 template <typename I>
 void ReplayStatusFormatter<I>::format(std::string *description) {
-
   dout(20) << "m_master_position=" << m_master_position
           << ", m_mirror_position=" << m_mirror_position
           << ", m_entries_behind_master=" << m_entries_behind_master << dendl;
 
-  std::stringstream ss;
-  ss << "master_position=";
-  if (m_master_position == cls::journal::ObjectPosition()) {
-    ss << "[]";
-  } else {
-    ss << m_master_position;
-  }
-  ss << ", mirror_position=";
-  if (m_mirror_position == cls::journal::ObjectPosition()) {
-    ss << "[]";
-  } else {
-    ss << m_mirror_position;
+  json_spirit::mObject root_obj;
+  root_obj["primary_position"] = to_json_object(m_master_position);
+  root_obj["non_primary_position"] = to_json_object(m_mirror_position);
+  root_obj["entries_behind_primary"] = (
+    m_entries_behind_master > 0 ? m_entries_behind_master : 0);
+
+  m_bytes_per_second(0);
+  root_obj["bytes_per_second"] = round_to_two_places(
+    m_bytes_per_second.get_average());
+
+  m_entries_per_second(0);
+  auto entries_per_second = m_entries_per_second.get_average();
+  root_obj["entries_per_second"] = round_to_two_places(entries_per_second);
+
+  if (m_entries_behind_master > 0 && entries_per_second > 0) {
+    auto seconds_until_synced = round_to_two_places(
+      m_entries_behind_master / entries_per_second);
+    if (seconds_until_synced >= std::numeric_limits<uint64_t>::max()) {
+      seconds_until_synced = std::numeric_limits<uint64_t>::max();
+    }
+
+    root_obj["seconds_until_synced"] = static_cast<uint64_t>(
+      seconds_until_synced);
   }
-  ss << ", entries_behind_master="
-     << (m_entries_behind_master > 0 ? m_entries_behind_master : 0);
 
-  *description = ss.str();
+  *description = json_spirit::write(
+    root_obj, json_spirit::remove_trailing_zeros);
 }
 
 } // namespace journal