]> arthur.barton.de Git - netdata.git/blobdiff - web/index.html
Merge pull request #912 from sehraf/master
[netdata.git] / web / index.html
index 041290b895e95dfd8843c49cf7faf4be44fb707b..3ea587b52976f0ec3cbd837fe9215ac431d86cb9 100644 (file)
         margin-top: 10px;
     }
 
-    .container {
-        width: 90% !important;
-    }
-
     #masthead h1 {
         /*font-size: 30px;*/
         line-height: 1;
         overflow: visible;
     }
 
+    /* make accordion use the whole header bar for expand/collapse */
+    .panel-title a {
+        display: block;
+        padding: 10px 15px;
+        margin: -10px -15px;
+    }
+
     /*
      * Side navigation
      *
         margin-top: 0;
     }
 
+    .container {
+        width: calc(100% - 20px) !important;
+    }
+
+    .charts-body {
+        display: inline-block;
+        width: 100%;
+    }
+
+    .sidebar-body {
+        position: absolute;
+        display: none;
+    }
+
     @media (min-width: 768px) {
+        .charts-body {
+            padding-left: 0%;
+            padding-right: 0%;
+        }
+
         .back-to-top,
         .dashboard-theme-toggle {
             display: block;
         }
+    }
 
-        /* Widen the fixed sidebar */
-        .dashboard-sidebar.affix,
-        .dashboard-sidebar.affix-top,
-        .dashboard-sidebar.affix-bottom {
-            width: 200px !important;
-        }
-
-        .dashboard-sidebar.affix {
-            position: fixed; /* Undo the static from mobile first approach */
-            top: 20px;
+    /* Show and affix the side nav when space allows it */
+    @media (min-width: 992px) {
+        .container {
+            padding-left: 0% !important;
         }
 
-        .dashboard-sidebar.affix-bottom {
-            position: absolute; /* Undo the static from mobile first approach */
+        .charts-body {
+            width: calc(100% - 213px) !important;
+            padding-left: 1% !important;
+            padding-right: 0% !important;
         }
 
-        .dashboard-sidebar.affix-bottom .dashboard-sidenav,
-        .dashboard-sidebar.affix .dashboard-sidenav {
-            margin-top: 0;
-            margin-bottom: 0;
+        .sidebar-body {
+            display: inline-block !important;
+            width: 213px !important;
         }
-    }
 
-    /* Show and affix the side nav when space allows it */
-    @media (min-width: 992px) {
         .dashboard-sidebar .nav > .active > ul {
             display: block;
         }
         .dashboard-sidebar.affix,
         .dashboard-sidebar.affix-top,
         .dashboard-sidebar.affix-bottom {
-            width: 200px !important;
+            width: 213px !important;
         }
         .dashboard-sidebar.affix {
             position: fixed; /* Undo the static from mobile first approach */
     }
 
     @media (min-width: 1200px) {
+        .container {
+            padding-left: 2% !important;
+        }
+
+        .charts-body {
+            width: calc(100% - 233px) !important;
+            padding-left: 1% !important;
+            padding-right: 1% !important;
+        }
+
+        .sidebar-body {
+            display: inline-block !important;
+            width: 233px !important;
+        }
+
         /* Widen the fixed sidebar again */
-        .dashboard-sidebar.affix-bottom,
+        .dashboard-sidebar.affix,
         .dashboard-sidebar.affix-top,
-        .dashboard-sidebar.affix {
-            width: 263px;
+        .dashboard-sidebar.affix-bottom {
+            width: 233px !important;
+        }
+    }
+    
+    @media (min-width: 1360px) {
+        .container {
+            padding-left: 3% !important;
+        }
+
+        .charts-body {
+            width: calc(100% - 263px) !important;
+            padding-left: 1% !important;
+            padding-right: 2% !important;
+        }
+
+        .sidebar-body {
+            display: inline-block !important;
+            width: 263px !important;
+        }
+
+        /* Widen the fixed sidebar again */
+        .dashboard-sidebar.affix,
+        .dashboard-sidebar.affix-top,
+        .dashboard-sidebar.affix-bottom {
+            width: 263px !important;
         }
     }
+
     </style>
 
     <!-- check which theme to use -->
     <script type="text/javascript">
+        // enable alarms checking and notifications
+        var netdataShowAlarms = true;
+
+        // enable registry updates
+        var netdataRegistry = true;
+        
         // --------------------------------------------------------------------
         // urlOptions
 
             a1 += '<li role="separator" class="divider"></li>';
 
             el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #999;" target="_blank">What is this?</a></li>';
-            a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fa fa-cog" aria-hidden="true" style="color: #999;"></i></a></li>'
+            a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fa fa-sliders" aria-hidden="true" style="color: #999;"></i></a></li>'
 
             document.getElementById('mynetdata_servers').innerHTML = el;
             document.getElementById('mynetdata_servers2').innerHTML = el;
     </script>
 
     <!-- load the dashboard manager - it will do the rest -->
-    <script type="text/javascript" src="dashboard.js?v41"></script>
+    <script type="text/javascript" src="dashboard.js?v46"></script>
 </head>
 <body data-spy="scroll" data-target="#sidebar">
     <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                 </button>
-                <a href="/" class="navbar-brand" id="hostname">netdata</a>
+                <a href="/" class="navbar-brand" id="hostname" title="reload the dashboard">netdata</a>
             </div>
             <nav class="collapse navbar-collapse navbar-right" role="navigation">
                 <ul class="nav navbar-nav">
-                    <li class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fa fa-cog"></i> settings</a></li>
-                    <li class="hidden-sm"><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank"><i class="fa fa-github"></i> community</a></li>
-                    <li class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal"><i class="fa fa-cloud-download"></i> update</a></li>
-                    <li class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#helpModal"><i class="fa fa-question-circle"></i> help</a></li>
+                    <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i></span>&nbsp;<span class="hidden-sm">Alarms&nbsp;</span><span id="alarms_count_badge" class="badge"></a></li>
+                    <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal" title="dashboard settings"><i class="fa fa-sliders"></i>&nbsp;<span class="hidden-sm">Settings</span></a></li>
+                    <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank" title="netdata community"><i class="fa fa-github"></i>&nbsp;<span class="hidden-sm hidden-md">Community</span></a></li>
+                    <li class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal" title="check for update"><i class="fa fa-cloud-download"></i><span id="update_badge" class="badge"></span>&nbsp;<span class="hidden-sm hidden-md">Update</span></a></li>
+                    <li class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#helpModal" title="dashboard help"><i class="fa fa-question-circle"></i>&nbsp;<span class="hidden-sm hidden-md">Help</span></a></li>
+                    <!--
                     <li class="dropdown hidden-md hidden-lg hidden-xs">
                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">Menu <strong class="caret"></strong></a>
                         <ul class="dropdown-menu scrollable-menu inpagemenu" role="menu">
-                            <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fa fa-cog"></i> settings</a></li>
+                            <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal"><i class="fa fa-bell"></i> alarms</a></li>
+                            <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fa fa-sliders"></i> settings</a></li>
                             <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank"><i class="fa fa-github"></i> community</a></li>
                             <li><a href="#" class="btn" data-toggle="modal" data-target="#helpModal"><i class="fa fa-question-circle"></i> help</a></li>
                         </ul>
                     </li>
+                    -->
                     <li class="dropdown hidden-sm hidden-md hidden-lg">
                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a>
                         <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu">
 
     <div class="container">
         <div class="row">
-            <div class="col-md-10" role="main">
+            <div class="charts-body" role="main">
                 <div id="charts_div"></div>
             </div>
-            <div class="col-md-2" role="complementary">
+            <div class="sidebar-body hidden-xs hidden-sm" role="complementary">
                 <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav>
             </div>
         </div>
         </div>
     </div>
 
+    <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel">
+        <div class="modal-dialog modal-lg" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4>
+                </div>
+                <div class="modal-body">
+                    <!-- Nav tabs -->
+                    <ul class="nav nav-tabs" role="tablist">
+                        <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li>
+                        <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li>
+                        <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li>
+                    </ul>
+
+                    <!-- Tab panes -->
+                    <div class="tab-content">
+                        <div role="tabpanel" class="tab-pane active" id="alarms_active">
+                            loading...
+                        </div>
+                        <div role="tabpanel" class="tab-pane" id="alarms_all">
+                            loading...
+                        </div>
+                        <div role="tabpanel" class="tab-pane" id="alarms_log">
+                            loading...
+                        </div>
+                    </div>
+                </div>
+                <div class="modal-footer">
+                    <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> -->
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel">
         <div class="modal-dialog modal-lg" role="document">
             <div class="modal-content">
@@ -1282,6 +1383,7 @@ function notifyForDeleteRegistry() {
 
 var options = {
     sparklines_registry: {},
+    menus: {},
     submenu_names: {},
     data: null,
     hostname: 'netdata_server', // will be overwritten by the netdata server
@@ -1395,89 +1497,106 @@ function gaugeChart(title, width, dimensions, colors) {
 var menuData = {
     'system': {
         title: 'System Overview',
+        icon: '<i class="fa fa-bookmark" aria-hidden="true"></i>',
         info: 'Overview of the key system metrics.'
     },
 
     'ap': {
         title: 'Access Points',
+        icon: '<i class="fa fa-wifi" aria-hidden="true"></i>',
         info: undefined
     },
 
     'tc': {
         title: 'Quality of Service',
+        icon: '<i class="fa fa-globe" aria-hidden="true"></i>',
         info: '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. If your QoS configuration includes overheads calculation, the values shown here will include these overheads (the total bandwidth for the same interface as reported in the Network Interfaces section, will be lower than the total bandwidth reported here). Also, data collection may have a slight time difference compared to the interface (QoS data collection is implemented with a BASH script, so a shift in data collection of a few milliseconds should be justified).'
     },
 
     'net': {
         title: 'Network Interfaces',
+        icon: '<i class="fa fa-share-alt" aria-hidden="true"></i>',
         info: 'Per network interface statistics collected from <code>/proc/net/dev</code>.'
     },
 
     'ipv4': {
         title: 'IPv4 Networking',
+        icon: '<i class="fa fa-cloud" aria-hidden="true"></i>',
         info: undefined
     },
 
     'ipv6': {
         title: 'IPv6 Networking',
+        icon: '<i class="fa fa-cloud" aria-hidden="true"></i>',
         info: undefined
     },
 
     'ipvs': {
         title: 'IP Virtual Server',
+        icon: '<i class="fa fa-eye" aria-hidden="true"></i>',
         info: undefined
     },
 
     'netfilter': {
         title: 'Firewall (netfilter)',
+        icon: '<i class="fa fa-shield" aria-hidden="true"></i>',
         info: undefined
     },
 
     'cpu': {
         title: 'CPUs',
+        icon: '<i class="fa fa-bolt" aria-hidden="true"></i>',
         info: undefined
     },
 
     'mem': {
         title: 'Memory',
+        icon: '<i class="fa fa-bolt" aria-hidden="true"></i>',
         info: undefined
     },
 
     'disk': {
         title: 'Disks',
+        icon: '<i class="fa fa-folder" aria-hidden="true"></i>',
         info: 'Charts with performance information for all the system disks. Special care has been given to present disk performance metrics in a way compatible with <code>iostat -x</code>. netdata by default prevents rendering performance charts for individual partitions and unmounted virtual disks. Disabled charts can still be enabled by altering the relative settings in the netdata configuration file.'
     },
 
     'sensors': {
         title: 'Sensors',
+        icon: '<i class="fa fa-leaf" aria-hidden="true"></i>',
         info: undefined
     },
 
     'nfsd': {
         title: 'File Server (nfsd)',
+        icon: '<i class="fa fa-folder-open" aria-hidden="true"></i>',
         info: undefined
     },
 
     'apps': {
         title: 'Applications',
+        icon: '<i class="fa fa-heartbeat" aria-hidden="true"></i>',
         info: '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 internally 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). The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.',
         height: 1.5
     },
 
     'users': {
         title: 'Users',
+        icon: '<i class="fa fa-user" aria-hidden="true"></i>',
         info: 'Per user statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics per user. The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.',
         height: 1.5
     },
 
     'groups': {
         title: 'User Groups',
+        icon: '<i class="fa fa-users" aria-hidden="true"></i>',
         info: 'Per user group statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics per user group. The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.',
         height: 1.5
     },
 
     'netdata': {
         title: 'Netdata Monitoring',
+        icon: '<i class="fa fa-bar-chart" aria-hidden="true"></i>',
         info: undefined
     },
 
@@ -1487,52 +1606,98 @@ var menuData = {
     },
 
     'cgroup': {
-        title: 'Container',
+        title: '',
+        icon: '<i class="fa fa-th" aria-hidden="true"></i>',
         info: undefined
     },
 
-    'cgroup-vm': {
-        title: 'VM',
+    'cgqemu': {
+        title: '',
+        icon: '<i class="fa fa-th-large" aria-hidden="true"></i>',
         info: undefined
     },
 
     'memcached': {
         title: 'memcached',
+        icon: '<i class="fa fa-database" aria-hidden="true"></i>',
         info: undefined
     },
 
     'mysql': {
         title: 'MySQL',
+        icon: '<i class="fa fa-database" aria-hidden="true"></i>',
         info: undefined
     },
 
     'redis': {
         title: 'Redis',
+        icon: '<i class="fa fa-database" aria-hidden="true"></i>',
+        info: undefined
+    },
+
+    'retroshare': {
+        title: 'RetroShare',
+        icon: '<i class="fa fa-share-alt" aria-hidden="true"></i>',
         info: undefined
     },
 
     'ipfs': {
         title: 'IPFS',
+        icon: '<i class="fa fa-folder-open" aria-hidden="true"></i>',
         info: undefined
     },
 
     'phpfpm': {
         title: 'PHP-FPM',
+        icon: '<i class="fa fa-eye" aria-hidden="true"></i>',
+        info: undefined,
+    },
+
+    'postfix': {
+        title: 'postfix',
+        icon: '<i class="fa fa-envelope" aria-hidden="true"></i>',
         info: undefined,
     },
 
     'nginx': {
         title: 'nginx',
+        icon: '<i class="fa fa-eye" aria-hidden="true"></i>',
         info: undefined,
     },
 
     'apache': {
         title: 'Apache',
+        icon: '<i class="fa fa-eye" aria-hidden="true"></i>',
         info: undefined,
     },
 
     'named': {
         title: 'named',
+        icon: '<i class="fa fa-tag" aria-hidden="true"></i>',
+        info: undefined
+    },
+
+    'squid': {
+        title: 'squid',
+        icon: '<i class="fa fa-exchange" aria-hidden="true"></i>',
+        info: undefined
+    },
+
+    'nut': {
+        title: 'UPS',
+        icon: '<i class="fa fa-battery-half" aria-hidden="true"></i>',
+        info: undefined
+    },
+
+    'smawebbox': {
+        title: 'Solar Power',
+        icon: '<i class="fa fa-sun-o" aria-hidden="true"></i>',
+        info: undefined
+    },
+
+    'snmp': {
+        title: 'SNMP',
+        icon: '<i class="fa fa-random" aria-hidden="true"></i>',
         info: undefined
     }
 };
@@ -1615,11 +1780,11 @@ var chartData = {
     },
 
     'system.processes': {
-        info: '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.'
+        info: 'System processes, read from <code>/proc/stat</code>. <b>Running</b> are the processes in the CPU. <b>Blocked</b> are processes that are willing to enter the CPU, but they cannot, e.g. because they wait for disk activity.'
     },
 
     'system.active_processes': {
-        info: 'All system active processes, read from <code>/proc/loadavg</code>.'
+        info: 'All system processes, read from <code>/proc/loadavg</code>.'
     },
 
     'system.ctxt': {
@@ -1948,6 +2113,39 @@ var chartData = {
 
     'netdata.response_time': {
         info: 'The netdata API response time measures the time netdata needed to serve requests. This time includes everything, from the reception of the first byte of a request, to the dispatch of the last byte of its reply, therefore it includes all network latencies involved (i.e. a client over a slow network will influence these metrics).'
+    },
+
+    // ------------------------------------------------------------------------
+    // RETROSHARE
+    'retroshare.bandwidth': {
+        info: 'Shows inbound and outbound traffic.',
+        mainheads: [
+            gaugeChart('Received', '12%', 'bandwidth_down_kb'),
+            gaugeChart('Sent', '12%', 'bandwidth_up_kb')
+        ]
+    },
+
+    'retroshare.peers': {
+        info: 'Shows the number of (connected) friends.',
+        mainheads: [
+            function(id) {
+                return  '<div data-netdata="' + id + '"'
+                    + ' data-dimensions="peers_connected"'
+                    + ' data-append-options="friends"'
+                    + ' data-chart-library="easypiechart"'
+                    + ' data-title="connected friends"'
+                    + ' data-units=""'
+                    + ' data-width="8%"'
+                    + ' data-before="0"'
+                    + ' data-after="-CHART_DURATION"'
+                    + ' data-points="CHART_DURATION"'
+                    + ' role="application"></div>';
+            }
+        ]
+    },
+
+    'retroshare.dht': {
+        info: 'Shows statistics about RetroShare\'s DHT. These values are estimated!'
     }
 };
 
@@ -1961,11 +2159,18 @@ function anyAttribute(obj, attr, key, def) {
 
 function menuTitle(chart) {
     if(typeof chart.menu_pattern !== 'undefined') {
-        return anyAttribute(menuData, 'title', chart.menu_pattern, chart.menu_pattern).toString()
-                + ': ' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString();
+        return (anyAttribute(menuData, 'title', chart.menu_pattern, chart.menu_pattern).toString()
+                + '&nbsp;' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
     }
 
-    return anyAttribute(menuData, 'title', chart.menu, chart.menu);
+    return (anyAttribute(menuData, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
+}
+
+function menuIcon(chart) {
+    if(typeof chart.menu_pattern !== 'undefined')
+        return anyAttribute(menuData, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString();
+
+    return anyAttribute(menuData, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>');
 }
 
 function menuInfo(menu) {
@@ -1978,7 +2183,13 @@ function menuHeight(menu, relative) {
 
 function submenuTitle(menu, submenu) {
     var key = menu + '.' + submenu;
-    return anyAttribute(submenuData, 'title', key, submenu);
+    var title = anyAttribute(submenuData, 'title', key, submenu).toString().replace(/_/g, ' ');;
+    if(title.length > 28) {
+        var a = title.substring(0, 13);
+        var b = title.substring(title.length - 12, title.length);
+        return a + '...' + b;
+    }
+    return title;
 }
 
 function submenuInfo(menu, submenu) {
@@ -2024,7 +2235,7 @@ function enrichChartData(chart) {
         case 'cgroup':
             chart.menu = chart.type;
             if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/))
-                chart.menu_pattern = 'cgroup-vm';
+                chart.menu_pattern = 'cgqemu';
             else
                 chart.menu_pattern = 'cgroup';
             break;
@@ -2035,10 +2246,13 @@ function enrichChartData(chart) {
         case 'mysql':
         case 'named':
         case 'nginx':
+        case 'nut':
         case 'phpfpm':
         case 'postfix':
         case 'redis':
+        case 'retroshare':
         case 'ipfs':
+        case 'smawebbox':
         case 'squid':
         case 'snmp':
         case 'tomcat':
@@ -2238,7 +2452,7 @@ function renderPage(menus, data) {
         // generate an entry at the main menu
 
         var menuid = name2id(menu);
-        sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].title + '</a><ul class="nav">';
+        sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
         html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div id="menu_' + menuid + '" role="document">';
 
         if(menus[menu].info !== null)
@@ -2308,7 +2522,7 @@ function renderPage(menus, data) {
 }
 
 function renderChartsAndMenu(data) {
-    var menus = {};
+    var menus = options.menus;
     var charts = data.charts;
 
     for(var c in charts) {
@@ -2320,6 +2534,7 @@ function renderChartsAndMenu(data) {
                 priority: charts[c].priority,
                 submenus: {},
                 title: menuTitle(charts[c]),
+                icon: menuIcon(charts[c]),
                 info: menuInfo(charts[c].menu),
                 height: menuHeight(charts[c].menu, options.chartsHeight)
             };
@@ -2363,30 +2578,321 @@ function renderChartsAndMenu(data) {
     renderPage(menus, data);
 }
 
+// ----------------------------------------------------------------------------
+
+function alarmsUpdateModal() {
+    var active = '<h3>Raised Alarms</h3><table class="table">';
+    var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
+    var log = '<h3>Alarm Log</h3><table class="table"><tr><th>When</th><th>Chart</th><th>Alarm</th><th>Status</th>';
+    var footer = '<hr/><a href="https://github.com/firehol/netdata/wiki/Generating-Badges" target="_blank">netdata badges</a> refresh automatically. Their color indicates the state of the alarm: <span style="color: #e05d44"><b>&nbsp;red&nbsp;</b></span> is critical, <span style="color:#fe7d37"><b>&nbsp;orange&nbsp;</b></span> is warning, <span style="color: #4c1"><b>&nbsp;bright green&nbsp;</b></span> is ok, <span style="color: #9f9f9f"><b>&nbsp;light grey&nbsp;</b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b>&nbsp;black&nbsp;</b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.';
+
+    NETDATA.alarms.get('all', function(data) {
+        options.alarm_families = new Array();
+
+        alarmsCallback(data);
+
+        if(data === null) {
+            document.getElementById('alarms_active').innerHTML =
+                    document.getElementById('alarms_all').innerHTML =
+                            document.getElementById('alarms_log').innerHTML =
+                                    'failed to load alarm data!';
+            return;
+        }
+
+        function frequency_text(seconds, sfx) {
+            if(seconds === 0)
+                return 'now';
+
+            var suffix = '';
+            if(seconds < 0) {
+                seconds = -seconds;
+                if(sfx) suffix = '&nbsp;ago';
+            }
+
+            var hours = Math.floor(seconds / 3600);
+            seconds -= (hours * 3600);
+
+            var minutes = Math.floor(seconds / 60);
+            seconds -= (minutes * 60);
+
+            var txt = '';
+            
+            if(hours > 1) txt += hours.toString() + '&nbsp;hours';
+            else if(hours === 1) txt += hours.toString() + '&nbsp;hour';
+
+            if(hours > 0 && minutes > 0 && seconds == 0)
+                txt += '&nbsp;and&nbsp;';
+            else if(hours > 0 && minutes > 0 && seconds > 0)
+                txt += ',&nbsp;';
+
+            if(minutes > 1) txt += minutes.toString() + '&nbsp;minutes';
+            else if(minutes === 1) txt += minutes.toString() + '&nbsp;minute';
+
+            if((minutes > 0 || minutes > 0) && seconds > 0)
+                txt += '&nbsp;and&nbsp;';
+
+            if(seconds > 1) txt += seconds.toString() + '&nbsp;seconds';
+            else if(seconds === 1) txt += seconds.toString() + '&nbsp;second';
+
+            return txt + suffix;
+        }
+
+        function alarm_lookup_explain(alarm, chart) {
+            var dimensions = ' of all values ';
+
+            if(chart.dimensions.length > 1)
+                dimensions = ' of the sum of all dimensions ';
+
+            if(typeof alarm.lookup_dimensions !== 'undefined') {
+                var d = alarm.lookup_dimensions.replace('|', ',');
+                var x = d.split(',');
+                if(x.length > 1)
+                    dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
+                else
+                    dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
+            }
+
+            return '<code>' + alarm.lookup_method + '</code> '
+                + dimensions + ', of chart <code>' + alarm.chart + '</code>'
+                + ', starting <code>' + frequency_text(alarm.lookup_after + alarm.lookup_before, true) + '</code> and up to <code>' + frequency_text(alarm.lookup_before, true) + '</code>'
+                + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ',&nbsp;') + '</code>'):'')
+                + '.';
+        }
+
+        function alarm_to_html(alarm, full) {
+            var chart = options.data.charts[alarm.chart];
+
+            var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/>&nbsp;<br/><embed src="' + NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto" type="image/svg+xml" height="20" /><br/>&nbsp;<br/><span style="font-size: 18px">' + alarm.info + '</span><br/>&nbsp;<br/>role: <b>' + alarm.recipient + '</b></td>'
+                + '<td><table class="table">'
+                + ((typeof alarm.warn !== 'undefined')?('<tr><td width="10%" style="text-align:right">warning&nbsp;when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>'):'')
+                + ((typeof alarm.crit !== 'undefined')?('<tr><td width="10%" style="text-align:right">critical&nbsp;when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>'):'');
+
+            if(full === true) {
+                    html += ((typeof alarm.lookup_after !== 'undefined')?('<tr><td width="10%" style="text-align:right">db&nbsp;lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>'):'')
+                    + ((typeof alarm.calc !== 'undefined')?('<tr><td width="10%" style="text-align:right">calculation</td><td><span style="font-family: monospace;">' + alarm.calc + '</span></td></tr>'):'')
+                    + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green&nbsp;threshold</td><td><code>' + chart.green + ' ' + chart.units + '</code></td></tr>'):'')
+                    + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red&nbsp;threshold</td><td><code>' + chart.red + ' ' + chart.units + '</code></td></tr>'):'');
+            }
+
+            html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + frequency_text(alarm.update_every) + '</td></tr>'
+                + '<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span></td></tr>'
+                + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
+                + '</table></td></tr>';
+
+            return html;
+        }
+
+        function alarm_family_show(id) {
+            var html = '<table class="table">';
+            var family = options.alarm_families[id];
+            var len = family.arr.length;
+            while(len--) {
+                var alarm = family.arr[len];
+                html += alarm_to_html(alarm, true);
+            }
+            html += '</table>';
+
+            $('#alarm_all_' + id.toString()).html(html);
+        }
+
+        // find the proper family of each alarm
+        var now = new Date().getTime();
+        var x;
+        var count_active = 0;
+        var count_all = 0;
+        var families = {};
+        var families_sort = new Array();
+        for(x in data.alarms) {
+            var alarm = data.alarms[x];
+            var family = alarm.family;
+
+            // find the chart
+            var chart = options.data.charts[alarm.chart];
+            if(typeof chart === 'undefined')
+                chart = options.data.charts_by_name[alarm.chart];
+
+            // not found - this should never happen!
+            if(typeof chart === 'undefined') {
+                console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
+                chart = { priority: 9999999 };
+            }
+            else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
+                // the family based on the chart
+                family = chart.menu + ' - ' + chart.submenu;
+
+            if(typeof families[family] === 'undefined') {
+                families[family] = {
+                    name: family,
+                    arr: new Array(),
+                    priority: chart.priority
+                };
+
+                families_sort.push(families[family]);
+            }
+
+            if(chart.priority < families[family].priority)
+                families[family].priority = chart.priority;
+
+            families[family].arr.push(alarm);
+        }
+
+        // sort the families, like the dashboard menu does
+        var families_sorted = families_sort.sort(function (a, b) {
+            if (a.priority > b.priority) return -1;
+            if (a.priority < b.priority) return 1;
+            if (a.name < b.name) return 1;
+            if (a.name > b.name) return -1;
+            return 0;
+        });
+
+        var fc = 0;
+        var len = families_sorted.length;
+        while(len--) {
+            var family = families_sorted[len].name;
+            var active_family_added = false;
+            var expanded = 'true';
+            var collapsed = '';
+            var cin = 'in';
+
+            if(fc !== 0) {
+                all += "</table></div></div></div>";
+                expanded = 'false';
+                collapsed = 'class="collapsed"'
+                cin = '';
+            }
+
+            all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">';
+
+            options.alarm_families[fc] = families[family];
+
+            fc++;
+
+            var arr = families[family].arr;
+            var c = arr.length;
+            while(c--) {
+                var alarm = arr[c];
+                if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
+                    if(!active_family_added) {
+                        active_family_added = true;
+                        active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
+                    }
+                    count_active++;
+                    active += alarm_to_html(alarm, false);
+                }
+
+                count_all++;
+            }
+        }
+        active += "</table>";
+        if(families_sorted.length > 0) all += "</div></div></div>";
+        all += "</div>";
+
+        if(!count_active)
+            active += "<h4>Everything is normal. No raised alarms.</h4>";
+        else
+            active += footer;
+
+        if(!count_all)
+            all += "<h4>No alarms are running in this system.</h4>";
+        else
+            all += footer;
+
+        document.getElementById('alarms_active').innerHTML = active;
+        document.getElementById('alarms_all').innerHTML = all;
+
+        if(families_sorted.length > 0) alarm_family_show(0);
+
+        // register bootstrap events
+        $('#alarms_all_accordion').on('show.bs.collapse', function (d) {
+            var target = $(d.target);
+            var id = $(target).data('alarm-id');
+            alarm_family_show(id);
+        });
+        $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) {
+            var target = $(d.target);
+            var id = $(target).data('alarm-id');
+            $('#alarm_all_' + id.toString()).html('');
+        });
+
+        NETDATA.alarms.get_log(0, function(data) {
+            if(data === null) {
+                document.getElementById('alarms_log').innerHTML =
+                        'failed to load alarm data!';
+                return;
+            }
+
+            var i = 0;
+            var len = data.length;
+            if(len > 50) len = 50;
+            while(i < len) {
+                var time = new Date(data[i].when * 1000);
+                log += '<tr><td>'
+                        + time.toLocaleDateString() + ' '
+                        + time.toLocaleTimeString() + '</td><td>'
+                        + data[i].chart.toString() + '</td><td>'
+                        + data[i].name.toString() + ' = ' + ((data[i].value !== null)?Math.floor(data[i].value):'NaN').toString() + ' ' + data[i].units.toString() + '</td><td>'
+                        + data[i].status.toString() + '</td></tr>';
+                i++;
+            }
+            log += "</table>";
+
+            if(i == 0)
+                log += "<h4>No alarms have been logged in this system.</h4>";
+
+            document.getElementById('alarms_log').innerHTML = log;
+        })
+    });
+}
+
+function alarmsCallback(data) {
+    var count = 0;
+    for(x in data.alarms) {
+        var alarm = data.alarms[x];
+        if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
+            count++;
+    }
+
+    if(count > 0)
+        document.getElementById('alarms_count_badge').innerHTML = count.toString();
+    else
+        document.getElementById('alarms_count_badge').innerHTML = '';
+}
+
 function downloadAllCharts(netdata_url) {
     if(typeof netdata_url === 'undefined' || netdata_url === null)
         netdata_url = NETDATA.serverDefault;
 
     NETDATA.pause(function() {
         $("#loadOverlay").css("display","none");
-        $("#loadOverlay").css("display","none");
+
+        NETDATA.alarms.callback = alarmsCallback;
 
         // download all the charts the server knows
         NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
 
-            options.data = data;
-            options.hostname = data.hostname;
-            document.getElementById('hostname').innerHTML = options.hostname;
-            document.getElementById('hostname').href = NETDATA.serverDefault;
-            document.title = options.hostname + ' netdata dashboard';
+            if(data !== null) {
+                options.hostname = data.hostname;
+                options.data = data;
+
+                // create a chart_by_name index
+                data.charts_by_name = {};
+                var charts = data.charts;
+                var x;
+                for(x in charts) {
+                    var chart = charts[x];
+                    data.charts_by_name[chart.name] = chart;
+                }
 
-            renderChartsAndMenu(data);
+                // update the dashboard hostname
+                document.getElementById('hostname').innerHTML = options.hostname;
+                document.getElementById('hostname').href = NETDATA.serverDefault;
 
-            // prepare our DOM
-//          prepareScreen(data);
+                // update the dashboard title
+                document.title = options.hostname + ' netdata dashboard';
 
-            // due to affix issues, prepareScreen() will unpause
-            // netdata as needed
+                // render all charts
+                renderChartsAndMenu(data);
+            }
         });
     });
 }
@@ -2453,7 +2959,6 @@ function checkForUpdate(callback) {
     return null;
 }
 
-var updateBlinkCounter = 0;
 function notifyForUpdate(force) {
     versionLog('<p>checking for updates...</p>');
 
@@ -2494,16 +2999,7 @@ function notifyForUpdate(force) {
 
             versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: ' + sha2.toString() + '</p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/firehol/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>');
 
-            function updateButtonBlink() {
-                updateBlinkCounter--;
-                if(updateBlinkCounter > 0)
-                    $('#updateButton').fadeOut(500).fadeIn(500, updateButtonBlink);
-            }
-
-            if(updateBlinkCounter === 0) {
-                updateBlinkCounter = 300;
-                updateButtonBlink();
-            }
+            document.getElementById('update_badge').innerHTML = '!';
         }
 
         if(save)
@@ -2687,7 +3183,7 @@ function finalizePage() {
     /* activate bootstrap scrollspy (needed for sidebar) */
     $(document.body).scrollspy({
         target: '#sidebar',
-        offset: $(window).height() / 3 // controls the diff of the <hX> element to the top, to select it
+        offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
     });
 
     // change the URL based on the current position of the screen
@@ -2772,6 +3268,18 @@ function finalizePage() {
         notifyForUpdate(true);
     });
 
+    $('#alarmsModal').on('shown.bs.modal', function() {
+        NETDATA.pause(alarmsUpdateModal);
+    });
+
+    $('#alarmsModal').on('hidden.bs.modal', function() {
+        NETDATA.unpause();
+        document.getElementById('alarms_active').innerHTML =
+                document.getElementById('alarms_all').innerHTML =
+                document.getElementById('alarms_log').innerHTML =
+                        'loading...';
+    });
+
     $('#deleteRegistryModal').on('hidden.bs.modal', function() {
         deleteRegistryGuid = null;
     });