Software /
code /
prosody-modules
Comparison
mod_statistics/mod_statistics.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 | 1074:cccd9f6a628d |
comparison
equal
deleted
inserted
replaced
1071:8f59b45fe6a7 | 1072:4dbdb1b465e8 |
---|---|
1 module:set_global(); | |
2 | |
3 local stats = module:require("mod_statistics/stats"); | |
4 local filters = require "util.filters"; | |
5 local serialize = require "util.serialization".serialize; | |
6 | |
7 local cached_values = {}; | |
8 | |
9 local sessions = {}; | |
10 | |
11 local function push_stat(conn, name, value) | |
12 local value_str = serialize(value); | |
13 return conn:write((("STAT %q (%s)\n"):format(name, value_str):gsub("\\\n", "\\n"))); | |
14 end | |
15 | |
16 local function push_stat_to_all(name, value) | |
17 for conn in pairs(sessions) do | |
18 push_stat(conn, name, value); | |
19 end | |
20 end | |
21 | |
22 local session_stats_tpl = ([[{ | |
23 message_in = %d, message_out = %d; | |
24 presence_in = %d, presence_out = %d; | |
25 iq_in = %d, iq_out = %d; | |
26 bytes_in = %d, bytes_out = %d; | |
27 }]]):gsub("%s", ""); | |
28 | |
29 | |
30 local jid_fields = { | |
31 c2s = "full_jid"; | |
32 s2sin = "from_host"; | |
33 s2sout = "to_host"; | |
34 component = "host"; | |
35 }; | |
36 | |
37 local function push_session_to_all(session, stats) | |
38 local id = tostring(session):match("[a-f0-9]+$"); -- FIXME: Better id? :/ | |
39 local stanzas_in, stanzas_out = stats.stanzas_in, stats.stanzas_out; | |
40 local s = (session_stats_tpl):format( | |
41 stanzas_in.message, stanzas_out.message, | |
42 stanzas_in.presence, stanzas_out.presence, | |
43 stanzas_in.iq, stanzas_out.iq, | |
44 stats.bytes_in, stats.bytes_out); | |
45 local jid = session[jid_fields[session.type]] or ""; | |
46 for conn in pairs(sessions) do | |
47 return conn:write(("SESS %q %q %s\n"):format(id, jid, s)); | |
48 end | |
49 end | |
50 | |
51 local available_stats = stats.stats; | |
52 local active_sessions = stats.active_sessions; | |
53 | |
54 -- Handle statistics provided by other modules | |
55 local function item_handlers(host) | |
56 host = host and (host.."/") or ""; | |
57 | |
58 return function (event) -- Added | |
59 local stats = event.item.statistics; | |
60 local group = host..(stats.name and (stats.name.."::") or ""); | |
61 for name, stat in pairs(stats) do | |
62 available_stats[group..name] = stat; | |
63 end | |
64 end, function (event) -- Removed | |
65 local stats = event.item.statistics; | |
66 local group = host..(stats.name and (stats.name.."::") or ""); | |
67 for name, stat in pairs(stats) do | |
68 available_stats[group..name] = nil; | |
69 end | |
70 end; | |
71 end | |
72 | |
73 module:handle_items("statistics-provider", item_handlers()); | |
74 function module.add_host(module) | |
75 module:handle_items("statistics-provider", item_handlers(module.host)); | |
76 end | |
77 | |
78 -- Network listener | |
79 local listener = {}; | |
80 | |
81 function listener.onconnect(conn) | |
82 sessions[conn] = {}; | |
83 push_stat(conn, "version", prosody.version); | |
84 for name, value in pairs(cached_values) do | |
85 push_stat(conn, name, value); | |
86 end | |
87 conn:write("\n"); -- Signal end of first batch (for non-streaming clients) | |
88 end | |
89 | |
90 function listener.onincoming(conn, data) | |
91 end | |
92 | |
93 function listener.ondisconnect(conn) | |
94 sessions[conn] = nil; | |
95 end | |
96 | |
97 function module.load() | |
98 if not(prosody and prosody.full_sessions) then return; end --FIXME: hack, need a proper flag | |
99 filters.add_filter_hook(stats.filter_hook); | |
100 | |
101 module:add_timer(1, function () | |
102 for stat_name, stat in pairs(available_stats) do | |
103 if stat.get then | |
104 local cached = cached_values[stat_name]; | |
105 local new_value = stat.get(); | |
106 if new_value ~= cached then | |
107 push_stat_to_all(stat_name, new_value); | |
108 cached_values[stat_name] = new_value; | |
109 end | |
110 end | |
111 end | |
112 for session, session_stats in pairs(active_sessions) do | |
113 active_sessions[session] = nil; | |
114 push_session_to_all(session, session_stats); | |
115 end | |
116 return 1; | |
117 end); | |
118 module:provides("net", { | |
119 default_port = 5782; | |
120 listener = listener; | |
121 }); | |
122 end | |
123 function module.unload() | |
124 filters.remove_filter_hook(stats.filter_hook); | |
125 end | |
126 function module.command( args ) | |
127 local command = args[1]; | |
128 if command == "top" then | |
129 local dir = module:get_directory(); | |
130 package.path = dir.."/?.lua;"..dir.."/?.lib.lua;"..package.path; | |
131 local prosodytop = require "prosodytop"; | |
132 prosodytop.run(); | |
133 end | |
134 end |