Software /
code /
prosody-modules
Diff
mod_statistics/prosodytop.lua @ 1072:4dbdb1b465e8
mod_statistics: Initial version, and a rough 'prosodyctl mod_statistics top'
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sat, 15 Jun 2013 19:08:34 +0100 |
child | 1085:56fc7a86eb20 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_statistics/prosodytop.lua Sat Jun 15 19:08:34 2013 +0100 @@ -0,0 +1,148 @@ +local curses = require "curses"; +local server = require "net.server_select"; +local timer = require "util.timer"; + +assert(curses.timeout, "Incorrect version of curses library. Try 'sudo luarocks install luaposix'"); + +local top = require "top"; + +function main() + local stdscr = curses.stdscr() -- it's a userdatum + --stdscr:clear(); + local view = top.new({ + stdscr = stdscr; + prosody = { up_since = os.time() }; + conn_list = {}; + }); + + timer.add_task(0.01, function () + local ch = stdscr:getch(); + if ch then + if stdscr:getch() == 410 then + view:resized(); + else + curses.ungetch(ch); + end + end + return 0.2; + end); + + timer.add_task(0, function () + view:draw(); + return 1; + end); + + --[[ + posix.signal(28, function () + table.insert(view.conn_list, { jid = "WINCH" }); + --view:draw(); + end); + ]] + + -- Fake socket object around stdin + local stdin = { + getfd = function () return 0; end; + dirty = function (self) return false; end; + settimeout = function () end; + send = function (_, d) return #d, 0; end; + close = function () end; + receive = function (_, patt) + local ch = stdscr:getch(); + if ch >= 0 and ch <=255 then + return string.char(ch); + elseif ch == 410 then + view:resized(); + else + table.insert(view.conn_list, { jid = tostring(ch) }); --FIXME + end + return ""; + end + }; + local function on_incoming(stdin, text) + -- TODO: Handle keypresses + if text:lower() == "q" then os.exit(); end + end + stdin = server.wrapclient(stdin, "stdin", 0, { + onincoming = on_incoming, ondisconnect = function () end + }, "*a"); + + local function handle_line(line) + local e = { + STAT = function (name) return function (value) + view:update_stat(name, value); + end end; + SESS = function (id) return function (jid) return function (stats) + view:update_session(id, jid, stats); + end end end; + }; + local chunk = assert(loadstring(line)); + setfenv(chunk, e); + chunk(); + end + + local stats_listener = {}; + + function stats_listener.onconnect(conn) + --stdscr:mvaddstr(6, 0, "CONNECTED"); + end + + local partial; + function stats_listener.onincoming(conn, data) + --print("DATA", data) + if partial then + partial, data = nil, partial..data; + end + if not data:match("\n") then + partial = data; + return; + end + local lastpos = 1; + for line, pos in data:gmatch("([^\n]+)\n()") do + lastpos = pos; + handle_line(line); + end + if lastpos == #data then + partial = nil; + else + partial = data:sub(lastpos+1); + end + end + + function stats_listener.ondisconnect(conn, err) + stdscr:mvaddstr(6, 0, "DISCONNECTED: "..(err or "unknown")); + end + + local conn = require "socket".tcp(); + assert(conn:connect("localhost", 5782)); + handler = server.wrapclient(conn, "localhost", 5279, stats_listener, "*a"); +end + +return { + run = function () + --os.setlocale("UTF-8", "all") + + curses.initscr() + curses.cbreak() + curses.echo(false) -- not noecho ! + curses.nl(false) -- not nonl ! + curses.timeout(0); + + local ok, err = pcall(main); + + --while true do stdscr:getch() end + --stdscr:endwin() + + if ok then + ok, err = xpcall(server.loop, debug.traceback); + end + + curses.endwin(); + + --stdscr:refresh(); + if not ok then + print(err); + end + + print"DONE" + end; +};