* luci/statistics: reworked some dispatcher, use new hashtable iterators to create...
[project/luci.git] / applications / luci-statistics / luasrc / controller / luci_statistics / luci_statistics.lua
1 --[[
2
3 Luci statistics - statistics controller module
4 (c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13
14 ]]--
15
16 module("luci.controller.luci_statistics.luci_statistics", package.seeall)
17
18 function index()
19
20         require("luci.fs")
21         require("luci.util")
22         require("luci.i18n")
23         require("luci.statistics.datatree")
24
25         -- load language file
26         luci.i18n.loadc("statistics")
27
28         -- get rrd data tree
29         local tree = luci.statistics.datatree.Instance()
30
31         -- override entry(): check for existance <plugin>.so where <plugin> is derived from the called path
32         function _entry( path, ... )
33                 local file = path[5] or path[4]
34                 if luci.fs.isfile( "/usr/lib/collectd/" .. file .. ".so" ) then
35                         entry( path, ... )
36                 end
37         end
38
39         -- override i18n(): try to translate stat_<str> or fall back to <str>
40         function _i18n( str )
41                 return luci.i18n.translate( "stat_" .. str, str )
42         end
43
44         -- our collectd menu
45         local collectd_menu = {
46                 output  = { "rrdtool", "network", "unixsock", "csv" },
47                 system  = { "exec", "email", "cpu", "df", "disk", "irq", "processes" },
48                 network = { "interface", "netlink", "iptables", "tcpconns", "ping", "dns", "wireless" }
49         }
50
51         -- create toplevel menu nodes
52         entry({"admin", "statistics"},             call("statistics_index"),        _i18n("statistics"), 80).i18n = "statistics"
53         entry({"admin", "statistics", "collectd"}, cbi("luci_statistics/collectd"), _i18n("collectd"),   10)
54
55         -- populate collectd plugin menu
56         local index = 1
57         for section, plugins in luci.util.kspairs( collectd_menu ) do
58                 entry(
59                         { "admin", "statistics", "collectd", section },
60                         call( "statistics_" .. section .. "plugins" ),
61                         _i18n( section .. "plugins" ),
62                         index * 10
63                 )
64
65                 for j, plugin in luci.util.vspairs( plugins ) do
66                         _entry(
67                                 { "admin", "statistics", "collectd", section, plugin },
68                                 cbi("luci_statistics/" .. plugin ),
69                                 _i18n( plugin ),
70                                 j * 10
71                         )
72                 end
73
74                 index = index + 1
75         end
76
77         -- output views
78         local page = entry( { "admin", "statistics", "graph" }, call("statistics_index"), _i18n("graphs"), 80)
79               page.i18n     = "statistics"
80               page.setuser  = "nobody"
81               page.setgroup = "nogroup"
82
83         local vars = luci.http.formvalues()
84         local span = vars.timespan or nil
85
86         for i, plugin in luci.util.vspairs( tree:plugins() ) do
87
88                 -- get plugin instances
89                 local instances = tree:plugin_instances( plugin )
90
91                 -- plugin menu entry
92                 entry(
93                         { "admin", "statistics", "graph", plugin },
94                         call("statistics_render"), _i18n( plugin ), i
95                 ).query = { timespan = span }
96
97                 -- if more then one instance is found then generate submenu
98                 if #instances > 1 then
99                         for j, inst in luci.util.vspairs(instances) do
100                                 -- instance menu entry
101                                 entry(
102                                         { "admin", "statistics", "graph", plugin, inst },
103                                         call("statistics_render"), inst, j
104                                 ).query = { timespan = span }
105                         end
106                 end
107         end
108 end
109
110 function statistics_index()
111         luci.template.render("admin_statistics/index")
112 end
113
114 function statistics_outputplugins()
115         local plugins = { }
116
117         for i, p in ipairs({ "rrdtool", "network", "unixsock", "csv" }) do
118                 plugins[p] = luci.i18n.translate( "stat_" .. p, p )
119         end
120
121         luci.template.render("admin_statistics/outputplugins", {plugins=plugins})
122 end
123
124 function statistics_systemplugins()
125         local plugins = { }
126
127         for i, p in ipairs({ "exec", "email", "df", "disk", "irq", "processes", "cpu" }) do
128                 plugins[p] = luci.i18n.translate( "stat_" .. p, p )
129         end
130
131         luci.template.render("admin_statistics/systemplugins", {plugins=plugins})
132 end
133
134 function statistics_networkplugins()
135         local plugins = { }
136
137         for i, p in ipairs({ "interface", "netlink", "iptables", "tcpconns", "ping", "dns", "wireless" }) do
138                 plugins[p] = luci.i18n.translate( "stat_" .. p, p )
139         end
140
141         luci.template.render("admin_statistics/networkplugins", {plugins=plugins})
142 end
143
144
145 function statistics_render()
146
147         require("luci.statistics.rrdtool")
148         require("luci.template")
149         require("luci.model.uci")
150
151         local vars  = luci.http.formvalues()
152         local req   = luci.dispatcher.request
153         local path  = luci.dispatcher.dispatched.path
154         local uci   = luci.model.uci
155         local spans = luci.util.split( uci.get( "luci_statistics", "collectd_rrdtool", "RRATimespans" ), "%s+", nil, true )
156         local span  = vars.timespan or uci.get( "luci_statistics", "rrdtool", "default_timespan" ) or spans[1]
157         local graph = luci.statistics.rrdtool.Graph( luci.util.parse_units( span ) )
158
159         local plugin, instances
160         local images = { }
161
162         -- find requested plugin and instance
163         for i, p in ipairs( luci.dispatcher.dispatched.path ) do
164                 if luci.dispatcher.dispatched.path[i] == "graph" then
165                         plugin    = luci.dispatcher.dispatched.path[i+1]
166                         instances = { luci.dispatcher.dispatched.path[i+2] }
167                 end
168         end
169
170         -- no instance requested, find all instances
171         if #instances == 0 then
172                 instances = { graph.tree:plugin_instances( plugin )[1] }
173
174         -- index instance requested
175         elseif instances[1] == "-" then
176                 instances[1] = ""
177         end
178
179
180         -- render graphs
181         for i, inst in ipairs( instances ) do
182                 for i, img in ipairs( graph:render( plugin, inst ) ) do
183                         table.insert( images, graph:strippngpath( img ) )
184                 end
185         end
186
187         luci.template.render( "public_statistics/graph", {
188                 images           = images,
189                 plugin           = plugin,
190                 timespans        = spans,
191                 current_timespan = span
192         } )
193 end