php-collection: New graph toolbox
[collectd.git] / contrib / php-collection / index.php
1 <?php // vim:fenc=utf-8:filetype=php:ts=4
2 /*
3  * Copyright (C) 2009  Bruno PrĂ©mont <bonbons AT linux-vserver.org>
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License as published by the Free Software
7  * Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 error_reporting(E_ALL | E_NOTICE | E_WARNING);
20
21 require('config.php');
22 require('functions.php');
23
24 /**
25  * Send back new list content
26  * @items Array of options values to return to browser
27  * @method Name of Javascript method that will be called to process data
28  */
29 function dhtml_response_list(&$items, $method) {
30         header("Content-Type: text/xml");
31
32         print('<?xml version="1.0" encoding="utf-8" ?>'."\n");
33         print("<response>\n");
34         printf(" <method>%s</method>\n", htmlspecialchars($method));
35         print(" <result>\n");
36         foreach ($items as &$item)
37                 printf('  <option>%s</option>'."\n", htmlspecialchars($item));
38         print(" </result>\n");
39         print("</response>");
40 }
41
42 /**
43  * Product page body with selection fields
44  */
45 function build_page() {
46         global $config;
47
48         if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/compatible; MSIE [0-9]+.[0-9];/', $_SERVER['HTTP_USER_AGENT'])) {
49                 // Internet Explorer does not support XHTML
50                 header("Content-Type: text/html");
51
52                 print('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">');
53                 print('<html lang="en">'."\n");
54         } else {
55                 header("Content-Type: application/xhtml+xml");
56
57                 print('<?xml version="1.0" encoding="utf-8" ?>'."\n");
58                 print('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'."\n");
59                 print('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">'."\n");
60         }
61         $url_base = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
62 ?>
63         <head>
64                 <title>Collectd graph viewer</title>
65                 <link rel="icon" href="favicon.png" type="image/png" />
66                 <style type="text/css">
67                         body, html { background-color: #EEEEEE; color: #000000; }
68                         h1 { text-align: center; }
69                         div.body { margin: auto; width: <?php echo isset($config['rrd_width']) ? 110+(int)$config['rrd_width'] : 600; ?>px; background: #FFFFFF; border: 1px solid #DDDDDD; }
70                         p.error { color: #CC0000; margin: 0em; }
71                         div.selector { margin: 0.5em 2em; }
72                         div.selectorbox { padding: 5px; border: 1px solid #CCCCCC; background-color: #F8F8F8; }
73                         div.selectorbox table { border: none; }
74                         div.selectorbox table td.s1 { border-bottom: 1px dashed #F0F0F0; padding-right: 1em; vertical-align: middle; }
75                         div.selectorbox table td.s2 { border-bottom: 1px dashed #F0F0F0; vertical-align: middle; }
76                         div.selectorbox table td.s3 { vertical-align: middle; }
77                         div.selectorbox table td.sc { padding: 0.5em 2em; text-align: center; }
78                         a img { border: none; }
79                         div.graphs { border-top: 1px solid #DDDDDD; padding: 5px; overflow: auto; }
80                         div.graphs_t { position: relative; }
81                         div.graph { text-align: right; }
82                         div.selector select { width: 100%; }
83                         table.toolbox { border: 1px solid #5500dd; padding: 0px; margin: 0px; background: #ffffff;}
84                         table.toolbox td.c1 { vertical-align: middle; text-align: left; padding-left: 0.3em; padding-right: 1em; border-right: 1px solid #5500dd; }
85                         table.toolbox td.c2 { vertical-align: middle; text-align: center; padding-left: 5px; padding-right: 5px; }
86                 </style>
87                 <script type="text/javascript">// <![CDATA[
88 var dhtml_url = '<?php echo addslashes($url_base.basename($_SERVER['PHP_SELF'])); ?>';
89 var graph_url = '<?php echo addslashes($url_base.'graph.php'); ?>';
90 //              ]]></script>
91                 <script type="text/javascript" src="<?php echo htmlspecialchars($url_base.'browser.js'); ?>"></script>
92         </head>
93
94         <body onload="ListRefreshHost(); GraphListRefresh(); "><div class="body">
95                 <h1><img src="collectd-logo.png" align="bottom" alt="" /> Collectd browser for system statistics graphs</h1>
96                 <div class="selector"><a href="javascript:toggleDiv('selector')"><span id="selector_sw">Hide</span> graph selection tool</a><div id="selector" class="selectorbox">
97                         <table>
98                                 <tr>
99                                         <td class="s1">Host:</td>
100                                         <td class="s2"><select id="host_list"   name="host"   disabled="disabled" onchange="ListRefreshPlugin()">
101                                         </select></td>
102                                         <td class="s3"><a href="javascript:ListRefreshHost()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh host list" /></a></td>
103                                 </tr>
104                                 <tr>
105                                         <td class="s1">Plugin:</td>
106                                         <td class="s2"><select id="plugin_list" name="plugin" disabled="disabled" onchange="ListRefreshPluginInstance()">
107                                         </select></td>
108                                         <td class="s3"><a href="javascript:ListRefreshPlugin()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh plugin list" /></a></td>
109                                 </tr>
110                                 <tr>
111                                         <td class="s1">Plugin instance:</td>
112                                         <td class="s2"><select id="pinst_list"  name="pinst"  disabled="disabled" onchange="ListRefreshType()">
113                                         </select></td>
114                                         <td class="s3"><a href="javascript:ListRefreshPluginInstance()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh plugin instance list" /></a></td>
115                                 </tr>
116                                 <tr>
117                                         <td class="s1">Type:</td>
118                                         <td class="s2"><select id="type_list"   name="type"   disabled="disabled" onchange="ListRefreshTypeInstance()">
119                                         </select></td>
120                                         <td class="s3"><a href="javascript:ListRefreshType()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh type list" /></a></td>
121                                 </tr>
122                                 <tr>
123                                         <td class="s1">Type instance:</td>
124                                         <td class="s2"><select id="tinst_list"  name="tinst"  disabled="disabled" onchange="RefreshButtons()">
125                                         </select></td>
126                                         <td class="s3"><a href="javascript:ListRefreshTypeInstance()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh type instance list" /></a></td>
127                                 </tr>
128                                 <tr>
129                                         <td class="s1">Graph settings:</td>
130                                         <td class="s2"><select id="timespan" name="timespan">
131 <?php                           foreach ($config['timespan'] as &$timespan)
132                                                 printf("\t\t\t\t\t\t<option value=\"%s\">%s</option>\n", htmlspecialchars($timespan['name']), htmlspecialchars($timespan['label']));
133 ?>                                      </select>
134                                         <br /><label><input id="logarithmic"  name="logarithmic" type="checkbox" value="1" /> Logarithmic scale</label>
135                                         <br /><label><input id="tinylegend"  name="tinylegend" type="checkbox" value="1" /> Minimal legend</label></td>
136                                         <td class="s3"></td>
137                                 </tr>
138                                 <tr>
139                                         <td class="sc" colspan="3"><input id="btnAdd"     name="btnAdd"     type="button" disabled="disabled" onclick="GraphAppend()" value="Add graph" />
140                                         <input id="btnClear"   name="btnClear"   type="button" disabled="disabled" onclick="GraphDropAll()" value="Remove all graphs" />
141                                         <input id="btnRefresh" name="btnRefresh" type="button" disabled="disabled" onclick="GraphRefreshAll()" value="Refresh all graphs" /></td>
142                                 </tr>
143                                 <tr>
144                                         <td class="s1" rowspan="2">Graph list favorites:</td>
145                                         <td class="s3"><input type="text" style="width: 100%" maxlength="30" id="GraphListName" name="GraphListName" value="default" onchange="GraphListCheckName(false)" /></td>
146                                         <td class="s3"><a href="javascript:GraphSave()"><img src="save.png" width="16" height="16" alt="S" title="Save graph list to cookie" /></a></td>
147                                 </tr>
148                                 <tr>
149                                         <td class="s2"><select id="GraphList" name="GraphList" onfocus="GraphListRefresh()">
150                                                 <option value="default">default</option>
151                                         </select></td>
152                                         <td class="s3"><a href="javascript:GraphLoad()"><img src="load.png" width="16" height="16" alt="L" title="Load graph list from cookie" /></a><a href="javascript:GraphDrop()"><img src="delete.png" width="16" height="16" alt="D" title="Delete graph list from cookie" /></a></td>
153                                 </tr>
154                         </table>
155                 </div></div>
156                 <div class="graphs"><div id="graphs" class="graphs_t">
157                         <div id="nograph">Please use above graph selection tool to add graphs to this area.<?php
158                         // Config checking
159                         if (!isset($config['datadirs']))
160                                 echo '<p class="error">Config error: $config["datadirs"] is not set</p>';
161                         else if (!is_array($config['datadirs']))
162                                 echo '<p class="error">Config error: $config["datadirs"] is not an array</p>';
163                         else if (count($config['datadirs']) == 0)
164                                 echo '<p class="error">Config error: $config["datadirs"] is empty</p>';
165                         else foreach ($config['datadirs'] as $datadir)
166                                 if (!is_dir($datadir))
167                                         echo '<p class="error">Config error: $config["datadirs"], '.htmlspecialchars($datadir).' does not exist</p>';
168                         if (!isset($config['rrd_width']))
169                                 echo '<p class="error">Config error: $config["rrd_width"] is not set</p>';
170                         else if (10 > (int)$config['rrd_width'])
171                                 echo '<p class="error">Config error: $config["rrd_width"] is invalid. Integer >= 10 expected</p>';
172                         if (!isset($config['rrd_height']))
173                                 echo '<p class="error">Config error: $config["rrd_height"] is not set</p>';
174                         else if (10 > (int)$config['rrd_height'])
175                                 echo '<p class="error">Config error: $config["rrd_height"] is invalid. Integer >= 10 expected</p>';
176                         if (!isset($config['rrd_opts']))
177                                 echo '<p class="error">Config error: $config["rrd_opts"] is not set</p>';
178                         else if (!is_array($config['rrd_opts']))
179                                 echo '<p class="error">Config error: $config["rrd_opts"] is not an array</p>';
180                         if (!isset($config['timespan']))
181                                 echo '<p class="error">Config error: $config["timespan"] is not set</p>';
182                         else if (!is_array($config['timespan']))
183                                 echo '<p class="error">Config error: $config["timespan"] is not an array</p>';
184                         else if (count($config['timespan']) == 0)
185                                 echo '<p class="error">Config error: $config["timespan"] is empty</p>';
186                         else foreach ($config['timespan'] as &$timespan)
187                                 if (!is_array($timespan) || !isset($timespan['name']) || !isset($timespan['label']) || !isset($timespan['seconds']) || 10 > (int)$timespan['seconds'])
188                                         echo '<p class="error">Config error: $config["timespan"], invalid entry found</p>';
189                         if (!is_null($config['collectd_sock']) && strncmp('unix://', $config['collectd_sock'], 7) != 0)
190                                 echo '<p class="error">Config error: $config["collectd_sock"] is not valid</p>';
191                         if (!defined('RRDTOOL'))
192                                 echo '<p class="error">Config error: RRDTOOL is not defined</p>';
193                         else if (!is_executable(RRDTOOL))
194                                 echo '<p class="error">Config error: RRDTOOL ('.htmlspecialchars(RRDTOOL).') is not executable</p>';
195                         ?></div>
196                 </div></div>
197                 <input type="hidden" name="ge_graphid" id="ge_graphid" value="" />
198                 <table id="ge" class="toolbox" style="position: absolute; display: none; " cellspacing="1" cellpadding="0">
199                         <tr>
200                                 <td class="c1" rowspan="3"><select id="ge_timespan" name="ge_timespan" onchange="GraphAdjust(null)"><?php
201                                 foreach ($config['timespan'] as &$timespan)
202                                         printf("\t\t\t\t\t\t<option value=\"%s\">%s</option>\n", htmlspecialchars($timespan['name']), htmlspecialchars($timespan['label']));
203                                 ?></select><br />
204                                 <label><input id="ge_logarithmic"  name="ge_logarithmic" type="checkbox" value="1" onchange="GraphAdjust(null)" /> Logarithmic scale</label><br />
205                                 <label><input id="ge_tinylegend"  name="ge_tinylegend" type="checkbox" value="1" onchange="GraphAdjust(null)" /> Minimal legend</label></td>
206                                 <td class="c2"><a href="javascript:GraphMoveUp(null)"><img src="move-up.png" alt="UP" title="Move graph up"/></a></td>
207                         </tr>
208                         <tr>
209                                 <td class="c2"><a href="javascript:GraphRefresh(null)"><img src="refresh.png" alt="R" title="Refresh graph"/></a>&nbsp;<a href="javascript:GraphRemove(null)"><img src="delete.png" alt="RM" title="Remove graph"/></a></td>
210                         </tr>
211                         <tr>
212                                 <td class="c2"><a href="javascript:GraphMoveDown(null)"><img src="move-down.png" alt="DN" title="Move graph down"/></a></td>
213                         </tr>
214                 </table>
215         </div></body>
216 </html><?php
217 }
218
219
220 /*
221  * Select action based on user input
222  */
223 $action = read_var('action', $_POST, 'overview');
224 switch ($action) {
225         case 'list_hosts':
226                 // Generate a list of hosts
227                 $hosts = collectd_list_hosts();
228                 return dhtml_response_list($hosts, 'ListOfHost');
229
230         case 'list_plugins':
231                 // Generate list of plugins for selected hosts
232                 $arg_hosts = read_var('host', $_POST, array());
233                 if (!is_array($arg_hosts))
234                         $arg_hosts = array($arg_hosts);
235                 $plugins = collectd_list_plugins(reset($arg_hosts));
236                 return dhtml_response_list($plugins, 'ListOfPlugin');
237
238         case 'list_pinsts':
239                 // Generate list of plugin_instances for selected hosts and plugin
240                 $arg_hosts = read_var('host', $_POST, array());
241                 if (!is_array($arg_hosts))
242                         $arg_hosts = array($arg_hosts);
243                 $arg_plugin = read_var('plugin', $_POST, '');
244                 $pinsts = collectd_list_pinsts(reset($arg_hosts), $arg_plugin);
245                 return dhtml_response_list($pinsts, 'ListOfPluginInstance');
246
247         case 'list_types':
248                 // Generate list of types for selected hosts, plugin and plugin-instance
249                 $arg_hosts  = read_var('host', $_POST, array());
250                 if (!is_array($arg_hosts))
251                         $arg_hosts = array($arg_hosts);
252                 $arg_plugin = read_var('plugin', $_POST, '');
253                 $arg_pinst  = read_var('plugin_instance', $_POST, '');
254                 $types = collectd_list_types(reset($arg_hosts), $arg_plugin, $arg_pinst);
255                 return dhtml_response_list($types, 'ListOfType');
256
257         case 'list_tinsts':
258                 // Generate list of types for selected hosts, plugin and plugin-instance
259                 $arg_hosts  = read_var('host', $_POST, array());
260                 if (!is_array($arg_hosts))
261                         $arg_hosts = array($arg_hosts);
262                 $arg_plugin = read_var('plugin', $_POST, '');
263                 $arg_pinst  = read_var('plugin_instance', $_POST, '');
264                 $arg_type   = read_var('type', $_POST, '');
265                 $tinsts = collectd_list_tinsts(reset($arg_hosts), $arg_plugin, $arg_pinst, $arg_type);
266                 if (count($tinsts)) {
267                         require('definitions.php');
268                         load_graph_definitions();
269                         if (isset($MetaGraphDefs[$arg_type])) {
270                                 $meta_tinsts = array('@');
271                                 return dhtml_response_list($meta_tinsts, 'ListOfTypeInstance');
272                         }
273                 }
274                 return dhtml_response_list($tinsts, 'ListOfTypeInstance');
275
276         case 'overview':
277         default:
278                 return build_page();
279                 break;
280 }
281 ?>