Skip to content

Commit

Permalink
Redis添加会话管理支持 (#2816)
Browse files Browse the repository at this point in the history
  • Loading branch information
feiazifeiazi authored Sep 20, 2024
1 parent b1efe08 commit 58c0145
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 36 deletions.
20 changes: 5 additions & 15 deletions sql/db_diagnostic.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
def process(request):
instance_name = request.POST.get("instance_name")
command_type = request.POST.get("command_type")
request_kwargs = {
key: value for key, value in request.POST.items() if key != "command_type"
}

try:
instance = user_instances(request.user).get(instance_name=instance_name)
Expand All @@ -31,21 +34,8 @@ def process(request):

query_engine = get_engine(instance=instance)
query_result = None
if instance.db_type == "mysql":
query_result = query_engine.processlist(command_type)

elif instance.db_type == "mongo":
query_result = query_engine.current_op(command_type)
elif instance.db_type == "oracle":
query_result = query_engine.session_list(command_type)
else:
result = {
"status": 1,
"msg": "暂时不支持{}类型数据库的进程列表查询".format(instance.db_type),
"data": [],
}
return HttpResponse(json.dumps(result), content_type="application/json")

# processlist方法已提升为父类方法,简化此处的逻辑。进程添加新数据库支持时,改前端即可。
query_result = query_engine.processlist(command_type=command_type, **request_kwargs)
if query_result:
if not query_result.error:
processlist = query_result.to_dict()
Expand Down
4 changes: 4 additions & 0 deletions sql/engines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ def server_version(self):
"""返回引擎服务器版本,返回对象为tuple (x,y,z)"""
return tuple()

def processlist(self, command_type, **kwargs) -> ResultSet:
"""获取连接信息"""
return ResultSet()

def kill_connection(self, thread_id):
"""终止数据库连接"""

Expand Down
2 changes: 1 addition & 1 deletion sql/engines/cloud/aliyun_rds.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self, instance=None):
self.instance_name = instance.instance_name

# 将sql/aliyun_rds.py的函数迁移值此
def processlist(self, command_type):
def processlist(self, command_type, **kwargs):
if command_type is None or command_type == "":
command_type = "Query"

Expand Down
2 changes: 1 addition & 1 deletion sql/engines/mongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,7 @@ def fill_query_columns(cursor, columns):
cols.append(key)
return cols

def current_op(self, command_type):
def processlist(self, command_type, **kwargs):
"""
获取当前连接信息
Expand Down
2 changes: 1 addition & 1 deletion sql/engines/mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ def osc_control(self, **kwargs):
"""
return self.inc_engine.osc_control(**kwargs)

def processlist(self, command_type):
def processlist(self, command_type, **kwargs):
"""获取连接信息"""
base_sql = "select id, user, host, db, command, time, state, ifnull(info,'') as info from information_schema.processlist"
# escape
Expand Down
2 changes: 1 addition & 1 deletion sql/engines/oracle.py
Original file line number Diff line number Diff line change
Expand Up @@ -1451,7 +1451,7 @@ def execute(self, db_name=None, sql="", close_conn=True, parameters=None):
self.close()
return result

def session_list(self, command_type):
def processlist(self, command_type, **kwargs):
"""获取会话信息"""
base_sql = """select
s.sid,
Expand Down
15 changes: 15 additions & 0 deletions sql/engines/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ def query_check(self, db_name=None, sql="", limit_num=0):
result["msg"] = "禁止执行该命令!"
return result

def processlist(self, command_type, **kwargs):
"""获取连接信息"""
sql = "client list"
result_set = ResultSet(full_sql=sql)
conn = self.get_connection(db_name=0)
clients = conn.client_list()
# 根据空闲时间排序
sort_by = "idle"
reverse = False
clients = sorted(
clients, key=lambda client: client.get(sort_by), reverse=reverse
)
result_set.rows = clients
return result_set

def query(self, db_name=None, sql="", limit_num=0, close_conn=True, **kwargs):
"""返回 ResultSet"""
result_set = ResultSet(full_sql=sql)
Expand Down
45 changes: 41 additions & 4 deletions sql/engines/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,43 @@ def test_execute_workflow_success(self, _execute_command):
self.assertIsInstance(execute_result, ReviewSet)
self.assertEqual(execute_result.rows[0].__dict__.keys(), row.__dict__.keys())

@patch("sql.engines.redis.RedisEngine.get_connection")
def test_processlist(self, mock_get_connection):
"""测试 processlist 方法,模拟获取连接并返回客户端列表"""

# 模拟 Redis 连接的客户端列表
mock_conn = Mock()

return_value_mock = [
{"id": "1", "idle": 10, "name": "client_1"},
{"id": "2", "idle": 5, "name": "client_2"},
{"id": "3", "idle": 20, "name": "client_3"},
]
mock_conn.client_list.return_value = return_value_mock

# 设置 get_connection 返回模拟连接
mock_get_connection.return_value = mock_conn

# 创建 RedisEngine 实例
new_engine = RedisEngine(instance=self.ins)

# 调用 processlist 方法并测试其返回值
command_types = ["All"] # 假设支持的命令类型
for command_type in command_types:
result_set = new_engine.processlist(command_type=command_type)

# 验证返回值是 ResultSet 实例
self.assertIsInstance(result_set, ResultSet)

# 验证返回的客户端列表被正确排序
sorted_clients = sorted(
return_value_mock, key=lambda client: client.get("idle"), reverse=False
)
self.assertEqual(result_set.rows, sorted_clients)

# 验证 get_connection 是否被调用
mock_get_connection.assert_called()


class TestPgSQL(TestCase):
@classmethod
Expand Down Expand Up @@ -1497,11 +1534,11 @@ def test_execute(self, _connect, _cursor, _execute):
self.assertIsInstance(execute_result, ResultSet)

@patch("sql.engines.oracle.OracleEngine.query")
def test_session_list(self, _query):
def test_processlist(self, _query):
new_engine = OracleEngine(instance=self.ins)
_query.return_value = ResultSet()
for command_type in ["All", "Active", "Others"]:
r = new_engine.session_list(command_type)
r = new_engine.processlist(command_type)
self.assertIsInstance(r, ResultSet)

@patch("sql.engines.oracle.OracleEngine.query")
Expand Down Expand Up @@ -1803,7 +1840,7 @@ def test_fill_query_columns(self):
self.assertEqual(cols, ["_id", "title", "tags", "likes", "text", "author"])

@patch("sql.engines.mongo.MongoEngine.get_connection")
def test_current_op(self, mock_get_connection):
def test_processlist(self, mock_get_connection):
class Aggregate:
def __enter__(self):
yield {"client": "single_client"}
Expand All @@ -1817,7 +1854,7 @@ def __exit__(self, *arg, **kwargs):
mock_get_connection.return_value = mock_conn
command_types = ["Full", "All", "Inner", "Active"]
for command_type in command_types:
result_set = self.engine.current_op(command_type)
result_set = self.engine.processlist(command_type)
self.assertIsInstance(result_set, ResultSet)

@patch("sql.engines.mongo.MongoEngine.get_connection")
Expand Down
127 changes: 114 additions & 13 deletions sql/templates/dbdiagnostic.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<optgroup id="optgroup-mysql" label="MySQL"></optgroup>
<optgroup id="optgroup-mongo" label="MongoDB"></optgroup>
<optgroup id="optgroup-oracle" label="Oracle"></optgroup>
<optgroup id="optgroup-redis" label="Redis"></optgroup>
</select>
</div>
<div id="command-div" class="form-group">
Expand Down Expand Up @@ -326,6 +327,111 @@ <h4 class="modal-title text-danger">确定要终止所选会话吗?</h4>
return html.join('');
}
]
,[
'redis',
["All"],
[{
title: '', // 用于多选框
field: 'checkbox',
checkbox: true
}, {
title: 'Id',
field: 'id',
sortable: true
}, {
title: '远程地址',
field: 'addr',
sortable: true
}, {
title: '本地地址',
field: 'laddr',
sortable: true
}, {
title: '客户端名称',
field: 'name',
sortable: true
}, {
title: '用户',
field: 'user',
sortable: true
},
{
title: '数据库',
field: 'db',
sortable: true
}, {
title: '连接耗时(秒)',
field: 'age',
sortable: true
}, {
title: '空闲时间(秒)',
field: 'idle',
sortable: true
}, {
title: '命令',
field: 'cmd',
sortable: true
}, {
title: '总内存',
field: 'tot-mem',
sortable: true
},{
title: '输出内存',
field: 'omem',
sortable: true
}, {
title: '标志',
field: 'flags',
sortable: true
},{
title: '文件描述符',
field: 'fd',
sortable: true
},{
title: '订阅数',
field: 'sub',
sortable: true
}, {
title: '模式订阅数',
field: 'psub',
sortable: true
}, {
title: 'MULTI 队列长度',
field: 'multi',
sortable: true
}, {
title: '查询缓冲区',
field: 'qbuf',
sortable: true
}, {
title: '查询缓冲区空闲',
field: 'qbuf-free',
sortable: true
}, {
title: '参数内存',
field: 'argv-mem',
sortable: true
}, {
title: '输出缓冲区长度',
field: 'obl',
sortable: true
}, {
title: '输出链长度',
field: 'oll',
sortable: true
}, {
title: '事件文件',
field: 'events',
sortable: true
}, {
title: '重定向',
field: 'redir',
sortable: true
}],
function (index, row) {
var html = [];
}
]
]


Expand Down Expand Up @@ -931,12 +1037,14 @@ <h4 class="modal-title text-danger">确定要终止所选会话吗?</h4>
$(document).ready(function () {
//获取用户实例列表
$(function () {
// 会话管理-支持的数据库类型
supportedDbType=['mysql','mongo', 'oracle','redis']
$.ajax({
type: "get",
url: "/group/user_all_instances/",
dataType: "json",
data: {
db_type: ['mysql','mongo', 'oracle']
db_type: supportedDbType
},
complete: function () {
//如果已选择instance_name进入页面自动填充并且重置激活id
Expand All @@ -951,20 +1059,13 @@ <h4 class="modal-title text-danger">确定要终止所选会话吗?</h4>
if (data.status === 0) {
let result = data['data'];
allInstances = result;
// $("#instance_name").empty();
$("#optgroup-mysql").empty();
$("#optgroup-mongo").empty();
$("#optgroup-oracle").empty();
supportedDbType.forEach(function(db) {
$("#optgroup-" + db).empty();
});
for (let i = 0; i < result.length; i++) {
let instance = "<option value=\"" + result[i]['instance_name'] + "\">" + result[i]['instance_name'] + "</option>";
// $("#instance_name").append(instance);
if (result[i]['db_type'] === 'mysql') {
$("#optgroup-mysql").append(instance);
} else if (result[i]['db_type'] === 'mongo') {
$("#optgroup-mongo").append(instance);
} else if (result[i]['db_type'] === 'oracle') {
$("#optgroup-oracle").append(instance);
}
var dbType = result[i]['db_type'];
$("#optgroup-" + dbType).append(instance);
}
$('#instance_name').selectpicker('render');
$('#instance_name').selectpicker('refresh');
Expand Down

0 comments on commit 58c0145

Please sign in to comment.