mirror of
https://github.com/netdata/netdata.git
synced 2025-04-17 03:02:41 +00:00
add userstats charts for mysql (#6118)
* add userstats charts for mysql
This commit is contained in:
parent
dd1ddace10
commit
6fc971fe4d
2 changed files with 145 additions and 2 deletions
collectors/python.d.plugin/mysql
|
@ -218,6 +218,24 @@ It will produce following charts (if data is available):
|
|||
45. **Flow Control** in ms
|
||||
* paused
|
||||
|
||||
46. **Users CPU time** in percentage
|
||||
* users
|
||||
|
||||
**Per user statistics:**
|
||||
|
||||
1. **Rows Operations** in operations/s
|
||||
* read
|
||||
* send
|
||||
* updated
|
||||
* inserted
|
||||
* deleted
|
||||
|
||||
2. **Commands** in commands/s
|
||||
* select
|
||||
* update
|
||||
* other
|
||||
|
||||
|
||||
### configuration
|
||||
|
||||
You can provide, per server, the following:
|
||||
|
@ -234,7 +252,7 @@ You can provide, per server, the following:
|
|||
- ca: the path name of the Certificate Authority (CA) certificate file. This option, if used, must specify the same certificate used by the server.
|
||||
- capath: the path name of the directory that contains trusted SSL CA certificate files.
|
||||
- cipher: the list of permitted ciphers for SSL encryption.
|
||||
|
||||
|
||||
Here is an example for 3 servers:
|
||||
|
||||
```yaml
|
||||
|
@ -260,6 +278,8 @@ remote:
|
|||
|
||||
If no configuration is given, module will attempt to connect to mysql server via unix socket at `/var/run/mysqld/mysqld.sock` without password and with username `root`
|
||||
|
||||
`userstats` graph works only if you enable such plugin in MariaDB server and set proper mysql priviliges (SUPER or PROCESS). For more detail please check [MariaDB User Statistics page](https://mariadb.com/kb/en/library/user-statistics/)
|
||||
|
||||
---
|
||||
|
||||
[]()
|
||||
|
|
|
@ -11,6 +11,7 @@ from bases.FrameworkServices.MySQLService import MySQLService
|
|||
QUERY_GLOBAL = 'SHOW GLOBAL STATUS;'
|
||||
QUERY_SLAVE = 'SHOW SLAVE STATUS;'
|
||||
QUERY_VARIABLES = 'SHOW GLOBAL VARIABLES LIKE \'max_connections\';'
|
||||
QUERY_USER_STATISTICS = 'SHOW USER_STATISTICS;'
|
||||
|
||||
GLOBAL_STATS = [
|
||||
'Bytes_received',
|
||||
|
@ -150,6 +151,18 @@ SLAVE_STATS = [
|
|||
('Slave_IO_Running', slave_running)
|
||||
]
|
||||
|
||||
USER_STATISTICS = [
|
||||
'Select_commands',
|
||||
'Update_commands',
|
||||
'Other_commands',
|
||||
'Cpu_time',
|
||||
'Rows_read',
|
||||
'Rows_sent',
|
||||
'Rows_deleted',
|
||||
'Rows_inserted',
|
||||
'Rows_updated'
|
||||
]
|
||||
|
||||
VARIABLES = [
|
||||
'max_connections'
|
||||
]
|
||||
|
@ -202,7 +215,8 @@ ORDER = [
|
|||
'galera_bytes',
|
||||
'galera_queue',
|
||||
'galera_conflicts',
|
||||
'galera_flow_control'
|
||||
'galera_flow_control',
|
||||
'userstats_cpu'
|
||||
]
|
||||
|
||||
CHARTS = {
|
||||
|
@ -579,10 +593,45 @@ CHARTS = {
|
|||
'lines': [
|
||||
['wsrep_flow_control_paused_ns', 'paused', 'incremental', 1, 1000000],
|
||||
]
|
||||
},
|
||||
'userstats_cpu': {
|
||||
'options': [None, 'Users CPU time', 'percentage', 'userstats', 'mysql.userstats_cpu', 'stacked'],
|
||||
'lines': []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def userstats_chart_template(name):
|
||||
order = [
|
||||
'userstats_rows_{0}'.format(name),
|
||||
'userstats_commands_{0}'.format(name)
|
||||
]
|
||||
family = 'userstats {0}'.format(name)
|
||||
|
||||
charts = {
|
||||
order[0]: {
|
||||
'options': [None, 'Rows Operations', 'operations/s', family, 'mysql.userstats_rows', 'stacked'],
|
||||
'lines': [
|
||||
['userstats_{0}_Rows_read'.format(name), 'read', 'incremental'],
|
||||
['userstats_{0}_Rows_send'.format(name), 'send', 'incremental'],
|
||||
['userstats_{0}_Rows_updated'.format(name), 'updated', 'incremental'],
|
||||
['userstats_{0}_Rows_inserted'.format(name), 'inserted', 'incremental'],
|
||||
['userstats_{0}_Rows_deleted'.format(name), 'deleted', 'incremental']
|
||||
]
|
||||
},
|
||||
order[1]: {
|
||||
'options': [None, 'Commands', 'commands/s', family, 'mysql.userstats_commands', 'stacked'],
|
||||
'lines': [
|
||||
['userstats_{0}_Select_commands'.format(name), 'select', 'incremental'],
|
||||
['userstats_{0}_Update_commands'.format(name), 'update', 'incremental'],
|
||||
['userstats_{0}_Other_commands'.format(name), 'other', 'incremental']
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
return order, charts
|
||||
|
||||
|
||||
class Service(MySQLService):
|
||||
def __init__(self, configuration=None, name=None):
|
||||
MySQLService.__init__(self, configuration=configuration, name=name)
|
||||
|
@ -592,6 +641,7 @@ class Service(MySQLService):
|
|||
global_status=QUERY_GLOBAL,
|
||||
slave_status=QUERY_SLAVE,
|
||||
variables=QUERY_VARIABLES,
|
||||
user_statistics=QUERY_USER_STATISTICS,
|
||||
)
|
||||
|
||||
def _get_data(self):
|
||||
|
@ -621,6 +671,12 @@ class Service(MySQLService):
|
|||
else:
|
||||
self.queries.pop('slave_status')
|
||||
|
||||
if 'user_statistics' in raw_data:
|
||||
if raw_data['user_statistics'][0]:
|
||||
to_netdata.update(self.get_userstats(raw_data))
|
||||
else:
|
||||
self.queries.pop('user_statistics')
|
||||
|
||||
if 'variables' in raw_data:
|
||||
variables = dict(raw_data['variables'][0])
|
||||
for key in VARIABLES:
|
||||
|
@ -628,3 +684,70 @@ class Service(MySQLService):
|
|||
to_netdata[key] = variables[key]
|
||||
|
||||
return to_netdata or None
|
||||
|
||||
# raw_data['user_statistics'] contains the following data structure:
|
||||
# (
|
||||
# (
|
||||
# ('netdata', 42L, 0L, 1264L, 3.111252999999968, 2.968510299999994, 110267L, 19741424L, 0L, 0L, 1265L, 0L,
|
||||
# 0L, 0L, 3L, 0L, 1301L, 0L, 0L, 7633L, 0L, 83L, 44L, 0L, 0L),
|
||||
# ('root', 60L, 0L, 184L, 0.22856499999999966, 0.1601419999999998, 11605L, 1516513L, 0L, 9L, 220L, 0L, 2L, 1L,
|
||||
# 6L, 4L,127L, 0L, 0L, 45L, 0L, 45L, 0L, 0L, 0L)
|
||||
# ),
|
||||
# (
|
||||
# ('User', 253, 9, 128, 128, 0, 0),
|
||||
# ('Total_connections', 3, 2, 11, 11, 0, 0),
|
||||
# ('Concurrent_connections', 3, 1, 11, 11, 0, 0),
|
||||
# ('Connected_time', 3, 4, 11, 11, 0, 0),
|
||||
# ('Busy_time', 5, 21, 21, 21, 31, 0),
|
||||
# ('Cpu_time', 5, 18, 21, 21, 31, 0),
|
||||
# ('Bytes_received', 8, 6, 21, 21, 0, 0),
|
||||
# ('Bytes_sent', 8, 8, 21, 21, 0, 0),
|
||||
# ('Binlog_bytes_written', 8, 1, 21, 21, 0, 0),
|
||||
# ('Rows_read', 8, 1, 21, 21, 0, 0),
|
||||
# ('Rows_sent', 8, 4, 21, 21, 0, 0),
|
||||
# ('Rows_deleted', 8, 1, 21, 21, 0, 0),
|
||||
# ('Rows_inserted', 8, 1, 21, 21, 0, 0),
|
||||
# ('Rows_updated', 8, 1, 21, 21, 0, 0),
|
||||
# ('Select_commands', 8, 1, 21, 21, 0, 0),
|
||||
# ('Update_commands', 8, 1, 21, 21, 0, 0),
|
||||
# ('Other_commands', 8, 4, 21, 21, 0, 0),
|
||||
# ('Commit_transactions', 8, 1, 21, 21, 0, 0),
|
||||
# ('Rollback_transactions', 8, 1, 21, 21, 0, 0),
|
||||
# ('Denied_connections', 8, 4, 21, 21, 0, 0),
|
||||
# ('Lost_connections', 8, 1, 21, 21, 0, 0),
|
||||
# ('Access_denied', 8, 2, 21, 21, 0, 0),
|
||||
# ('Empty_queries', 8, 2, 21, 21, 0, 0),
|
||||
# ('Total_ssl_connections', 8, 1, 21, 21, 0, 0),
|
||||
# ('Max_statement_time_exceeded', 8, 1, 21, 21, 0, 0)),
|
||||
# )
|
||||
def get_userstats(self, raw_data):
|
||||
data = dict()
|
||||
userstats_vars = [e[0] for e in raw_data['user_statistics'][1]]
|
||||
for i, _ in enumerate(raw_data['user_statistics'][0]):
|
||||
user_name = raw_data['user_statistics'][0][i][0]
|
||||
userstats = dict(zip(userstats_vars, raw_data['user_statistics'][0][i]))
|
||||
|
||||
if len(self.charts) > 0:
|
||||
if ('userstats_{0}_Cpu_time'.format(user_name)) not in self.charts['userstats_cpu']:
|
||||
self.add_userstats_dimensions(user_name)
|
||||
self.create_new_userstats_charts(user_name)
|
||||
|
||||
for key in USER_STATISTICS:
|
||||
if key in userstats:
|
||||
data['userstats_{0}_{1}'.format(user_name, key)] = userstats[key]
|
||||
|
||||
return data
|
||||
|
||||
def add_userstats_dimensions(self, name):
|
||||
self.charts['userstats_cpu'].add_dimension(['userstats_{0}_Cpu_time'.format(name), name, 'incremental', 100, 1])
|
||||
|
||||
def create_new_userstats_charts(self, tube):
|
||||
order, charts = userstats_chart_template(tube)
|
||||
|
||||
for chart_name in order:
|
||||
params = [chart_name] + charts[chart_name]['options']
|
||||
dimensions = charts[chart_name]['lines']
|
||||
|
||||
new_chart = self.charts.add_chart(params)
|
||||
for dimension in dimensions:
|
||||
new_chart.add_dimension(dimension)
|
||||
|
|
Loading…
Add table
Reference in a new issue