]> arthur.barton.de Git - netdata.git/blob - web/dashboard_full.html
29db4db395e5afe4e33894eead1120dc3642730c
[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                         switch(c.category) {
484                                 case 'system':
485                                         c.category_priority = 10;
486                                         c.category_title = 'System Summary';
487                                         c.glyphicon = "glyphicon-dashboard";
488                                         break;
489
490                                 case 'tc':
491                                         c.category_priority = 20;
492                                         c.category_title = 'Quality Of Service';
493                                         c.glyphicon = "glyphicon-random";
494                                         break;
495
496                                 case 'net':
497                                         c.category_priority = 30;
498                                         c.category_title = 'Network Interfaces';
499                                         c.glyphicon = "glyphicon-transfer";
500                                         break;
501
502                                 case 'apps':
503                                         c.category_priority = 40;
504                                         c.category_title = 'Applications Monitoring';
505                                         c.glyphicon = "glyphicon-tasks";
506                                         break;
507
508                                 case 'ipvs':
509                                         c.category_priority = 50;
510                                         c.category_title = 'IP Virtual Server';
511                                         c.glyphicon = "glyphicon-transfer";
512                                         break;
513
514                                 case 'netfilter':
515                                         c.category_priority = 60;
516                                         c.category_title = 'Netfilter / IPTables';
517                                         c.glyphicon = "glyphicon-cloud";
518                                         break;
519
520                                 case 'ipv4':
521                                         c.category_priority = 70;
522                                         c.category_title = 'IPv4 Summary';
523                                         c.glyphicon = "glyphicon-globe";
524                                         break;
525
526                                 case 'mem':
527                                         c.category_priority = 80;
528                                         c.category_title = 'Memory';
529                                         c.glyphicon = "glyphicon-dashboard";
530                                         break;
531
532                                 case 'cpu':
533                                         c.category_priority = 90;
534                                         c.category_title = 'CPUs';
535                                         c.glyphicon = "glyphicon-dashboard";
536                                         break;
537
538                                 case 'disk':
539                                         c.category_priority = 100;
540                                         c.category_title = 'Disks';
541                                         c.glyphicon = "glyphicon-hdd";
542                                         break;
543
544                                 case 'nfsd':
545                                         c.category_priority = 110;
546                                         c.category_title = 'NFS Server';
547                                         c.glyphicon = "glyphicon-hdd";
548                                         break;
549
550                                 case 'squid':
551                                         c.category_priority = 140;
552                                         c.category_title = 'Proxy Server';
553                                         c.glyphicon = "glyphicon-link";
554                                         break;
555
556                                 case 'netdata':
557                                         c.category_priority = 150;
558                                         c.category_title = 'Netdata Monitoring';
559                                         c.glyphicon = "glyphicon-thumbs-up";
560                                         break;
561
562                                 case 'sensors':
563                                         c.category_priority = 160;
564                                         c.category_title = 'Hardware Sensors';
565                                         c.glyphicon = "glyphicon-thumbs-up";
566                                         break;
567
568                                 case 'postfix':
569                                         c.category_priority = 170;
570                                         c.category_title = 'Mail Server';
571                                         c.glyphicon = "glyphicon-thumbs-up";
572                                         break;
573
574                                 case 'example':
575                                         c.category_priority = 100000;
576                                         c.category_title = 'Example Plugins';
577                                         c.glyphicon = "glyphicon-search";
578                                         break;
579
580                                 default:
581                                         c.category_priority = 150;
582                                         c.category_title = c.type;
583                                         c.glyphicon = "glyphicon-dashboard";
584                                         break;
585                         }
586
587                         // find the unique categories
588                         if(typeof options.categories_idx[c.category] === 'undefined') {
589                                 options.categories_idx[c.category] = {
590                                         charts: new Array()
591                                 }
592                                 options.categories.push({
593                                         name: c.category,
594                                         title: c.category_title,
595                                         priority: c.category_priority,
596                                         glyphicon: c.glyphicon,
597                                         charts: options.categories_idx[c.category].charts
598                                 });
599                         }
600                         options.categories_idx[c.category].charts.push(c);
601
602                         // find the unique families
603                         if(typeof options.families_idx[c.family] === 'undefined') {
604                                 options.families_idx[c.family] = {
605                                         charts: new Array()
606                                 };
607                                 options.families.push({
608                                         name: c.family,
609                                         title: c.family,
610                                         priority: c.category_priority,
611                                         glyphicon: c.glyphicon,
612                                         charts: options.categories_idx[c.category].charts
613                                 });
614                         }
615                         options.families_idx[c.family].charts.push(c);
616                 }
617         });
618
619         function prioritySort(a, b) {
620                 if(a.priority < b.priority) return -1;
621                 if(a.priority > b.priority) return 1;
622                 if(a.name < b.name) return -1;
623                 return 1;
624         }
625
626         // sort all of them
627         options.categories.sort(prioritySort);
628         options.families.sort(prioritySort);
629         $.each(options.families,   function(i, c) { c.charts.sort(prioritySort); });
630
631         var div = document.getElementById('charts_div');
632         var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
633
634         // find the proper duration for per-second updates
635         var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
636         var html = '';
637         var sidebar = '<ul class="nav dashboard-sidenav" id="sidebar_ul">';
638
639         function getMessage(id) {
640                 if(typeof messages[id] !== 'undefined')
641                         return '<div class="chart-message" role="document">' + messages[id] + '</div>';
642                 else
643                         return '';
644         }
645
646         // render the charts
647         $.each(options.categories, function(i, t) {
648                 t.charts.sort(prioritySort);
649
650                 sidebar += '<li class="' + ((i === 0)?'active':'').toString() + '"><a href="#' + t.name + '">' + t.title + '</a>';
651                 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">';
652
653                 if(t.name === 'net' || t.name === 'tc') {
654                         var interfaces = uniq_with_list(t.charts, function(c) { return c.family; });
655
656                         sidebar += '<ul class="nav">';
657                         $.each(interfaces, function(j, c) {
658                                 sidebar += '<li class><a href="#' + t.name + '_' + c.name + '">' + c.name + '</a></li>';
659                                 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>';
660                                 $.each(c.values, function(x, f) {
661                                         var c = null;
662                                         var h = options.chartsHeight / 2;
663                                         switch(f.type) {
664                                                 case 'net'        : h = options.chartsHeight; break;
665                                                 case 'tc'         : h = options.chartsHeight; break;
666                                         }
667
668                                         html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
669                                                 + ' data-width="100%"'
670                                                 + ' data-height="' + h.toString() + 'px"'
671                                                 + ' data-before="0"'
672                                                 + ' data-after="-' + duration.toString() + '"'
673                                                 + ' data-colors="' + c + '"'
674                                                 + ' role="application"></div>';
675                                 });
676                                 html += '</div>'; // netdata-group-container
677                         });
678                         sidebar += '</ul>';
679                 }
680                 else if(t.name === 'disk') {
681                         var disks = uniq_with_list(t.charts, function(c) { return c.family; });
682
683                         sidebar += '<ul class="nav">';
684                         $.each(disks, function(j, c) {
685                                 sidebar += '<li class><a href="#' + c.name + '">' + c.name + '</a></li>';
686                                 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>';
687                                 $.each(c.values, function(x, f) {
688                                         var c = null;
689                                         var h = options.chartsHeight / 2;
690                                         switch(f.type) {
691                                                 case 'disk'        : h = options.chartsHeight; break;
692                                                 case 'disk_backlog': c = '#DD4477'; break;
693                                                 case 'disk_util'   : c = '#109618'; break;
694                                                 case 'disk_qops'   : c = '#E67300'; break;
695                                         }
696
697                                         html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
698                                                 + ' data-width="100%"'
699                                                 + ' data-height="' + h.toString() + 'px"'
700                                                 + ' data-before="0"'
701                                                 + ' data-after="-' + duration.toString() + '"'
702                                                 + ' data-colors="' + c + '"'
703                                                 + ' role="application"></div>';
704                                 });
705                                 html += '</div>'; // netdata-group-container
706                         });
707                         sidebar += '</ul>';
708                 }
709                 else if(t.name === 'apps') {
710                         $.each(t.charts, function(x, f) {
711                                 var c = null;
712                                 var h = options.chartsHeight / 2;
713                                 switch(f.id) {
714                                         case 'apps.cpu'         : h = options.chartsHeight; break;
715                                         case 'apps.preads'      : h = options.chartsHeight; break;
716                                         case 'apps.pwrites'     : h = options.chartsHeight; break;
717                                         case 'apps.mem'         : h = options.chartsHeight; break;
718                                         case 'apps.major_faults': h = options.chartsHeight; break;
719                                 }
720
721                                 html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
722                                         + ' data-width="100%"'
723                                         + ' data-height="' + h.toString() + 'px"'
724                                         + ' data-before="0"'
725                                         + ' data-after="-' + duration.toString() + '"'
726                                         + ' data-colors="' + c + '"'
727                                         + ' role="application"></div>';
728                         });
729                 }
730                 else {
731                         $.each(t.charts, function(x, c) {
732                                 html += getMessage(c.id) + '<div data-netdata="' + c.id + '"'
733                                         + ' data-width="' + pcent_width.toString() + '%"'
734                                         + ' data-height="' + options.chartsHeight.toString() + 'px"'
735                                         + ' data-before="0"'
736                                         + ' data-after="-' + duration.toString() + '"'
737                                         + ' role="application"></div>';
738                         });
739                 }
740
741                 sidebar += '</li>';
742                 html += '</div>'; // document
743                 html += '</div>'; // section
744                 html += '<hr role="separator"/>';
745         });
746         sidebar += '</ul>';
747 /*
748         // show the colors
749         html += '<br/><div class="row">'
750         $.each(NETDATA.colors, function(i, c){
751                 html += '<div style="display: inline-block;"><div style="display: inline-block; width: 100px; height: 100px; background: ' + c + ';"></div><br/>' + c + '</div>';
752         });
753         html += '</div>'
754 */
755         div.innerHTML = html;
756         document.getElementById('sidebar').innerHTML = sidebar;
757
758         // resize all charts - without starting the background thread
759         // this has to be done while NETDATA is paused
760         // if we ommit this, the affix menu will be wrong, since all
761         // the Dom elements are initially zero-sized
762         NETDATA.parseDom();
763
764         // let it run (update the charts)
765         NETDATA.unpause();
766
767         // check if we have to jump to a specific section
768         var hash = location.hash.replace('#','');
769         if(hash != '') {
770                 // Clear the hash in the URL
771                 // location.hash = '';   // delete front "//" if you want to change the address bar
772                 var offset = $(location.hash).offset();
773                 if(typeof offset !== 'undefined')
774                         $('html, body').animate({ scrollTop: offset.top }, 0);
775         }
776
777         /* activate bootstrap scrollspy (needed for sidebar) */
778         $(document.body).scrollspy({
779                 target: '#sidebar',
780                 offset: $(window).height() / 3 // controls the diff of the <hX> element to the top, to select it
781         });
782
783         /* activate bootstrap sidebar (affix) */
784         $('#sidebar').affix({
785                 offset: {
786                         top: 200,
787                         bottom: 0
788                 }
789         });
790
791         /* fix scrolling of very long affix lists
792            http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
793          */
794         $('#sidebar').on('affixed.bs.affix', function() {
795                 $(this).removeAttr('style');
796         });
797 }
798
799 NETDATA.ready(function() {
800
801         $('#welcomeModal').on('hidden.bs.modal', function (e) {
802                 NETDATA.updatedDom();
803         });
804         $('#welcomeModal').on('shown.bs.modal', function (e) {
805                 NETDATA.updatedDom();
806         });
807
808         // download all the charts the server knows
809         NETDATA.chartRegistry.downloadAll(NETDATA.serverDefault, function(data) {
810
811                 // pause the NETDATA thread that updates the charts
812                 NETDATA.pause(function() {
813
814                         if(document.location.hostname === demo_hostname)
815                                 $('#welcomeModal').modal();
816
817                         // prepare our DOM
818                         // this will be called when NETDATA is paused
819                         prepareScreen(data);
820                 });
821         });
822 });
823
824 </script>