From: guidosarducci Date: Sat, 3 Mar 2018 21:45:23 +0000 (-0800) Subject: luci-app-statistics: only graph data supported by APC UPS X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=refs%2Fpull%2F1653%2Fhead;p=oweals%2Fluci.git luci-app-statistics: only graph data supported by APC UPS Some graph definitions rely on data not supported across all APC UPSes. Due to recent upstream changes in collectd, the daemon no longer creates a NaN-filled .rrd file corresponding to any missing UPS data. Depending on the connected UPS, this may result in some "broken" graphs on the Luci Statistics page since rrdtool cannot find the expected .rrd file. Include the add_supported() function to determine the UPS data available at runtime and update any definitions of graphs to include only supported data. For example, the whole chart stack of AC input and output voltages will normally be "broken" if the UPS only measures AC input voltage. With these changes, the output voltage graph definition is stripped out, allowing the chart to render. Make consistent use of data types and instances in graph definitions. All definitions now use the same format with the 'instances' key. Unnecessary 'types' and 'sources' keys are removed. Fix the definition of 'line frequency' graph, based on upstream collectd apcups plugin code: type is 'frequency' but instance should be 'input'. This also includes some code and whitespace cleanup. Signed-off-by: Tony Ambardar --- diff --git a/applications/luci-app-statistics/luasrc/statistics/rrdtool/definitions/apcups.lua b/applications/luci-app-statistics/luasrc/statistics/rrdtool/definitions/apcups.lua index 2a8aceec0..9f7a51a86 100644 --- a/applications/luci-app-statistics/luasrc/statistics/rrdtool/definitions/apcups.lua +++ b/applications/luci-app-statistics/luasrc/statistics/rrdtool/definitions/apcups.lua @@ -3,25 +3,80 @@ module("luci.statistics.rrdtool.definitions.apcups",package.seeall) -function rrdargs( graph, plugin, plugin_instance, dtype ) +function rrdargs( graph, plugin, plugin_instance ) + + local lu = require("luci.util") + local rv = { } + + -- Types and instances supported by APC UPS + -- e.g. ups_types -> { 'timeleft', 'charge', 'percent', 'voltage' } + -- e.g. ups_inst['voltage'] -> { 'input', 'battery' } + + local ups_types = graph.tree:data_types( plugin, plugin_instance ) + + local ups_inst = {} + for _, t in ipairs(ups_types) do + ups_inst[t] = graph.tree:data_instances( plugin, plugin_instance, t ) + end + + + -- Check if hash table or array is empty or nil-filled + + local function empty( t ) + for _, v in pairs(t) do + if type(v) then return false end + end + return true + end + + + -- Append graph definition but only types/instances which are + -- supported and available to the plugin and UPS. + + local function add_supported( t, defs ) + local def_inst = defs['data']['instances'] + + if type(def_inst) == "table" then + for k, v in pairs( def_inst ) do + if lu.contains( ups_types, k) then + for j = #v, 1, -1 do + if not lu.contains( ups_inst[k], v[j] ) then + table.remove( v, j ) + end + end + if #v == 0 then + def_inst[k] = nil -- can't assign v: immutable + end + else + def_inst[k] = nil -- can't assign v: immutable + end + end + if empty(def_inst) then return end + end + table.insert( t, defs ) + end + + + -- Graph definitions for APC UPS measurements MUST use only 'instances': + -- e.g. instances = { voltage = { "input", "output" } } local voltagesdc = { title = "%H: Voltages on APC UPS - Battery", vlabel = "Volts DC", - alt_autoscale = true, + alt_autoscale = true, number_format = "%5.1lfV", data = { instances = { voltage = { "battery" } }, - - options = { + options = { voltage = { title = "Battery voltage", noarea=true } } } } - - local voltages = { + add_supported( rv, voltagesdc ) + + local voltagesac = { title = "%H: Voltages on APC UPS - AC", vlabel = "Volts AC", alt_autoscale = true, @@ -30,13 +85,13 @@ function rrdargs( graph, plugin, plugin_instance, dtype ) instances = { voltage = { "input", "output" } }, - options = { voltage_output = { color = "00e000", title = "Output voltage", noarea=true, overlay=true }, voltage_input = { color = "ffb000", title = "Input voltage", noarea=true, overlay=true } } } } + add_supported( rv, voltagesac ) local percentload = { title = "%H: Load on APC UPS ", @@ -45,17 +100,15 @@ function rrdargs( graph, plugin, plugin_instance, dtype ) y_max = "100", number_format = "%5.1lf%%", data = { - sources = { - percent_load = { "value" } - }, instances = { - percent = "load" + percent = { "load" } }, options = { percent_load = { color = "00ff00", title = "Load level" } } } } + add_supported( rv, percentload ) local charge_percent = { title = "%H: Battery charge on APC UPS ", @@ -64,54 +117,59 @@ function rrdargs( graph, plugin, plugin_instance, dtype ) y_max = "100", number_format = "%5.1lf%%", data = { - types = { "charge" }, + instances = { + charge = { "" } + }, options = { charge = { color = "00ff0b", title = "Charge level" } } } } + add_supported( rv, charge_percent ) local temperature = { title = "%H: Battery temperature on APC UPS ", vlabel = "\176C", number_format = "%5.1lf\176C", data = { - types = { "temperature" }, + instances = { + temperature = { "" } + }, options = { temperature = { color = "ffb000", title = "Battery temperature" } } } } + add_supported( rv, temperature ) local timeleft = { title = "%H: Time left on APC UPS ", vlabel = "Minutes", number_format = "%.1lfm", data = { - sources = { - timeleft = { "value" } + instances = { + timeleft = { "" } }, options = { timeleft = { color = "0000ff", title = "Time left" } } } } + add_supported( rv, timeleft ) local frequency = { title = "%H: Incoming line frequency on APC UPS ", vlabel = "Hz", number_format = "%5.0lfhz", data = { - sources = { - frequency_input = { "value" } - }, instances = { - frequency = "frequency" + frequency = { "input" } }, options = { - frequency_frequency = { color = "000fff", title = "Line frequency" } + frequency_input = { color = "000fff", title = "Line frequency" } } } } + add_supported( rv, frequency ) - return { voltages, voltagesdc, percentload, charge_percent, temperature, timeleft, frequency } + return rv end