f->close_section();
}
+void OpHistory::dump_ops_by_duration(utime_t now, Formatter *f)
+{
+ Mutex::Locker history_lock(ops_history_lock);
+ cleanup(now);
+ f->open_object_section("op_history");
+ f->dump_int("size", history_size);
+ f->dump_int("duration", history_duration);
+ {
+ f->open_array_section("ops");
+ if (arrived.size()) {
+ vector<pair<double, TrackedOpRef> > durationvec;
+ durationvec.reserve(arrived.size());
+
+ for (set<pair<utime_t, TrackedOpRef> >::const_iterator i =
+ arrived.begin();
+ i != arrived.end();
+ ++i) {
+ durationvec.push_back(pair<double, TrackedOpRef>(i->second->get_duration(), i->second));
+ }
+
+ sort(durationvec.begin(), durationvec.end());
+
+ for (auto i = durationvec.rbegin(); i != durationvec.rend(); ++i) {
+ f->open_object_section("op");
+ i->second->dump(now, f);
+ f->close_section();
+ }
+ }
+ f->close_section();
+ }
+ f->close_section();
+}
+
struct ShardedTrackingData {
Mutex ops_in_flight_lock_sharded;
TrackedOp::tracked_op_list_t ops_in_flight_sharded;
}
}
-bool OpTracker::dump_historic_ops(Formatter *f)
+bool OpTracker::dump_historic_ops(Formatter *f, bool by_duration)
{
RWLock::RLocker l(lock);
if (!tracking_enabled)
return false;
utime_t now = ceph_clock_now();
- history.dump_ops(now, f);
+ if (by_duration) {
+ history.dump_ops_by_duration(now, f);
+ } else {
+ history.dump_ops(now, f);
+ }
return true;
}
}
void insert(utime_t now, TrackedOpRef op);
void dump_ops(utime_t now, Formatter *f);
+ void dump_ops_by_duration(utime_t now, Formatter *f);
void on_shutdown();
void set_size_and_duration(uint32_t new_size, uint32_t new_duration) {
history_size = new_size;
tracking_enabled = enable;
}
bool dump_ops_in_flight(Formatter *f, bool print_only_blocked=false);
- bool dump_historic_ops(Formatter *f);
+ bool dump_historic_ops(Formatter *f, bool by_duration = false);
bool register_inflight_op(TrackedOp *i);
void unregister_inflight_op(TrackedOp *i);
asok_hook,
"show slowest recent ops");
assert(r == 0);
+ r = admin_socket->register_command("dump_historic_ops_by_duration", "dump_historic_ops_by_duration",
+ asok_hook,
+ "show slowest recent ops, sorted by op duration");
+ assert(r == 0);
r = admin_socket->register_command("scrub_path",
"scrub_path name=path,type=CephString "
"name=scrubops,type=CephChoices,"
admin_socket->unregister_command("ops");
admin_socket->unregister_command("dump_blocked_ops");
admin_socket->unregister_command("dump_historic_ops");
+ admin_socket->unregister_command("dump_historic_ops_by_duration");
admin_socket->unregister_command("scrub_path");
admin_socket->unregister_command("tag path");
admin_socket->unregister_command("flush_path");
ss << "op_tracker tracking is not enabled now, so no ops are tracked currently, even those get stuck. \
please enable \"osd_enable_op_tracker\", and the tracker will start to track new ops received afterwards.";
}
+ } else if (command == "dump_historic_ops_by_duration") {
+ if (!op_tracker.dump_historic_ops(f, true)) {
+ ss << "op_tracker tracking is not enabled now, so no ops are tracked currently, even those get stuck. \
+ please enable \"osd_enable_op_tracker\", and the tracker will start to track new ops received afterwards.";
+ }
} else if (command == "osdmap barrier") {
int64_t target_epoch = 0;
bool got_val = cmd_getval(g_ceph_context, cmdmap, "target_epoch", target_epoch);
Please enable \"osd_enable_op_tracker\", and the tracker will start to track new ops received afterwards.";
}
} else if (command == "dump_historic_ops") {
- if (!op_tracker.dump_historic_ops(f)) {
+ if (!op_tracker.dump_historic_ops(f, false)) {
+ ss << "op_tracker tracking is not enabled now, so no ops are tracked currently, even those get stuck. \
+ Please enable \"osd_enable_op_tracker\", and the tracker will start to track new ops received afterwards.";
+ }
+ } else if (command == "dump_historic_ops_by_duration") {
+ if (!op_tracker.dump_historic_ops(f, true)) {
ss << "op_tracker tracking is not enabled now, so no ops are tracked currently, even those get stuck. \
Please enable \"osd_enable_op_tracker\", and the tracker will start to track new ops received afterwards.";
}
asok_hook,
"show slowest recent ops");
assert(r == 0);
+ r = admin_socket->register_command("dump_historic_ops_by_duration", "dump_historic_ops_by_duration",
+ asok_hook,
+ "show slowest recent ops, sorted by duration");
+ assert(r == 0);
r = admin_socket->register_command("dump_op_pq_state", "dump_op_pq_state",
asok_hook,
"dump op priority queue state");
cct->get_admin_socket()->unregister_command("ops");
cct->get_admin_socket()->unregister_command("dump_blocked_ops");
cct->get_admin_socket()->unregister_command("dump_historic_ops");
+ cct->get_admin_socket()->unregister_command("dump_historic_ops_by_duration");
cct->get_admin_socket()->unregister_command("dump_op_pq_state");
cct->get_admin_socket()->unregister_command("dump_blacklist");
cct->get_admin_socket()->unregister_command("dump_watchers");