Skip to content

Commit b780963

Browse files
committed
doris支持会话管理功能
1 parent c647f07 commit b780963

File tree

6 files changed

+142
-31
lines changed

6 files changed

+142
-31
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
| ODPS || × | × | × | × | × | × | × | × | × |
3535
| ClickHouse |||| × | × | × | × | × | × | × |
3636
| Cassandra || × || × | × | × | × | × | × | × |
37-
| Doris || × || × | × | × | × | × | × | × |
37+
| Doris || × || × | × | × | | × | × | × |
3838

3939

4040

common/static/dbdiagnostic/js/db_info.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,92 @@ const mysqlDiagnosticInfo = {
103103
],
104104
}
105105

106+
const dorisDiagnosticInfo = {
107+
fieldsProcesslist: [
108+
'doris',
109+
["All","Not Sleep","Query"],
110+
[{
111+
title: '',
112+
field: 'checkbox',
113+
checkbox: true
114+
}, {
115+
title: 'THEEAD ID',
116+
field: 'id',
117+
sortable: true
118+
}, {
119+
title: 'USER',
120+
field: 'user',
121+
sortable: true
122+
}, {
123+
title: 'HOST',
124+
field: 'host',
125+
sortable: true
126+
}, {
127+
title: 'CATALOG',
128+
field: 'catalog',
129+
sortable: true
130+
}, {
131+
title: 'DATABASE',
132+
field: 'db',
133+
sortable: true
134+
}, {
135+
title: 'TIME(s)',
136+
field: 'time',
137+
sortable: true
138+
}, {
139+
title: 'COMMAND',
140+
field: 'command',
141+
sortable: true
142+
}, {
143+
title: 'STATE',
144+
field: 'state',
145+
sortable: true
146+
}, {
147+
title: 'INFO',
148+
field: 'info',
149+
sortable: true,
150+
formatter: function (value, row, index) {
151+
if (value.length > 20) {
152+
var sql = value.substr(0, 20) + '...';
153+
return sql;
154+
} else {
155+
return value
156+
}
157+
}
158+
}, {
159+
title: 'QUERYID',
160+
field: 'query_id',
161+
sortable: true,
162+
visible: false // 默认不显示
163+
}, {
164+
title: '完整INFO',
165+
field: 'info',
166+
sortable: true,
167+
visible: false // 默认不显示
168+
}, {
169+
title: 'FE',
170+
field: 'fe',
171+
sortable: true,
172+
visible: false // 默认不显示
173+
}],
174+
function (index, row) {
175+
var html = [];
176+
$.each(row, function (key, value) {
177+
if (key === 'info') {
178+
var sql = window.sqlFormatter.format(value);
179+
//替换所有的换行符
180+
sql = sql.replace(/\r\n/g, "<br>");
181+
sql = sql.replace(/\n/g, "<br>");
182+
//替换所有的空格
183+
sql = sql.replace(/\s/g, "&nbsp;");
184+
html.push('<span>' + sql + '</span>');
185+
}
186+
});
187+
return html.join('');
188+
}
189+
]
190+
}
191+
106192
const mongoDiagnosticInfo = {
107193
fieldsProcesslist: [
108194
'mongo',

sql/db_diagnostic.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,9 @@ def create_kill_session(request):
6464

6565
result = {"status": 0, "msg": "ok", "data": []}
6666
query_engine = get_engine(instance=instance)
67-
if instance.db_type == "mysql":
68-
result["data"] = query_engine.get_kill_command(json.loads(thread_ids))
69-
elif instance.db_type == "mongo":
70-
kill_command = query_engine.get_kill_command(json.loads(thread_ids))
71-
result["data"] = kill_command
72-
elif instance.db_type == "oracle":
67+
try:
7368
result["data"] = query_engine.get_kill_command(json.loads(thread_ids))
74-
else:
69+
except AttributeError:
7570
result = {
7671
"status": 1,
7772
"msg": "暂时不支持{}类型数据库通过进程id构建请求".format(instance.db_type),
@@ -100,7 +95,7 @@ def kill_session(request):
10095

10196
engine = get_engine(instance=instance)
10297
r = None
103-
if instance.db_type == "mysql":
98+
if instance.db_type in ["mysql", "doris"]:
10499
r = engine.kill(json.loads(thread_ids))
105100
elif instance.db_type == "mongo":
106101
r = engine.kill_op(json.loads(thread_ids))
@@ -136,11 +131,9 @@ def tablespace(request):
136131
return HttpResponse(json.dumps(result), content_type="application/json")
137132

138133
query_engine = get_engine(instance=instance)
139-
if instance.db_type == "mysql":
140-
query_result = query_engine.tablespace(offset, limit)
141-
elif instance.db_type == "oracle":
134+
try:
142135
query_result = query_engine.tablespace(offset, limit)
143-
else:
136+
except AttributeError:
144137
result = {
145138
"status": 1,
146139
"msg": "暂时不支持{}类型数据库的表空间信息查询".format(instance.db_type),
@@ -212,9 +205,9 @@ def innodb_trx(request):
212205
return HttpResponse(json.dumps(result), content_type="application/json")
213206

214207
query_engine = get_engine(instance=instance)
215-
if instance.db_type == "mysql":
208+
try:
216209
query_result = query_engine.get_long_transaction()
217-
else:
210+
except AttributeError:
218211
result = {
219212
"status": 1,
220213
"msg": "暂时不支持{}类型数据库的长事务查询".format(instance.db_type),

sql/engines/doris.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def server_version(self):
2929
version = result.rows[0][-1].split("-")[0]
3030
return tuple([int(n) for n in version.split(".")[:3]])
3131

32+
'''
3233
def query(self, db_name=None, sql="", limit_num=0, close_conn=True, **kwargs):
3334
"""返回 ResultSet"""
3435
result_set = ResultSet(full_sql=sql)
@@ -52,13 +53,28 @@ def query(self, db_name=None, sql="", limit_num=0, close_conn=True, **kwargs):
5253
if close_conn:
5354
self.close()
5455
return result_set
56+
'''
5557

5658
forbidden_databases = [
5759
"__internal_schema",
5860
"INFORMATION_SCHEMA",
5961
"information_schema",
6062
]
6163

64+
def processlist(
65+
self,
66+
command_type,
67+
base_sql="select id, user, host, catalog, db, command, time, state, query_id, ifnull(info,'') as info, fe from information_schema.processlist",
68+
**kwargs,
69+
):
70+
return super(DorisEngine, self).processlist(command_type, base_sql)
71+
72+
def get_kill_command(self, thread_ids, thread_ids_check=False):
73+
return super(DorisEngine, self).get_kill_command(thread_ids, thread_ids_check)
74+
75+
def kill(self, thread_ids, thread_ids_check=False):
76+
return super(DorisEngine, self).kill(thread_ids, thread_ids_check)
77+
6278
def execute_check(self, db_name=None, sql=""):
6379
"""上线单执行前的检查, 返回Review set"""
6480
check_result = ReviewSet(full_sql=sql)
@@ -186,3 +202,10 @@ def execute(self, db_name=None, sql="", close_conn=True):
186202
if close_conn:
187203
self.close()
188204
return execute_result
205+
206+
def get_long_transaction(self, *args, **kwargs):
207+
# 不支持的方法需要抛出错误
208+
raise AttributeError(f"{self.__class__.__name__} has no attribute 'get_long_transaction'")
209+
210+
def trxandlocks(self, *args, **kwargs):
211+
raise AttributeError(f"{self.__class__.__name__} has no attribute 'trxandlocks'")

sql/engines/mysql.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class MysqlForkType(Enum):
6262

6363

6464
class MysqlEngine(EngineBase):
65+
name = "MySQL"
66+
info = "MySQL engine"
6567
test_query = "SELECT 1"
6668
_server_version = None
6769
_server_fork_type = None
@@ -103,10 +105,6 @@ def get_connection(self, db_name=None):
103105
self.thread_id = self.conn.thread_id()
104106
return self.conn
105107

106-
name = "MySQL"
107-
108-
info = "MySQL engine"
109-
110108
def escape_string(self, value: str) -> str:
111109
"""字符串参数转义"""
112110
return pymysql.escape_string(value)
@@ -540,7 +538,7 @@ def query(
540538
result_set = self.result_set_binary_as_hex(result_set)
541539
except Exception as e:
542540
logger.warning(
543-
f"MySQL语句执行报错,语句:{sql},错误信息{traceback.format_exc()}"
541+
f"{self.name}语句执行报错,语句:{sql},错误信息{traceback.format_exc()}"
544542
)
545543
result_set.error = str(e)
546544
finally:
@@ -721,7 +719,7 @@ def execute(self, db_name=None, sql="", close_conn=True, parameters=None):
721719
cursor.close()
722720
except Exception as e:
723721
logger.warning(
724-
f"MySQL语句执行报错,语句:{sql},错误信息{traceback.format_exc()}"
722+
f"{self.name}语句执行报错,语句:{sql},错误信息{traceback.format_exc()}"
725723
)
726724
result.error = str(e)
727725
if close_conn:
@@ -762,9 +760,13 @@ def osc_control(self, **kwargs):
762760
"""
763761
return self.inc_engine.osc_control(**kwargs)
764762

765-
def processlist(self, command_type, **kwargs):
763+
def processlist(
764+
self,
765+
command_type,
766+
base_sql="select id, user, host, db, command, time, state, ifnull(info,'') as info from information_schema.processlist",
767+
**kwargs,
768+
):
766769
"""获取连接信息"""
767-
base_sql = "select id, user, host, db, command, time, state, ifnull(info,'') as info from information_schema.processlist"
768770
# escape
769771
command_type = self.escape_string(command_type)
770772
if not command_type:
@@ -778,11 +780,12 @@ def processlist(self, command_type, **kwargs):
778780

779781
return self.query("information_schema", sql)
780782

781-
def get_kill_command(self, thread_ids):
783+
def get_kill_command(self, thread_ids, thread_ids_check=True):
782784
"""由传入的线程列表生成kill命令"""
783785
# 校验传参
784-
if [i for i in thread_ids if not isinstance(i, int)]:
785-
return None
786+
if thread_ids_check:
787+
if [i for i in thread_ids if not isinstance(i, int)]:
788+
return None
786789
sql = "select concat('kill ', id, ';') from information_schema.processlist where id in ({});".format(
787790
",".join(str(tid) for tid in thread_ids)
788791
)
@@ -793,11 +796,12 @@ def get_kill_command(self, thread_ids):
793796

794797
return kill_sql
795798

796-
def kill(self, thread_ids):
799+
def kill(self, thread_ids, thread_ids_check=True):
797800
"""kill线程"""
798801
# 校验传参
799-
if [i for i in thread_ids if not isinstance(i, int)]:
800-
return ResultSet(full_sql="")
802+
if thread_ids_check:
803+
if [i for i in thread_ids if not isinstance(i, int)]:
804+
return ResultSet(full_sql="")
801805
sql = "select concat('kill ', id, ';') from information_schema.processlist where id in ({});".format(
802806
",".join(str(tid) for tid in thread_ids)
803807
)

sql/templates/dbdiagnostic.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<optgroup id="optgroup-oracle" label="Oracle"></optgroup>
3030
<optgroup id="optgroup-redis" label="Redis"></optgroup>
3131
<optgroup id="optgroup-pgsql" label="PgSQL"></optgroup>
32+
<optgroup id="optgroup-doris" label="Doris"></optgroup>
3233
</select>
3334
</div>
3435
<div id="command-div" class="form-group">
@@ -123,7 +124,9 @@ <h4 class="modal-title text-danger">确定要终止所选会话吗?</h4>
123124
if (typeof oracleDiagnosticInfo !== "undefined" && Array.isArray(oracleDiagnosticInfo.fieldsProcesslist)) {
124125
processListTableInfos.push(oracleDiagnosticInfo?.fieldsProcesslist);
125126
}
126-
127+
if (typeof dorisDiagnosticInfo !== "undefined" && Array.isArray(dorisDiagnosticInfo.fieldsProcesslist)) {
128+
processListTableInfos.push(dorisDiagnosticInfo?.fieldsProcesslist);
129+
}
127130

128131

129132
// 问题诊断--进程列表
@@ -246,6 +249,8 @@ <h4 class="modal-title text-danger">确定要终止所选会话吗?</h4>
246249
}]
247250
]
248251
]
252+
let dorisTableInfo = ['doris',tablespaceListTableInfos[0][1]]
253+
tablespaceListTableInfos.push(dorisTableInfo)
249254

250255
// 问题诊断--表空间列表
251256
function get_space_list() {
@@ -729,7 +734,7 @@ <h4 class="modal-title text-danger">确定要终止所选会话吗?</h4>
729734
//获取用户实例列表
730735
$(function () {
731736
// 会话管理-支持的数据库类型
732-
supportedDbType=['mysql','mongo', 'oracle','redis','pgsql']
737+
supportedDbType=['mysql','mongo', 'oracle','redis','pgsql','doris']
733738
$.ajax({
734739
type: "get",
735740
url: "/group/user_all_instances/",

0 commit comments

Comments
 (0)