You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kyuubi.apache.org by ch...@apache.org on 2023/04/05 09:31:21 UTC
[kyuubi] branch master updated: [KYUUBI #3650][UI] Add Operation Statistics Page
This is an automated email from the ASF dual-hosted git repository.
chengpan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kyuubi.git
The following commit(s) were added to refs/heads/master by this push:
new 015b80015 [KYUUBI #3650][UI] Add Operation Statistics Page
015b80015 is described below
commit 015b800156d7e0e56ba1246fe6a3781950620e3a
Author: He Zhao <he...@cisco.com>
AuthorDate: Wed Apr 5 17:31:10 2023 +0800
[KYUUBI #3650][UI] Add Operation Statistics Page
### _Why are the changes needed?_
Close #3650
### _How was this patch tested?_
- [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible
- [ ] Add screenshots for manual tests if appropriate
- [ ] [Run test](https://kyuubi.readthedocs.io/en/master/develop_tools/testing.html#running-tests) locally before make a pull request
![popo_2023-04-04 15-50-15](https://user-images.githubusercontent.com/52876270/229724723-c6ddc892-0a1c-4d38-acf6-f2c6c8bf20b2.jpg)
Closes #4663 from zwangsheng/KYUUBI_3650.
Closes #3650
277e544e6 [Cheng Pan] Update kyuubi-server/web-ui/src/views/operation/operation-statistics/index.vue
688cfb44e [zwangsheng] i18n
ed314d7c8 [zwangsheng] [KYUUBI #3650][UI] Add Operation Statistics Page
c1965031a [zwangsheng] [KYUUBI #3650][UI] Add Operation Statistics Page
65779b878 [zwangsheng] [KYUUBI #3650][UI] Add Operation Statistics Page
Lead-authored-by: He Zhao <he...@cisco.com>
Co-authored-by: zwangsheng <22...@qq.com>
Co-authored-by: Cheng Pan <pa...@gmail.com>
Signed-off-by: Cheng Pan <ch...@apache.org>
---
.../src/{locales/en_US => api/operation}/index.ts | 31 +++--
kyuubi-server/web-ui/src/locales/en_US/index.ts | 14 +-
kyuubi-server/web-ui/src/locales/zh_CN/index.ts | 14 +-
kyuubi-server/web-ui/src/router/operation/index.ts | 5 +
.../src/{locales/en_US/index.ts => utils/unit.ts} | 34 +++--
.../src/views/layout/components/aside/types.ts | 5 +
.../views/operation/operation-statistics/index.vue | 144 +++++++++++++++++++++
7 files changed, 220 insertions(+), 27 deletions(-)
diff --git a/kyuubi-server/web-ui/src/locales/en_US/index.ts b/kyuubi-server/web-ui/src/api/operation/index.ts
similarity index 69%
copy from kyuubi-server/web-ui/src/locales/en_US/index.ts
copy to kyuubi-server/web-ui/src/api/operation/index.ts
index 99e851651..51a3b5394 100644
--- a/kyuubi-server/web-ui/src/locales/en_US/index.ts
+++ b/kyuubi-server/web-ui/src/api/operation/index.ts
@@ -15,17 +15,24 @@
* limitations under the License.
*/
-export default {
- test: 'test',
- user: 'User',
- client_ip: 'Client IP',
- kyuubi_instance: 'Kyuubi Instance',
- session_id: 'Session ID',
- create_time: 'Create Time',
- operation: 'Operation',
- delete_confirm: 'Delete Confirm',
- message: {
- delete_succeeded: 'Delete {name} Succeeded',
- delete_failed: 'Delete {name} Failed'
+import request from '@/utils/request'
+
+export function getAllOperations() {
+ return request({
+ url: 'api/v1/admin/operations',
+ method: 'get'
+ })
+}
+
+export function actionOnOperation(
+ operationId: string,
+ data: {
+ action: 'CANCEL' | 'CLOSE'
}
+) {
+ return request({
+ url: `api/v1/operations/${operationId}`,
+ method: 'put',
+ data
+ })
}
diff --git a/kyuubi-server/web-ui/src/locales/en_US/index.ts b/kyuubi-server/web-ui/src/locales/en_US/index.ts
index 99e851651..d50f22915 100644
--- a/kyuubi-server/web-ui/src/locales/en_US/index.ts
+++ b/kyuubi-server/web-ui/src/locales/en_US/index.ts
@@ -21,11 +21,23 @@ export default {
client_ip: 'Client IP',
kyuubi_instance: 'Kyuubi Instance',
session_id: 'Session ID',
+ operation_id: 'Operation ID',
create_time: 'Create Time',
operation: 'Operation',
delete_confirm: 'Delete Confirm',
+ close_confirm: 'Close Confirm',
+ cancel_confirm: 'Cancel Confirm',
+ start_time: 'State Time',
+ complete_time: 'Completed Time',
+ state: 'State',
+ duration: 'Duration',
+ statement: 'Statement',
message: {
delete_succeeded: 'Delete {name} Succeeded',
- delete_failed: 'Delete {name} Failed'
+ delete_failed: 'Delete {name} Failed',
+ close_succeeded: 'Close {name} Succeeded',
+ close_failed: 'Close {name} Failed',
+ cancel_succeeded: 'Cancel {name} Succeeded',
+ cancel_failed: 'Cancel {name} Failed'
}
}
diff --git a/kyuubi-server/web-ui/src/locales/zh_CN/index.ts b/kyuubi-server/web-ui/src/locales/zh_CN/index.ts
index 016aaa8e7..443d129cc 100644
--- a/kyuubi-server/web-ui/src/locales/zh_CN/index.ts
+++ b/kyuubi-server/web-ui/src/locales/zh_CN/index.ts
@@ -21,11 +21,23 @@ export default {
client_ip: '客户端地址',
kyuubi_instance: '服务端地址',
session_id: 'Session ID',
+ operation_id: 'Operation ID',
create_time: '创建时间',
operation: '操作',
delete_confirm: '确认删除',
+ close_confirm: '确认关闭',
+ cancel_confirm: '确认取消',
+ start_time: '开始时间',
+ complete_time: '完成时间',
+ state: '状态',
+ duration: '运行时间',
+ statement: 'Statement',
message: {
delete_succeeded: '删除 {name} 成功',
- delete_failed: '删除 {name} 失败'
+ delete_failed: '删除 {name} 失败',
+ close_succeeded: '关闭 {name} 成功',
+ close_failed: '关闭 {name} 失败',
+ cancel_succeeded: '取消 {name} 成功',
+ cancel_failed: '取消 {name} 失败'
}
}
diff --git a/kyuubi-server/web-ui/src/router/operation/index.ts b/kyuubi-server/web-ui/src/router/operation/index.ts
index 03ba4c285..8d6dfbd91 100644
--- a/kyuubi-server/web-ui/src/router/operation/index.ts
+++ b/kyuubi-server/web-ui/src/router/operation/index.ts
@@ -25,6 +25,11 @@ const routes = [
path: '/operation/completedJobs',
name: 'operation-completedJobs',
component: () => import('@/views/operation/completedJobs/index.vue')
+ },
+ {
+ path: '/operation/operation-statistics',
+ name: 'operation-statistics',
+ component: () => import('@/views/operation/operation-statistics/index.vue')
}
]
diff --git a/kyuubi-server/web-ui/src/locales/en_US/index.ts b/kyuubi-server/web-ui/src/utils/unit.ts
similarity index 59%
copy from kyuubi-server/web-ui/src/locales/en_US/index.ts
copy to kyuubi-server/web-ui/src/utils/unit.ts
index 99e851651..7e43e48f9 100644
--- a/kyuubi-server/web-ui/src/locales/en_US/index.ts
+++ b/kyuubi-server/web-ui/src/utils/unit.ts
@@ -15,17 +15,25 @@
* limitations under the License.
*/
-export default {
- test: 'test',
- user: 'User',
- client_ip: 'Client IP',
- kyuubi_instance: 'Kyuubi Instance',
- session_id: 'Session ID',
- create_time: 'Create Time',
- operation: 'Operation',
- delete_confirm: 'Delete Confirm',
- message: {
- delete_succeeded: 'Delete {name} Succeeded',
- delete_failed: 'Delete {name} Failed'
- }
+function millTransfer(val: number) {
+ return secondTransfer(val / 1000)
}
+
+function secondTransfer(val: number) {
+ const h = Math.floor(val / 3600)
+ const min = Math.floor((val - 3600 * h) / 60)
+ const sec = Math.round(val - 3600 * h - 60 * min)
+ return h === 0
+ ? min == 0
+ ? `${sec} sec`
+ : sec === 0
+ ? `${min} min`
+ : `${min} min ${sec} sec`
+ : sec === 0
+ ? min !== 0
+ ? `${h} hour ${min} min`
+ : `${h} hour`
+ : `${h} hour ${min} min ${sec} sec`
+}
+
+export { millTransfer, secondTransfer }
diff --git a/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts b/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts
index 71d1d0128..4772c1a4e 100644
--- a/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts
+++ b/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts
@@ -61,6 +61,11 @@ export const MENUS = [
label: 'Operation',
icon: 'List',
children: [
+ {
+ label: 'Operation Statistics',
+ icon: 'VideoPlay',
+ router: '/operation/operation-statistics'
+ },
{
label: 'Running Jobs',
icon: 'VideoPlay',
diff --git a/kyuubi-server/web-ui/src/views/operation/operation-statistics/index.vue b/kyuubi-server/web-ui/src/views/operation/operation-statistics/index.vue
new file mode 100644
index 000000000..ff6706c72
--- /dev/null
+++ b/kyuubi-server/web-ui/src/views/operation/operation-statistics/index.vue
@@ -0,0 +1,144 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<template>
+ <el-card class="table-container">
+ <el-table v-loading="loading" :data="tableData" style="width: 100%">
+ <el-table-column prop="sessionUser" :label="$t('user')" width="160" />
+ <el-table-column
+ prop="identifier"
+ :label="$t('operation_id')"
+ width="300" />
+ <el-table-column prop="statement" :label="$t('statement')" width="160" />
+ <el-table-column prop="state" :label="$t('state')" width="160" />
+ <el-table-column :label="$t('start_time')" width="160">
+ <template #default="scope">
+ {{
+ scope.row.startTime != null && scope.row.startTime > 0
+ ? format(scope.row.startTime, 'yyyy-MM-dd HH:mm:ss')
+ : '-'
+ }}
+ </template>
+ </el-table-column>
+ <el-table-column :label="$t('complete_time')" width="160">
+ <template #default="scope">
+ {{
+ scope.row.completeTime != null && scope.row.completeTime > 0
+ ? format(scope.row.completeTime, 'yyyy-MM-dd HH:mm:ss')
+ : '-'
+ }}
+ </template>
+ </el-table-column>
+ <el-table-column :label="$t('duration')" width="140">
+ <template #default="scope">{{
+ scope.row.startTime != null &&
+ scope.row.completeTime != null &&
+ scope.row.startTime > 0 &&
+ scope.row.completeTime > 0
+ ? millTransfer(scope.row.completeTime - scope.row.startTime)
+ : '-'
+ }}</template>
+ </el-table-column>
+ <el-table-column fixed="right" :label="$t('operation')" width="110">
+ <template #default="scope">
+ <el-space wrap>
+ <el-popconfirm
+ v-if="!isTerminalState(scope.row.state)"
+ :title="$t('cancel_confirm')"
+ @confirm="handleOperate(scope.row.identifier, 'CANCEL')">
+ <template #reference>
+ <span>
+ <el-tooltip
+ effect="dark"
+ :content="$t('cancel')"
+ placement="top">
+ <template #default>
+ <el-button type="danger" icon="Remove" circle />
+ </template>
+ </el-tooltip>
+ </span>
+ </template>
+ </el-popconfirm>
+ <el-popconfirm
+ :title="$t('close_confirm')"
+ @confirm="handleOperate(scope.row.identifier, 'CLOSE')">
+ <template #reference>
+ <span>
+ <el-tooltip
+ effect="dark"
+ :content="$t('close')"
+ placement="top">
+ <template #default>
+ <el-button type="danger" icon="CircleClose" circle />
+ </template>
+ </el-tooltip>
+ </span>
+ </template>
+ </el-popconfirm>
+ </el-space>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-card>
+</template>
+
+<script lang="ts" setup>
+ import { getAllOperations, actionOnOperation } from '@/api/operation'
+ import { millTransfer } from '@/utils/unit'
+ import { format } from 'date-fns'
+ import { useI18n } from 'vue-i18n'
+ import { ElMessage } from 'element-plus'
+ import { useTable } from '@/views/common/use-table'
+
+ const { t } = useI18n()
+ const { tableData, loading, getList: _getList } = useTable()
+ const handleOperate = (operationId: string, action: 'CANCEL' | 'CLOSE') => {
+ actionOnOperation(operationId, { action: action }).then(() => {
+ // TODO add delete success or failed logic after api support
+ ElMessage({
+ message: t(`${action.toLowerCase()}_succeeded`, {
+ operationId: operationId
+ }),
+ type: 'success'
+ })
+ getList()
+ })
+ }
+ const getList = () => {
+ _getList(getAllOperations)
+ }
+
+ const terminalStates = new Set([
+ 'FINISHED_STATE',
+ 'CLOSED_STATE',
+ 'CANCELED_STATE',
+ 'TIMEOUT_STATE',
+ 'ERROR_STATE'
+ ])
+
+ function isTerminalState(state: string): Boolean {
+ return terminalStates.has(state)
+ }
+ getList()
+</script>
+<style lang="scss" scoped>
+ header {
+ display: flex;
+ justify-content: flex-end;
+ }
+</style>