diff options
-rw-r--r-- | detail.php | 23 | ||||
-rw-r--r-- | graph.php | 20 | ||||
-rw-r--r-- | host.php | 9 | ||||
-rw-r--r-- | inc/functions.inc.php | 70 | ||||
-rw-r--r-- | inc/html.inc.php | 116 | ||||
-rw-r--r-- | index.php | 2 | ||||
-rw-r--r-- | layout/style-b.css | 0 | ||||
-rw-r--r-- | layout/style-c.css | 43 | ||||
-rw-r--r-- | layout/style-d.css | 3 | ||||
-rw-r--r-- | layout/style.css | 67 | ||||
-rw-r--r-- | plugin/df.json | 20 | ||||
-rw-r--r-- | plugin/swap.json | 20 | ||||
-rw-r--r-- | type/GenericIO.class.php | 6 |
13 files changed, 287 insertions, 112 deletions
@@ -15,12 +15,12 @@ if (empty($_GET['y'])) | |||
15 | if ($CONFIG['graph_type'] == 'hybrid') | 15 | if ($CONFIG['graph_type'] == 'hybrid') |
16 | $CONFIG['graph_type'] = 'canvas'; | 16 | $CONFIG['graph_type'] = 'canvas'; |
17 | 17 | ||
18 | $host = validate_get(GET('h'), 'host'); | 18 | $host = GET('h'); |
19 | $plugin = validate_get(GET('p'), 'plugin'); | 19 | $plugin = GET('p'); |
20 | $pinstance = validate_get(GET('pi'), 'pinstance'); | 20 | $pinstance = GET('pi'); |
21 | $category = validate_get(GET('c'), 'category'); | 21 | $category = GET('c'); |
22 | $type = validate_get(GET('t'), 'type'); | 22 | $type = GET('t'); |
23 | $tinstance = validate_get(GET('ti'), 'tinstance'); | 23 | $tinstance = GET('ti'); |
24 | $seconds = GET('s'); | 24 | $seconds = GET('s'); |
25 | 25 | ||
26 | $selected_plugins = !$plugin ? $CONFIG['overview'] : array($plugin); | 26 | $selected_plugins = !$plugin ? $CONFIG['overview'] : array($plugin); |
@@ -30,6 +30,12 @@ html_start(); | |||
30 | printf('<fieldset id="%s">', htmlentities($host)); | 30 | printf('<fieldset id="%s">', htmlentities($host)); |
31 | printf('<legend>%s</legend>', htmlentities($host)); | 31 | printf('<legend>%s</legend>', htmlentities($host)); |
32 | 32 | ||
33 | echo <<<EOT | ||
34 | <input type="checkbox" id="navicon" class="navicon" /> | ||
35 | <label for="navicon"></label> | ||
36 | |||
37 | EOT; | ||
38 | |||
33 | if (!$plugins = collectd_plugins($host)) { | 39 | if (!$plugins = collectd_plugins($host)) { |
34 | echo "Unknown host\n"; | 40 | echo "Unknown host\n"; |
35 | return false; | 41 | return false; |
@@ -40,7 +46,7 @@ plugins_list($host, $selected_plugins); | |||
40 | echo '<div class="graphs">'; | 46 | echo '<div class="graphs">'; |
41 | plugin_header($host, $plugin); | 47 | plugin_header($host, $plugin); |
42 | 48 | ||
43 | $args = $_GET; | 49 | $args = GET(); |
44 | print '<ul class="time-range">' . "\n"; | 50 | print '<ul class="time-range">' . "\n"; |
45 | foreach($CONFIG['term'] as $key => $s) { | 51 | foreach($CONFIG['term'] as $key => $s) { |
46 | $args['s'] = $s; | 52 | $args['s'] = $s; |
@@ -59,7 +65,8 @@ if ($CONFIG['graph_type'] == 'canvas') { | |||
59 | } else { | 65 | } else { |
60 | printf("<img src=\"%s%s\">\n", | 66 | printf("<img src=\"%s%s\">\n", |
61 | htmlentities($CONFIG['weburl']), | 67 | htmlentities($CONFIG['weburl']), |
62 | htmlentities(build_url('graph.php', $_GET))); | 68 | htmlentities(build_url('graph.php', GET())) |
69 | ); | ||
63 | } | 70 | } |
64 | echo '</div>'; | 71 | echo '</div>'; |
65 | echo "</fieldset>\n"; | 72 | echo "</fieldset>\n"; |
@@ -4,8 +4,8 @@ require_once 'conf/common.inc.php'; | |||
4 | require_once 'inc/functions.inc.php'; | 4 | require_once 'inc/functions.inc.php'; |
5 | require_once 'inc/collectd.inc.php'; | 5 | require_once 'inc/collectd.inc.php'; |
6 | 6 | ||
7 | $plugin = validate_get(GET('p'), 'plugin'); | 7 | $plugin = GET('p'); |
8 | $type = validate_get(GET('t'), 'type'); | 8 | $type = GET('t'); |
9 | $width = GET('x') ? filter_var(GET('x'), FILTER_VALIDATE_INT, array( | 9 | $width = GET('x') ? filter_var(GET('x'), FILTER_VALIDATE_INT, array( |
10 | 'min_range' => 10, | 10 | 'min_range' => 10, |
11 | 'max_range' => $CONFIG['max-width'] | 11 | 'max_range' => $CONFIG['max-width'] |
@@ -18,12 +18,12 @@ $height = GET('y') ? filter_var(GET('y'), FILTER_VALIDATE_INT, array( | |||
18 | if ($width === NULL || $height === NULL) { | 18 | if ($width === NULL || $height === NULL) { |
19 | error_log(sprintf('Invalid image dimension, x="%s", y="%s"', | 19 | error_log(sprintf('Invalid image dimension, x="%s", y="%s"', |
20 | urlencode(GET('x')), | 20 | urlencode(GET('x')), |
21 | urlencode(GET('y')))); | 21 | urlencode(GET('y')) |
22 | )); | ||
22 | error_image(); | 23 | error_image(); |
23 | } | 24 | } |
24 | 25 | ||
25 | if (validate_get(GET('h'), 'host') === NULL) { | 26 | if (GET('h') === NULL) { |
26 | error_log('Invalid host: "' . urlencode(GET('h')) . '"'); | ||
27 | error_image(); | 27 | error_image(); |
28 | } | 28 | } |
29 | 29 | ||
@@ -31,7 +31,7 @@ $typesdb = parse_typesdb_file($CONFIG['typesdb']); | |||
31 | 31 | ||
32 | if ($plugin == 'aggregation') { | 32 | if ($plugin == 'aggregation') { |
33 | $pi = explode("-", GET('pi')); | 33 | $pi = explode("-", GET('pi')); |
34 | $plugin = $_GET['p'] = validate_get($pi[0], 'plugin'); | 34 | $plugin = $_GET['p'] = GET('p', $pi[0]); |
35 | } | 35 | } |
36 | 36 | ||
37 | # plugin json | 37 | # plugin json |
@@ -61,19 +61,19 @@ if (!isset($plugin_json[$type]['type'])) | |||
61 | switch ($plugin_json[$type]['type']) { | 61 | switch ($plugin_json[$type]['type']) { |
62 | case 'stacked': | 62 | case 'stacked': |
63 | require_once 'type/GenericStacked.class.php'; | 63 | require_once 'type/GenericStacked.class.php'; |
64 | $obj = new Type_GenericStacked($CONFIG, $_GET); | 64 | $obj = new Type_GenericStacked($CONFIG, GET()); |
65 | break; | 65 | break; |
66 | case 'io': | 66 | case 'io': |
67 | require_once 'type/GenericIO.class.php'; | 67 | require_once 'type/GenericIO.class.php'; |
68 | $obj = new Type_GenericIO($CONFIG, $_GET); | 68 | $obj = new Type_GenericIO($CONFIG, GET()); |
69 | break; | 69 | break; |
70 | case 'uptime': | 70 | case 'uptime': |
71 | require_once 'type/Uptime.class.php'; | 71 | require_once 'type/Uptime.class.php'; |
72 | $obj = new Type_Uptime($CONFIG, $_GET); | 72 | $obj = new Type_Uptime($CONFIG, GET()); |
73 | break; | 73 | break; |
74 | default: | 74 | default: |
75 | require_once 'type/Default.class.php'; | 75 | require_once 'type/Default.class.php'; |
76 | $obj = new Type_Default($CONFIG, $_GET); | 76 | $obj = new Type_Default($CONFIG, GET()); |
77 | break; | 77 | break; |
78 | } | 78 | } |
79 | 79 | ||
@@ -4,8 +4,8 @@ require_once 'conf/common.inc.php'; | |||
4 | require_once 'inc/html.inc.php'; | 4 | require_once 'inc/html.inc.php'; |
5 | require_once 'inc/collectd.inc.php'; | 5 | require_once 'inc/collectd.inc.php'; |
6 | 6 | ||
7 | $host = validate_get(GET('h'), 'host'); | 7 | $host = GET('h'); |
8 | $plugin = validate_get(GET('p'), 'plugin'); | 8 | $plugin = GET('p'); |
9 | 9 | ||
10 | $selected_plugins = !$plugin ? $CONFIG['overview'] : array($plugin); | 10 | $selected_plugins = !$plugin ? $CONFIG['overview'] : array($plugin); |
11 | 11 | ||
@@ -14,6 +14,11 @@ html_start(); | |||
14 | printf("<fieldset id=\"%s\">", htmlentities($host)); | 14 | printf("<fieldset id=\"%s\">", htmlentities($host)); |
15 | printf("<legend>%s</legend>", htmlentities($host)); | 15 | printf("<legend>%s</legend>", htmlentities($host)); |
16 | 16 | ||
17 | echo <<<EOT | ||
18 | <input type="checkbox" id="navicon" class="navicon" /> | ||
19 | <label for="navicon"></label> | ||
20 | |||
21 | EOT; | ||
17 | 22 | ||
18 | if (!strlen($host) || !$plugins = collectd_plugins($host)) { | 23 | if (!strlen($host) || !$plugins = collectd_plugins($host)) { |
19 | echo "Unknown host\n"; | 24 | echo "Unknown host\n"; |
diff --git a/inc/functions.inc.php b/inc/functions.inc.php index abe0763..9e56868 100644 --- a/inc/functions.inc.php +++ b/inc/functions.inc.php | |||
@@ -2,28 +2,66 @@ | |||
2 | 2 | ||
3 | # global functions | 3 | # global functions |
4 | 4 | ||
5 | function GET($index) { | 5 | function GET($index = NULL, $value = NULL) { |
6 | if (isset($_GET[$index])) | 6 | # parse all values from $_GET when no index is given |
7 | return $_GET[$index]; | 7 | if ($index === NULL) { |
8 | return null; | 8 | $arr = array(); |
9 | } | 9 | foreach($_GET as $i => $v) { |
10 | $arr[$i] = GET($i); | ||
11 | } | ||
12 | return $arr; | ||
13 | } | ||
14 | |||
15 | if (!isset($_GET[$index])) | ||
16 | return NULL; | ||
17 | |||
18 | if ($value === NULL) | ||
19 | $value = $_GET[$index]; | ||
10 | 20 | ||
11 | function validate_get($value, $type) { | 21 | $desc = array( |
12 | switch($type) { | 22 | 'h' => 'host', |
13 | case 'host': | 23 | 'p' => 'plugin', |
14 | if (!preg_match('/^[\w-.]+$/u', $value)) | 24 | 'c' => 'category', |
25 | 't' => 'type', | ||
26 | 'pi' => 'plugin instance', | ||
27 | 'ti' => 'type instance', | ||
28 | 's' => 'seconds', | ||
29 | 'x' => 'x-axis', | ||
30 | 'y' => 'y-axis', | ||
31 | ); | ||
32 | |||
33 | switch($index) { | ||
34 | case 'h': # host | ||
35 | if (!preg_match('/^[\w-.]+$/u', $value)) { | ||
36 | error_log(sprintf('Invalid %s in $_GET["%s"]: "%s"', $desc[$index], $index, $value)); | ||
37 | return NULL; | ||
38 | } | ||
39 | break; | ||
40 | case 'p': # plugin | ||
41 | case 'c': # category | ||
42 | case 't': # type | ||
43 | if (!preg_match('/^\w+$/u', $value)) { | ||
44 | error_log(sprintf('Invalid %s in $_GET["%s"]: "%s"', $desc[$index], $index, $value)); | ||
15 | return NULL; | 45 | return NULL; |
46 | } | ||
16 | break; | 47 | break; |
17 | case 'plugin': | 48 | case 'pi': # plugin instance |
18 | case 'category': | 49 | case 'ti': # type instance |
19 | case 'type': | 50 | if (!preg_match('/^[\w-]+$/u', $value)) { |
20 | if (!preg_match('/^\w+$/u', $value)) | 51 | error_log(sprintf('Invalid %s in $_GET["%s"]: "%s"', $desc[$index], $index, $value)); |
21 | return NULL; | 52 | return NULL; |
53 | } | ||
22 | break; | 54 | break; |
23 | case 'pinstance': | 55 | case 's': # seconds |
24 | case 'tinstance': | 56 | case 'x': # x-axis |
25 | if (!preg_match('/^[\w-]+$/u', $value)) | 57 | case 'y': # y-axis |
58 | if (!is_numeric($value)) { | ||
59 | error_log(sprintf('Invalid %s in $_GET["%s"]: "%s"', $desc[$index], $index, $value)); | ||
26 | return NULL; | 60 | return NULL; |
61 | } | ||
62 | break; | ||
63 | default: | ||
64 | return NULL; | ||
27 | break; | 65 | break; |
28 | } | 66 | } |
29 | 67 | ||
diff --git a/inc/html.inc.php b/inc/html.inc.php index 2d745ec..7312601 100644 --- a/inc/html.inc.php +++ b/inc/html.inc.php | |||
@@ -19,8 +19,11 @@ function html_start() { | |||
19 | <head> | 19 | <head> |
20 | <meta charset="utf-8"> | 20 | <meta charset="utf-8"> |
21 | <title>CGP{$path}</title> | 21 | <title>CGP{$path}</title> |
22 | <meta name="viewport" content="width=device-width"> | ||
22 | <link rel="stylesheet" href="{$html_weburl}layout/style.css" type="text/css"> | 23 | <link rel="stylesheet" href="{$html_weburl}layout/style.css" type="text/css"> |
23 | <meta name="viewport" content="width=1050, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes"> | 24 | <link rel="stylesheet" href="{$html_weburl}layout/style-b.css" type="text/css" media="(max-width: 1000px),(max-device-width: 1000px) and (orientation: portrait),(max-device-width: 767px) and (orientation: landscape)"> |
25 | <link rel="stylesheet" href="{$html_weburl}layout/style-c.css" type="text/css" media="(max-width: 767px),(max-device-width: 767px) and (orientation: portrait),(max-device-width: 499px) and (orientation: landscape)"> | ||
26 | <link rel="stylesheet" href="{$html_weburl}layout/style-d.css" type="text/css" media="(max-width: 499px),(max-device-width: 499px) and (orientation: portrait)"> | ||
24 | 27 | ||
25 | EOT; | 28 | EOT; |
26 | if (isset($CONFIG['page_refresh']) && is_numeric($CONFIG['page_refresh'])) { | 29 | if (isset($CONFIG['page_refresh']) && is_numeric($CONFIG['page_refresh'])) { |
@@ -91,32 +94,33 @@ echo <<<EOT | |||
91 | EOT; | 94 | EOT; |
92 | } | 95 | } |
93 | 96 | ||
94 | function html_end() { | 97 | function html_end($footer = false) { |
95 | global $CONFIG; | 98 | global $CONFIG; |
96 | 99 | ||
97 | $git = '/usr/bin/git'; | 100 | if ($footer) { |
98 | $changelog = $CONFIG['webdir'].'/doc/CHANGELOG'; | 101 | $git = '/usr/bin/git'; |
99 | 102 | $changelog = $CONFIG['webdir'].'/doc/CHANGELOG'; | |
100 | $version = 'v?'; | ||
101 | if (file_exists($git) && is_dir($CONFIG['webdir'].'/.git')) { | ||
102 | chdir($CONFIG['webdir']); | ||
103 | $version = exec($git.' describe --tags'); | ||
104 | } elseif (file_exists($changelog)) { | ||
105 | $changelog = file($changelog); | ||
106 | $version = explode(' ', $changelog[0]); | ||
107 | $version = 'v'.$version[0]; | ||
108 | } | ||
109 | 103 | ||
110 | $html_weburl = htmlentities($CONFIG['weburl']); | 104 | $version = 'v?'; |
105 | if (file_exists($git) && is_dir($CONFIG['webdir'].'/.git')) { | ||
106 | chdir($CONFIG['webdir']); | ||
107 | $version = exec($git.' describe --tags'); | ||
108 | } elseif (file_exists($changelog)) { | ||
109 | $changelog = file($changelog); | ||
110 | $version = explode(' ', $changelog[0]); | ||
111 | $version = 'v'.$version[0]; | ||
112 | } | ||
111 | 113 | ||
112 | echo <<<EOT | 114 | $html_weburl = htmlentities($CONFIG['weburl']); |
115 | |||
116 | echo <<<EOT | ||
113 | </div> | 117 | </div> |
114 | <div id="footer"> | 118 | <div id="footer"> |
115 | <hr><span class="small"><a href="http://pommi.nethuis.nl/category/cgp/" rel="external">Collectd Graph Panel</a> ({$version}) is distributed under the <a href="{$html_weburl}doc/LICENSE" rel="licence">GNU General Public License (GPLv3)</a></span> | 119 | <hr><span class="small"><a href="http://pommi.nethuis.nl/category/cgp/" rel="external">Collectd Graph Panel</a> ({$version}) is distributed under the <a href="{$html_weburl}doc/LICENSE" rel="license">GNU General Public License (GPLv3)</a></span> |
116 | </div> | 120 | </div> |
117 | 121 | ||
118 | EOT; | 122 | EOT; |
119 | 123 | } | |
120 | if ($CONFIG['graph_type'] == 'canvas') { | 124 | if ($CONFIG['graph_type'] == 'canvas') { |
121 | if ($CONFIG['rrd_fetch_method'] == 'async') { | 125 | if ($CONFIG['rrd_fetch_method'] == 'async') { |
122 | $js_async = 'true'; | 126 | $js_async = 'true'; |
@@ -221,7 +225,7 @@ function host_summary($cat, $hosts) { | |||
221 | 225 | ||
222 | printf('<fieldset id="%s">', htmlentities($cat)); | 226 | printf('<fieldset id="%s">', htmlentities($cat)); |
223 | printf('<legend>%s</legend>', htmlentities($cat)); | 227 | printf('<legend>%s</legend>', htmlentities($cat)); |
224 | echo "<table class=\"summary\">\n"; | 228 | echo "<div class=\"summary\">\n"; |
225 | 229 | ||
226 | $row_style = array(0 => "even", 1 => "odd"); | 230 | $row_style = array(0 => "even", 1 => "odd"); |
227 | $host_counter = 0; | 231 | $host_counter = 0; |
@@ -229,12 +233,14 @@ function host_summary($cat, $hosts) { | |||
229 | foreach($hosts as $host) { | 233 | foreach($hosts as $host) { |
230 | $host_counter++; | 234 | $host_counter++; |
231 | 235 | ||
232 | printf('<tr class="%s">', $row_style[$host_counter % 2]); | 236 | printf('<div class="row %s">', $row_style[$host_counter % 2]); |
233 | printf('<th><a href="%shost.php?h=%s">%s</a></th>', | 237 | printf('<label><a href="%shost.php?h=%s">%s</a></label>', |
234 | htmlentities($CONFIG['weburl']), | 238 | htmlentities($CONFIG['weburl']), |
235 | urlencode($host), | 239 | urlencode($host), |
236 | htmlentities($host)); | 240 | htmlentities($host)); |
237 | 241 | ||
242 | echo "<div class=\"hostinfo\">"; | ||
243 | |||
238 | if ($CONFIG['showload']) { | 244 | if ($CONFIG['showload']) { |
239 | require_once 'type/Default.class.php'; | 245 | require_once 'type/Default.class.php'; |
240 | $load = array('h' => $host, 'p' => 'load', 't' => 'load'); | 246 | $load = array('h' => $host, 'p' => 'load', 't' => 'load'); |
@@ -243,11 +249,8 @@ function host_summary($cat, $hosts) { | |||
243 | 249 | ||
244 | $rrd_info = $rrd->rrd_info($CONFIG['datadir'].'/'.$host.'/load/load.rrd'); | 250 | $rrd_info = $rrd->rrd_info($CONFIG['datadir'].'/'.$host.'/load/load.rrd'); |
245 | 251 | ||
246 | # ignore if file does not exist | 252 | if ($rrd_info && |
247 | if (!$rrd_info) | 253 | isset($rrd_info['ds[shortterm].last_ds']) && |
248 | continue; | ||
249 | |||
250 | if (isset($rrd_info['ds[shortterm].last_ds']) && | ||
251 | isset($rrd_info['ds[midterm].last_ds']) && | 254 | isset($rrd_info['ds[midterm].last_ds']) && |
252 | isset($rrd_info['ds[longterm].last_ds'])) { | 255 | isset($rrd_info['ds[longterm].last_ds'])) { |
253 | 256 | ||
@@ -256,11 +259,11 @@ function host_summary($cat, $hosts) { | |||
256 | foreach (array('ds[shortterm].last_ds', 'ds[midterm].last_ds', 'ds[longterm].last_ds') as $info) { | 259 | foreach (array('ds[shortterm].last_ds', 'ds[midterm].last_ds', 'ds[longterm].last_ds') as $info) { |
257 | $class = ''; | 260 | $class = ''; |
258 | if ($cores > 0 && $rrd_info[$info] > $cores * 2) | 261 | if ($cores > 0 && $rrd_info[$info] > $cores * 2) |
259 | $class = ' class="crit"'; | 262 | $class = ' crit'; |
260 | elseif ($cores > 0 && $rrd_info[$info] > $cores) | 263 | elseif ($cores > 0 && $rrd_info[$info] > $cores) |
261 | $class = ' class="warn"'; | 264 | $class = ' warn'; |
262 | 265 | ||
263 | printf('<td%s>%.2f</td>', $class, $rrd_info[$info]); | 266 | printf('<div class="field%s">%.2f</div>', $class, $rrd_info[$info]); |
264 | } | 267 | } |
265 | } | 268 | } |
266 | } | 269 | } |
@@ -272,56 +275,57 @@ function host_summary($cat, $hosts) { | |||
272 | $rrd_info_ca = $rrd->rrd_info($CONFIG['datadir'].'/'.$host.'/memory/memory-cached.rrd'); | 275 | $rrd_info_ca = $rrd->rrd_info($CONFIG['datadir'].'/'.$host.'/memory/memory-cached.rrd'); |
273 | 276 | ||
274 | # ignore if file does not exist | 277 | # ignore if file does not exist |
275 | if (!$rrd_info_mu || !$rrd_info_mf || !$rrd_info_bf || !$rrd_info_ca) | 278 | if ($rrd_info_mu && $rrd_info_mf && $rrd_info_bf && $rrd_info_ca) { |
276 | continue; | 279 | $info='ds[value].last_ds'; |
280 | if (isset($rrd_info_mu[$info]) && isset($rrd_info_mf[$info]) && isset($rrd_info_bf[$info]) && isset($rrd_info_ca[$info]) ) { | ||
281 | $percent_mem = $rrd_info_mu[$info] * 100 / ($rrd_info_mu[$info] + $rrd_info_mf[$info] + $rrd_info_bf[$info] + $rrd_info_ca[$info]); | ||
277 | 282 | ||
278 | $info='ds[value].last_ds'; | 283 | $class = ''; |
279 | if (isset($rrd_info_mu[$info]) && isset($rrd_info_mf[$info]) && isset($rrd_info_bf[$info]) && isset($rrd_info_ca[$info]) ) { | 284 | if ($percent_mem > 90) |
280 | $percent_mem = $rrd_info_mu[$info] * 100 / ($rrd_info_mu[$info] + $rrd_info_mf[$info] + $rrd_info_bf[$info] + $rrd_info_ca[$info]); | 285 | $class = ' crit'; |
281 | 286 | elseif ($percent_mem > 70) | |
282 | $class = ''; | 287 | $class = ' warn'; |
283 | if ($percent_mem > 90) | ||
284 | $class = ' class="crit"'; | ||
285 | elseif ($percent_mem > 70) | ||
286 | $class = ' class="warn"'; | ||
287 | 288 | ||
288 | printf('<td%s>%d%%</td>', $class, $percent_mem); | 289 | printf('<div class="field%s">%d%%</div>', $class, $percent_mem); |
290 | } | ||
289 | } | 291 | } |
290 | } | 292 | } |
291 | 293 | ||
292 | if ($CONFIG['showtime']) { | 294 | if ($CONFIG['showtime']) { |
293 | $rrd_info = $rrd->rrd_info($CONFIG['datadir'].'/'.$host.'/load/load.rrd'); | 295 | $rrd_info = $rrd->rrd_info($CONFIG['datadir'].'/'.$host.'/load/load.rrd'); |
294 | $time = time() - $rrd_info['last_update']; | 296 | if ($rrd_info) { |
297 | $time = time() - $rrd_info['last_update']; | ||
295 | 298 | ||
296 | $class = 'wide'; | 299 | $class = 'wide'; |
297 | if ($time > 300) | 300 | if ($time > 300) |
298 | $class .= ' crit'; | 301 | $class .= ' crit'; |
299 | elseif ($time > 60) | 302 | elseif ($time > 60) |
300 | $class .= ' warn'; | 303 | $class .= ' warn'; |
301 | 304 | ||
302 | printf('<td class="%s"><time class="timeago" datetime="%s">%d seconds ago</time></td>', | 305 | printf('<div class="field %s"><time class="timeago" datetime="%s">%d seconds ago</time></div>', |
303 | $class, date('c', $rrd_info['last_update']), $time); | 306 | $class, date('c', $rrd_info['last_update']), $time); |
307 | } | ||
304 | } | 308 | } |
305 | 309 | ||
306 | print "</tr>\n"; | 310 | print "</div></div>\n"; |
307 | } | 311 | } |
308 | 312 | ||
309 | echo "</table>\n"; | 313 | echo "</div>\n"; |
310 | echo "</fieldset>\n"; | 314 | echo "</fieldset>\n"; |
311 | } | 315 | } |
312 | 316 | ||
313 | 317 | ||
314 | function breadcrumbs() { | 318 | function breadcrumbs() { |
315 | $path = ''; | 319 | $path = ''; |
316 | if (validate_get(GET('h'), 'host')) | 320 | if (GET('h')) |
317 | $path .= ' - '.ucfirst(GET('h')); | 321 | $path .= ' - '.ucfirst(GET('h')); |
318 | if (validate_get(GET('p'), 'plugin')) | 322 | if (GET('p')) |
319 | $path .= ' - '.ucfirst(GET('p')); | 323 | $path .= ' - '.ucfirst(GET('p')); |
320 | if (validate_get(GET('pi'), 'pinstance')) | 324 | if (GET('pi')) |
321 | $path .= ' - '.GET('pi'); | 325 | $path .= ' - '.GET('pi'); |
322 | if (validate_get(GET('t'), 'type') && validate_get(GET('p'), 'plugin') && GET('t') != GET('p')) | 326 | if (GET('t') && GET('p') && GET('t') != GET('p')) |
323 | $path .= ' - '.GET('t'); | 327 | $path .= ' - '.GET('t'); |
324 | if (validate_get(GET('ti'), 'tinstance')) | 328 | if (GET('ti')) |
325 | $path .= ' - '.GET('ti'); | 329 | $path .= ' - '.GET('ti'); |
326 | 330 | ||
327 | return $path; | 331 | return $path; |
@@ -37,4 +37,4 @@ jQuery(document).ready(function() { | |||
37 | EOT; | 37 | EOT; |
38 | } | 38 | } |
39 | 39 | ||
40 | html_end(); | 40 | html_end(true); |
diff --git a/layout/style-b.css b/layout/style-b.css new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/layout/style-b.css | |||
diff --git a/layout/style-c.css b/layout/style-c.css new file mode 100644 index 0000000..702cc04 --- /dev/null +++ b/layout/style-c.css | |||
@@ -0,0 +1,43 @@ | |||
1 | label[for="navicon"] { | ||
2 | display: block; | ||
3 | } | ||
4 | |||
5 | #header h1 { | ||
6 | padding-left: 30px; | ||
7 | } | ||
8 | |||
9 | #content { | ||
10 | padding-left: 5px; | ||
11 | } | ||
12 | |||
13 | #footer { | ||
14 | padding-left: 5px; | ||
15 | } | ||
16 | |||
17 | .row .hostinfo { | ||
18 | font-size: 0.7em; | ||
19 | opacity: 0.6; | ||
20 | } | ||
21 | |||
22 | .plugins { | ||
23 | position: absolute; | ||
24 | z-index: 0; | ||
25 | display: none; | ||
26 | } | ||
27 | |||
28 | .navicon:checked ~ .plugins { | ||
29 | display: block; | ||
30 | } | ||
31 | |||
32 | .graphs { | ||
33 | position: relative; | ||
34 | z-index: 1; | ||
35 | background: #fff; | ||
36 | min-height: 100%; | ||
37 | min-width: 100%; | ||
38 | bottom: 100%; | ||
39 | } | ||
40 | |||
41 | .navicon:checked ~ .graphs { | ||
42 | left: 125px; | ||
43 | } | ||
diff --git a/layout/style-d.css b/layout/style-d.css new file mode 100644 index 0000000..244e96a --- /dev/null +++ b/layout/style-d.css | |||
@@ -0,0 +1,3 @@ | |||
1 | .graphs img { | ||
2 | width: 99%; | ||
3 | } | ||
diff --git a/layout/style.css b/layout/style.css index 9bf4c7e..768c0c6 100644 --- a/layout/style.css +++ b/layout/style.css | |||
@@ -3,14 +3,41 @@ body { | |||
3 | margin: 0px; | 3 | margin: 0px; |
4 | } | 4 | } |
5 | 5 | ||
6 | label[for="navicon"] { | ||
7 | display: none; | ||
8 | |||
9 | position: absolute; | ||
10 | left: 5px; top: 5px; | ||
11 | z-index: 2; | ||
12 | |||
13 | height: 25px; | ||
14 | width: 25px; | ||
15 | cursor: pointer; | ||
16 | background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' width='25px' height='25px' viewBox='0 0 25 25' enable-background='new 0 0 25 25' xml:space='preserve'><rect width='25' height='5' style='fill:white'/><rect y='20' width='25' height='5' style='fill:white'/><rect y='10' width='25' height='5' style='fill:white'/></svg>"); | ||
17 | background-size: contain; | ||
18 | } | ||
19 | |||
20 | .navicon { | ||
21 | position: absolute; | ||
22 | clip: rect(0, 0, 0, 0); | ||
23 | } | ||
24 | |||
6 | #header { | 25 | #header { |
7 | background: #4d79b5; | 26 | background: #4d79b5; |
8 | padding-left: 10px; | 27 | padding-left: 10px; |
28 | color: #fff; | ||
29 | } | ||
30 | |||
31 | #header h1 { | ||
32 | position: relative; | ||
33 | display: inline-block; | ||
34 | padding: 8px; | ||
35 | margin: 0; | ||
36 | font-size: 1em; | ||
9 | } | 37 | } |
10 | 38 | ||
11 | #header a{ | 39 | #header a{ |
12 | display: block; | 40 | display: block; |
13 | padding: 8px; | ||
14 | color: #fff; | 41 | color: #fff; |
15 | text-decoration: none; | 42 | text-decoration: none; |
16 | } | 43 | } |
@@ -28,11 +55,7 @@ body { | |||
28 | #footer { | 55 | #footer { |
29 | clear: both; | 56 | clear: both; |
30 | padding: 0px 20px 16px; | 57 | padding: 0px 20px 16px; |
31 | } | 58 | background: #fff; |
32 | |||
33 | h1 { | ||
34 | margin: 0; | ||
35 | font-size: 1em; | ||
36 | } | 59 | } |
37 | 60 | ||
38 | h2 { | 61 | h2 { |
@@ -49,28 +72,35 @@ a:hover { | |||
49 | text-decoration: underline; | 72 | text-decoration: underline; |
50 | } | 73 | } |
51 | 74 | ||
52 | table.summary th { | 75 | .row { |
53 | width: 300px; | 76 | clear: left; |
54 | font-weight: normal; | 77 | padding: 4px; |
55 | text-align: left; | ||
56 | } | 78 | } |
57 | 79 | ||
58 | table.summary tr.even { | 80 | .row.even { |
59 | /* background: #eeeeee; */ | 81 | /* background: #eeeeee; */ |
60 | } | 82 | } |
61 | 83 | ||
62 | table.summary tr.odd { | 84 | .row.odd { |
63 | /* background: #cccccc; */ | 85 | /* background: #cccccc; */ |
64 | } | 86 | } |
65 | 87 | ||
66 | table.summary td { | 88 | .row label { |
67 | width: 50px; | 89 | float: left; |
68 | text-align: right; | 90 | width: 20em; |
91 | } | ||
92 | |||
93 | .row .hostinfo { | ||
94 | float: left; | ||
95 | } | ||
96 | |||
97 | .row .field { | ||
98 | float: left; | ||
99 | width: 3.4em; | ||
69 | } | 100 | } |
70 | 101 | ||
71 | table.summary td.wide { | 102 | .row .field.wide { |
72 | width: 125px; | 103 | width: 8em; |
73 | text-align: right; | ||
74 | } | 104 | } |
75 | 105 | ||
76 | img { | 106 | img { |
@@ -119,6 +149,7 @@ hr { | |||
119 | .plugins { | 149 | .plugins { |
120 | float: left; | 150 | float: left; |
121 | margin-right: 25px; | 151 | margin-right: 25px; |
152 | width: 100px; | ||
122 | } | 153 | } |
123 | 154 | ||
124 | .plugins ul > li:first-of-type { | 155 | .plugins ul > li:first-of-type { |
diff --git a/plugin/df.json b/plugin/df.json index f066dcd..2570163 100644 --- a/plugin/df.json +++ b/plugin/df.json | |||
@@ -39,5 +39,25 @@ | |||
39 | } | 39 | } |
40 | }, | 40 | }, |
41 | "legend_format": "%5.1lf%s" | 41 | "legend_format": "%5.1lf%s" |
42 | }, | ||
43 | "percent_bytes": { | ||
44 | "title": "Free space percentage ({{PI}}) on {{HOST}}", | ||
45 | "vertical": "Percent", | ||
46 | "type": "stacked", | ||
47 | "legend": { | ||
48 | "reserved": { | ||
49 | "name": "Reserved", | ||
50 | "color": "aaaaaa" | ||
51 | }, | ||
52 | "free": { | ||
53 | "name": "Free", | ||
54 | "color": "00ff00" | ||
55 | }, | ||
56 | "used": { | ||
57 | "name": "Used", | ||
58 | "color": "ff0000" | ||
59 | } | ||
60 | }, | ||
61 | "legend_format": "%5.1lf%%" | ||
42 | } | 62 | } |
43 | } | 63 | } |
diff --git a/plugin/swap.json b/plugin/swap.json index c443428..15b2768 100644 --- a/plugin/swap.json +++ b/plugin/swap.json | |||
@@ -20,6 +20,26 @@ | |||
20 | "legend_format": "%5.1lf%s", | 20 | "legend_format": "%5.1lf%s", |
21 | "base": "1024" | 21 | "base": "1024" |
22 | }, | 22 | }, |
23 | "percent": { | ||
24 | "title": "Swap utilization percentage on {{HOST}}", | ||
25 | "vertical": "Percentage", | ||
26 | "type": "stacked", | ||
27 | "legend": { | ||
28 | "free": { | ||
29 | "name": "Free", | ||
30 | "color": "00e000" | ||
31 | }, | ||
32 | "cached": { | ||
33 | "name": "Cached", | ||
34 | "color": "0000ff" | ||
35 | }, | ||
36 | "used": { | ||
37 | "name": "Used", | ||
38 | "color": "ff0000" | ||
39 | } | ||
40 | }, | ||
41 | "legend_format": "%5.1lf%%" | ||
42 | }, | ||
23 | "swap_io": { | 43 | "swap_io": { |
24 | "title": "Swapped I/O pages on {{HOST}}", | 44 | "title": "Swapped I/O pages on {{HOST}}", |
25 | "vertical": "Pages", | 45 | "vertical": "Pages", |
diff --git a/type/GenericIO.class.php b/type/GenericIO.class.php index a0a9666..3a29948 100644 --- a/type/GenericIO.class.php +++ b/type/GenericIO.class.php | |||
@@ -35,6 +35,8 @@ class Type_GenericIO extends Type_Base { | |||
35 | $rrdgraph[] = sprintf('VDEF:tot_%1$s=avg_%1$s,TOTAL', crc32hex($sources[$i])); | 35 | $rrdgraph[] = sprintf('VDEF:tot_%1$s=avg_%1$s,TOTAL', crc32hex($sources[$i])); |
36 | if ($this->percentile) | 36 | if ($this->percentile) |
37 | $rrdgraph[] = sprintf('VDEF:pct_%1$s=avg_%1$s,%2$s,PERCENT', crc32hex($sources[$i]), $this->percentile); | 37 | $rrdgraph[] = sprintf('VDEF:pct_%1$s=avg_%1$s,%2$s,PERCENT', crc32hex($sources[$i]), $this->percentile); |
38 | if ($this->percentile && $this->negative_io && $i == 1) | ||
39 | $rrdgraph[] = sprintf('VDEF:pct_%1$s_neg=avg_%1$s_neg,%2$s,PERCENT', crc32hex($sources[$i]), 100 - $this->percentile); | ||
38 | $i++; | 40 | $i++; |
39 | } | 41 | } |
40 | } | 42 | } |
@@ -70,10 +72,12 @@ class Type_GenericIO extends Type_Base { | |||
70 | 72 | ||
71 | if ($this->percentile) { | 73 | if ($this->percentile) { |
72 | $rrdgraph[] = 'COMMENT: \l'; | 74 | $rrdgraph[] = 'COMMENT: \l'; |
75 | $i=0; | ||
73 | foreach($sources as $source) { | 76 | foreach($sources as $source) { |
74 | $legend = empty($this->legend[$source]) ? $source : $this->legend[$source]; | 77 | $legend = empty($this->legend[$source]) ? $source : $this->legend[$source]; |
75 | $rrdgraph[] = sprintf('HRULE:pct_%s#%s:%sth Percentile %s', crc32hex($source), $this->get_faded_color($this->colors[$source], '000000', 0.6), $this->percentile, $this->rrd_escape($legend)); | 78 | $rrdgraph[] = sprintf('LINE:pct_%s%s#%s:%sth Percentile %s', crc32hex($source), ($i == 1 && $this->negative_io) ? '_neg' : '', $this->get_faded_color($this->colors[$source], '000000', 0.6), $this->percentile, $this->rrd_escape($legend)); |
76 | $rrdgraph[] = sprintf('GPRINT:pct_%s:%s\l', crc32hex($source), $this->rrd_format); | 79 | $rrdgraph[] = sprintf('GPRINT:pct_%s:%s\l', crc32hex($source), $this->rrd_format); |
80 | $i++; | ||
77 | } | 81 | } |
78 | } | 82 | } |
79 | 83 | ||