Small updates to dash.html (#7757)
* dash.html docs and styling improvements * Fixing whitespace * Futher whitespace fixing * Finally fixed whitespace * Tabs to spaces * Fix Netdata capitalization Co-Authored-By: Joel Hans <joel.g.hans@gmail.com> * Fix Netdata capitalization Co-Authored-By: Joel Hans <joel.g.hans@gmail.com> Co-authored-by: Joel Hans <joel.g.hans@gmail.com>
Thomas Anderson committed
Jan 27, 2020 at 17:52 UTC
5f7899070197b5d6e7c3c72f8ece271470aeeb81
2 files changed
+738
-721
web/gui/custom/README.md
+25
-15
@@ -16,7 +16,7 @@ source](../demo.html)**.
16
17
You should also look at the [custom dashboard
18
template](https://my-netdata.io/dashboard.html), which contains samples of all
19
-supported charts. The code is [here](../dashboard.html).
19
+supported charts. The code is [here](../dashboard.html).
20
21
If you plan to put the dashboard on TV, check out [tv.html](../tv.html). Here's
22
is a screenshot of it, monitoring two servers on the same page:
@@ -65,7 +65,11 @@ header:
65
66
## Dash (Multi-Host Dashboard)
67
68
-`dash-example.html` is an all-in-one page that automatically fetches graphs from all your hosts. Just add your graphs and charts (or use the defaults) one time using the `dash-*` syntax and it will be automatically replicated for all of your hosts; showing alarms and graphs for all your hosts on **one page!**
68
+`dash-example.html` is an all-in-one page that automatically fetches graphs from all your hosts. Just add your graphs and charts (or use the defaults) one time using the `dash-*` syntax, and your selections will be automatically replicated for all of your hosts; showing alarms and graphs for all your hosts on **one page!**
69
+
70
+__**Dash will only work if you have implemented netdata streaming using `stream.conf`**__
71
+
72
+`dash-example.html` was created as an experiment to demonstrate the capabilities of netdata in a multi-host environment. If you desire more features, submit a pull request or check out Netdata Cloud!
73
74
### Configure Dash
75
@@ -74,29 +78,31 @@ First, rename the file so it doesn't get overwritten. For instance, with a webro
78
cp /usr/share/netdata/web/dash-example.html /usr/share/netdata/web/dash.html
79
```
80
77
-Change the following line in `dash.html` to reflect your URLs. The second URL is used if you access your netdata dashboard from a reverse proxy. The reverse proxy URL is optional, if it is not set then both will use the netdata host URL.
81
+Find and change the following line in `dash.html` to reflect your Netdata URLs. The second URL is only used if you access your Netdata dashboard through a reverse proxy. The reverse proxy URL is optional; if it is not set then both will use the Netdata host URL.
82
83
```js
84
/*
85
* TUTORIAL: Change this to the URL of your netdata host
86
* If you use netdata behind a reverse proxy, add a second parameter for the reverse proxy url like so:
83
-* new Dash('http://localhost:19999', 'https://my-domain.com/stats');
87
+* new Dash('http://localhost:19999', 'https://my-domain.com/stats');
88
*/
89
var dash = new Dash('http://localhost:19999');
90
```
91
88
-If you want to change the graphs or styling to fit your needs, just add an element to the page as shown. child divs will be generated to create your graph/chart:
92
+### The `dash-*` Syntax
93
+
94
+If you want to change the graphs or styling to fit your needs, just add an element to the page as shown. Child divs will be generated to create your graph/chart:
95
```
90
-<div class="dash-graph" <---- Use class dash-graph for line graphs, etc
91
- data-dash-netdata="system.cpu" <---- REQUIRED: Use data-dash-netdata to set the data source
92
- data-dygraph-valuerange="[0, 100]"> <---- OPTIONAL: This overrides the default config. Any other data-* attributes will
93
-</div> be added to the generated div, so you can set any desired options here
96
+<div class="dash-graph" <---- Use class dash-graph for line graphs, etc
97
+ data-dash-netdata="system.cpu" <---- REQUIRED: Use data-dash-netdata to set the data source
98
+ data-dygraph-valuerange="[0, 100]"> <---- OPTIONAL: This overrides the default config. Any other data-* attributes will
99
+</div> be added to the generated div, so you can set any desired options here
100
95
-<div class="dash-chart" <---- Use class dash-chart for pie charts, etc. CHARTS ARE SQUARE
96
- data-dash-netdata="system.io" <---- REQUIRED: Use data-dash-netdata to set the data source
97
- data-dimensions="in" <---- Use this to override or append default options
98
- data-title="Disk Read" <---- Use this to override or append default options
99
- data-common-units="dash.io"> <---- Use this to override or append default options
101
+<div class="dash-chart" <---- Use class dash-chart for pie charts, etc. CHARTS ARE SQUARE
102
+ data-dash-netdata="system.io" <---- REQUIRED: Use data-dash-netdata to set the data source
103
+ data-dimensions="in" <---- Use this to override or append default options
104
+ data-title="Disk Read" <---- Use this to override or append default options
105
+ data-common-units="dash.io"> <---- Use this to override or append default options
106
</div>
107
```
108
@@ -104,7 +110,7 @@ To change the sizes of graphs and charts, find the `Dash.options` object in `das
110
```js
111
/*
112
* TUTORIAL: Change your graph/chart dimensions here. Host columns will automatically adjust.
107
-* Charts are square! Their width is the same as their height.
113
+* Charts are square! Their width is the same as their height.
114
*/
115
this.options = {
116
graph_width: '40em',
@@ -115,6 +121,10 @@ this.options = {
121
122
To change the display order of your hosts, which is saved in localStorage, click the settings gear in the lower right corner
123
124
+We hope you like it!
125
+
126
+---
127
+
128
129
## dashboard.js
130
web/gui/dash-example.html
+713
-706
@@ -1,104 +1,106 @@
1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
- <meta charset="utf-8">
6
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7
- <meta name="viewport" content="width=device-width, initial-scale=1">
8
- <meta name="apple-mobile-web-app-capable" content="yes">
9
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <meta charset="utf-8">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <meta name="apple-mobile-web-app-capable" content="yes">
9
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
10
</head>
11
<body>
12
- <div id="alarms" class="collapsed">
13
- <div class="alarm-collapse-button" onclick="dash.toggle_alarm_collapse()">›</div>
14
- <span class="alarm-count"></span>
15
- <h1>Alarms</h1>
16
- <div class="alarm-host-list"></div>
17
- <div class="settings-button" onclick="dash.reorder_hosts()">⚙</div>
18
- </div>
19
- <div id="dash">
20
- <div class="netdata-host-stats-container template">
21
- <div class="drag-anchor"></div>
22
- <div class="netdata-host-name">host</div>
23
- <div class="netdata-host-stats">
24
- <div class="dash-graph"
25
- data-dash-netdata="system.cpu"
26
- data-dygraph-valuerange="[0, 100]">
27
- </div>
28
- <div class="dash-graph"
29
- data-dash-netdata="system.load">
30
- </div>
31
- <div class="dash-graph"
32
- data-dash-netdata="system.ram">
33
- </div>
34
- <div class="dash-graph"
35
- data-dash-netdata="system.net">
36
- </div>
37
- <div class="dash-graph"
38
- data-dash-netdata="system.processes">
39
- </div>
40
- <div class="dash-graph"
41
- data-dash-netdata="apps.cpu">
42
- </div>
43
- <div class="dash-graph"
44
- data-dash-netdata="apps.mem">
45
- </div>
46
- <div class="dash-charts">
47
- <div class="dash-chart"
48
- data-dash-netdata="system.io"
49
- data-dimensions="in"
50
- data-title="Disk Read"
51
- data-common-units="dash.io">
52
- </div>
53
- <div class="dash-chart"
54
- data-dash-netdata="system.io"
55
- data-dimensions="out"
56
- data-title="Disk Write"
57
- data-common-units="dash.io">
58
- </div>
59
- <div class="dash-chart"
60
- data-dash-netdata="system.cpu"
61
- data-chart-library="gauge"
62
- data-title="CPU"
63
- data-units="%"
64
- data-gauge-max-value="100"
65
- data-colors="#22AA99"
66
- data-gauge-stroke-color="#373B40">
67
- </div>
68
- <div class="dash-chart"
69
- data-dash-netdata="system.net"
70
- data-dimensions="received"
71
- data-title="Net Inbound"
72
- data-common-units="dash.net">
73
- </div>
74
- <div class="dash-chart"
75
- data-dash-netdata="system.net"
76
- data-dimensions="sent"
77
- data-title="Net Outbound"
78
- data-common-units="dash.net">
79
- </div>
80
- <div class="dash-chart"
81
- data-dash-netdata="system.ram"
82
- data-dimensions="used|buffers|active|wired"
83
- data-append-options="percentage"
84
- data-title="Used RAM"
85
- data-units="%"
86
- data-easypiechart-max-value="100"
87
- data-colors="#EE9911">
88
- </div>
89
- </div>
90
- </div>
91
- </div>
92
- </div>
12
+ <div id="alarms" class="collapsed">
13
+ <div class="alarm-collapse-button" onclick="dash.toggle_alarm_collapse()">›</div>
14
+ <span class="alarm-count"></span>
15
+ <h1>Alarms</h1>
16
+ <div class="alarm-host-list"></div>
17
+ <div class="settings-button" onclick="dash.reorder_hosts()">⚙︎</div>
18
+ </div>
19
+ <div id="dash">
20
+ <div class="netdata-host-stats-container template">
21
+ <div class="netdata-host-name">host</div>
22
+ <div class="netdata-host-stats">
23
+ <div class="dash-graph"
24
+ data-dash-netdata="system.cpu"
25
+ data-dygraph-valuerange="[0, 100]">
26
+ </div>
27
+ <div class="dash-graph"
28
+ data-dash-netdata="system.load">
29
+ </div>
30
+ <div class="dash-graph"
31
+ data-dash-netdata="system.ram">
32
+ </div>
33
+ <div class="dash-graph"
34
+ data-dash-netdata="disk_space._">
35
+ </div>
36
+ <div class="dash-graph"
37
+ data-dash-netdata="system.net">
38
+ </div>
39
+ <div class="dash-graph"
40
+ data-dash-netdata="system.processes">
41
+ </div>
42
+ <div class="dash-graph"
43
+ data-dash-netdata="apps.cpu">
44
+ </div>
45
+ <div class="dash-graph"
46
+ data-dash-netdata="apps.mem">
47
+ </div>
48
+ <div class="dash-charts">
49
+ <div class="dash-chart"
50
+ data-dash-netdata="system.io"
51
+ data-dimensions="in"
52
+ data-title="Disk Read"
53
+ data-common-units="dash.io">
54
+ </div>
55
+ <div class="dash-chart"
56
+ data-dash-netdata="system.io"
57
+ data-dimensions="out"
58
+ data-title="Disk Write"
59
+ data-common-units="dash.io">
60
+ </div>
61
+ <div class="dash-chart"
62
+ data-dash-netdata="system.cpu"
63
+ data-chart-library="gauge"
64
+ data-title="CPU"
65
+ data-units="%"
66
+ data-gauge-max-value="100"
67
+ data-colors="#22AA99"
68
+ data-gauge-stroke-color="#373B40">
69
+ </div>
70
+ <div class="dash-chart"
71
+ data-dash-netdata="system.net"
72
+ data-dimensions="received"
73
+ data-title="Net Inbound"
74
+ data-common-units="dash.net">
75
+ </div>
76
+ <div class="dash-chart"
77
+ data-dash-netdata="system.net"
78
+ data-dimensions="sent"
79
+ data-title="Net Outbound"
80
+ data-common-units="dash.net">
81
+ </div>
82
+ <div class="dash-chart"
83
+ data-dash-netdata="system.ram"
84
+ data-dimensions="used|buffers|active|wired"
85
+ data-append-options="percentage"
86
+ data-title="Used RAM"
87
+ data-units="%"
88
+ data-easypiechart-max-value="100"
89
+ data-colors="#EE9911">
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
</body>
96
<script
95
- src="https://code.jquery.com/jquery-3.4.1.min.js"
96
- integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
97
- crossorigin="anonymous">
97
+ src="https://code.jquery.com/jquery-3.4.1.min.js"
98
+ integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
99
+ crossorigin="anonymous">
100
</script>
101
<script type="text/javascript">
102
class PickNSort {
101
- // PickNSort.js
103
+ // PickNSort.js
104
105
constructor (dark) {
106
this.items = [];
@@ -294,6 +296,9 @@ class PickNSort {
296
}
297
298
add_css_to_page (dark) {
299
+ /*
300
+ * TUTORIAL: Change your theme colors here. Not sure how well it will work...
301
+ */
302
var light_theme = {
303
windowbg: "#FFF",
304
itembg: "#F4F4F4",
@@ -304,10 +309,10 @@ class PickNSort {
309
itembg: "#333",
310
itemcolor: "#DBDBDB"
311
}
312
+
313
var current_theme = (dark) ? dark_theme : light_theme;
308
- $("<style>")
309
- .prop("type", "text/css")
310
- .html(`
314
+
315
+ var css_string = `
316
#picknsort-container {
317
position: fixed;
318
z-index: 9999 !important;
@@ -390,624 +395,626 @@ class PickNSort {
395
padding: 0em 0.5em;
396
height: calc(100% - 0.2em);
397
}
393
- `).appendTo("head");
398
+ ` // End multiline string
399
+
400
+
401
+ $("<style>")
402
+ .prop("type", "text/css")
403
+ .html(css_string).appendTo("head");
404
}
405
}
406
</script>
407
<script type="text/javascript">
398
- // Dash JS
399
-
400
- function picknsort_setup () {
401
- if (localStorage.getItem('netdata_ordered_hosts')) {
402
- picknsort.last_output = JSON.parse(localStorage.getItem('netdata_ordered_hosts'));
403
- } else {
404
- picknsort.last_output = {
405
- enabled: dash.netdata_info.mirrored_hosts,
406
- disabled: []
407
- }
408
- }
409
- }
410
-
411
- class Dash {
412
- constructor (base_url, link_base_url) {
413
- this.base_url = base_url; // URL of netdata host, with port
414
- this.link_base_url = link_base_url || base_url; // Reverse proxy URL (Optional)
415
- this.current_alarms = {};
416
- this.new_alarms = {};
417
- this.first_build = true;
418
- /*
419
- * TUTORIAL: Change your graph/chart dimensions here. Host columns will automatically adjust.
420
- * Charts are square! Their width is the same as their height.
421
- */
422
- this.options = {
423
- graph_width: '40em',
424
- graph_height: '20em',
425
- chart_width: '10em' // Charts are square
426
- };
427
-
428
- this.init();
429
- }
430
-
431
- reorder_hosts () {
432
- picknsort.popup(dash.update_ordered_hosts, dash.find_new_hosts);
433
- }
434
-
435
- get_enabled_hosts () {
436
- try {
437
- return JSON.parse(localStorage.getItem('netdata_ordered_hosts')).enabled
438
- } catch (e) {
439
- return this.netdata_info.mirrored_hosts;
440
- }
441
- }
442
-
443
- get_ordered_hosts () {
444
- try {
445
- return JSON.parse(localStorage.getItem('netdata_ordered_hosts'));
446
- } catch (e) {
447
- return null;
448
- }
449
- }
450
-
451
- set_ordered_hosts (hosts) {
452
- localStorage.setItem('netdata_ordered_hosts', JSON.stringify(hosts));
453
- location.reload();
454
- }
455
-
456
- update_ordered_hosts (enabled, disabled) {
457
- if (enabled === null && disabled === null) {
458
- return;
459
- }
460
- dash.set_ordered_hosts({
461
- enabled: enabled,
462
- disabled: disabled
463
- });
464
- }
465
-
466
- find_new_hosts () {
467
- var newhosts = dash.netdata_info.mirrored_hosts.slice();
468
- var currenthosts = dash.get_ordered_hosts();
469
-
470
- for (var i=0,len=currenthosts.enabled.length; i<len; i++) {
471
- var found = newhosts.indexOf(currenthosts.enabled[i]);
472
-
473
- if (found > -1) {
474
- newhosts.splice(found, 1);
475
- } else {
476
- currenthosts.enabled.splice(i, 1);
477
- }
478
- }
479
-
480
- for (var i=0,len=currenthosts.disabled.length; i<len; i++) {
481
- var found = newhosts.indexOf(currenthosts.disabled[i]);
482
-
483
- if (found > -1) {
484
- newhosts.splice(found, 1);
485
- } else {
486
- currenthosts.enabled.splice(i, 1);
487
- }
488
- }
489
-
490
- for (var i=0,len=newhosts.length; i<len; i++) {
491
- currenthosts.enabled.push(newhosts[i]);
492
- }
493
-
494
- dash.set_ordered_hosts(currenthosts);
495
- }
496
-
497
- get_host_url (hostname, link) {
498
- var base = ( link ) ? this.link_base_url : this.base_url;
499
- return (hostname) ? base + '/host/' + hostname : base;
500
- }
501
-
502
- get_api_url (hostname) {
503
- return this.get_host_url(hostname) + '/api/v1'
504
- }
505
-
506
-
507
- init () {
508
- var that = this;
509
- $.get(this.get_api_url() + '/info', function (data) {
510
- that.netdata_info = data;
511
- picknsort_setup()
512
- that.build();
513
- });
514
- }
515
-
516
- digest () {
517
- this.fetch_active_alarms();
518
- this.fix_layout_errors();
519
- }
520
-
521
- build () {
522
- // Fix vertically misaligned stats on load error
523
- $('.dash-graph').css({
524
- height: this.options.graph_height,
525
- width: this.options.graph_width
526
- });
527
- $('.dash-chart').css({
528
- height: this.options.chart_width, // Charts are square
529
- width: this.options.chart_width
530
- });
531
-
532
- // Fix chart alignment
533
- $('.netdata-host-stats-container').css({
534
- width: 'calc(' + this.options.graph_width + ' + (2 * ' + $('.netdata-host-stats-container').css('padding-left') + '))'
535
- });
536
-
537
- var $template = $('.netdata-host-stats-container').first();
538
-
539
- var hosts = this.get_enabled_hosts();
540
-
541
- for (var i=0, len=hosts.length; i<len; i++) {
542
- var hostname = hosts[i];
543
- $('#alarms .alarm-host-list').append('<div class="host-alarms ' + hostname + '"><a target="_blank" href="' + this.get_host_url(hostname, true) + '/"><h2>' + hostname + '</h2></a></div>');
544
-
545
- $template.clone().removeClass('template').appendTo('#dash');
546
- var $newest = $('.netdata-host-stats-container').last();
547
- this.build_stats($newest, hostname);
548
- }
549
-
550
-
551
- if (this.first_build === true) {
552
- this.remove_template_elements();
553
- this.first_build = false;
554
- }
555
- }
556
-
557
- build_stats ($hoststats, hostname) {
558
- var that = this;
559
-
560
- $hoststats.find('.netdata-host-stats .dash-graph').each(function () {
561
- that.build_graph($(this), hostname);
562
- });
563
-
564
- $hoststats.find('.netdata-host-stats .dash-chart').each(function () {
565
- that.build_chart($(this), hostname);
566
- });
567
-
568
- $hoststats.find('.netdata-host-name').html('<a target="_blank" href="' + that.get_host_url(hostname, true) + '/">' + hostname + '</a>');
569
- }
570
-
571
- build_graph ($wrapper, hostname) {
572
- var that = this;
573
- var $graph = $('<div>', {
574
- // Defaults
575
- 'data-netdata': $wrapper.attr('data-dash-netdata'),
576
- 'data-host': that.get_host_url(hostname),
577
- 'data-before': '0',
578
- 'data-after': '-540',
579
- 'role': 'application',
580
- 'data-width': that.options.graph_width,
581
- 'data-height': that.options.graph_height
582
- });
583
-
584
- $.each($wrapper[0].attributes, function (key, node) {
585
- if ( node.name.match(/^data-(?!dash).*/ ) ) {
586
- $graph.attr(node.name, node.value);
587
- }
588
- });
589
-
590
- $graph.appendTo($wrapper);
591
- }
592
-
593
- build_chart ($wrapper, hostname) {
594
- var that = this;
595
- var $graph = $('<div>', {
596
- // Defaults
597
- 'data-netdata': $wrapper.attr('data-dash-netdata'),
598
- 'data-host': that.get_host_url(hostname),
599
- 'data-before': '0',
600
- 'data-after': '-540',
601
- 'data-points': '540',
602
- 'role': 'application',
603
- 'data-width': that.options.chart_width,
604
- 'data-title': ' ',
605
- 'data-easypiechart-trackcolor': "#373B40",
606
- 'data-chart-library': 'easypiechart'
607
-
608
- })
609
-
610
- $.each($wrapper[0].attributes, function (key, node) {
611
- if ( node.name.match(/^data-(?!dash).*/ ) ) {
612
- $graph.attr(node.name, node.value);
613
- }
614
- });
615
-
616
- $graph.appendTo($wrapper);
617
- }
618
-
619
- all_alarms_are_warnings () {
620
- var out = true;
621
- $.each(this.current_alarms, function (host, alarms) {
622
- if (out === false) {
623
- return false; // Maximum efficiency
624
- }
625
- $.each(alarms, function (name, data) {
626
- if (data.status != "WARNING") {
627
- out = false;
628
- return false;
629
- }
630
- });
631
- });
632
- return out;
633
- }
634
-
635
- update_alarm_count () {
636
- console.log(this.all_alarms_are_warnings());
637
- var count = $('img.alarm-badge').length;
638
- $('.alarm-count').text($('img.alarm-badge').length);
639
- $('.alarm-count').removeClass('no-alarms warnings-only');
640
- if ( count === 0 ) {
641
- $('.alarm-count').addClass('no-alarms');
642
- return
643
- }
644
- if (this.all_alarms_are_warnings()) {
645
- $('.alarm-count').addClass('warnings-only');
646
- }
647
- }
648
-
649
- fetch_active_alarms () {
650
- var that = this;
651
- console.log("Getting alarms...");
652
- var hosts = this.get_enabled_hosts();
653
- for (var i=0, len=hosts.length; i<len; i++) {
654
- var hostname = hosts[i];
655
-
656
- $.get(this.get_api_url(hostname) + '/alarms', function (data) {
657
- that.new_alarms[ data.hostname ] = data.alarms;
658
- if ( Object.keys(that.new_alarms).length === len ) {
659
- // All responses received
660
- if ( that.check_new_current_alarms() ) {
661
- console.log("No alarm changes detected... Refreshing images.");
662
- that.new_alarms = {};
663
- that.refresh_alarm_images();
664
- return;
665
- }
666
-
667
- that.current_alarms = that.new_alarms;
668
- that.new_alarms = {};
669
- that.draw_alarms();
670
- that.update_alarm_count();
671
- }
672
- });
673
- }
674
- }
675
-
676
- toggle_alarm_collapse () {
677
- $('#alarms').toggleClass('collapsed');
678
- }
679
-
680
- check_new_current_alarms () {
681
- // Create arrays of property names
682
- var a = this.current_alarms;
683
- var b = this.new_alarms;
684
- var aProps = Object.keys(a);
685
- var bProps = Object.keys(b);
686
-
687
- // If number of properties is different,
688
- // objects are not equivalent
689
- if (aProps.length != bProps.length) {
690
- return false;
691
- }
692
-
693
- for (var i = 0; i < aProps.length; i++) {
694
- var propName = aProps[i];
695
- var aa = a[propName];
696
- var aaProps = Object.keys(aa);
697
- var bb = b[propName];
698
- var bbProps = Object.keys(bb);
699
-
700
- if (aaProps.length != bbProps.length) {
701
- return false;
702
- }
703
-
704
- for (var n = 0, len=aaProps.length; i < len; i++) {
705
- if ( bb[aaProps[n]] === undefined ) {
706
- return false;
707
- }
708
- }
709
- }
710
-
711
- // If we made it this far, objects
712
- // are considered equivalent
713
- return true;
714
- }
715
-
716
- refresh_alarm_images () {
717
- // Use Math.random() to "reload" the image
718
- $('.alarm-badge').each(function () {
719
- var old_src = $(this).attr('src').replace(/&rand=.*/g, "");
720
- $(this).attr('src', old_src + "&rand=" + Math.random());
721
- });
722
- }
723
-
724
- draw_alarms () {
725
- var that = this;
726
- console.log("Drawing...", that.current_alarms);
727
- $.each(that.current_alarms, function(hostname, alarms) {
728
- $('#alarms .host-alarms.' + hostname + ' .alarm-badge').remove();
729
- $.each(alarms, function (index, alarm) {
730
- that.draw_alarm(hostname, alarm);
731
- })
732
- });
733
- }
734
-
735
- draw_alarm (hostname, alarm) {
736
- var queryStr = '/badge.svg?alarm=' + alarm.name + '&chart=' + alarm.chart
737
- $('<img />', {
738
- src: this.get_api_url(hostname) + queryStr,
739
- class: 'alarm-badge'
740
- }).appendTo($('#alarms .host-alarms.' + hostname));
741
- }
742
-
743
- remove_template_elements () {
744
- $('.netdata-host-stats-container').first().remove();
745
- }
746
-
747
- fix_layout_errors () {
748
- $('.dash-graph:contains("chart not found")').html('<div class="loading-error">Not found</div>');
749
- $('.dash-chart:contains("chart not found")').html('<div class="loading-error">Not found</div>');
750
- }
751
- }
752
-
753
- /*
754
- * TUTORIAL: Change this to the URL of your netdata host
755
- * If you use netdata behind a reverse proxy, add a second parameter for the reverse proxy url like so:
756
- * new Dash('http://localhost:19999', 'https://my-domain.com/stats');
757
- */
758
- var dash = new Dash('http://localhost:19999');
759
-
760
- var picknsort = new PickNSort(true);
761
-
762
- // Import dashboard.js
763
- $.getScript(dash.base_url + '/dashboard.js', function() {
764
- console.log("Loaded dashboard.js");
765
- setTimeout(function () {
766
- $('#alarms').css("visibility", "visible");
767
- }, 400);
768
- });
769
-
770
- setInterval(function () {
771
- dash.digest();
772
- }, 6 * 1000);
408
+ // Dash JS
409
+
410
+ function picknsort_setup () {
411
+ if (localStorage.getItem('netdata_ordered_hosts')) {
412
+ picknsort.last_output = JSON.parse(localStorage.getItem('netdata_ordered_hosts'));
413
+ } else {
414
+ picknsort.last_output = {
415
+ enabled: dash.netdata_info.mirrored_hosts,
416
+ disabled: []
417
+ }
418
+ }
419
+ }
420
+
421
+ class Dash {
422
+ constructor (base_url, link_base_url) {
423
+ this.base_url = base_url; // URL of netdata host, with port
424
+ this.link_base_url = link_base_url || base_url; // Reverse proxy URL (Optional)
425
+ this.current_alarms = {};
426
+ this.new_alarms = {};
427
+ this.first_build = true;
428
+ /*
429
+ * TUTORIAL: Change your graph/chart dimensions here. Host columns will automatically adjust.
430
+ * Charts are square! Their width is the same as their height.
431
+ */
432
+ this.options = {
433
+ graph_width: '40em',
434
+ graph_height: '20em',
435
+ chart_width: '10em' // Charts are square
436
+ };
437
+
438
+ this.init();
439
+ }
440
+
441
+ reorder_hosts () {
442
+ picknsort.popup(dash.update_ordered_hosts, dash.find_new_hosts);
443
+ }
444
+
445
+ get_enabled_hosts () {
446
+ try {
447
+ return JSON.parse(localStorage.getItem('netdata_ordered_hosts')).enabled
448
+ } catch (e) {
449
+ return this.netdata_info.mirrored_hosts;
450
+ }
451
+ }
452
+
453
+ get_ordered_hosts () {
454
+ try {
455
+ return JSON.parse(localStorage.getItem('netdata_ordered_hosts'));
456
+ } catch (e) {
457
+ return null;
458
+ }
459
+ }
460
+
461
+ set_ordered_hosts (hosts) {
462
+ localStorage.setItem('netdata_ordered_hosts', JSON.stringify(hosts));
463
+ location.reload();
464
+ }
465
+
466
+ update_ordered_hosts (enabled, disabled) {
467
+ if (enabled === null && disabled === null) {
468
+ return;
469
+ }
470
+ dash.set_ordered_hosts({
471
+ enabled: enabled,
472
+ disabled: disabled
473
+ });
474
+ }
475
+
476
+ find_new_hosts () {
477
+ var newhosts = dash.netdata_info.mirrored_hosts.slice();
478
+ var currenthosts = dash.get_ordered_hosts();
479
+
480
+ for (var i=0,len=currenthosts.enabled.length; i<len; i++) {
481
+ var found = newhosts.indexOf(currenthosts.enabled[i]);
482
+
483
+ if (found > -1) {
484
+ newhosts.splice(found, 1);
485
+ } else {
486
+ currenthosts.enabled.splice(i, 1);
487
+ }
488
+ }
489
+
490
+ for (var i=0,len=currenthosts.disabled.length; i<len; i++) {
491
+ var found = newhosts.indexOf(currenthosts.disabled[i]);
492
+
493
+ if (found > -1) {
494
+ newhosts.splice(found, 1);
495
+ } else {
496
+ currenthosts.enabled.splice(i, 1);
497
+ }
498
+ }
499
+
500
+ for (var i=0,len=newhosts.length; i<len; i++) {
501
+ currenthosts.enabled.push(newhosts[i]);
502
+ }
503
+
504
+ dash.set_ordered_hosts(currenthosts);
505
+ }
506
+
507
+ get_host_url (hostname, link) {
508
+ var base = ( link ) ? this.link_base_url : this.base_url;
509
+ return (hostname) ? base + '/host/' + hostname : base;
510
+ }
511
+
512
+ get_api_url (hostname) {
513
+ return this.get_host_url(hostname) + '/api/v1'
514
+ }
515
+
516
+
517
+ init () {
518
+ var that = this;
519
+ $.get(this.get_api_url() + '/info', function (data) {
520
+ that.netdata_info = data;
521
+ picknsort_setup()
522
+ that.build();
523
+ });
524
+ }
525
+
526
+ digest () {
527
+ this.fetch_active_alarms();
528
+ this.fix_layout_errors();
529
+ }
530
+
531
+ build () {
532
+ // Fix vertically misaligned stats on load error
533
+ $('.dash-graph').css({
534
+ height: this.options.graph_height,
535
+ width: this.options.graph_width
536
+ });
537
+ $('.dash-chart').css({
538
+ height: this.options.chart_width, // Charts are square
539
+ width: this.options.chart_width
540
+ });
541
+
542
+ // Fix chart alignment
543
+ $('.netdata-host-stats-container').css({
544
+ width: 'calc(' + this.options.graph_width + ' + (2 * ' + $('.netdata-host-stats-container').css('padding-left') + '))'
545
+ });
546
+
547
+ var $template = $('.netdata-host-stats-container').first();
548
+
549
+ var hosts = this.get_enabled_hosts();
550
+
551
+ for (var i=0, len=hosts.length; i<len; i++) {
552
+ var hostname = hosts[i];
553
+ $('#alarms .alarm-host-list').append('<div class="host-alarms ' + hostname + '"><a target="_blank" href="' + this.get_host_url(hostname, true) + '/"><h2>' + hostname + '</h2></a></div>');
554
+
555
+ $template.clone().removeClass('template').appendTo('#dash');
556
+ var $newest = $('.netdata-host-stats-container').last();
557
+ this.build_stats($newest, hostname);
558
+ }
559
+
560
+
561
+ if (this.first_build === true) {
562
+ this.remove_template_elements();
563
+ this.first_build = false;
564
+ }
565
+ }
566
+
567
+ build_stats ($hoststats, hostname) {
568
+ var that = this;
569
+
570
+ $hoststats.find('.netdata-host-stats .dash-graph').each(function () {
571
+ that.build_graph($(this), hostname);
572
+ });
573
+
574
+ $hoststats.find('.netdata-host-stats .dash-chart').each(function () {
575
+ that.build_chart($(this), hostname);
576
+ });
577
+
578
+ $hoststats.find('.netdata-host-name').html('<a target="_blank" href="' + that.get_host_url(hostname, true) + '/">' + hostname + '</a>');
579
+ }
580
+
581
+ build_graph ($wrapper, hostname) {
582
+ var that = this;
583
+ var $graph = $('<div>', {
584
+ // Defaults
585
+ 'data-netdata': $wrapper.attr('data-dash-netdata'),
586
+ 'data-host': that.get_host_url(hostname),
587
+ 'data-before': '0',
588
+ 'data-after': '-540',
589
+ 'role': 'application',
590
+ 'data-width': that.options.graph_width,
591
+ 'data-height': that.options.graph_height
592
+ });
593
+
594
+ $.each($wrapper[0].attributes, function (key, node) {
595
+ if ( node.name.match(/^data-(?!dash).*/ ) ) {
596
+ $graph.attr(node.name, node.value);
597
+ }
598
+ });
599
+
600
+ $graph.appendTo($wrapper);
601
+ }
602
+
603
+ build_chart ($wrapper, hostname) {
604
+ var that = this;
605
+ var $graph = $('<div>', {
606
+ // Defaults
607
+ 'data-netdata': $wrapper.attr('data-dash-netdata'),
608
+ 'data-host': that.get_host_url(hostname),
609
+ 'data-before': '0',
610
+ 'data-after': '-540',
611
+ 'data-points': '540',
612
+ 'role': 'application',
613
+ 'data-width': that.options.chart_width,
614
+ 'data-title': ' ',
615
+ 'data-easypiechart-trackcolor': "#373B40",
616
+ 'data-chart-library': 'easypiechart'
617
+
618
+ })
619
+
620
+ $.each($wrapper[0].attributes, function (key, node) {
621
+ if ( node.name.match(/^data-(?!dash).*/ ) ) {
622
+ $graph.attr(node.name, node.value);
623
+ }
624
+ });
625
+
626
+ $graph.appendTo($wrapper);
627
+ }
628
+
629
+ all_alarms_are_warnings () {
630
+ var out = true;
631
+ $.each(this.current_alarms, function (host, alarms) {
632
+ if (out === false) {
633
+ return false; // Maximum efficiency
634
+ }
635
+ $.each(alarms, function (name, data) {
636
+ if (data.status != "WARNING") {
637
+ out = false;
638
+ return false;
639
+ }
640
+ });
641
+ });
642
+ return out;
643
+ }
644
+
645
+ update_alarm_count () {
646
+ console.log(this.all_alarms_are_warnings());
647
+ var count = $('img.alarm-badge').length;
648
+ $('.alarm-count').text($('img.alarm-badge').length);
649
+ $('.alarm-count').removeClass('no-alarms warnings-only');
650
+ if ( count === 0 ) {
651
+ $('.alarm-count').addClass('no-alarms');
652
+ return
653
+ }
654
+ if (this.all_alarms_are_warnings()) {
655
+ $('.alarm-count').addClass('warnings-only');
656
+ }
657
+ }
658
+
659
+ fetch_active_alarms () {
660
+ var that = this;
661
+ console.log("Getting alarms...");
662
+ var hosts = this.get_enabled_hosts();
663
+ for (var i=0, len=hosts.length; i<len; i++) {
664
+ var hostname = hosts[i];
665
+
666
+ $.get(this.get_api_url(hostname) + '/alarms', function (data) {
667
+ that.new_alarms[ data.hostname ] = data.alarms;
668
+ if ( Object.keys(that.new_alarms).length === len ) {
669
+ // All responses received
670
+ if ( that.check_new_current_alarms() ) {
671
+ console.log("No alarm changes detected... Refreshing images.");
672
+ that.new_alarms = {};
673
+ that.refresh_alarm_images();
674
+ return;
675
+ }
676
+
677
+ that.current_alarms = that.new_alarms;
678
+ that.new_alarms = {};
679
+ that.draw_alarms();
680
+ that.update_alarm_count();
681
+ }
682
+ });
683
+ }
684
+ }
685
+
686
+ toggle_alarm_collapse () {
687
+ $('#alarms').toggleClass('collapsed');
688
+ }
689
+
690
+ check_new_current_alarms () {
691
+ // Create arrays of property names
692
+ var a = this.current_alarms;
693
+ var b = this.new_alarms;
694
+ var aProps = Object.keys(a);
695
+ var bProps = Object.keys(b);
696
+
697
+ // If number of properties is different,
698
+ // objects are not equivalent
699
+ if (aProps.length != bProps.length) {
700
+ return false;
701
+ }
702
+
703
+ for (var i = 0; i < aProps.length; i++) {
704
+ var propName = aProps[i];
705
+ var aa = a[propName];
706
+ var aaProps = Object.keys(aa);
707
+ var bb = b[propName];
708
+ var bbProps = Object.keys(bb);
709
+
710
+ if (aaProps.length != bbProps.length) {
711
+ return false;
712
+ }
713
+
714
+ for (var n = 0, len=aaProps.length; i < len; i++) {
715
+ if ( bb[aaProps[n]] === undefined ) {
716
+ return false;
717
+ }
718
+ }
719
+ }
720
+
721
+ // If we made it this far, objects
722
+ // are considered equivalent
723
+ return true;
724
+ }
725
+
726
+ refresh_alarm_images () {
727
+ // Use Math.random() to "reload" the image
728
+ $('.alarm-badge').each(function () {
729
+ var old_src = $(this).attr('src').replace(/&rand=.*/g, "");
730
+ $(this).attr('src', old_src + "&rand=" + Math.random());
731
+ });
732
+ }
733
+
734
+ draw_alarms () {
735
+ var that = this;
736
+ console.log("Drawing...", that.current_alarms);
737
+ $.each(that.current_alarms, function(hostname, alarms) {
738
+ $('#alarms .host-alarms.' + hostname + ' .alarm-badge').remove();
739
+ $.each(alarms, function (index, alarm) {
740
+ that.draw_alarm(hostname, alarm);
741
+ })
742
+ });
743
+ }
744
+
745
+ draw_alarm (hostname, alarm) {
746
+ var queryStr = '/badge.svg?alarm=' + alarm.name + '&chart=' + alarm.chart
747
+ $('<img />', {
748
+ src: this.get_api_url(hostname) + queryStr,
749
+ class: 'alarm-badge'
750
+ }).appendTo($('#alarms .host-alarms.' + hostname));
751
+ }
752
+
753
+ remove_template_elements () {
754
+ $('.netdata-host-stats-container').first().remove();
755
+ }
756
+
757
+ fix_layout_errors () {
758
+ $('.dash-graph:contains("chart not found")').html('<div class="loading-error">Not found</div>');
759
+ $('.dash-chart:contains("chart not found")').html('<div class="loading-error">Not found</div>');
760
+ }
761
+ }
762
+
763
+ /*
764
+ * TUTORIAL: Change this to the URL of your netdata host
765
+ * If you use netdata behind a reverse proxy, add a second parameter for the reverse proxy url like so:
766
+ * new Dash('http://localhost:19999', 'https://my-domain.com/stats');
767
+ */
768
+ var dash = new Dash('http://localhost:19999');
769
+
770
+ var picknsort = new PickNSort(true);
771
+
772
+ // Import dashboard.js
773
+ $.getScript(dash.base_url + '/dashboard.js', function() {
774
+ console.log("Loaded dashboard.js");
775
+ setTimeout(function () {
776
+ $('#alarms').css("visibility", "visible");
777
+ }, 400);
778
+ });
779
+
780
+ setInterval(function () {
781
+ dash.digest();
782
+ }, 6 * 1000);
783
784
</script>
785
<style type="text/css">
776
- body {
777
- background-color: #272b30;
778
- }
779
-
780
- a, a:hover {
781
- color: #AAA !important;
782
- }
783
-
784
- #dash {
785
- overflow: scroll;
786
- width: 100vw;
787
- white-space: nowrap;
788
- height: 100vh;
789
-
790
- }
791
-
792
- #alarms {
793
- display: block;
794
- z-index: 9999;
795
- position: fixed;
796
- right: 0;
797
- top: 0;
798
- bottom: 0;
799
- background-color: #111;
800
- width: 23em;
801
- padding: 1em;
802
- color: #AAA;
803
- box-shadow: 0 0 3em #060606;
804
- border: solid 1px #2d2d2d;
805
- visibility: hidden;
806
- }
807
-
808
-
809
-
810
- #alarms h1 {
811
- text-align: center;
812
- margin: 0;
813
- margin-bottom: 0.5em;
814
- margin-top: -0.1em;
815
- font-size: 2em;
816
- }
817
-
818
- #alarms h2 {
819
- font-size: 1.5em;
820
- }
821
-
822
- #alarms .alarm-collapse-button {
823
- position: absolute;
824
- top: 0;
825
- left: 0;
826
- width: 0.9em;
827
- height: 0.9em;
828
- font-size: 4em;
829
- line-height: 0.8;
830
- background: #111;
831
- text-align: center;
832
- cursor: default;
833
- }
834
-
835
- #alarms .alarm-collapse-button:hover {
836
- background: #000;
837
- }
838
-
839
- #alarms.collapsed {
840
- width: 4em;
841
- }
842
-
843
- #alarms.collapsed .alarm-collapse-button {
844
- position: fixed;
845
- left: auto;
846
- right: 0;
847
- top: 0;
848
- bottom: 0;
849
- width: 4em;
850
- height: 100vh;
851
- opacity: 0;
852
- z-index: 9999;
853
- }
854
-
855
- #alarms.collapsed h1 {
856
- transform: rotate(-90deg);
857
- position: absolute;
858
- left: -9.1em;
859
- top: 4em;
860
- width: 20em;
861
- }
862
-
863
- #alarms .alarm-host-list {
864
- margin-top: 1em;
865
- height: 100%;
866
- overflow-y: scroll;
867
- scrollbar-width: thin;
868
- }
869
-
870
- #alarms.collapsed .alarm-host-list {
871
- display: none;
872
- }
873
-
874
-
875
-
876
- #alarms .host-alarms {
877
- background: #1d1d1d;
878
- margin-bottom: 1em;
879
- padding: 0.2em 1em;
880
- padding-bottom: 1.5em;
881
- border-top: 1px solid;
882
- position: relative;
883
- }
884
-
885
- .host-alarms a:last-child:after {
886
- position: absolute;
887
- display: block;
888
- content: 'no alarms';
889
- width: 6em;
890
- height: 1em;
891
- right: 0;
892
- top: 2em;
893
- color: #646464;
894
- }
895
-
896
- #alarms .host-alarms img.alarm-badge {
897
- margin: .25em;
898
- height: 1.2em;
899
- }
900
-
901
- #alarms .alarm-count {
902
- width: 1.5em;
903
- height: 1.5em;
904
- text-align: center;
905
- position: absolute;
906
- right: 0.5em;
907
- top: 0.5em;
908
- font-size: 1.5em;
909
- background: #6f1515;
910
- border-radius: 50%;
911
- }
912
-
913
- #alarms .alarm-count:empty {
914
- background: #333;
915
- }
916
-
917
- #alarms .no-alarms {
918
- background: #156f15;
919
- color: rgba(0,0,0,0);
920
- }
921
-
922
- #alarms .warnings-only {
923
- background: #f48041;
924
- color: #EEE;
925
- }
926
-
927
- .settings-button {
928
- position: absolute;
929
- bottom: 0;
930
- right: 0;
931
- font-size: 3em;
932
- width: 1.3em;
933
- height: 1.3em;
934
- z-index: 9999;
935
- text-align: center;
936
- line-height: 1.2;
937
- cursor: default;
938
- }
939
-
940
- .settings-button:hover {
941
- background: #424242;
942
- }
943
-
944
- .drag-anchor {
945
- position: absolute;
946
- top: 0;
947
- left: 0;
948
- width: 100%;
949
- height: 2em;
950
- background: #111;
951
-
952
- }
953
-
954
- .netdata-host-name {
955
- font-size: 3em;
956
- color: #FFF;
957
- text-align: center;
958
- white-space: nowrap;
959
- }
960
-
961
- .netdata-host-stats-container {
962
- position: relative;
963
- margin: 0 1em;
964
- padding: 3em 2em;
965
- display: inline-block;
966
- text-align: center;
967
- color: #CCC;
968
- background: #232323;
969
- }
970
-
971
- .netdata-host-stats-container:last-of-type {
972
- margin-right: 27em;
973
- }
974
-
975
- .netdata-host-stats {
976
-
977
- }
978
-
979
- .netdata-message {
980
- }
981
-
982
- .dash-graph {
983
- margin-bottom: 1em;
984
- }
985
-
986
- .netdata-legend-resize-handler {
987
- display: none
988
- }
989
-
990
- .dash-charts {
991
- white-space: normal;
992
- margin: 2em 0;
993
- }
994
-
995
- .dash-chart {
996
- display: inline-block;
997
- vertical-align: top;
998
- }
999
-
1000
- .easyPieChartLabel {
1001
- color: #FFF;
1002
- }
1003
-
1004
- .loading-error {
1005
- padding-top: 2em;
1006
- font-size: 2em;
1007
- }
1008
-
1009
- .netdata-legend-value, .netdata-legend-toolbox, .netdata-legend-toolbox-button, .netdata-legend-resize-handler {
1010
- background: initial;
1011
- }
786
+ body {
787
+ background-color: #272b30;
788
+ }
789
+
790
+ a, a:hover {
791
+ color: #AAA !important;
792
+ }
793
+
794
+ #dash {
795
+ overflow: scroll;
796
+ width: 100vw;
797
+ white-space: nowrap;
798
+ height: 100vh;
799
+
800
+ }
801
+
802
+ #alarms {
803
+ display: block;
804
+ z-index: 9999;
805
+ position: fixed;
806
+ right: 0;
807
+ top: 0;
808
+ bottom: 0;
809
+ background-color: #111;
810
+ width: 23em;
811
+ padding: 1em;
812
+ color: #AAA;
813
+ box-shadow: 0 0 3em #060606;
814
+ border: solid 1px #2d2d2d;
815
+ visibility: hidden;
816
+ }
817
+
818
+
819
+
820
+ #alarms h1 {
821
+ text-align: center;
822
+ margin: 0;
823
+ margin-bottom: 0.5em;
824
+ margin-top: -0.1em;
825
+ font-size: 2em;
826
+ }
827
+
828
+ #alarms h2 {
829
+ font-size: 1.5em;
830
+ }
831
+
832
+ #alarms .alarm-collapse-button {
833
+ position: absolute;
834
+ top: 0;
835
+ left: 0;
836
+ width: 0.9em;
837
+ height: 0.9em;
838
+ font-size: 4em;
839
+ line-height: 0.8;
840
+ background: #111;
841
+ text-align: center;
842
+ cursor: default;
843
+ }
844
+
845
+ #alarms .alarm-collapse-button:hover {
846
+ background: #000;
847
+ }
848
+
849
+ #alarms.collapsed {
850
+ width: 4em;
851
+ }
852
+
853
+ #alarms.collapsed .alarm-collapse-button {
854
+ position: fixed;
855
+ left: auto;
856
+ right: 0;
857
+ top: 0;
858
+ bottom: 0;
859
+ width: 4em;
860
+ height: 100vh;
861
+ opacity: 0;
862
+ z-index: 9999;
863
+ }
864
+
865
+ #alarms.collapsed h1 {
866
+ transform: rotate(-90deg);
867
+ position: absolute;
868
+ left: -9.1em;
869
+ top: 4em;
870
+ width: 20em;
871
+ }
872
+
873
+ #alarms .alarm-host-list {
874
+ margin-top: 1em;
875
+ height: 100%;
876
+ overflow-y: scroll;
877
+ scrollbar-width: thin;
878
+ }
879
+
880
+ #alarms.collapsed .alarm-host-list {
881
+ display: none;
882
+ }
883
+
884
+
885
+
886
+ #alarms .host-alarms {
887
+ background: #1d1d1d;
888
+ margin-bottom: 1em;
889
+ padding: 0.2em 1em;
890
+ padding-bottom: 1.5em;
891
+ border-top: 1px solid;
892
+ position: relative;
893
+ }
894
+
895
+ .host-alarms a:last-child:after {
896
+ position: absolute;
897
+ display: block;
898
+ content: 'no alarms';
899
+ width: 6em;
900
+ height: 1em;
901
+ right: 0;
902
+ top: 2em;
903
+ color: #646464;
904
+ }
905
+
906
+ #alarms .host-alarms img.alarm-badge {
907
+ margin: .25em;
908
+ height: 1.2em;
909
+ }
910
+
911
+ #alarms .alarm-count {
912
+ width: 1.5em;
913
+ height: 1.5em;
914
+ text-align: center;
915
+ position: absolute;
916
+ right: 0.5em;
917
+ top: 0.5em;
918
+ font-size: 1.5em;
919
+ background: #6f1515;
920
+ border-radius: 50%;
921
+ }
922
+
923
+ #alarms .alarm-count:empty {
924
+ background: #333;
925
+ }
926
+
927
+ #alarms .no-alarms {
928
+ background: #156f15;
929
+ color: rgba(0,0,0,0);
930
+ }
931
+
932
+ #alarms .warnings-only {
933
+ background: #f48041;
934
+ color: #EEE;
935
+ }
936
+
937
+ .settings-button {
938
+ position: absolute;
939
+ bottom: 0;
940
+ right: 0;
941
+ font-size: 3em;
942
+ width: 1.3em;
943
+ height: 1.3em;
944
+ z-index: 9999;
945
+ text-align: center;
946
+ line-height: 1.2;
947
+ cursor: default;
948
+ }
949
+
950
+ .settings-button:hover {
951
+ background: #424242;
952
+ }
953
+
954
+ .netdata-host-name {
955
+ font-size: 3em;
956
+ color: #FFF;
957
+ text-align: center;
958
+ white-space: nowrap;
959
+ background: inherit;
960
+ position: sticky;
961
+ top: 0;
962
+ z-index: 9998;
963
+ box-shadow: 0 0.5em 1em #232323;
964
+ margin-bottom: 0.5em;
965
+ border-bottom: solid 0.1em #AAA;
966
+ }
967
+
968
+ .netdata-host-stats-container {
969
+ position: relative;
970
+ margin: 0 1em;
971
+ padding: 1em 2em;
972
+ display: inline-block;
973
+ text-align: center;
974
+ color: #CCC;
975
+ background: #232323;
976
+ }
977
+
978
+ .netdata-host-stats-container:last-of-type {
979
+ margin-right: 27em;
980
+ }
981
+
982
+ .netdata-host-stats {
983
+
984
+ }
985
+
986
+ .netdata-message {
987
+ }
988
+
989
+ .dash-graph {
990
+ margin-bottom: 1em;
991
+ }
992
+
993
+ .netdata-legend-resize-handler {
994
+ display: none
995
+ }
996
+
997
+ .dash-charts {
998
+ white-space: normal;
999
+ margin: 2em 0;
1000
+ }
1001
+
1002
+ .dash-chart {
1003
+ display: inline-block;
1004
+ vertical-align: top;
1005
+ }
1006
+
1007
+ .easyPieChartLabel {
1008
+ color: #FFF;
1009
+ }
1010
+
1011
+ .loading-error {
1012
+ padding-top: 2em;
1013
+ font-size: 2em;
1014
+ }
1015
+
1016
+ .netdata-legend-value, .netdata-legend-toolbox, .netdata-legend-toolbox-button, .netdata-legend-resize-handler {
1017
+ background: initial;
1018
+ }
1019
</style>
1020
</html>