| 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("nixio.fs") |
|---|
| 21 | require("luci.util") |
|---|
| 22 | require("luci.statistics.datatree") |
|---|
| 23 | |
|---|
| 24 | -- override entry(): check for existance <plugin>.so where <plugin> is derived from the called path |
|---|
| 25 | function _entry( path, ... ) |
|---|
| 26 | local file = path[5] or path[4] |
|---|
| 27 | if nixio.fs.access( "/usr/lib/collectd/" .. file .. ".so" ) then |
|---|
| 28 | entry( path, ... ) |
|---|
| 29 | end |
|---|
| 30 | end |
|---|
| 31 | |
|---|
| 32 | local labels = { |
|---|
| 33 | s_output = _("Output plugins"), |
|---|
| 34 | s_system = _("System plugins"), |
|---|
| 35 | s_network = _("Network plugins"), |
|---|
| 36 | |
|---|
| 37 | conntrack = _("Conntrack"), |
|---|
| 38 | cpu = _("Processor"), |
|---|
| 39 | csv = _("CSV Output"), |
|---|
| 40 | df = _("Disk Space Usage"), |
|---|
| 41 | disk = _("Disk Usage"), |
|---|
| 42 | dns = _("DNS"), |
|---|
| 43 | email = _("Email"), |
|---|
| 44 | exec = _("Exec"), |
|---|
| 45 | interface = _("Interfaces"), |
|---|
| 46 | iptables = _("Firewall"), |
|---|
| 47 | irq = _("Interrupts"), |
|---|
| 48 | iwinfo = _("Wireless"), |
|---|
| 49 | load = _("System Load"), |
|---|
| 50 | memory = _("Memory"), |
|---|
| 51 | netlink = _("Netlink"), |
|---|
| 52 | network = _("Network"), |
|---|
| 53 | olsrd = _("OLSRd"), |
|---|
| 54 | ping = _("Ping"), |
|---|
| 55 | processes = _("Processes"), |
|---|
| 56 | rrdtool = _("RRDTool"), |
|---|
| 57 | tcpconns = _("TCP Connections"), |
|---|
| 58 | unixsock = _("UnixSock") |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | -- our collectd menu |
|---|
| 62 | local collectd_menu = { |
|---|
| 63 | output = { "csv", "network", "rrdtool", "unixsock" }, |
|---|
| 64 | system = { "cpu", "df", "disk", "email", "exec", "irq", "load", "memory", "processes" }, |
|---|
| 65 | network = { "conntrack", "dns", "interface", "iptables", "netlink", "olsrd", "ping", "tcpconns", "iwinfo" } |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | -- create toplevel menu nodes |
|---|
| 69 | local st = entry({"admin", "statistics"}, template("admin_statistics/index"), _("Statistics"), 80) |
|---|
| 70 | st.i18n = "statistics" |
|---|
| 71 | st.index = true |
|---|
| 72 | |
|---|
| 73 | entry({"admin", "statistics", "collectd"}, cbi("luci_statistics/collectd"), _("Collectd"), 10).subindex = true |
|---|
| 74 | |
|---|
| 75 | |
|---|
| 76 | -- populate collectd plugin menu |
|---|
| 77 | local index = 1 |
|---|
| 78 | for section, plugins in luci.util.kspairs( collectd_menu ) do |
|---|
| 79 | local e = entry( |
|---|
| 80 | { "admin", "statistics", "collectd", section }, |
|---|
| 81 | firstchild(), labels["s_"..section], index * 10 |
|---|
| 82 | ) |
|---|
| 83 | |
|---|
| 84 | e.index = true |
|---|
| 85 | e.i18n = "rrdtool" |
|---|
| 86 | |
|---|
| 87 | for j, plugin in luci.util.vspairs( plugins ) do |
|---|
| 88 | _entry( |
|---|
| 89 | { "admin", "statistics", "collectd", section, plugin }, |
|---|
| 90 | cbi("luci_statistics/" .. plugin ), |
|---|
| 91 | labels[plugin], j * 10 |
|---|
| 92 | ) |
|---|
| 93 | end |
|---|
| 94 | |
|---|
| 95 | index = index + 1 |
|---|
| 96 | end |
|---|
| 97 | |
|---|
| 98 | -- output views |
|---|
| 99 | local page = entry( { "admin", "statistics", "graph" }, template("admin_statistics/index"), _("Graphs"), 80) |
|---|
| 100 | page.i18n = "statistics" |
|---|
| 101 | page.setuser = "nobody" |
|---|
| 102 | page.setgroup = "nogroup" |
|---|
| 103 | |
|---|
| 104 | local vars = luci.http.formvalue(nil, true) |
|---|
| 105 | local span = vars.timespan or nil |
|---|
| 106 | local host = vars.host or nil |
|---|
| 107 | |
|---|
| 108 | -- get rrd data tree |
|---|
| 109 | local tree = luci.statistics.datatree.Instance(host) |
|---|
| 110 | |
|---|
| 111 | for i, plugin in luci.util.vspairs( tree:plugins() ) do |
|---|
| 112 | |
|---|
| 113 | -- get plugin instances |
|---|
| 114 | local instances = tree:plugin_instances( plugin ) |
|---|
| 115 | |
|---|
| 116 | -- plugin menu entry |
|---|
| 117 | entry( |
|---|
| 118 | { "admin", "statistics", "graph", plugin }, |
|---|
| 119 | call("statistics_render"), labels[plugin], i |
|---|
| 120 | ).query = { timespan = span , host = host } |
|---|
| 121 | |
|---|
| 122 | -- if more then one instance is found then generate submenu |
|---|
| 123 | if #instances > 1 then |
|---|
| 124 | for j, inst in luci.util.vspairs(instances) do |
|---|
| 125 | -- instance menu entry |
|---|
| 126 | entry( |
|---|
| 127 | { "admin", "statistics", "graph", plugin, inst }, |
|---|
| 128 | call("statistics_render"), inst, j |
|---|
| 129 | ).query = { timespan = span , host = host } |
|---|
| 130 | end |
|---|
| 131 | end |
|---|
| 132 | end |
|---|
| 133 | end |
|---|
| 134 | |
|---|
| 135 | function statistics_render() |
|---|
| 136 | |
|---|
| 137 | require("luci.statistics.rrdtool") |
|---|
| 138 | require("luci.template") |
|---|
| 139 | require("luci.model.uci") |
|---|
| 140 | |
|---|
| 141 | local vars = luci.http.formvalue() |
|---|
| 142 | local req = luci.dispatcher.context.request |
|---|
| 143 | local path = luci.dispatcher.context.path |
|---|
| 144 | local uci = luci.model.uci.cursor() |
|---|
| 145 | local spans = luci.util.split( uci:get( "luci_statistics", "collectd_rrdtool", "RRATimespans" ), "%s+", nil, true ) |
|---|
| 146 | local span = vars.timespan or uci:get( "luci_statistics", "rrdtool", "default_timespan" ) or spans[1] |
|---|
| 147 | local host = vars.host or uci:get( "luci_statistics", "collectd", "Hostname" ) or luci.sys.hostname() |
|---|
| 148 | local opts = { host = vars.host } |
|---|
| 149 | local graph = luci.statistics.rrdtool.Graph( luci.util.parse_units( span ), opts ) |
|---|
| 150 | local hosts = graph.tree:host_instances() |
|---|
| 151 | |
|---|
| 152 | local is_index = false |
|---|
| 153 | |
|---|
| 154 | -- deliver image |
|---|
| 155 | if vars.img then |
|---|
| 156 | local l12 = require "luci.ltn12" |
|---|
| 157 | local png = io.open(graph.opts.imgpath .. "/" .. vars.img:gsub("%.+", "."), "r") |
|---|
| 158 | if png then |
|---|
| 159 | luci.http.prepare_content("image/png") |
|---|
| 160 | l12.pump.all(l12.source.file(png), luci.http.write) |
|---|
| 161 | png:close() |
|---|
| 162 | end |
|---|
| 163 | return |
|---|
| 164 | end |
|---|
| 165 | |
|---|
| 166 | local plugin, instances |
|---|
| 167 | local images = { } |
|---|
| 168 | |
|---|
| 169 | -- find requested plugin and instance |
|---|
| 170 | for i, p in ipairs( luci.dispatcher.context.path ) do |
|---|
| 171 | if luci.dispatcher.context.path[i] == "graph" then |
|---|
| 172 | plugin = luci.dispatcher.context.path[i+1] |
|---|
| 173 | instances = { luci.dispatcher.context.path[i+2] } |
|---|
| 174 | end |
|---|
| 175 | end |
|---|
| 176 | |
|---|
| 177 | -- no instance requested, find all instances |
|---|
| 178 | if #instances == 0 then |
|---|
| 179 | --instances = { graph.tree:plugin_instances( plugin )[1] } |
|---|
| 180 | instances = graph.tree:plugin_instances( plugin ) |
|---|
| 181 | is_index = true |
|---|
| 182 | |
|---|
| 183 | -- index instance requested |
|---|
| 184 | elseif instances[1] == "-" then |
|---|
| 185 | instances[1] = "" |
|---|
| 186 | is_index = true |
|---|
| 187 | end |
|---|
| 188 | |
|---|
| 189 | |
|---|
| 190 | -- render graphs |
|---|
| 191 | for i, inst in ipairs( instances ) do |
|---|
| 192 | for i, img in ipairs( graph:render( plugin, inst, is_index ) ) do |
|---|
| 193 | table.insert( images, graph:strippngpath( img ) ) |
|---|
| 194 | images[images[#images]] = inst |
|---|
| 195 | end |
|---|
| 196 | end |
|---|
| 197 | |
|---|
| 198 | luci.template.render( "public_statistics/graph", { |
|---|
| 199 | images = images, |
|---|
| 200 | plugin = plugin, |
|---|
| 201 | timespans = spans, |
|---|
| 202 | current_timespan = span, |
|---|
| 203 | hosts = hosts, |
|---|
| 204 | current_host = host, |
|---|
| 205 | is_index = is_index |
|---|
| 206 | } ) |
|---|
| 207 | end |
|---|