info: number of metrics lost due to repeating failures to contact the backend server
to: dba
- alarm: backend_slow
- on: netdata.backend_latency
- units: %
- calc: $latency * 100 / ($update_every * 1000)
- every: 10s
- warn: $this > 50
- crit: $this > 100
- delay: down 5m multiplier 1.5 max 1h
- info: the percentage of time between iterations needed by the backend time to process the data sent by netdata
- to: dba
+# this chart has been removed from netdata
+# alarm: backend_slow
+# on: netdata.backend_latency
+# units: %
+# calc: $latency * 100 / ($update_every * 1000)
+# every: 10s
+# warn: $this > 50
+# crit: $this > 100
+# delay: down 5m multiplier 1.5 max 1h
+# info: the percentage of time between iterations needed by the backend time to process the data sent by netdata
+# to: dba
delay: down 5m multiplier 1.5 max 1h
info: number of seconds since the last successful data collection
to: dba
+
+
+# -----------------------------------------------------------------------------
+# slow queries
+
+template: mysql_10s_slow_queries
+ on: mysql.queries
+ lookup: sum -10s of slow_queries
+ units: slow queries
+ every: 10s
+ warn: $this > (($status >= $WARNING) ? (5) : (10))
+ crit: $this > (($status == $CRITICAL) ? (10) : (20))
+ delay: down 5m multiplier 1.5 max 1h
+ info: number of mysql slow queries over the last 10 seconds
+ to: dba
+
+
+# -----------------------------------------------------------------------------
+# lock waits
+
+template: mysql_10s_table_locks_immediate
+ on: mysql.table_locks
+ lookup: sum -10s absolute of immediate
+ units: immediate locks
+ every: 10s
+ info: number of table immediate locks over the last 10 seconds
+ to: dba
+
+template: mysql_10s_table_locks_waited
+ on: mysql.table_locks
+ lookup: sum -10s absolute of waited
+ units: waited locks
+ every: 10s
+ info: number of table waited locks over the last 10 seconds
+ to: dba
+
+template: mysql_10s_waited_locks_ratio
+ on: mysql.table_locks
+ calc: ($mysql_10s_table_locks_waited * 100) / ($mysql_10s_table_locks_waited + $mysql_10s_table_locks_immediate)
+ units: %
+ every: 10s
+ warn: $this > (($status >= $WARNING) ? (10) : (25))
+ crit: $this > (($status == $CRITICAL) ? (25) : (50))
+ delay: down 30m multiplier 1.5 max 1h
+ info: the ratio of mysql waited table locks, for the last 10 seconds
+ to: dba
+
+
+# -----------------------------------------------------------------------------
+# replication
+
+template: mysql_replication
+ on: mysql.slave_status
+ calc: ($sql_running == -1 OR $io_running == -1)?0:1
+ units: status
+ every: 10s
+ crit: $this == 0
+ delay: down 5m multiplier 1.5 max 1h
+ info: checks if mysql replication has stopped
+ to: dba
+
+template: mysql_replication_lag
+ on: mysql.slave_behind
+ calc: $seconds
+ units: seconds
+ every: 10s
+ warn: $this > (($status >= $WARNING) ? (5) : (10))
+ crit: $this > (($status == $CRITICAL) ? (10) : (30))
+ delay: down 15m multiplier 1.5 max 1h
+ info: the number of seconds mysql replication is behind this master
+ to: dba
+
['1fa47f32ab52a22f8e7087cae85dd25e']='health.d/net.conf'
['20be73f473e59bc7de1fe61d53466aba']='health.d/ram.conf'
['21924a6ab8008d16ffac340f226ebad9']='python.d/nginx.conf'
+ ['219c5bb81965fa17d4940d4aa343c282']='health.d/mysql.conf'
['22952dbf42647c583b005054b23b545f']='health.d/disks.conf'
['22ceb822983134a7ca67343241f30341']='health.d/disks.conf'
['2385e5d35b440619621c4af62492d91b']='health.d/disks.conf'
['6b917300747e7e8314844237e2462261']='python.d/apache_cache.conf'
['6bf0de6e3b251b765b10a71d8c5c319d']='python.d/apache.conf'
['6cba40e32a7e98a98c31a209913839cc']='python.d/nginx_log.conf'
+ ['6d02c2dd0863e09ad9dbba53e3b58116']='health.d/mysql.conf'
+ ['6ea958ca521e0514af57c08b518d8c5c']='health.d/backend.conf'
['70105b1744a8e13f49083d7f1981aea2']='python.d/ipfs.conf'
['707a63f53f4b32e01d134ae90ba94aad']='health_alarm_notify.conf'
['707a63f53f4b32e01d134ae90ba94aad']='health_email_recipients.conf'
['899bcb0b3f4375b0a1280296be930201']='health.d/named.conf'
['89fb3cbb223be4fa0cb676cfa3b07055']='health.d/backend.conf'
['8a1b95d375992d7b11330a0ac46f369c']='health.d/disks.conf'
+ ['8a66a3085ad8892a002ff39b18b2cb07']='python.d/fail2ban.conf'
['8c1d41e2c88aeca78bc319ed74c8748c']='python.d/phpfpm.conf'
['8d0552371a7c9725a04196fa560813d1']='health.d/cpu.conf'
['8dc0bd0a70b5117454bd5f5b98f91c2c']='health.d/disks.conf'
['919911d13901d60a7580f5dfd7fc87bb']='health.d/ram.conf'
['91c757ef6be3abdb86906d9dbb9c217a']='fping.conf'
['91cf3b3d42cac969b8b3fd4f531ecfb3']='python.d/squid.conf'
+ ['9542f80def48ba105190f6cdaa18248e']='health.d/mysql.conf'
['97eee7a30e6419df4537242e9d4a719d']='health.d/mysql.conf'
['97f337eb96213f3ede05e522e3743a6c']='python.d/memcached.conf'
['99a3de85d1e7826ed64a5f8576712e5d']='python.d.conf'
# query executed on MySQL server
QUERY = "SHOW GLOBAL STATUS;"
+QUERY_SLAVE = "SHOW SLAVE STATUS;"
ORDER = ['net',
'queries',
'innodb_buffer_pool_read_ahead', 'innodb_buffer_pool_reqs', 'innodb_buffer_pool_ops',
'qcache_ops', 'qcache', 'qcache_freemem', 'qcache_memblocks',
'key_blocks', 'key_requests', 'key_disk_ops',
- 'files', 'files_rate']
+ 'files', 'files_rate', 'slave_behind', 'slave_status']
CHARTS = {
'net': {
["Connection_errors_peer_address", "peer_addr", "incremental"],
["Connection_errors_select", "select", "incremental"],
["Connection_errors_tcpwrap", "tcpwrap", "incremental"]
+ ]},
+ 'slave_behind': {
+ 'options': [None, 'Slave Behind Seconds', 'seconds', 'slave', 'mysql.slave_behind', 'line'],
+ 'lines': [
+ ["slave_behind", "seconds", "absolute"]
+ ]},
+ 'slave_status': {
+ 'options': [None, 'Slave Status', 'status', 'slave', 'mysql.slave_status', 'line'],
+ 'lines': [
+ ["slave_sql", "sql_running", "absolute"],
+ ["slave_io", "io_running", "absolute"]
]}
-
}
self.order = ORDER
self.definitions = CHARTS
self.connection = None
+ self.do_slave = -1
def _parse_config(self, configuration):
"""
self.error("problem connecting to server:", e)
raise RuntimeError
+ def _get_data_slave(self):
+ """
+ Get slave raw data from MySQL server
+ :return: dict
+ """
+ if self.connection is None:
+ try:
+ self._connect()
+ except RuntimeError:
+ return None
+
+ slave_data = None
+ slave_raw_data = None
+ try:
+ cursor = self.connection.cursor()
+ if cursor.execute(QUERY_SLAVE):
+ slave_raw_data = dict(list(zip([elem[0] for elem in cursor.description], cursor.fetchone())))
+
+ except MySQLdb.OperationalError as e:
+ self.debug("Reconnecting for query", QUERY_SLAVE, ":", str(e))
+ try:
+ self._connect()
+ cursor = self.connection.cursor()
+ if cursor.execute(QUERY_SLAVE):
+ slave_raw_data = dict(list(zip([elem[0] for elem in cursor.description], cursor.fetchone())))
+ except Exception as e:
+ self.error("retried, but cannot execute query", QUERY_SLAVE, ":", str(e))
+ self.connection.close()
+ self.connection = None
+ return None
+
+ except Exception as e:
+ self.error("cannot execute query", QUERY_SLAVE, ":", str(e))
+ self.connection.close()
+ self.connection = None
+ return None
+
+ if slave_raw_data is not None:
+ slave_data = {
+ 'slave_behind': None,
+ 'slave_sql': None,
+ 'slave_io': None
+ }
+
+ try:
+ slave_data['slave_behind'] = int(slave_raw_data.setdefault('Seconds_Behind_Master', -1))
+ except:
+ slave_data['slave_behind'] = None
+
+ try:
+ slave_data['slave_sql'] = 1 if slave_raw_data.get('Slave_SQL_Running') == 'Yes' else -1
+ except:
+ slave_data['slave_sql'] = None
+
+ try:
+ slave_data['slave_io'] = 1 if slave_raw_data.get('Slave_IO_Running') == 'Yes' else -1
+ except:
+ slave_data['slave_io'] = None
+
+ return slave_data
+
def _get_data(self):
"""
Get raw data from MySQL server
cursor = self.connection.cursor()
cursor.execute(QUERY)
raw_data = cursor.fetchall()
+
except MySQLdb.OperationalError as e:
- self.debug("Reconnecting due to", str(e))
- self._connect()
- cursor = self.connection.cursor()
- cursor.execute(QUERY)
- raw_data = cursor.fetchall()
+ self.debug("Reconnecting for query", QUERY, ":", str(e))
+ try:
+ self._connect()
+ cursor = self.connection.cursor()
+ cursor.execute(QUERY)
+ raw_data = cursor.fetchall()
+ except Exception as e:
+ self.error("retried, but cannot execute query", QUERY, ":", str(e))
+ self.connection.close()
+ self.connection = None
+ return None
+
except Exception as e:
- self.error("cannot execute query.", e)
+ self.error("cannot execute query", QUERY, ":", str(e))
self.connection.close()
self.connection = None
return None
data = dict(raw_data)
+
+ # check for slave data
+ # the first time is -1 (so we do it)
+ # then it is set to 1 or 0 and we keep it like that
+ if self.do_slave != 0:
+ slave_data = self._get_data_slave()
+ if slave_data is not None:
+ data.update(slave_data)
+ if self.do_slave == -1:
+ self.do_slave = 1
+ else:
+ if self.do_slave == -1:
+ self.error("replication metrics will be disabled - please allow netdata to collect them.")
+ self.do_slave = 0
+
+ # do calculations
try:
data["Thread_cache_misses"] = int(data["Threads_created"] * 10000 / float(data["Connections"]))
except:
- data["Thread_cache_misses"] = 0
+ data["Thread_cache_misses"] = None
return data
.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
background-color: #aaa; /* scrollbar color when dragged away */
- height: 4px;
+ height: 5px;
}
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
background-color: #aaa; /* scrollbar color when dragged away */
- width: 4px;
+ width: 5px;
}
.ps-container > .ps-scrollbar-x-rail {
transition: background-color .2s linear, opacity .2s linear;
bottom: 0px;
/* there must be 'bottom' for ps-scrollbar-x-rail */
- height: 8px;
+ height: 15px;
}
.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;
bottom: 2px;
/* there must be 'bottom' for ps-scrollbar-x */
- height: 4px; /* the width of the scrollbar */
+ height: 5px; /* the width of the scrollbar */
}
.ps-container > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-container > .ps-scrollbar-x-rail:active > .ps-scrollbar-x {
transition: background-color .2s linear, opacity .2s linear;
right: 0;
/* there must be 'right' for ps-scrollbar-y-rail */
- width: 8px;
+ width: 15px;
}
.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;
right: 2px;
/* there must be 'right' for ps-scrollbar-y */
- width: 4px; /* the width of the scrollbar */
+ width: 5px; /* the width of the scrollbar */
}
.ps-container > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-container > .ps-scrollbar-y-rail:active > .ps-scrollbar-y {
- width: 4px;
+ width: 5px;
}
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
background-color: #bbb; /* scrollbar color when dragged */
- height: 4px;
+ height: 5px;
}
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
background-color: #bbb; /* scrollbar color when dragged */
- width: 4px;
+ width: 5px;
}
.ps-container:hover > .ps-scrollbar-x-rail,
NETDATA.themes = {
white: {
bootstrap_css: NETDATA.serverDefault + 'css/bootstrap-3.3.7.css',
- dashboard_css: NETDATA.serverDefault + 'dashboard.css?v20161229-1',
+ dashboard_css: NETDATA.serverDefault + 'dashboard.css?v20161229-2',
background: '#FFFFFF',
foreground: '#000000',
grid: '#F0F0F0',
},
slate: {
bootstrap_css: NETDATA.serverDefault + 'css/bootstrap-slate-flat-3.3.7.css?v20161229-1',
- dashboard_css: NETDATA.serverDefault + 'dashboard.slate.css?v20161229-1',
+ dashboard_css: NETDATA.serverDefault + 'dashboard.slate.css?v20161229-2',
background: '#272b30',
foreground: '#C8C8C8',
grid: '#283236',
.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
background-color: #aaa; /* scrollbar color when dragged away */
- height: 4px;
+ height: 5px;
}
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
background-color: #aaa; /* scrollbar color when dragged away */
- width: 4px;
+ width: 5px;
}
.ps-container > .ps-scrollbar-x-rail {
transition: background-color .2s linear, opacity .2s linear;
bottom: 0px;
/* there must be 'bottom' for ps-scrollbar-x-rail */
- height: 8px;
+ height: 15px;
}
.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;
bottom: 2px;
/* there must be 'bottom' for ps-scrollbar-x */
- height: 4px; /* the width of the scrollbar */
+ height: 5px; /* the width of the scrollbar */
}
.ps-container > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-container > .ps-scrollbar-x-rail:active > .ps-scrollbar-x {
- height: 4px;
+ height: 5px;
}
.ps-container > .ps-scrollbar-y-rail {
transition: background-color .2s linear, opacity .2s linear;
right: 0;
/* there must be 'right' for ps-scrollbar-y-rail */
- width: 8px;
+ width: 15px;
}
.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;
right: 2px;
/* there must be 'right' for ps-scrollbar-y */
- width: 4px; /* the width of the scrollbar */
+ width: 5px; /* the width of the scrollbar */
}
.ps-container > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-container > .ps-scrollbar-y-rail:active > .ps-scrollbar-y {
- width: 4px;
+ width: 5px;
}
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
background-color: #bbb; /* scrollbar color when dragged */
- height: 4px;
+ height: 5px;
}
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
background-color: #bbb; /* scrollbar color when dragged */
- width: 4px;
+ width: 5px;
}
.ps-container:hover > .ps-scrollbar-x-rail,
function alarm_to_html(alarm, full) {
var chart = options.data.charts[alarm.chart];
+ var has_alarm = ((typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined')?true:false);
var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/> <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/> <br/><span style="font-size: 18px">' + alarm.info + '</span><br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small> <a href="#" onClick="NETDATA.alarms.scrollToChart(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;">jump to chart</a></small></td>'
+ '<td><table class="table">'
}
html += '<tr><td width="10%" style="text-align:right">check every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>'
- + '<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'
+ + ((has_alarm === true)?('<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</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>';
});
Ps.update(sidebar);
- var registry = document.getElementById('registry-dropdown');
+ var registry = document.getElementById('myNetdataDropdownUL');
Ps.initialize(registry, {
- wheelSpeed: 0.5,
+ wheelSpeed: 1,
wheelPropagation: false,
swipePropagation: false,
minScrollbarLength: null,
Ps.update(sidebar);
Ps.update(registry);
};
+
+ $('#myNetdataDropdownParent')
+ .on('show.bs.dropdown', function () {
+ NETDATA.pause(function() {});
+ })
+ .on('shown.bs.dropdown', function () {
+ Ps.update(registry);
+ })
+ .on('hidden.bs.dropdown', function () {
+ NETDATA.unpause();
+ });
}
function resetDashboardOptions() {
<div class="container">
<nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;">
<ul class="nav navbar-nav">
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a>
- <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu" id="registry-dropdown">
+ <li class="dropdown" id="myNetdataDropdownParent">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
+ <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu" id="myNetdataDropdownUL">
<div class="row">
<div class="col-sm-6" style="width: 85%; padding-right: 0;">
<ul id="mynetdata_servers" class="multi-column-dropdown">
<li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i> <span class="hidden-sm">Alarms </span><span id="alarms_count_badge" class="badge"></span></a></li>
<li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal" title="dashboard settings"><i class="fa fa-sliders"></i> <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> <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> <span class="hidden-sm hidden-md">Update</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 class="hidden-sm hidden-md">Update </span><span id="update_badge" class="badge"></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> <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="#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>
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
<ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu">
<li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
</ul>
</div>
</body>
</html>
-<script type="text/javascript" src="dashboard.js?v20161229-3"></script>
+<script type="text/javascript" src="dashboard.js?v20161229-4"></script>