mirror of
https://github.com/ceph/ceph
synced 2026-08-01 22:45:39 +00:00
mgr: add heap admin socket command
the mon, osd and mds register a "heap" asok command that forwards to ceph_heap_profiler_handle_command, but the mgr never did, so `ceph daemon mgr.<id> heap stats` returns "no valid command found". that leaves no way to tcmalloc-profile a leaking mgr through its admin socket, which is what chasing mgr memory growth needs. register the same command on MgrStandby's admin socket. its hook lives for the whole process, so it works on both the standby and the active mgr. heap output goes to the bufferlist, as on the other daemons, while status keeps using the formatter. Signed-off-by: Kefu Chai <k.chai@proxmox.com>
This commit is contained in:
parent
c11c7144fc
commit
d8dde402b6
@ -17,7 +17,10 @@
|
||||
|
||||
#include "common/errno.h"
|
||||
#include "common/signal.h"
|
||||
#include "common/cmdparse.h"
|
||||
#include "include/compat.h"
|
||||
#include "include/str_list.h"
|
||||
#include "perfglue/heap_profiler.h"
|
||||
|
||||
#include "include/stringify.h"
|
||||
#include "global/global_context.h"
|
||||
@ -42,6 +45,7 @@ using std::map;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using namespace std::literals;
|
||||
using ceph::common::cmd_getval;
|
||||
|
||||
class MgrHook : public AdminSocketHook {
|
||||
MgrStandby* mgr;
|
||||
@ -55,7 +59,7 @@ public:
|
||||
bufferlist& outbl) override {
|
||||
int r = 0;
|
||||
try {
|
||||
r = mgr->asok_command(admin_command, cmdmap, f, errss);
|
||||
r = mgr->asok_command(admin_command, cmdmap, f, errss, outbl);
|
||||
} catch (const TOPNSPC::common::bad_cmd_get& e) {
|
||||
errss << e.what();
|
||||
r = -EINVAL;
|
||||
@ -141,13 +145,32 @@ void MgrStandby::handle_conf_change(
|
||||
}
|
||||
}
|
||||
|
||||
int MgrStandby::asok_command(std::string_view cmd, const cmdmap_t& cmdmap, Formatter* f, std::ostream& errss)
|
||||
int MgrStandby::asok_command(std::string_view cmd, const cmdmap_t& cmdmap,
|
||||
Formatter* f, std::ostream& errss,
|
||||
ceph::buffer::list& outbl)
|
||||
{
|
||||
dout(10) << __func__ << ": " << cmd << dendl;
|
||||
if (cmd == "status") {
|
||||
f->open_object_section("status");
|
||||
f->close_section();
|
||||
return 0;
|
||||
} else if (cmd == "heap") {
|
||||
if (!ceph_using_tcmalloc()) {
|
||||
errss << "could not issue heap profiler command -- not using tcmalloc!";
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
std::string heapcmd;
|
||||
cmd_getval(cmdmap, "heapcmd", heapcmd);
|
||||
std::vector<std::string> cmd_vec;
|
||||
get_str_vec(heapcmd, cmd_vec);
|
||||
std::string val;
|
||||
if (cmd_getval(cmdmap, "value", val)) {
|
||||
cmd_vec.push_back(val);
|
||||
}
|
||||
std::ostringstream outss;
|
||||
ceph_heap_profiler_handle_command(cmd_vec, outss);
|
||||
outbl.append(outss.str());
|
||||
return 0;
|
||||
} else {
|
||||
return -ENOSYS;
|
||||
}
|
||||
@ -182,6 +205,14 @@ int MgrStandby::init()
|
||||
{
|
||||
int r = admin_socket->register_command("status", asok_hook.get(), "show status");
|
||||
ceph_assert(r == 0);
|
||||
r = admin_socket->register_command(
|
||||
"heap " \
|
||||
"name=heapcmd,type=CephChoices,strings=" \
|
||||
"dump|start_profiler|stop_profiler|release|get_release_rate|set_release_rate|stats " \
|
||||
"name=value,type=CephString,req=false",
|
||||
asok_hook.get(),
|
||||
"show heap usage info (available only if compiled with tcmalloc)");
|
||||
ceph_assert(r == 0);
|
||||
}
|
||||
|
||||
poolctx.start(2);
|
||||
|
||||
@ -39,7 +39,8 @@ public:
|
||||
std::vector<std::string> get_tracked_keys() const noexcept override;
|
||||
void handle_conf_change(const ConfigProxy& conf,
|
||||
const std::set <std::string> &changed) override;
|
||||
int asok_command(std::string_view cmd, const cmdmap_t& cmdmap, Formatter* f, std::ostream& errss);
|
||||
int asok_command(std::string_view cmd, const cmdmap_t& cmdmap, Formatter* f,
|
||||
std::ostream& errss, ceph::buffer::list& outbl);
|
||||
|
||||
protected:
|
||||
ceph::async::io_context_pool poolctx;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user