Comparison

plugins/mod_admin_shell.lua @ 13334:aefcb6b4f47d

mod_admin_shell: Add debug:async() command to show blocked async runners
author Matthew Wild <mwild1@gmail.com>
date Tue, 21 Nov 2023 18:48:58 +0000
parent 13287:1e2d65403867
child 13338:470ab6b55e93
comparison
equal deleted inserted replaced
13333:fa4143163e01 13334:aefcb6b4f47d
319 elseif section == "stats" then -- luacheck: ignore 542 319 elseif section == "stats" then -- luacheck: ignore 542
320 print [[stats:show(pattern) - Show internal statistics, optionally filtering by name with a pattern]] 320 print [[stats:show(pattern) - Show internal statistics, optionally filtering by name with a pattern]]
321 print [[stats:show():cfgraph() - Show a cumulative frequency graph]] 321 print [[stats:show():cfgraph() - Show a cumulative frequency graph]]
322 print [[stats:show():histogram() - Show a histogram of selected metric]] 322 print [[stats:show():histogram() - Show a histogram of selected metric]]
323 elseif section == "debug" then 323 elseif section == "debug" then
324 print [[debug:async() - Show information about pending asynchronous tasks]]
324 print [[debug:logevents(host) - Enable logging of fired events on host]] 325 print [[debug:logevents(host) - Enable logging of fired events on host]]
325 print [[debug:events(host, event) - Show registered event handlers]] 326 print [[debug:events(host, event) - Show registered event handlers]]
326 print [[debug:timers() - Show information about scheduled timers]] 327 print [[debug:timers() - Show information about scheduled timers]]
327 elseif section == "watch" then 328 elseif section == "watch" then
328 print [[watch:log() - Follow debug logs]] 329 print [[watch:log() - Follow debug logs]]
2012 end 2013 end
2013 end 2014 end
2014 return true; 2015 return true;
2015 end 2016 end
2016 2017
2018 function def_env.debug:async(runner_id)
2019 local print = self.session.print;
2020 local async = require "prosody.util.async";
2021 local time_now = require "prosody.util.time".now();
2022
2023 local function format_time(t)
2024 return os.date("%F %T", math.floor(normalize_time(t)));
2025 end
2026
2027 if runner_id then
2028 local matched;
2029 for runner, since in pairs(async.waiting_runners) do
2030 if runner.id == runner_id then
2031 matched = runner;
2032 print("ID ", runner.id);
2033 local f = runner.func;
2034 if f == async.default_runner_func then
2035 print("Function ", tostring(runner.current_item).." (from work queue)");
2036 else
2037 print("Function ", tostring(f));
2038 if st.is_stanza(runner.current_item) then
2039 print("Stanza:")
2040 print("\t"..runner.current_item:indent(2):pretty_print());
2041 else
2042 print("Work item", serialize(runner.current_item, "debug"));
2043 end
2044 end
2045
2046 print("Coroutine ", tostring(runner.thread).." ("..coroutine.status(runner.thread)..")");
2047 print("Since ", since);
2048 print("Status ", ("%s since %s (%0.2f seconds ago)"):format(runner.state, os.date("%Y-%m-%d %R:%S", math.floor(since)), time_now-since));
2049 print("");
2050 print(debug.traceback(runner.thread));
2051 return true, "Runner is "..runner.state;
2052 end
2053 end
2054 return nil, "Runner not found or is currently idle";
2055 end
2056
2057 local row = format_table({ { title = "ID", width = 12 }, { title = "Function", width = "10p" }, { title = "Status", width = "16" }, { title = "Location", width = "10p" } }, self.session.width);
2058 print(row())
2059
2060 local c = 0;
2061 for runner, since in pairs(async.waiting_runners) do
2062 c = c + 1;
2063 local f = runner.func;
2064 if f == async.default_runner_func then
2065 f = runner.current_item;
2066 end
2067 -- We want to fetch the location in the code that the runner yielded from,
2068 -- excluding util.async's wrapper code. A level of `2` assumes that we
2069 -- yielded directly from a function in util.async. This is *currently* true
2070 -- of all util.async yields, but it's fragile.
2071 local location = debug.getinfo(runner.thread, 2);
2072 print(row {
2073 runner.id;
2074 tostring(f);
2075 ("%s (%0.2fs)"):format(runner.state, time_now - since);
2076 location.short_src..(location.currentline and ":"..location.currentline or "");
2077 });
2078 end
2079 return true, ("%d runners pending"):format(c);
2080 end
2081
2017 -- COMPAT: debug:timers() was timer:info() for some time in trunk 2082 -- COMPAT: debug:timers() was timer:info() for some time in trunk
2018 def_env.timer = { info = def_env.debug.timers }; 2083 def_env.timer = { info = def_env.debug.timers };
2019 2084
2020 def_env.stats = {}; 2085 def_env.stats = {};
2021 2086