Software / code / prosody
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 |