Skip to content

Commit

Permalink
Merge pull request apache#168 from jianyi-gronk/feature/ui/service
Browse files Browse the repository at this point in the history
Implement service related UI
  • Loading branch information
chickenlj authored Jan 24, 2024
2 parents 50094c4 + 51d1024 commit 694e807
Show file tree
Hide file tree
Showing 13 changed files with 845 additions and 15 deletions.
86 changes: 86 additions & 0 deletions ui-vue3/src/api/mock/mockService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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.
*/

import Mock from 'mockjs'

Mock.mock('/mock/service/search', 'get', {
code: 200,
message: 'success',
data: {
total: 8,
curPage: 1,
pageSize: 1,
data: [
{
serviceName: 'org.apache.dubbo.samples.UserService',
interfaceNum: 4,
avgQPS: 6,
avgRT: '194ms',
requestTotal: 200
},
{
serviceName: 'org.apache.dubbo.samples.OrderService',
interfaceNum: 12,
avgQPS: 13,
avgRT: '189ms',
requestTotal: 164
},
{
serviceName: 'org.apache.dubbo.samples.DetailService',
interfaceNum: 14,
avgQPS: 0.5,
avgRT: '268ms',
requestTotal: 1324
},
{
serviceName: 'org.apache.dubbo.samples.PayService',
interfaceNum: 8,
avgQPS: 9,
avgRT: '346ms',
requestTotal: 189
},
{
serviceName: 'org.apache.dubbo.samples.CommentService',
interfaceNum: 9,
avgQPS: 8,
avgRT: '936ms',
requestTotal: 200
},
{
serviceName: 'org.apache.dubbo.samples.RepayService',
interfaceNum: 16,
avgQPS: 17,
avgRT: '240ms',
requestTotal: 146
},
{
serviceName: 'org.apche.dubbo.samples.TransportService',
interfaceNum: 5,
avgQPS: 43,
avgRT: '89ms',
requestTotal: 367
},
{
serviceName: 'org.apche.dubbo.samples.DistributionService',
interfaceNum: 5,
avgQPS: 4,
avgRT: '78ms',
requestTotal: 145
}
]
}
})
26 changes: 26 additions & 0 deletions ui-vue3/src/api/service/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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.
*/

import request from '@/base/http/request'

export const searchService = (params: any): Promise<any> => {
return request({
url: '/service/search',
method: 'get',
params
})
}
12 changes: 11 additions & 1 deletion ui-vue3/src/base/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,17 @@ const words: I18nType = {
},
backHome: 'Back Home',
noPageTip: 'Sorry, the page you visited does not exist.',
globalSearchTip: 'Search ip, application, instance, service'
globalSearchTip: 'Search ip, application, instance, service',

details: 'Details',
debug: 'Debug',
distribution: 'Distribution',
monitor: 'Monitor',
tracing: 'Tracing',
event: 'Event',

provideService: 'Provide Service',
dependentService: 'Dependent Service'
}

export default words
11 changes: 10 additions & 1 deletion ui-vue3/src/base/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,17 @@ const words: I18nType = {
},
backHome: '回到首页',
noPageTip: '抱歉,你访问的页面不存在',
globalSearchTip: '搜索ip,应用,实例,服务',

globalSearchTip: '搜索ip,应用,实例,服务'
details: '详情',
debug: '调试',
distribution: '分布',
monitor: '监控',
tracing: '链路追踪',
event: '事件',

provideService: '提供服务',
dependentService: '依赖服务'
}

export default words
63 changes: 62 additions & 1 deletion ui-vue3/src/router/defaultRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,69 @@ export const routes: Readonly<RouteRecordType[]> = [
{
path: '/services',
name: 'services',
redirect: 'search',
component: () => import('../views/resources/services/index.vue'),
meta: {}
meta: {
tab_parent: true
},
children: [
{
path: '/search',
name: 'search',
component: () => import('../views/resources/services/search.vue'),
meta: {
hidden: true
}
},
{
path: '/detail/:serviceName',
name: 'detail',
component: () => import('../views/resources/services/tabs/detail.vue'),
meta: {
tab: true
}
},
{
path: '/debug/:serviceName',
name: 'debug',
component: () => import('../views/resources/services/tabs/debug.vue'),
meta: {
tab: true
}
},
{
path: '/distribution/:serviceName',
name: 'distribution',
component: () => import('../views/resources/services/tabs/distribution.vue'),
meta: {
tab: true
}
},
{
path: '/monitor/:serviceName',
name: 'monitor',
component: () => import('../views/resources/services/tabs/monitor.vue'),
meta: {
tab: true
}
},
{
path: '/tracing/:serviceName',
name: 'tracing',
component: () => import('../views/resources/services/tabs/tracing.vue'),
meta: {
tab: true
}
},
{
path: '/event/:serviceName',
name: 'event',
component: () => import('../views/resources/services/tabs/event.vue'),
meta: {
tab: true
}
}
]
}
]
},
Expand Down
31 changes: 28 additions & 3 deletions ui-vue3/src/views/resources/services/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,33 @@
~ limitations under the License.
-->
<template>
<div class="__container_resources_services_index">服务</div>
<div class="__container_services">
<Icon
icon="material-symbols:arrow-back-ios-new-rounded"
v-if="route.name !== 'search'"
@click="backSearch"
class="icon-back"
/>
<LayoutTab></LayoutTab>
</div>
</template>

<script setup lang="ts"></script>
<style lang="less" scoped></style>
<script setup lang="ts">
import LayoutTab from '@/layout/tab/layout_tab.vue'
import { Icon } from '@iconify/vue'
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const backSearch = () => {
router.push({ name: 'search' })
}
</script>
<style lang="less" scoped>
.__container_services {
.icon-back:hover {
cursor: pointer;
}
}
</style>
127 changes: 127 additions & 0 deletions ui-vue3/src/views/resources/services/search.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<!--
~ 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>
<div class="__container_services_index">
<a-flex vertical>
<a-flex class="service-filter">
<a-input-search
v-model:value="serviceName"
placeholder="请输入"
class="service-name-input"
@search="debounceSearch"
enter-button
/>
</a-flex>
<a-table
:columns="columns"
:data-source="dataSource"
:pagination="pagination"
:scroll="{ y: '55vh' }"
>
<template #bodyCell="{ column, text }">
<template v-if="column.dataIndex === 'serviceName'">
<a-button type="link" @click="viewDetail(text)">{{ text }}</a-button>
</template>
</template>
</a-table>
</a-flex>
</div>
</template>

<script setup lang="ts">
import { useRouter } from 'vue-router'
import type { ComponentInternalInstance } from 'vue'
import { ref, getCurrentInstance } from 'vue'
import { searchService } from '@/api/service/service.ts'
import { debounce } from 'lodash'
const {
appContext: {
config: { globalProperties }
}
} = <ComponentInternalInstance>getCurrentInstance()
const serviceName = ref('')
const router = useRouter()
const columns = [
{
title: '服务',
dataIndex: 'serviceName',
sorter: true,
width: '30%'
},
{
title: '接口数',
dataIndex: 'interfaceNum',
sorter: true,
width: '10%'
},
{
title: '近 1min QPS',
dataIndex: 'avgQPS',
sorter: true,
width: '15%'
},
{
title: '近 1min RT',
dataIndex: 'avgRT',
sorter: true,
width: '15%'
},
{
title: '近 1min 请求总量',
dataIndex: 'requestTotal',
sorter: true,
width: '15%'
}
]
const dataSource = ref([])
const onSearch = async () => {
let { data } = await searchService({})
dataSource.value = data.data
}
onSearch()
const debounceSearch = debounce(onSearch, 300)
const viewDetail = (serviceName: string) => {
router.push({ name: 'detail', params: { serviceName } })
}
const pagination = {
showTotal: (v: any) =>
globalProperties.$t('searchDomain.total') +
': ' +
v +
' ' +
globalProperties.$t('searchDomain.unit')
}
</script>
<style lang="less" scoped>
.__container_services_index {
.service-filter {
margin-bottom: 20px;
.service-name-input {
width: 500px;
}
}
}
</style>
Loading

0 comments on commit 694e807

Please sign in to comment.