* Added support for htdocs module directory
[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", "load" },
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.getvalue()
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.getvalue()
152 local req = luci.dispatcher.context.request
153 local path = luci.dispatcher.context.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.context.dispatched.path ) do
164 if luci.dispatcher.context.dispatched.path[i] == "graph" then
165 plugin = luci.dispatcher.context.dispatched.path[i+1]
166 instances = { luci.dispatcher.context.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