]> arthur.barton.de Git - netdata.git/blob - web/dashboard_full.html
added resize functionality to all charts with legend
[netdata.git] / web / dashboard_full.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4         <title>netdata dashboard</title>
5
6         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7         <meta charset="utf-8">
8         <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
9         <meta name="viewport" content="width=device-width, initial-scale=1">
10         <meta name="apple-mobile-web-app-capable" content="yes">
11         <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
12         <meta name="author" content="costa@tsaousis.gr">
13
14         <link rel="shortcut icon" href="images/seo-performance-multi-size.ico">
15         
16         <link rel="apple-touch-icon" href="images/seo-performance-72.png">
17         <link rel="apple-touch-icon" sizes="72x72" href="images/seo-performance-72.png">
18         <link rel="apple-touch-icon" sizes="114x114" href="images/seo-performance-114.png">
19
20         <link rel="icon" type="image/png" sizes="512x512" href="images/seo-performance-512.png">
21         <link rel="icon" type="image/png" sizes="256x256" href="images/seo-performance-256.png">
22         <link rel="icon" type="image/png" sizes="128x128" href="images/seo-performance-128.png">
23         <link rel="icon" type="image/png" sizes="64x64" href="images/seo-performance-64.png">
24         <link rel="icon" type="image/png" sizes="48x48" href="images/seo-performance-48.png">
25         <link rel="icon" type="image/png" sizes="32x32" href="images/seo-performance-32.png">
26         <link rel="icon" type="image/png" sizes="24x24" href="images/seo-performance-24.png">
27         <link rel="icon" type="image/png" sizes="16x16" href="images/seo-performance-16.png">
28
29         <style>
30
31         /* prevent body from hidding under the navbar */
32         body {
33                 padding-top: 50px;
34         }
35
36         /* fix # anchors scrolling under the navbar
37            https://github.com/twbs/bootstrap/issues/1768#issuecomment-46519033
38          */
39         h1 {
40                 position: relative;
41                 z-index: -1;
42         }
43         h2 {
44                 position: relative;
45                 z-index: -2;
46         }
47         h1:before, h2:before { 
48                 display: block; 
49                 content: " "; 
50                 margin-top: -70px;
51                 height: 70px;
52                 visibility: hidden; 
53         }
54
55         .p {
56                 display: block;
57                 margin-top: 15px;
58         }
59
60         .chart-message {
61                 display: block; 
62                 margin-top: 10px;
63         }
64
65         .container {
66                 width: 90% !important;
67         }
68
69         #masthead h1 {
70                 /*font-size: 30px;*/
71                 line-height: 1;
72                 padding-top: 30px;
73         }
74
75         #masthead .well {
76                 margin-top:4%;
77         }
78
79
80         /*
81          * Side navigation
82          *
83          * Scrollspy and affixed enhanced navigation to highlight sections and secondary
84          * sections of docs content.
85          */
86
87         .dashboard-sidebar {
88                 max-height: calc(100% - 70px) !important;
89                 overflow-y: auto;
90                 width: 170px !important;
91         }
92
93         /* By default it's not affixed in mobile views, so undo that */
94         .dashboard-sidebar.affix {
95                 position: static;
96         }
97         @media (min-width: 768px) {
98                 .dashboard-sidebar {
99                         padding-left: 20px;
100                 }
101         }
102
103         .affix {
104                 position: static;
105                 top: 70px !important;
106                 width: 170px;
107         }
108         .affix-top {
109                 width: 170px;
110         }
111
112         /* First level of nav */
113         .dashboard-sidenav {
114                 margin-top: 20px;
115                 margin-bottom: 20px;
116         }
117
118         /* All levels of nav */
119         .dashboard-sidebar .nav > li > a {
120                 display: block;
121                 padding: 4px 20px;
122                 font-size: 13px;
123                 font-weight: 500;
124                 color: #767676;
125         }
126         .dashboard-sidebar .nav > li > a:hover,
127         .dashboard-sidebar .nav > li > a:focus {
128                 padding-left: 19px;
129                 color: #563d7c;
130                 text-decoration: none;
131                 background-color: transparent;
132                 border-left: 1px solid #563d7c;
133         }
134         .dashboard-sidebar .nav > .active > a,
135         .dashboard-sidebar .nav > .active:hover > a,
136         .dashboard-sidebar .nav > .active:focus > a {
137                 padding-left: 18px;
138                 font-weight: bold;
139                 color: #563d7c;
140                 background-color: transparent;
141                 border-left: 2px solid #563d7c;
142         }
143
144         /* Nav: second level (shown on .active) */
145         .dashboard-sidebar .nav .nav {
146                 display: none; /* Hide by default, but at >768px, show it */
147                 padding-bottom: 10px;
148         }
149         .dashboard-sidebar .nav .nav > li > a {
150                 padding-top: 1px;
151                 padding-bottom: 1px;
152                 padding-left: 30px;
153                 font-size: 12px;
154                 font-weight: normal;
155         }
156         .dashboard-sidebar .nav .nav > li > a:hover,
157         .dashboard-sidebar .nav .nav > li > a:focus {
158                 padding-left: 29px;
159         }
160         .dashboard-sidebar .nav .nav > .active > a,
161         .dashboard-sidebar .nav .nav > .active:hover > a,
162         .dashboard-sidebar .nav .nav > .active:focus > a {
163                 padding-left: 28px;
164                 font-weight: 500;
165         }
166
167         /* Back to top (hidden on mobile) */
168         .back-to-top,
169         .dashboard-theme-toggle {
170                 display: none;
171                 padding: 4px 10px;
172                 margin-top: 10px;
173                 margin-left: 10px;
174                 font-size: 12px;
175                 font-weight: 500;
176                 color: #999;
177         }
178         .back-to-top:hover,
179         .dashboard-theme-toggle:hover {
180                 color: #563d7c;
181                 text-decoration: none;
182         }
183         .dashboard-theme-toggle {
184                 margin-top: 0;
185         }
186
187         @media (min-width: 768px) {
188                 .back-to-top,
189                 .dashboard-theme-toggle {
190                         display: block;
191                 }
192         }
193
194         /* Show and affix the side nav when space allows it */
195         @media (min-width: 992px) {
196                 .dashboard-sidebar .nav > .active > ul {
197                         display: block;
198                 }
199                 /* Widen the fixed sidebar */
200                 .dashboard-sidebar.affix,
201                 .dashboard-sidebar.affix-bottom {
202                         width: 213px;
203                 }
204                 .dashboard-sidebar.affix {
205                         position: fixed; /* Undo the static from mobile first approach */
206                         top: 20px;
207                 }
208                 .dashboard-sidebar.affix-bottom {
209                         position: absolute; /* Undo the static from mobile first approach */
210                 }
211                 .dashboard-sidebar.affix-bottom .dashboard-sidenav,
212                 .dashboard-sidebar.affix .dashboard-sidenav {
213                         margin-top: 0;
214                         margin-bottom: 0;
215                 }
216         }
217         @media (min-width: 1200px) {
218                 /* Widen the fixed sidebar again */
219                 .dashboard-sidebar.affix-bottom,
220                 .dashboard-sidebar.affix {
221                         width: 263px;
222                 }
223         }
224         </style>
225         
226         <!-- you can set your netdata server globally, by ucommenting this -->
227         <!-- you can also give a different server per chart, with the attribute: data-host="http://netdata.server:19999" -->
228         <!-- <script> netdataServer = "http://box:19999"; </script> -->
229
230         <!-- load the dashboard manager - it will do the rest -->
231         <script type="text/javascript" src="dashboard.js"></script>
232 </head>
233 <body data-spy="scroll">
234         <nav class="navbar navbar-default navbar-fixed-top" role="banner">
235                 <div class="container">
236                         <div class="navbar-header">
237                                 <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse">
238                                         <span class="sr-only">Toggle navigation</span>
239                                         <span class="icon-bar"></span>
240                                         <span class="icon-bar"></span>
241                                         <span class="icon-bar"></span>
242                                 </button>
243                                 <a href="/" class="navbar-brand" id="hostname">netdata</a>
244                         </div>
245 <!--                    <nav class="collapse navbar-collapse" role="navigation">
246                                 <ul class="nav navbar-nav">
247                                         <li><a href="#sec">Get Started</a></li>
248                                         <li><a href="#sec">Edit</a></li>
249                                         <li><a href="#sec">Visualize</a></li>
250                                         <li><a href="#sec">Prototype</a></li>
251                                 </ul>
252                         </nav>
253 -->             </div>
254         </nav>
255
256         <div id="masthead" style="display: none;">
257                 <div class="container">
258                         <div class="row">
259                                 <div class="col-md-7">
260                                         <h1>Netdata Dashboard
261                                                 <p class="lead">Real time data collection and graphs...</p>
262                                         </h1>
263                                 </div>
264                                 <div class="col-md-5">
265                                         <div class="well well-lg">
266                                                 <div class="row">
267                                                 <div class="col-md-6">
268                                                         <b>Drag</b> charts to pan.
269                                                         <b>Shift + wheel</b> on them, to zoom in and out.
270                                                         <b>Double-click</b> on them, to reset.
271                                                         <b>Hover</b> on them too!
272                                                         </div>
273                                                 <div class="col-md-6">
274                                                         <div data-netdata="system.intr" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dygraph-type="line" data-dygraph-strokewidth="3" data-dygraph-smooth="true" data-dygraph-highlightcirclesize="6" data-after="-90" data-height="60px" data-colors="#C66"></div>
275                                                         </div>
276                                                 </div>
277                                         </div>
278                                 </div>
279                         </div>
280                 </div>
281         </div>
282
283         <div class="container">
284                 <div class="row">
285                         <div class="col-md-10" role="main">
286                                 <div id="charts_div"></div>
287                         </div>
288                         <div class="col-md-2" role="complementary">
289                                 <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" data-spy="affix" id="sidebar" role="menu"></nav>
290                         </div>
291                 </div>
292         </div>
293
294 <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel">
295         <div class="modal-dialog modal-lg" role="document">
296                 <div class="modal-content">
297                         <div class="modal-header">
298                                 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
299                                 <h4 class="modal-title" id="welcomeModalLabel">Welcome to netdata!</h4>
300                         </div>
301                         <div class="modal-body">
302                                         <div class="p">
303                                         <b><a href="https://github.com/firehol/netdata/" target="_blank">netdata</a></b> is the fastest way to visualize data. It is a resource efficient, highly optimized system for collecting and visualizing any type of realtime timeseries data, from CPU usage, disk activity, SQL queries, to web site visitors, e-shop orders, revenue and profits.
304                                         </div>
305                                         <div class="p">
306                                         To make a chart in <b><a href="https://github.com/firehol/netdata/" target="_blank">netdata</a></b>, you just need a <b>number</b>. Just a number you can read somehow. <b><a href="https://github.com/firehol/netdata/" target="_blank">netdata</a></b> will turn this number to a real time web chart. For collecting these numbers, it supports <a href="https://github.com/firehol/netdata/tree/master/plugins.d" target="_blank">external plugins</a>, even <a href="https://github.com/firehol/netdata/tree/master/charts.d" target="_blank">bash shell plugins</a>. Any computer program, in any language, that can print a few lines of text on its standard output, can be a netdata data collector.
307                                         </div>
308                                         <div class="p">
309                                         <b><a href="https://github.com/firehol/netdata/" target="_blank">netdata</a></b> can embed charts everywhere, like this one <div data-netdata="system.cpu" data-dimensions="system" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-system-at="system.cpu.system.modal.1"></div> (my CPU system usage which is <span id="system.cpu.system.modal.1" style="display: inline-block; width: 40px; text-align: right;"></span>%),
310                                         or this one <div data-netdata="ipv4.tcppackets" data-dimensions="received" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-received-at="ipv4.tcppackets.received.modal.1"></div> (my IPv4 received TCP packets, which are <span id="ipv4.tcppackets.received.modal.1" style="display: inline-block; width: 60px; text-align: right;"></span>/second).
311                                         </div>
312                                         <div class="p">
313                                         You can have <b><a href="https://github.com/firehol/netdata/" target="_blank">netdata</a></b> charts on your site too. Just give it a <code>div</code> and a real time chart, zoomable and draggable will appear (try it even on these tiny ones - <b>drag</b> them to pan horizontally, <b>shift + drag</b> to zoom in, on <b>chrome shift + mouse wheel</b> to zoom in/out, <b>double click</b> on them to reset them - don't be afraid of <b><a href="https://github.com/firehol/netdata/" target="_blank">netdata</a></b> performance - <a href="https://github.com/firehol/netdata/issues/36" target="_blank">a raspberry pi 2 can sustain 300 charts updates per second</a>!).
314                                         </div>
315                                         <div class="p">
316                                         If you like this project, <b>we need help writing documentation, coding plugins, testing new features, supporting end users.</b>
317                                         </div>
318                                         <div class="p">
319                                         We will be glad to have you on board...
320                                         </div>
321                         </div>
322                         <div class="modal-footer">
323                                 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
324                         </div>
325                 </div>
326         </div>
327 </div>
328
329 </body>
330 </html>
331 <script>
332
333
334 var demo_hostname = 'netdata.firehol.org';
335 // var demo_hostname = 'box';
336
337 //if(document.location.hostname === demo_hostname) {
338         document.getElementById('masthead').style.display = 'block';
339 //}
340
341 var options = {
342         sparklines_registry: {},
343         data: null,
344         hostname: 'netdata_server', // will be overwritten by the netdata server
345         categories: new Array(),
346         categories_idx: {},
347         families: new Array(),
348         families_idx: {},
349
350         chartsPerRow: 0,
351         chartsMinWidth: 1450,
352         chartsHeight: 180,
353         sparklinesHeight: 60
354 };
355
356 // generate a sparkline
357 // used in the documentation
358 function sparkline(chart, dimension, units) {
359         var key = chart + '.' + dimension;
360
361         if(typeof units === 'undefined')
362                 units = '';
363
364         if(typeof options.sparklines_registry[key] === 'undefined')
365                 options.sparklines_registry[key] = { count: 1 };
366         else
367                 options.sparklines_registry[key].count++;
368
369         key = key + '.' + options.sparklines_registry[key].count;
370
371         var h = '<div data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')';
372
373         return h;
374 }
375
376 // documentation for each category and chart
377 var messages = {
378
379         // categories / sections
380         'system': 'Overview of the key system metrices.',
381         'tc': 'Netdata collects and visualizes tc class utilization using its <a href="https://github.com/firehol/netdata/blob/master/plugins.d/tc-qos-helper.sh" target="_blank">tc-helper plugin</a>. If you also use <a href="http://firehol.org/#fireqos" target="_blank">FireQOS</a> for setting up QoS, netdata automatically collects interface and class names.',
382         'net': 'Per network interface statistics collected from <code>/proc/net/dev</code>.',
383         'apps': 'Per application statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics for applications of interest, defined in <code>/etc/netdata/apps_groups.conf</code> (the default is <a href="https://github.com/firehol/netdata/blob/master/conf.d/apps_groups.conf" target="_blank">here</a>). The plugin internaly builds a process tree (much like <code>ps fax</code> does), and groups processes together (evaluating both child and parent processes) so that the result is always a chart with a predefined set of dimensions (of course, only application groups found running are reported).<br/><b>IMPORTANT</b>: The values shown here are not 100% accurate. They only include values for the processes running. If an application is spawning childs continiously, which are terminated in just a few milliseconds (like shell scripts do), the values reported will be inaccurate. Linux does report the values for the exited childs of a process. However, these values are reported to the parent process <b>only when the child exits</b>. If these values, of the exited child processes, were also aggregated in the charts below, the charts would have been full of spikes, presenting unrealisting utilization for each process group. So, we decided to ignore these values and present only the utilization of <b>the currently running processes</b>.',
384
385         // charts
386         'system.cpu': 'Total CPU utilization (all cores). 100% here means there is no CPU idle time at all. You can get per core usage at the <a href="#cpu">CPUs</a> section and per application usage at the <a href="#apps">Applications Monitoring</a> section.<br/>Keep an eye on <b>iowait</b> ' + sparkline('system.cpu', 'iowait', '%') + '. If it is constantly high, your disks are a bottleneck and they slow your system down.<br/>Another important metric worth monitoring, is <b>softirq</b> ' + sparkline('system.cpu', 'softirq', '%') + '. A constantly high percentage of softirq may indicate network drivers issues.',
387         'system.io': 'Total Disk I/O, for all disks, read from <code>/proc/vmstat</code>. You can get detailed information about each disk at the <a href="#disk">Disks</a> section and per application Disk usage at the <a href="#apps">Applications Monitoring</a> section.',
388         'system.swapio': 'Total Swap I/O, read from <code>/proc/vmstat</code>. (netdata measures both <code>in</code> and <code>out</code>. If either of them is not shown in the chart, it is because it is zero - you can change the page settings to always render all the available dimensions on all charts).',
389         'system.pgfaults': 'Total page faults, read from <code>/proc/vmstat</code>. <b>Major page faults</b> indicates that the system is using its swap. You can find which applications use the swap at the <a href="#apps">Applications Monitoring</a> section.',
390         'system.entropy': '<a href="https://en.wikipedia.org/wiki/Entropy_(computing)" target="_blank">Entropy</a>, read from <code>/proc/sys/kernel/random/entropy_avail</code>, is like a pool of random numbers that are mainly used in cryptography. It is advised that the pool remains always <a href="https://blog.cloudflare.com/ensuring-randomness-with-linuxs-random-number-generator/" target="_blank">above 200</a>. If the pool of entropy gets empty, you risk your security to be predictable and you should install a user-space random numbers generating daemon, like <a href="http://www.issihosts.com/haveged/" target="_blank">haveged</a>, to keep the pool in healthy levels.',
391         'system.forks': 'The number of new processes created per second, read from <code>/proc/stat</code>.',
392         'system.intr': 'Total number of CPU interrupts, read from <code>/proc/stat</code>. Check <code>system.interrupts</code> that gives more detail about each interrupt and also the <a href="#cpu">CPUs</a> section where interrupts are analyzed per CPU core.',
393         'system.interrupts': 'CPU interrupts in detail, read from <code>/proc/interrupts</code>. At the <a href="#cpu">CPUs</a> section, interrupts are analyzed per CPU core.',
394         'system.softirqs': 'CPU softirqs in detail, read from <code>/proc/softirqs</code>. At the <a href="#cpu">CPUs</a> section, softirqs are analyzed per CPU core.',
395         'system.processes': 'System processes, read from <code>/proc/stat</code>. <b>Blocked</b> are processes that are willing to execute but they cannot, e.g. because they wait for disk activity.',
396         'system.ctxt': '<a href="https://en.wikipedia.org/wiki/Context_switch" target="_blank">Context Switches</a>, read from <code>/proc/stat</code>, is the switching of the CPU from one process, task or thread to another. If there are many processes or threads willing to execute and very few CPU cores available to handle them, the system is making more context switching to balance the CPU resources among them. The whole process is computationally intensive. The more the context switches, the slower the system gets.',
397         'system.idlejitter': 'Idle jitter is calculated by netdata. A thread is spawned that requests to sleep for a few microseconds. When the system wakes it up, it measures how many microseconds have passed. The different between the requested and the actual duration of the sleep, is the <b>idle jitter</b>. This number is useful in realtime environments, where CPU jitter can affect the quality of the service (like VoIP media gateways).',
398         'system.ipv4': 'Total IPv4 Traffic, read from <code>/proc/net/netstat</code>. This includes <code>lo</code> device traffic.',
399         'system.ram': 'System memory, read from <code>/proc/meminfo</code>.',
400         'system.swap': 'System swap memory, read from <code>/proc/meminfo</code>.',
401
402         // just a line to allow ending all entries above with comma
403         'end': 'end'
404 };
405
406 function screenWidth() {
407         return (($(window).width() * 0.95) - 50);
408 }
409
410 function chartsPerRow(total) {
411         if(options.chartsPerRow === 0) {
412                 width = Math.floor(total / options.chartsMinWidth);
413                 if(width === 0) width = 1;
414                 return width;
415         }
416         else return options.chartsPerRow;
417 }
418
419 function chartsPrioritySort(a, b) {
420         if(a.priority === b.priority) {
421                 if(a.name < b.name) return -1;
422         }
423         else if(a.priority < b.priority) return -1;
424         return 1;
425 }
426
427 function uniq(array, find_key, get_result) {
428         if(typeof get_result === 'undefined' || get_result === null)
429                 get_result = find_key;
430
431         var idx = {};
432         var result = new Array();
433
434         $.each(array, function(i, c) {
435                 key = find_key(c);
436                 if(typeof idx[key] === 'undefined') {
437                         idx[key] = true;
438                         result.push(get_result(c));
439                 }
440         });
441         return result;
442 }
443
444 function uniq_with_list(array, find_key_function) {
445         var idx = {};
446         var result = new Array();
447
448         $.each(array, function(i, c) {
449                 key = find_key_function(c);
450                 if(typeof idx[key] === 'undefined') {
451                         idx[key] = new Array();
452                         result.push( { name: key, values: idx[key] } );
453                 }
454                 idx[key].push(c);
455         });
456         result.sort(function(a, b) {
457                 if(a.name < b.name) return -1;
458                 return 1;
459         });
460         return result;
461 }
462
463 function prepareScreen(data) {
464         // console.log('NETDATA is paused - ready to prepare the screen');
465         // console.log(data);
466
467         options.data = data;
468         options.hostname = data.hostname;
469         document.getElementById('hostname').innerHTML = options.hostname;
470         document.title = options.hostname + ' dashboard';
471         var charts = data.charts;
472
473         $.each(charts, function(i, c) {
474                 if(c.enabled === true) {
475
476                         // find the category of the chart
477                         c.category = c.type.split('.')[0];
478
479                         var tmp = c.category.split('_')[0];
480                         if(tmp === 'net' || tmp === 'disk')
481                                 c.category = tmp;
482
483                         if(c.category === 'cpu') {
484                                 if(c.id.match(/^cpu\.cpu[0-9]+$/)) {
485                                         c.family = 'Utilization';
486                                 }
487                                 else if(c.id.match(/^cpu\.cpu[0-9]+_interrupts$/)) {
488                                         c.family = 'Interrupts';
489                                 }
490                                 else if(c.id.match(/^cpu\.cpu[0-9]+_softirqs$/)) {
491                                         c.family = 'SoftIRQs';
492                                 }
493                         }
494
495                         switch(c.category) {
496                                 case 'system':
497                                         c.category_priority = 10;
498                                         c.category_title = 'System Summary';
499                                         c.glyphicon = "glyphicon-dashboard";
500                                         break;
501
502                                 case 'tc':
503                                         c.category_priority = 20;
504                                         c.category_title = 'Quality Of Service';
505                                         c.glyphicon = "glyphicon-random";
506                                         break;
507
508                                 case 'net':
509                                         c.category_priority = 30;
510                                         c.category_title = 'Network Interfaces';
511                                         c.glyphicon = "glyphicon-transfer";
512                                         break;
513
514                                 case 'apps':
515                                         c.category_priority = 40;
516                                         c.category_title = 'Applications Monitoring';
517                                         c.glyphicon = "glyphicon-tasks";
518                                         break;
519
520                                 case 'ipvs':
521                                         c.category_priority = 50;
522                                         c.category_title = 'IP Virtual Server';
523                                         c.glyphicon = "glyphicon-transfer";
524                                         break;
525
526                                 case 'netfilter':
527                                         c.category_priority = 60;
528                                         c.category_title = 'Netfilter / IPTables';
529                                         c.glyphicon = "glyphicon-cloud";
530                                         break;
531
532                                 case 'ipv4':
533                                         c.category_priority = 70;
534                                         c.category_title = 'IPv4 Summary';
535                                         c.glyphicon = "glyphicon-globe";
536                                         break;
537
538                                 case 'mem':
539                                         c.category_priority = 80;
540                                         c.category_title = 'Memory';
541                                         c.glyphicon = "glyphicon-dashboard";
542                                         break;
543
544                                 case 'cpu':
545                                         c.category_priority = 90;
546                                         c.category_title = 'CPU Cores';
547                                         c.glyphicon = "glyphicon-dashboard";
548                                         break;
549
550                                 case 'disk':
551                                         c.category_priority = 100;
552                                         c.category_title = 'Disks';
553                                         c.glyphicon = "glyphicon-hdd";
554                                         break;
555
556                                 case 'nfsd':
557                                         c.category_priority = 110;
558                                         c.category_title = 'NFS Server';
559                                         c.glyphicon = "glyphicon-hdd";
560                                         break;
561
562                                 case 'squid':
563                                         c.category_priority = 140;
564                                         c.category_title = 'Proxy Server';
565                                         c.glyphicon = "glyphicon-link";
566                                         break;
567
568                                 case 'netdata':
569                                         c.category_priority = 150;
570                                         c.category_title = 'Netdata Monitoring';
571                                         c.glyphicon = "glyphicon-thumbs-up";
572                                         break;
573
574                                 case 'sensors':
575                                         c.category_priority = 160;
576                                         c.category_title = 'Hardware Sensors';
577                                         c.glyphicon = "glyphicon-thumbs-up";
578                                         break;
579
580                                 case 'postfix':
581                                         c.category_priority = 170;
582                                         c.category_title = 'Mail Server';
583                                         c.glyphicon = "glyphicon-thumbs-up";
584                                         break;
585
586                                 case 'example':
587                                         c.category_priority = 100000;
588                                         c.category_title = 'Example Plugins';
589                                         c.glyphicon = "glyphicon-search";
590                                         break;
591
592                                 default:
593                                         c.category_priority = 150;
594                                         c.category_title = c.type;
595                                         c.glyphicon = "glyphicon-dashboard";
596                                         break;
597                         }
598
599                         // find the unique categories
600                         if(typeof options.categories_idx[c.category] === 'undefined') {
601                                 options.categories_idx[c.category] = {
602                                         charts: new Array()
603                                 }
604                                 options.categories.push({
605                                         name: c.category,
606                                         title: c.category_title,
607                                         priority: c.category_priority,
608                                         glyphicon: c.glyphicon,
609                                         charts: options.categories_idx[c.category].charts
610                                 });
611                         }
612                         options.categories_idx[c.category].charts.push(c);
613
614                         // find the unique families
615                         if(typeof options.families_idx[c.family] === 'undefined') {
616                                 options.families_idx[c.family] = {
617                                         charts: new Array()
618                                 };
619                                 options.families.push({
620                                         name: c.family,
621                                         title: c.family,
622                                         priority: c.category_priority,
623                                         glyphicon: c.glyphicon,
624                                         charts: options.categories_idx[c.category].charts
625                                 });
626                         }
627                         options.families_idx[c.family].charts.push(c);
628                 }
629         });
630
631         function prioritySort(a, b) {
632                 if(a.priority < b.priority) return -1;
633                 if(a.priority > b.priority) return 1;
634                 if(a.name < b.name) return -1;
635                 return 1;
636         }
637
638         // sort all of them
639         options.categories.sort(prioritySort);
640         options.families.sort(prioritySort);
641         $.each(options.families,   function(i, c) { c.charts.sort(prioritySort); });
642
643         var div = document.getElementById('charts_div');
644         var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
645
646         // find the proper duration for per-second updates
647         var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
648         var html = '';
649         var sidebar = '<ul class="nav dashboard-sidenav" id="sidebar_ul">';
650
651         function getMessage(id) {
652                 if(typeof messages[id] !== 'undefined')
653                         return '<div class="chart-message" role="document">' + messages[id] + '</div>';
654                 else
655                         return '';
656         }
657
658         // render the charts
659         $.each(options.categories, function(i, t) {
660                 t.charts.sort(prioritySort);
661
662                 sidebar += '<li class="' + ((i === 0)?'active':'').toString() + '"><a href="#' + t.name + '">' + t.title + '</a>';
663                 html += '<div role="section"><div role="sectionhead"><h1 id="' + t.name + '" role="heading">' + t.title + '</h1>' + getMessage(t.name) + '</div><div id="' + t.name + '" role="document">';
664
665                 if(t.name === 'cpu') {
666                         var families = uniq_with_list(t.charts, function(c) { return c.family; });
667
668                         sidebar += '<ul class="nav">';
669                         $.each(families, function(j, c) {
670                                 sidebar += '<li class><a href="#' + t.name + '_' + c.name + '">' + c.name + '</a></li>';
671                                 html += '<div class="netdata-group-container" id="family_' + t.name + '_' + c.name + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + t.name + '_' + c.name + '" class="netdata-chart-alignment" role="heading">' + c.name + '</h2>';
672                                 $.each(c.values, function(x, f) {
673                                         var c = null;
674                                         var h = options.chartsHeight;
675
676                                         html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
677                                                 + ' data-width="100%"'
678                                                 + ' data-height="' + h.toString() + 'px"'
679                                                 + ' data-before="0"'
680                                                 + ' data-after="-' + duration.toString() + '"'
681                                                 + ' data-colors="' + c + '"'
682                                                 + ' role="application"></div>';
683                                 });
684                                 html += '</div>'; // netdata-group-container
685                         });
686                         sidebar += '</ul>';
687                 }
688                 else if(t.name === 'net' || t.name === 'tc') {
689                         var interfaces = uniq_with_list(t.charts, function(c) { return c.family; });
690
691                         sidebar += '<ul class="nav">';
692                         $.each(interfaces, function(j, c) {
693                                 sidebar += '<li class><a href="#' + t.name + '_' + c.name + '">' + c.name + '</a></li>';
694                                 html += '<div class="netdata-group-container" id="interface_' + t.name + '_' + c.name + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + t.name + '_' + c.name + '" class="netdata-chart-alignment" role="heading">' + c.name + '</h2>';
695                                 $.each(c.values, function(x, f) {
696                                         var c = null;
697                                         var h = options.chartsHeight / 2;
698                                         switch(f.type) {
699                                                 case 'net'        : h = options.chartsHeight; break;
700                                                 case 'tc'         : h = options.chartsHeight; break;
701                                         }
702
703                                         html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
704                                                 + ' data-width="100%"'
705                                                 + ' data-height="' + h.toString() + 'px"'
706                                                 + ' data-before="0"'
707                                                 + ' data-after="-' + duration.toString() + '"'
708                                                 + ' data-colors="' + c + '"'
709                                                 + ' role="application"></div>';
710                                 });
711                                 html += '</div>'; // netdata-group-container
712                         });
713                         sidebar += '</ul>';
714                 }
715                 else if(t.name === 'disk') {
716                         var disks = uniq_with_list(t.charts, function(c) { return c.family; });
717
718                         sidebar += '<ul class="nav">';
719                         $.each(disks, function(j, c) {
720                                 sidebar += '<li class><a href="#' + c.name + '">' + c.name + '</a></li>';
721                                 html += '<div class="netdata-group-container" id="disk_' + c.name + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + c.name + '" class="netdata-chart-alignment" role="heading">' + c.name + '</h2>';
722                                 $.each(c.values, function(x, f) {
723                                         var c = null;
724                                         var h = options.chartsHeight / 2;
725                                         switch(f.type) {
726                                                 case 'disk'        : h = options.chartsHeight; break;
727                                                 case 'disk_backlog': c = '#DD4477'; break;
728                                                 case 'disk_util'   : c = '#109618'; break;
729                                                 case 'disk_qops'   : c = '#E67300'; break;
730                                         }
731
732                                         html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
733                                                 + ' data-width="100%"'
734                                                 + ' data-height="' + h.toString() + 'px"'
735                                                 + ' data-before="0"'
736                                                 + ' data-after="-' + duration.toString() + '"'
737                                                 + ' data-colors="' + c + '"'
738                                                 + ' role="application"></div>';
739                                 });
740                                 html += '</div>'; // netdata-group-container
741                         });
742                         sidebar += '</ul>';
743                 }
744                 else if(t.name === 'apps') {
745                         $.each(t.charts, function(x, f) {
746                                 var c = null;
747                                 var h = options.chartsHeight / 2;
748                                 switch(f.id) {
749                                         case 'apps.cpu'         : h = options.chartsHeight; break;
750                                         case 'apps.preads'      : h = options.chartsHeight; break;
751                                         case 'apps.pwrites'     : h = options.chartsHeight; break;
752                                         case 'apps.mem'         : h = options.chartsHeight; break;
753                                         case 'apps.major_faults': h = options.chartsHeight; break;
754                                 }
755
756                                 html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
757                                         + ' data-width="100%"'
758                                         + ' data-height="' + h.toString() + 'px"'
759                                         + ' data-before="0"'
760                                         + ' data-after="-' + duration.toString() + '"'
761                                         + ' data-colors="' + c + '"'
762                                         + ' role="application"></div>';
763                         });
764                 }
765                 else {
766                         $.each(t.charts, function(x, c) {
767                                 html += getMessage(c.id) + '<div data-netdata="' + c.id + '"'
768                                         + ' data-width="' + pcent_width.toString() + '%"'
769                                         + ' data-height="' + options.chartsHeight.toString() + 'px"'
770                                         + ' data-before="0"'
771                                         + ' data-after="-' + duration.toString() + '"'
772                                         + ' role="application"></div>';
773                         });
774                 }
775
776                 sidebar += '</li>';
777                 html += '</div>'; // document
778                 html += '</div>'; // section
779                 html += '<hr role="separator"/>';
780         });
781         sidebar += '</ul>';
782 /*
783         // show the colors
784         html += '<br/><div class="row">'
785         $.each(NETDATA.colors, function(i, c){
786                 html += '<div style="display: inline-block;"><div style="display: inline-block; width: 100px; height: 100px; background: ' + c + ';"></div><br/>' + c + '</div>';
787         });
788         html += '</div>'
789 */
790         div.innerHTML = html;
791         document.getElementById('sidebar').innerHTML = sidebar;
792
793         // resize all charts - without starting the background thread
794         // this has to be done while NETDATA is paused
795         // if we ommit this, the affix menu will be wrong, since all
796         // the Dom elements are initially zero-sized
797         NETDATA.parseDom();
798
799         // let it run (update the charts)
800         NETDATA.unpause();
801
802         // check if we have to jump to a specific section
803         var hash = location.hash.replace('#','');
804         if(hash != '') {
805                 // Clear the hash in the URL
806                 // location.hash = '';   // delete front "//" if you want to change the address bar
807                 var offset = $(location.hash).offset();
808                 if(typeof offset !== 'undefined')
809                         $('html, body').animate({ scrollTop: offset.top }, 0);
810         }
811
812         /* activate bootstrap scrollspy (needed for sidebar) */
813         $(document.body).scrollspy({
814                 target: '#sidebar',
815                 offset: $(window).height() / 3 // controls the diff of the <hX> element to the top, to select it
816         });
817
818         /* activate bootstrap sidebar (affix) */
819         $('#sidebar').affix({
820                 offset: {
821                         top: 200,
822                         bottom: 0
823                 }
824         });
825
826         /* fix scrolling of very long affix lists
827            http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
828          */
829         $('#sidebar').on('affixed.bs.affix', function() {
830                 $(this).removeAttr('style');
831         });
832 }
833
834 NETDATA.ready(function() {
835
836         $('#welcomeModal').on('hidden.bs.modal', function (e) {
837                 NETDATA.updatedDom();
838         });
839         $('#welcomeModal').on('shown.bs.modal', function (e) {
840                 NETDATA.updatedDom();
841         });
842
843         // download all the charts the server knows
844         NETDATA.chartRegistry.downloadAll(NETDATA.serverDefault, function(data) {
845
846                 // pause the NETDATA thread that updates the charts
847                 NETDATA.pause(function() {
848
849                         if(document.location.hostname === demo_hostname)
850                                 $('#welcomeModal').modal();
851
852                         // prepare our DOM
853                         // this will be called when NETDATA is paused
854                         prepareScreen(data);
855                 });
856         });
857 });
858
859 </script>