pull/632/head
Mr Chen 5 months ago
parent a5bc06acf6
commit 00002a8540
  1. 99
      plugins/data_query/sql_mysql.py
  2. 10
      plugins/data_query/static/html/index.html
  3. 179
      plugins/data_query/static/js/app.js
  4. 38
      plugins/task_manager/js/task_manager.js
  5. 8
      web/core/orm.py

@ -90,7 +90,7 @@ class nosqlMySQL():
keys = ["bind_ip", "port"]
result['host'] = '127.0.0.1'
rep = 'port\s*=\s*(.*)'
rep = r'port\s*=\s*(.*)'
port_re = re.search(rep, my_content)
if port_re:
@ -98,7 +98,7 @@ class nosqlMySQL():
else:
result['port'] = 3306
socket_rep = 'socket\s*=\s*(.*)'
socket_rep = r'socket\s*=\s*(.*)'
socket_re = re.search(socket_rep, my_content)
if socket_re:
result['socket'] = socket_re.groups()[0].strip()
@ -281,6 +281,88 @@ class nosqlMySQLCtr():
rdata['list'] = result
return mw.returnData(True,'ok', rdata)
def getNetRow(self, my_instance):
row = {}
data = my_instance.find("SHOW GLOBAL STATUS LIKE 'Com_select'")
row['select'] = data['Value']
data = my_instance.find("SHOW GLOBAL STATUS LIKE 'Com_insert'")
row['insert'] = data['Value']
data = my_instance.find("SHOW GLOBAL STATUS LIKE 'Com_update'")
row['update'] = data['Value']
data = my_instance.find("SHOW GLOBAL STATUS LIKE 'Com_delete'")
row['delete'] = data['Value']
data = my_instance.find("SHOW GLOBAL STATUS LIKE 'Bytes_received'")
row['recv_bytes'] = data['Value']
data = my_instance.find("SHOW GLOBAL STATUS LIKE 'Bytes_sent'")
row['send_bytes'] = data['Value']
return row
def getNetList(self, args):
from datetime import datetime
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
rdata = []
row = {}
row1 = self.getNetRow(my_instance)
# 等待1秒
time.sleep(1)
row2 = self.getNetRow(my_instance)
data = my_instance.find("SHOW GLOBAL VARIABLES LIKE 'max_connections'")
row['max_conn'] = data['Value']
data = my_instance.find("SHOW GLOBAL STATUS LIKE 'Threads_connected'")
row['conn'] = data['Value']
current_time = datetime.now()
row['current_time'] = current_time.strftime("%Y-%m-%d %H:%M:%S")
row['select'] = int(row2['select']) - int(row1['select'])
row['insert'] = int(row2['insert']) - int(row1['insert'])
row['update'] = int(row2['update']) - int(row1['update'])
row['delete'] = int(row2['delete']) - int(row1['delete'])
recv_per_second = int(row2['recv_bytes']) - int(row1['recv_bytes'])
send_per_second = int(row2['send_bytes']) - int(row1['send_bytes'])
# 将每秒接收和发送数据量从字节转换为兆比特
row['recv_mbps'] = "{:.2f}".format(recv_per_second * 8 / 1000000) + " MBit/s"
row['send_mbps'] = "{:.2f}".format(send_per_second * 8 / 1000000) + " MBit/s"
rdata.append(row)
return mw.returnData(True, 'ok', rdata)
def getTopnList(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
is_performance_schema = my_instance.find("SELECT @@performance_schema")
if is_performance_schema["@@performance_schema"] == 0:
msg = "performance_schema参数未开启。\n"
msg += "在my.cnf配置文件里添加performance_schema=1,并重启mysqld进程生效。"
return mw.returnData(False, msg)
my_instance.execute("SET @sys.statement_truncate_len=4096")
data = my_instance.query("select query,db,last_seen,exec_count,max_latency,avg_latency from sys.statement_analysis order by exec_count desc, last_seen desc limit 10")
if data is None:
return mw.returnData(False, "查询失败!")
return mw.returnData(True, 'ok', data)
# ---------------------------------- run ----------------------------------
# 获取 mysql 列表
def get_db_list(args):
@ -308,6 +390,19 @@ def get_stats_list(args):
t = nosqlMySQLCtr()
return t.showStatsList(args)
# 查询执行次数最频繁的前N条SQL语句
def get_topn_list(args):
t = nosqlMySQLCtr()
return t.getTopnList(args)
# MySQL服务器的QPS/TPS/网络带宽指标
def get_net_list(args):
t = nosqlMySQLCtr()
return t.getNetList(args)
# 测试
def test(args):

@ -51,9 +51,11 @@
<input name="mysql_field_value" type="text" class="bt-input-text" placeholder="请输入查找内容">
</div>
<button type="button" class="mysql_find btn btn-success btn-sm mr5 ml5" style="float:right;">
<span>查找</span>
</button>
<div style="float:left;">
<button type="button" class="mysql_find btn btn-success btn-sm mr5 ml5" >查找</button>
<button id="mysql_common" type="button" class="mysql_find btn btn-success btn-sm mr5 ml5">常用功能</button>
</div>
</div>
</div>
@ -78,6 +80,8 @@
</div>
</div>
<hr style="border:none;" />
<div class="col-md-12" style="padding-left: 3px;">
<div id="mysql_list_tab" style="padding-top:0px;">
<div class="tab-nav">

@ -267,6 +267,185 @@ function initTabMySQL(){
var name = $(this).data('name');
mysqlRunMysqlTab(name);
});
mysqlCommonFunc();
}
function mysqlCommonFuncMysqlNSQL(){
function renderSQL(){
var sid = mysqlGetSid();
myPostCBN('get_topn_list',{'sid':sid} ,function(rdata){
var data = rdata.data;
if (data['status']){
var items = data.data;
var tbody = '';
for (var i = 0; i < items.length; i++) {
var t = '<tr>';
t += '<td>'+items[i].query+'</td>';
t += '<td>'+items[i].db+'</td>';
t += '<td>'+items[i].last_seen+'</td>';
t += '<td>'+items[i].exec_count+'</td>';
t += '<td>'+items[i].max_latency+'</td>';
t += '<td>'+items[i].avg_latency+'</td>';
t += '</tr>';
tbody += t;
}
$('#topn_list tbody').html(tbody);
} else {
layer.msg(data.msg,{icon:2});
}
});
}
var sql_timer = null;
layer.open({
type: 1,
title: "查询执行次数最频繁的前N条SQL语句",
area: ['1200px', '500px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20 divtable taskdivtable">\
<div class="mr20 pull-left" style="border-right: 1px solid #ccc; padding-right: 20px;">\
<div class="ss-text pull-left">\
<em>实时监控</em>\
<div class="ssh-item">\
<input class="btswitch btswitch-ios" id="real_time_monitoring" type="checkbox">\
<label id="real_time_label" class="btswitch-btn" for="real_time_monitoring"></label>\
</div>\
</div>\
</div>\
<hr />\
<table class="table table-hover" id="topn_list">\
<thead>\
<th>SQL</th>\
<th style="width:100px;">数据名</th>\
<th>最近时间</th>\
<th style="width:100px;">总次数</th>\
<th style="width:100px;">最大时间</th>\
<th style="width:100px;">平均时间</th>\
</thead>\
<tbody></tbody>\
</table>\
</div>',
success:function(i,l){
renderSQL();
$('#real_time_label').click(function(){
sql_timer = setInterval(function(){
var t = $('#real_time_monitoring').is(':checked');
if (t){
renderSQL();
} else{
clearInterval(sql_timer);
}
}, 3000);
});
}
});
}
function mysqlCommonFuncMysqlNet(){
function renderSQL(){
var sid = mysqlGetSid();
myPostCBN('get_net_list',{'sid':sid} ,function(rdata){
var data = rdata.data;
if (data['status']){
var items = data.data;
var tbody = '';
for (var i = 0; i < items.length; i++) {
var t = '<tr>';
t += '<td>'+items[i]['current_time']+'</td>';
t += '<td>'+items[i]['select']+'</td>';
t += '<td>'+items[i]['insert']+'</td>';
t += '<td>'+items[i]['update']+'</td>';
t += '<td>'+items[i]['delete']+'</td>';
t += '<td>'+items[i]['conn']+'</td>';
t += '<td>'+items[i]['max_conn']+'</td>';
t += '<td>'+items[i]['recv_mbps']+'</td>';
t += '<td>'+items[i]['send_mbps']+'</td>';
t += '</tr>';
tbody += t;
}
$('#net_list tbody').html(tbody);
} else {
layer.msg(data.msg,{icon:2});
}
});
}
var sql_timer = null;
layer.open({
type: 1,
title: "MySQL服务器的QPS/TPS/网络带宽指标",
area: ['700px', '220px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20 divtable taskdivtable">\
<div class="mr20 pull-left" style="border-right: 1px solid #ccc; padding-right: 20px;">\
<div class="ss-text pull-left">\
<em>实时监控</em>\
<div class="ssh-item">\
<input class="btswitch btswitch-ios" id="real_qps_monitoring" type="checkbox">\
<label id="real_qps_label" class="btswitch-btn" for="real_qps_monitoring"></label>\
</div>\
</div>\
</div>\
<hr />\
<table class="table table-hover" id="net_list">\
<thead>\
<th style="width:160px;">时间</th>\
<th style="width:50px;">Select</th>\
<th style="width:50px;">Insert</th>\
<th style="width:50px;">Update</th>\
<th style="width:50px;">Delete</th>\
<th style="width:50px;">Conn</th>\
<th style="width:50px;">Max_conn</th>\
<th style="width:90px;">Recv</th>\
<th style="width:90px;">Send</th>\
</thead>\
<tbody></tbody>\
</table>\
</div>',
success:function(i,l){
renderSQL();
$('#real_qps_label').click(function(){
sql_timer = setInterval(function(){
var t = $('#real_qps_monitoring').is(':checked');
if (t){
renderSQL();
} else{
clearInterval(sql_timer);
}
}, 3000);
});
}
});
}
function mysqlCommonFunc(){
$('#mysql_common').click(function(){
layer.open({
type: 1,
title: "MySQL常用功能",
area: ['600px', '400px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20">\
<button id="mysql_top_nsql" type="button" class="btn btn-default btn-sm">查询执行次数最频繁的前N条SQL语句</button>\
<button id="mysql_net_stat" type="button" class="btn btn-default btn-sm">MySQL服务器的QPS/TPS/网络带宽指标</button>\
</div>',
success:function(i,l){
$('#mysql_top_nsql').click(function(){
mysqlCommonFuncMysqlNSQL();
});
$('#mysql_net_stat').click(function(){
mysqlCommonFuncMysqlNet();
});
}
});
});
}
function mysqlRunMysqlTab(name){

@ -506,25 +506,25 @@ function get_resource_list() {
buildRealProcess()
var tbody_tr = createProcessTable(true);
var tbody = '<thead>\
<tr style="cursor: pointer;">\
<th style="width:120px;" class="pro_name pro_ps" onclick="get_process_list(\'ps\',\'' + res_list[reverse] + '\')">应用名称</th>\
<th class="pro_pid" onclick="get_process_list(\'pid\',\'' + res_list[reverse] + '\')">PID</th>\
<th style="width:50px;"class="pro_threads" onclick="get_process_list(\'threads\',\'True\')">线程</th>\
<th style="width:60px;" class="pro_user" onclick="get_process_list(\'user\',\'' + res_list[reverse] + '\')">用户</th>\
<th style="width:70px;" class="pro_cpu_percent" onclick="get_process_list(\'cpu_percent\',\'True\')">CPU</th>\
<th style="width:70px;" class="pro_memory_used" onclick="get_process_list(\'memory_used\',\'True\')">内存</th>\
<th style="width:70px;" class="pro_io_read_speed" onclick="get_process_list(\'io_read_speed\',\'True\')">io读</th>\
<th style="width:70px;" class="pro_io_write_speed" onclick="get_process_list(\'io_write_speed\',\'True\')">io写</th>\
<th style="width:70px;" class="pro_up" onclick="get_process_list(\'up\',\'True\')">上行</th>\
<th style="width:70px;" class="pro_down" onclick="get_process_list(\'down\',\'True\')">下行</th>\
<th style="width:50px;" class="pro_connects" onclick="get_process_list(\'connects\',\'True\')">连接</th>\
<th style="width:50px;" class="pro_status" onclick="get_process_list(\'status\',\'' + res_list[reverse] + '\')">状态</th>\
<th style="width:50px;cursor:text">操作</th>\
</tr>\
</thead>\
<tbody>' + tbody_tr + '</tbody>'
$('#taskResourceTable').html(tbody);
$(".table-cont").css("height", "220px");
<tr style="cursor: pointer;">\
<th style="width:120px;" class="pro_name pro_ps" onclick="get_process_list(\'ps\',\'' + res_list[reverse] + '\')">应用名称</th>\
<th class="pro_pid" onclick="get_process_list(\'pid\',\'' + res_list[reverse] + '\')">PID</th>\
<th style="width:50px;"class="pro_threads" onclick="get_process_list(\'threads\',\'True\')">线程</th>\
<th style="width:60px;" class="pro_user" onclick="get_process_list(\'user\',\'' + res_list[reverse] + '\')">用户</th>\
<th style="width:70px;" class="pro_cpu_percent" onclick="get_process_list(\'cpu_percent\',\'True\')">CPU</th>\
<th style="width:70px;" class="pro_memory_used" onclick="get_process_list(\'memory_used\',\'True\')">内存</th>\
<th style="width:70px;" class="pro_io_read_speed" onclick="get_process_list(\'io_read_speed\',\'True\')">io读</th>\
<th style="width:70px;" class="pro_io_write_speed" onclick="get_process_list(\'io_write_speed\',\'True\')">io写</th>\
<th style="width:70px;" class="pro_up" onclick="get_process_list(\'up\',\'True\')">上行</th>\
<th style="width:70px;" class="pro_down" onclick="get_process_list(\'down\',\'True\')">下行</th>\
<th style="width:50px;" class="pro_connects" onclick="get_process_list(\'connects\',\'True\')">连接</th>\
<th style="width:50px;" class="pro_status" onclick="get_process_list(\'status\',\'' + res_list[reverse] + '\')">状态</th>\
<th style="width:50px;cursor:text">操作</th>\
</tr>\
</thead>\
<tbody>' + tbody_tr + '</tbody>';
$('#taskResourceTable').html(tbody);
$(".table-cont").css("height", "220px");
})
$("#load_average").html('')

@ -119,6 +119,12 @@ class ORM:
print(e)
return True
def find(self, sql):
d = self.query(sql)
if d is not None:
return d[0]
return None
def query(self, sql):
# 执行SQL语句返回数据集
if not self.__Conn():
@ -132,7 +138,7 @@ class ORM:
self.__Close()
return result
except Exception as ex:
return ex
return None
def __Close(self):
# 关闭连接

Loading…
Cancel
Save