This is an automated email from the ASF dual-hosted git repository. wusheng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking-rocketbot-ui.git
The following commit(s) were added to refs/heads/master by this push: new c49ea82 feat: implement Alerts for query errors (#542) c49ea82 is described below commit c49ea825b75fd54270da99482897558b548dc5f8 Author: Fine0830 <fine0...@outlook.com> AuthorDate: Fri Sep 24 20:17:48 2021 +0800 feat: implement Alerts for query errors (#542) --- src/components/index.ts | 6 +- src/components/rk-alert.vue | 131 +++++++++++++++++++++ src/components/rk-icon.vue | 7 +- src/components/rk-sidebox.vue | 4 +- src/graph/index.ts | 26 ++-- src/store/modules/alarm/index.ts | 14 ++- .../modules/dashboard/dashboard-data-query.ts | 10 +- src/store/modules/dashboard/dashboard-data.ts | 23 +++- src/store/modules/dashboard/mutation-types.ts | 2 + src/store/modules/event/index.ts | 13 +- src/store/modules/global/selectors.ts | 42 ++++++- src/store/modules/log/index.ts | 11 ++ src/store/modules/profile/profile-store.ts | 50 +++++--- src/store/modules/topology/index.ts | 57 ++++++++- src/store/modules/trace/index.ts | 42 ++++++- src/store/mutation-types.ts | 6 + src/utils/tooltip.ts | 15 +-- src/views/components/common/alerts-content.vue | 72 +++++++++++ .../components/common}/rk-footer.vue | 3 +- .../components/common}/rk-header.vue | 2 +- .../components/dashboard/charts/chart-edit.vue | 10 +- src/views/components/dashboard/dashboard-item.vue | 3 +- .../components/dashboard/tool-bar/tool-bar.vue | 8 +- src/views/components/dashboard/tool-group.vue | 1 - src/views/components/profile/profile-header.vue | 5 +- src/views/components/profile/profile-task.vue | 4 +- .../components/profile/profile-trace-detail.vue | 10 +- src/views/components/profile/task-list.vue | 3 +- .../components/topology/topo-service-metrics.vue | 2 +- src/views/components/topology/topo-services.vue | 1 + src/views/components/trace/trace-search.vue | 51 ++++---- src/views/containers/dashboard.vue | 7 +- src/views/containers/index.vue | 10 +- src/views/containers/profile.vue | 6 +- src/views/containers/topology/alarm/alarm-tool.vue | 2 + .../topology/endpoint-dependency/index.vue | 2 +- src/views/containers/trace.vue | 2 +- 37 files changed, 548 insertions(+), 115 deletions(-) diff --git a/src/components/index.ts b/src/components/index.ts index a5f02e8..7918f5a 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -16,8 +16,6 @@ */ import noty from './noty'; -import RkHeader from './rk-header.vue'; -import RkFooter from './rk-footer.vue'; import RkFooterTime from './rk-footer-time.vue'; import RkProgress from './rk-progress.vue'; import RkPage from './rk-page.vue'; @@ -33,10 +31,9 @@ import RkBack from './rk-back.vue'; import RkButton from './rk-button.vue'; import RkIcon from './rk-icon.vue'; import RkRadio from './rk-radio.vue'; +import RkAlert from './rk-alert.vue'; const components: any = { - RkHeader, - RkFooter, RkProgress, RkDate, RkPanel, @@ -52,6 +49,7 @@ const components: any = { RkButton, RkIcon, RkRadio, + RkAlert, }; const componentsName: string[] = Object.keys(components); diff --git a/src/components/rk-alert.vue b/src/components/rk-alert.vue new file mode 100644 index 0000000..e2dee68 --- /dev/null +++ b/src/components/rk-alert.vue @@ -0,0 +1,131 @@ +<!-- 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 v-if="show" class="rk-alert flex-h" :class="type"> + <span v-show="closable" @click="closeAlert"> + <rk-icon icon="clearclose" class="close" /> + </span> + <rk-icon v-show="showIcon" :icon="iconType" class="xll mr-5 tip-icon" /> + <div class="rk-alert-content"> + <div class="rk-alert-message">{{ message }}</div> + <div class="rk-alert-description">{{ description }}</div> + </div> + </div> +</template> + +<script lang="ts"> + import { Vue, Component, Prop } from 'vue-property-decorator'; + @Component + export default class RkAlert extends Vue { + @Prop() private message!: string; + @Prop() private type!: string; + @Prop() private description!: string; + @Prop({ default: true }) private showIcon!: boolean; + @Prop({ default: true }) private closable!: boolean; + @Prop() private show!: boolean; + + private iconType: string = 'error'; + + private mounted() { + this.iconType = + this.type === 'error' + ? 'highlight_remove' + : this.type === 'warning' + ? 'error_outline' + : this.type === 'info' + ? 'info_outline' + : 'sentiment_satisfied_alt'; + setTimeout(() => { + this.$emit('update:show', false); + }, 30000); + } + + private closeAlert() { + this.$emit('update:show', false); + } + } +</script> + +<style lang="scss" scoped> + .rk-alert { + position: relative; + display: flex; + word-wrap: break-word; + width: 580px; + z-index: 1000; + color: #000; + border-radius: 2px; + padding: 10px 10px; + align-items: flex-start; + transition: all 0.7s; + margin-bottom: 15px; + &.error { + border: 1px solid #ffccc7; + background-color: #fff2f0; + } + &.warning { + border: 1px solid #ffe58f; + background-color: #fffbe6; + } + &.info { + border: 1px solid #91d5ff; + background-color: #e6f7ff; + } + &.success { + border: 1px solid #b7eb8f; + background-color: #f6ffed; + } + } + .error { + .tip-icon { + color: #ff4d4f; + } + } + .warning { + .tip-icon { + color: #faad14; + } + } + .info { + .tip-icon { + color: #1890ff; + } + } + .success { + .tip-icon { + color: #52c41a; + } + } + .close { + font-size: 20px; + color: #00000073; + transition: color 0.3s; + position: absolute; + top: 2px; + right: 0; + cursor: pointer; + z-index: 1001; + } + .rk-alert-message { + font-size: 16px; + } + .rk-alert-content { + flex: 1; + min-width: 0; + } + .rk-alert-description { + line-height: 22px; + } +</style> diff --git a/src/components/rk-icon.vue b/src/components/rk-icon.vue index 9a224ff..f9f0360 100644 --- a/src/components/rk-icon.vue +++ b/src/components/rk-icon.vue @@ -18,6 +18,7 @@ limitations under the License. --> :class="{ sm: size === 'sm', lg: size === 'lg', + xll: size === 'xll', offset: offset, loading: loading, }" @@ -46,13 +47,17 @@ limitations under the License. --> vertical-align: middle; fill: currentColor; &.sm { - width: 13px; + width: 1px; height: 13px; } &.lg { width: 18px; height: 18px; } + &.xll { + width: 25px; + height: 25px; + } &.offset { margin-top: -2px; } diff --git a/src/components/rk-sidebox.vue b/src/components/rk-sidebox.vue index 55b23a6..7cc1660 100644 --- a/src/components/rk-sidebox.vue +++ b/src/components/rk-sidebox.vue @@ -35,7 +35,9 @@ limitations under the License. --> export default { name: 'RkSidebox', props: { - show: {}, + show: { + default: false, + }, title: { default: '', }, diff --git a/src/graph/index.ts b/src/graph/index.ts index e6fa409..d54560a 100644 --- a/src/graph/index.ts +++ b/src/graph/index.ts @@ -44,14 +44,24 @@ class Graph { return this; } public params(variablesData: any): AxiosPromise<void> { - return axios.post( - '/graphql', - { - query: query[this.queryData], - variables: variablesData, - }, - { cancelToken: cancelToken() }, - ); + return axios + .post( + '/graphql', + { + query: query[this.queryData], + variables: variablesData, + }, + { cancelToken: cancelToken() }, + ) + .then((res: any) => { + if (res.data.errors) { + res.data.errors = res.data.errors.map((e: { message: string }) => e.message).join(' '); + } + return res; + }) + .catch((err) => { + throw err; + }); } } diff --git a/src/store/modules/alarm/index.ts b/src/store/modules/alarm/index.ts index 265eb11..5163398 100644 --- a/src/store/modules/alarm/index.ts +++ b/src/store/modules/alarm/index.ts @@ -24,11 +24,13 @@ import { Alarm, AlarmParams } from '@/types/alarm'; export interface State { alarmService: Alarm[]; total: number; + alarmErrors: { [key: string]: string }; } const initState: State = { alarmService: [], total: 0, + alarmErrors: {}, }; // getters @@ -44,15 +46,25 @@ const mutations: MutationTree<State> = { state.alarmService = []; state.total = 0; }, + [types.SET_ALARM_ERRORS](state: State, data: { msg: string; desc: string }) { + state.alarmErrors = { + ...state.alarmErrors, + [data.msg]: data.desc, + }; + }, }; // actions const actions: ActionTree<State, any> = { - GET_ALARM(context: { commit: Commit; state: State }, params: AlarmParams): Promise<void> { + GET_ALARM(context: { commit: Commit; state: State }, params: AlarmParams): Promise<any> { return graph .query('queryAlarms') .params(params) .then((res: AxiosResponse<any>) => { + context.commit(types.SET_ALARM_ERRORS, { msg: 'queryAlarms', desc: res.data.errors || '' }); + if (res.data.errors) { + return; + } if (res.data.data.getAlarm.items) { context.commit(types.SET_ALARM, res.data.data.getAlarm); } diff --git a/src/store/modules/dashboard/dashboard-data-query.ts b/src/store/modules/dashboard/dashboard-data-query.ts index 7318cce..1488ed3 100644 --- a/src/store/modules/dashboard/dashboard-data-query.ts +++ b/src/store/modules/dashboard/dashboard-data-query.ts @@ -15,8 +15,9 @@ * limitations under the License. */ -import { Commit, ActionTree, Dispatch } from 'vuex'; +import { Commit, ActionTree, Dispatch, MutationTree } from 'vuex'; import { AxiosResponse } from 'axios'; +import * as types from './mutation-types'; import { State } from './dashboard-data'; import graph from '@/graph'; import { TopologyType } from '@/constants/constant'; @@ -236,6 +237,13 @@ const actions: ActionTree<State, any> = { .query(config.queryMetricType) .params(variable) .then((res: AxiosResponse) => { + if (res.data.errors) { + context.commit(types.SET_DASHBOARD_ERRORS, { + msg: variable.condition.name, + desc: res.data.errors, + }); + return; + } const resData = res.data.data; return { ...resData, config, metricName: variable.condition.name }; diff --git a/src/store/modules/dashboard/dashboard-data.ts b/src/store/modules/dashboard/dashboard-data.ts index 298a96c..da6054c 100644 --- a/src/store/modules/dashboard/dashboard-data.ts +++ b/src/store/modules/dashboard/dashboard-data.ts @@ -38,6 +38,7 @@ export interface State { enableEvents: boolean; eventsPageType: string; currentSeriesType: Option[]; + dashboardErrors: { [key: string]: string }; } const initState: State = { @@ -47,11 +48,12 @@ const initState: State = { enableEvents: false, eventsPageType: PageEventsType.DASHBOARD_EVENTS, currentSeriesType: [], + dashboardErrors: {}, ...dashboardLayout.state, }; // mutations -const mutations: MutationTree<any> = { +const mutations: MutationTree<State> = { ...dashboardLayout.mutations, [types.SET_DASHBOARD_EVENTS](state: State, param: { events: Event[]; type: string; duration: DurationTime }) { const events = param.events.map((d: Event, index: number) => { @@ -122,6 +124,12 @@ const mutations: MutationTree<any> = { item.checked = false; } }, + [types.SET_DASHBOARD_ERRORS](state: State, data: { msg: string; desc: string }) { + state.dashboardErrors = { + ...state.dashboardErrors, + [data.msg]: data.desc, + }; + }, }; // actions @@ -179,6 +187,10 @@ const actions: ActionTree<State, any> = { .query('queryTypeOfMetrics') .params({ name: item }) .then((res: AxiosResponse) => { + context.commit(types.SET_DASHBOARD_ERRORS, { msg: 'queryTypeOfMetrics', desc: res.data.errors }); + if (res.data.errors) { + return; + } return res.data.data; }); }), @@ -189,7 +201,8 @@ const actions: ActionTree<State, any> = { .query('queryGetAllTemplates') .params({}) .then((res: AxiosResponse) => { - if (!res.data.data) { + context.commit(types.SET_DASHBOARD_ERRORS, { msg: 'queryGetAllTemplates', desc: res.data.errors }); + if (res.data.errors) { return; } return res.data.data.getAllTemplates || []; @@ -200,9 +213,11 @@ const actions: ActionTree<State, any> = { .query('queryEvents') .params({ condition: params.condition }) .then((res: AxiosResponse) => { - if (!(res.data.data && res.data.data.fetchEvents)) { + context.commit(types.SET_DASHBOARD_ERRORS, { msg: 'queryEvents', desc: res.data.errors }); + if (res.data.errors) { context.commit('SET_DASHBOARD_EVENTS', { events: [], type: params.type, duration: params.condition.time }); - return []; + + return; } context.commit('SET_DASHBOARD_EVENTS', { events: res.data.data.fetchEvents.events, diff --git a/src/store/modules/dashboard/mutation-types.ts b/src/store/modules/dashboard/mutation-types.ts index a526130..9d20042 100644 --- a/src/store/modules/dashboard/mutation-types.ts +++ b/src/store/modules/dashboard/mutation-types.ts @@ -45,6 +45,8 @@ export const SET_CLEAR_SELECTED_EVENTS = 'SET_CLEAR_SELECTED_EVENTS'; export const SET_SERVICE_DEPENDENCY = 'SET_SERVICE_DEPENDENCY'; export const SET_SERVICE_INSTANCE_DEPENDENCY = 'SET_SERVICE_INSTANCE_DEPENDENCY'; export const SET_ENDPOINT_DEPENDENCY = 'SET_ENDPOINT_DEPENDENCY'; +export const SET_SELECTOR_ERRORS = 'SET_SELECTOR_ERRORS'; +export const SET_DASHBOARD_ERRORS = 'SET_DASHBOARD_ERRORS'; // comp export const SET_CURRENT_GROUP = 'SET_CURRENT_GROUP'; diff --git a/src/store/modules/event/index.ts b/src/store/modules/event/index.ts index 03cb2b0..57c4e38 100644 --- a/src/store/modules/event/index.ts +++ b/src/store/modules/event/index.ts @@ -27,11 +27,15 @@ const Scopes = ['Service', 'ServiceInstance', 'Endpoint']; export interface State { currentEvents: Event[]; totalSize: number; + errorMessage: string; + eventErrors: { [key: string]: string }; } const initState: State = { currentEvents: [], totalSize: 1, + errorMessage: '', + eventErrors: {}, }; // mutations @@ -46,6 +50,12 @@ const mutations: MutationTree<any> = { [types.SET_TOTAL_SIZE](state: State, total: number) { state.totalSize = total; }, + [types.SET_EVENT_ERRORS](state: State, data: { msg: string; desc: string }) { + state.eventErrors = { + ...state.eventErrors, + [data.msg]: data.desc, + }; + }, }; // actions @@ -55,7 +65,8 @@ const actions: ActionTree<State, any> = { .query('queryEvents') .params({ condition: params.condition }) .then((res: AxiosResponse) => { - if (!(res.data.data && res.data.data.fetchEvents)) { + context.commit(types.SET_EVENT_ERRORS, { msg: 'queryEvents', desc: res.data.errors || '' }); + if (res.data.errors) { context.commit('UPDATE_EVENTS', { events: [], duration: params.condition.time }); context.commit('SET_TOTAL_SIZE', 1); return []; diff --git a/src/store/modules/global/selectors.ts b/src/store/modules/global/selectors.ts index 03768ab..e30593c 100644 --- a/src/store/modules/global/selectors.ts +++ b/src/store/modules/global/selectors.ts @@ -37,6 +37,7 @@ export interface State { destService: Option; destInstance: Option; destEndpoint: Option; + selectorErrors: { [key: string]: string }; } const initState: State = { @@ -53,6 +54,7 @@ const initState: State = { destService: { key: '', label: '' }, destInstance: { key: '', label: '' }, destEndpoint: { key: '', label: '' }, + selectorErrors: {}, }; // mutations @@ -134,6 +136,12 @@ const mutations: MutationTree<State> = { state.destEndpoint = { key: call.destEndpointId, label: call.destEndpointName }; state.updateDashboard = { key: TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY + call.id }; }, + [types.SET_SELECTOR_ERRORS](state: State, data: { msg: string; desc: string }) { + state.selectorErrors = { + ...state.selectorErrors, + [data.msg]: data.desc, + }; + }, }; // actions @@ -146,6 +154,11 @@ const actions: ActionTree<State, any> = { .query('queryServices') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_SELECTOR_ERRORS, { msg: 'serviceErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_SERVICES, []); + return; + } context.commit(types.SET_SERVICES, res.data.data.services); }); }, @@ -167,6 +180,11 @@ const actions: ActionTree<State, any> = { keyword: params.keyword, }) .then((res: AxiosResponse) => { + context.commit(types.SET_SELECTOR_ERRORS, { msg: 'endpointErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_ENDPOINTS, []); + return; + } context.commit(types.SET_ENDPOINTS, res.data.data.getEndpoints); }); }, @@ -179,6 +197,11 @@ const actions: ActionTree<State, any> = { .query('queryInstances') .params({ serviceId: context.state.currentService.key || '', ...params }) .then((res: AxiosResponse) => { + context.commit(types.SET_SELECTOR_ERRORS, { msg: 'instanceErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_INSTANCES, []); + return; + } context.commit(types.SET_INSTANCES, res.data.data.getServiceInstances); }); }, @@ -187,6 +210,11 @@ const actions: ActionTree<State, any> = { .query('queryDatabases') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_SELECTOR_ERRORS, { msg: 'databaseErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_DATABASES, []); + return; + } context.commit(types.SET_DATABASES, res.data.data.services); }); }, @@ -288,6 +316,10 @@ const actions: ActionTree<State, any> = { .query('queryEndpoints') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_SELECTOR_ERRORS, { msg: 'itemEndpointErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + return []; + } return res.data.data.getEndpoints; }); }, @@ -296,6 +328,10 @@ const actions: ActionTree<State, any> = { .query('queryInstances') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_SELECTOR_ERRORS, { msg: 'itemInstanceErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + return []; + } return res.data.data.getServiceInstances; }); }, @@ -307,7 +343,11 @@ const actions: ActionTree<State, any> = { .query('queryServices') .params(params) .then((res: AxiosResponse) => { - return res.data.data.services || []; + context.commit(types.SET_SELECTOR_ERRORS, { msg: 'itemServiceErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + return []; + } + return res.data.data.services; }); }, }; diff --git a/src/store/modules/log/index.ts b/src/store/modules/log/index.ts index 2890f1d..6a61f97 100644 --- a/src/store/modules/log/index.ts +++ b/src/store/modules/log/index.ts @@ -30,6 +30,7 @@ export interface State { loading: boolean; conditions: any; supportQueryLogsByKeywords: boolean; + logErrors: { [key: string]: string }; } const categories: Option[] = [ @@ -63,6 +64,7 @@ const logState: State = { : [], }, supportQueryLogsByKeywords: true, + logErrors: {}, }; // mutations @@ -100,6 +102,12 @@ const mutations: MutationTree<State> = { localStorage.removeItem('logTags'); localStorage.removeItem('logTraceId'); }, + [types.SET_LOG_ERRORS](state: State, data: { msg: string; desc: string }) { + state.logErrors = { + ...state.logErrors, + [data.msg]: data.desc, + }; + }, }; // actions @@ -112,6 +120,7 @@ const actions: ActionTree<State, any> = { .query('queryBrowserErrorLogs') .params(params) .then((res: AxiosResponse<any>) => { + context.commit(types.SET_LOG_ERRORS, { msg: 'queryBrowserErrorLogs', desc: res.data.errors || '' }); if (res.data && res.data.errors) { context.commit('SET_LOGS', []); context.commit('SET_LOGS_TOTAL', 0); @@ -129,6 +138,7 @@ const actions: ActionTree<State, any> = { .query('queryServiceLogs') .params(params) .then((res: AxiosResponse<any>) => { + context.commit(types.SET_LOG_ERRORS, { msg: 'queryServiceLogs', desc: res.data.errors || '' }); if (res.data && res.data.errors) { context.commit('SET_LOGS', []); context.commit('SET_LOGS_TOTAL', 0); @@ -150,6 +160,7 @@ const actions: ActionTree<State, any> = { .query('queryLogsByKeywords') .params({}) .then((res: AxiosResponse<any>) => { + context.commit(types.SET_LOG_ERRORS, { msg: 'queryLogsByKeywords', desc: res.data.errors || '' }); if (res.data && res.data.errors) { return; } diff --git a/src/store/modules/profile/profile-store.ts b/src/store/modules/profile/profile-store.ts index 666fd8b..b62bf9b 100644 --- a/src/store/modules/profile/profile-store.ts +++ b/src/store/modules/profile/profile-store.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Commit, Dispatch } from 'vuex'; +import { Commit, Dispatch, MutationTree } from 'vuex'; import { AxiosResponse } from 'axios'; import graph from '@/graph'; @@ -41,6 +41,7 @@ export interface State { profileAnalyzation: any; highlightTop: boolean; currentSpan: any; + profileErrors: { [key: string]: string }; } const initState: State = { headerSource: { @@ -64,6 +65,7 @@ const initState: State = { profileAnalyzation: [], highlightTop: true, currentSpan: {}, + profileErrors: {}, }; // getters const getters = { @@ -73,7 +75,7 @@ const getters = { }; // mutations -const mutations = { +const mutations: MutationTree<State> = { [types.SET_SERVICES](state: State, data: any[]) { state.headerSource.serviceSource = [{ key: 'all', label: 'All' }, ...data]; state.headerSource.currentService = state.headerSource.serviceSource[0]; @@ -114,6 +116,12 @@ const mutations = { [types.SET_HIGHLIGHT_TOP](state: State) { state.highlightTop = !state.highlightTop; }, + [types.SET_PROFILE_ERRORS](state: State, data: { msg: string; desc: string }) { + state.profileErrors = { + ...state.profileErrors, + [data.msg]: data.desc, + }; + }, }; // actions @@ -126,8 +134,9 @@ const actions = { .query('queryServices') .params(params) .then((res: AxiosResponse) => { - if (!res.data.data) { - return; + context.commit(types.SET_PROFILE_ERRORS, { msg: 'serviceErrors', desc: res.data.errors || '' }); + if (res.data.errors) { + return context.commit(types.SET_SERVICES, []); } context.commit(types.SET_SERVICES, res.data.data.services); context.dispatch('GET_TASK_LIST'); @@ -144,17 +153,17 @@ const actions = { .query('getProfileTaskList') .params(param) .then((res: AxiosResponse) => { - if (!res.data.data) { - return; + context.commit(types.SET_PROFILE_ERRORS, { msg: 'getProfileTaskList', desc: res.data.errors || '' }); + if (res.data.errors) { + return context.commit(types.SET_TASK_LIST, []); } context.commit(types.SET_TASK_LIST, res.data.data.getProfileTaskList); - return res.data.data.getProfileTaskList; - }) - .then((data: any) => { - if (!data) { + const list = res.data.data.getProfileTaskList; + if (!list.length) { return; } - context.dispatch('GET_SEGMENT_LIST', { taskID: data[0].id }); + context.dispatch('GET_SEGMENT_LIST', { taskID: list[0].id }); + return; }); }, GET_SEGMENT_LIST(context: { commit: Commit; dispatch: Dispatch }, params: { taskID: string }) { @@ -162,8 +171,9 @@ const actions = { .query('getProfileTaskSegmentList') .params(params) .then((res: AxiosResponse) => { - if (!res.data.data.getProfileTaskSegmentList) { - return; + context.commit(types.SET_PROFILE_ERRORS, { msg: 'getProfileTaskSegmentList', desc: res.data.errors || '' }); + if (res.data.errors) { + return context.commit(types.SET_SEGMENT_LIST, []); } const { getProfileTaskSegmentList } = res.data.data; @@ -185,6 +195,10 @@ const actions = { .query('queryProfileSegment') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_PROFILE_ERRORS, { msg: 'queryProfileSegment', desc: res.data.errors || '' }); + if (res.data.errors) { + return context.commit(types.SET_SEGMENT_SPANS, []); + } const { getProfiledSegment } = res.data.data; if (!getProfiledSegment) { return; @@ -208,9 +222,13 @@ const actions = { .query('getProfileAnalyze') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_PROFILE_ERRORS, { msg: 'getProfileAnalyze', desc: res.data.errors || '' }); + if (res.data.errors) { + return context.commit(types.SET_PROFILE_ANALYZATION, []); + } const { getProfileAnalyze, tip } = res.data.data; if (tip) { - return tip; + return { tip }; } if (!getProfileAnalyze) { context.commit(types.SET_PROFILE_ANALYZATION, []); @@ -243,6 +261,10 @@ const actions = { .query('saveProfileTask') .params({ creationRequest }) .then((res: AxiosResponse) => { + context.commit(types.SET_PROFILE_ERRORS, { msg: 'saveProfileTask', desc: res.data.errors || '' }); + if (res.data.errors) { + return; + } if (res.data.data && res.data.data.createTask && res.data.data.createTask.errorReason) { return res.data.data.createTask; } diff --git a/src/store/modules/topology/index.ts b/src/store/modules/topology/index.ts index 2288f39..d1b84e9 100644 --- a/src/store/modules/topology/index.ts +++ b/src/store/modules/topology/index.ts @@ -55,6 +55,11 @@ export interface State { instanceDependencyMode: string; editDependencyMetrics: boolean; topoTemplatesType: { [key: string]: any }; + endpointErrors: string; + getTopoErrors: string; + endpointTopoErrors: string; + instanceTopoErrors: string; + topoErrors: { [key: string]: string }; } const DefaultConfig = { @@ -98,6 +103,11 @@ const initState: State = { editDependencyMetrics: false, topoEndpointDependency: {}, topoTemplatesType: JSON.parse(localStorage.getItem('topoTemplateTypes') || JSON.stringify({})), + endpointErrors: '', + getTopoErrors: '', + endpointTopoErrors: '', + instanceTopoErrors: '', + topoErrors: {}, }; // getters @@ -552,6 +562,12 @@ const mutations = { state.topoTemplatesType = data; localStorage.setItem('topoTemplateTypes', JSON.stringify(data)); }, + [types.SET_TOPO_ERRORS](state: State, data: { msg: string; desc: string }) { + state.topoErrors = { + ...state.topoErrors, + [data.msg]: data.desc, + }; + }, }; // actions @@ -564,6 +580,10 @@ const actions: ActionTree<State, any> = { .query('queryServices') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_TOPO_ERRORS, { msg: 'serviceErrors', desc: res.data.errors }); + if (res.data.errors) { + return []; + } return res.data.data.services || []; }); }, @@ -578,6 +598,10 @@ const actions: ActionTree<State, any> = { .query('queryEndpoints') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointErrors', desc: res.data.errors }); + if (res.data.errors) { + return []; + } return res.data.data.getEndpoints || []; }); }, @@ -599,6 +623,7 @@ const actions: ActionTree<State, any> = { .query(query) .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_TOPO_ERRORS, { msg: query, desc: res.data.errors || '' }); if (res.data.errors) { context.commit(types.SET_TOPO, { calls: [], nodes: [] }); return; @@ -612,6 +637,11 @@ const actions: ActionTree<State, any> = { .query('queryTopoInfo') .params({ ...params, ids, idsC, idsS }) .then((info: AxiosResponse) => { + context.commit(types.SET_TOPO_ERRORS, { msg: 'queryTopoInfo', desc: info.data.errors || '' }); + if (info.data.errors) { + context.commit(types.SET_TOPO, { calls: [], nodes: [] }); + return; + } const resInfo = info.data.data; if (!resInfo.sla) { return context.commit(types.SET_TOPO, { calls, nodes }); @@ -732,6 +762,9 @@ const actions: ActionTree<State, any> = { .post('/graphql', { query: querys, variables: { duration: params.duration } }, { cancelToken: cancelToken() }) .then((res: AxiosResponse) => { if (res.data.errors) { + const msg = res.data.errors.map((e: { message: string }) => e.message).join(' '); + + context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: msg }); context.commit(types.SET_ENDPOINT_DEPENDENCY, { calls: [], nodes: [] }); return; } @@ -743,6 +776,7 @@ const actions: ActionTree<State, any> = { nodes.push(...topo[key].nodes); } if (!nodes.length) { + context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: '' }); context.commit(types.SET_ENDPOINT_DEPENDENCY, { calls: [], nodes: [] }); return; } @@ -795,9 +829,13 @@ const actions: ActionTree<State, any> = { .post('/graphql', { query, variables: { duration: params.duration } }, { cancelToken: cancelToken() }) .then((json: AxiosResponse<any>) => { if (json.data.errors) { + const msg = json.data.errors.map((e: { message: string }) => e.message).join(' '); + + context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: msg }); context.commit(types.SET_ENDPOINT_DEPENDENCY, { calls: [], nodes: [] }); return; } + context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: '' }); const cpms = json.data.data; const keys = Object.keys(cpms); for (const key of keys) { @@ -823,8 +861,9 @@ const actions: ActionTree<State, any> = { .query('queryTopoInstanceDependency') .params(params) .then((res: AxiosResponse) => { - if (!(res.data && res.data.data)) { - return; + context.commit(types.SET_TOPO_ERRORS, { msg: 'queryTopoInstanceDependency', desc: res.data.errors || '' }); + if (res.data.errors) { + return []; } const clientIdsC = [] as string[]; const serverIdsC = [] as string[]; @@ -846,6 +885,13 @@ const actions: ActionTree<State, any> = { duration: params.duration, }) .then((json: AxiosResponse) => { + context.commit(types.SET_TOPO_ERRORS, { + msg: 'queryDependencyInstanceClientMetric', + desc: json.data.errors || '', + }); + if (json.data.errors) { + return []; + } const clientCalls = [] as string[]; for (const call of topoCalls) { for (const cpm of json.data.data.cpmC.values) { @@ -870,6 +916,13 @@ const actions: ActionTree<State, any> = { duration: params.duration, }) .then((jsonResp: AxiosResponse) => { + context.commit(types.SET_TOPO_ERRORS, { + msg: 'queryDependencyInstanceServerMetric', + desc: jsonResp.data.errors || '', + }); + if (jsonResp.data.errors) { + return []; + } const serverCalls = [] as string[]; for (const call of topoCalls) { for (const cpm of jsonResp.data.data.cpmC.values) { diff --git a/src/store/modules/trace/index.ts b/src/store/modules/trace/index.ts index 2fbdd3d..fd430d4 100644 --- a/src/store/modules/trace/index.ts +++ b/src/store/modules/trace/index.ts @@ -33,6 +33,10 @@ export interface State { currentTrace: Trace; traceSpanLogs: any[]; traceSpanLogsTotal: number; + traceListErrors: string; + traceSpanErrors: string; + traceSpanLogErrors: string; + traceErrors: { [key: string]: string }; } const initState: State = { @@ -56,6 +60,10 @@ const initState: State = { }, traceSpanLogs: [], traceSpanLogsTotal: 0, + traceListErrors: '', + traceSpanErrors: '', + traceSpanLogErrors: '', + traceErrors: {}, }; // mutations @@ -119,6 +127,12 @@ const mutations: MutationTree<State> = { [types.SET_TRACE_SPAN_LOGS_TOTAL](state: State, data: number) { state.traceSpanLogsTotal = data; }, + [types.SET_TRACE_ERRORS](state: State, data: { msg: string; desc: string }) { + state.traceErrors = { + ...state.traceErrors, + [data.msg]: data.desc, + }; + }, }; // actions @@ -131,6 +145,11 @@ const actions: ActionTree<State, any> = { .query('queryServices') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_TRACE_ERRORS, { msg: 'serviceError', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_SERVICES, []); + return; + } context.commit(types.SET_SERVICES, res.data.data.services); }); }, @@ -139,6 +158,11 @@ const actions: ActionTree<State, any> = { .query('queryServiceInstance') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_TRACE_ERRORS, { msg: 'instanceError', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_INSTANCES, []); + return; + } context.commit(types.SET_INSTANCES, res.data.data.instanceId); }); }, @@ -147,6 +171,11 @@ const actions: ActionTree<State, any> = { .query('queryEndpoints') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_TRACE_ERRORS, { msg: 'endpointError', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_ENDPOINTS, []); + return; + } context.commit(types.SET_ENDPOINTS, res.data.data.getEndpoints); }); }, @@ -159,6 +188,12 @@ const actions: ActionTree<State, any> = { .query('queryTraces') .params({ condition: context.state.traceForm }) .then((res: AxiosResponse) => { + context.commit(types.SET_TRACE_ERRORS, { msg: 'queryTraces', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_TRACELIST, []); + context.commit(types.SET_TRACELIST_TOTAL, 0); + return; + } context.commit(types.SET_TRACELIST, res.data.data.data.traces); context.commit(types.SET_TRACELIST_TOTAL, res.data.data.data.total); }); @@ -169,6 +204,11 @@ const actions: ActionTree<State, any> = { .query('queryTrace') .params(params) .then((res: AxiosResponse) => { + context.commit(types.SET_TRACE_ERRORS, { msg: 'queryTraceSpan', desc: res.data.errors || '' }); + if (res.data.errors) { + context.commit(types.SET_TRACE_SPANS, []); + return; + } context.commit(types.SET_TRACE_SPANS, res.data.data.trace.spans); }); }, @@ -177,10 +217,10 @@ const actions: ActionTree<State, any> = { .query('queryServiceLogs') .params(params) .then((res: AxiosResponse<any>) => { + context.commit(types.SET_TRACE_ERRORS, { msg: 'queryServiceLogs', desc: res.data.errors || '' }); if (res.data && res.data.errors) { context.commit('SET_TRACE_SPAN_LOGS', []); context.commit('SET_TRACE_SPAN_LOGS_TOTAL', 0); - return; } context.commit('SET_TRACE_SPAN_LOGS', res.data.data.queryLogs.logs); diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts index a348f5e..be751d7 100644 --- a/src/store/mutation-types.ts +++ b/src/store/mutation-types.ts @@ -59,6 +59,7 @@ export const SET_INSTANCE_INFO = 'SET_INSTANCE_INFO'; // alarm export const SET_ALARM = 'SET_ALARM'; export const CLEAR_ALARM = 'CLEAR_ALARM'; +export const SET_ALARM_ERRORS = 'SET_ALARM_ERRORS'; // trace export const SET_TRACELIST = 'SET_TRACELIST'; @@ -72,6 +73,7 @@ export const SET_TRACE_LOGS = 'SET_TRACE_LOGS'; export const SET_TRACE_LOGS_TOTAL = 'SET_TRACE_LOGS_TOTAL'; export const SET_TRACE_SPAN_LOGS_TOTAL = 'SET_TRACE_SPAN_LOGS_TOTAL'; export const SET_TRACE_SPAN_LOGS = 'SET_TRACE_SPAN_LOGS'; +export const SET_TRACE_ERRORS = 'SET_TRACE_ERRORS'; // topo export const SET_TOPO = 'SET_TOPO'; @@ -121,6 +123,7 @@ export const ADD_TOPO_ENDPOINT_DEPENDENCY_COMP = 'ADD_TOPO_ENDPOINT_DEPENDENCY_C export const EDIT_ENDPOINT_DEPENDENCY_CONFIG = 'EDIT_ENDPOINT_DEPENDENCY_CONFIG'; export const DELETE_TOPO_ENDPOINT_DEPENDENCY = 'DELETE_TOPO_ENDPOINT_DEPENDENCY'; export const UPDATE_TOPO_TEMPLATE_TYPES = 'UPDATE_TOPO_TEMPLATE_TYPES'; +export const SET_TOPO_ERRORS = 'SET_TOPO_ERRORS'; // profile export const SET_TASK_OPTIONS = 'SET_TASK_OPTIONS'; @@ -133,6 +136,7 @@ export const SET_CURRENT_SEGMENT = 'SET_CURRENT_SEGMENT'; export const SET_PROFILE_ANALYZATION = 'SET_PROFILE_ANALYZATION'; export const SET_HIGHLIGHT_TOP = 'SET_HIGHLIGHT_TOP'; export const SET_CURRENT_SPAN = 'SET_CURRENT_SPAN'; +export const SET_PROFILE_ERRORS = 'SET_PROFILE_ERRORS'; // Log export const SELECT_LOG_TYPE = 'SELECT_LOG_TYPE'; @@ -149,10 +153,12 @@ export const SET_CURRENT_LOG_INSTANCE = 'SET_CURRENT_LOG_INSTANCE'; export const SET_LOG_CONDITIONS = 'SET_LOG_CONDITIONS'; export const SET_SUPPORT_QUERY_LOGS_KEYWORDS = 'SET_SUPPORT_QUERY_LOGS_KEYWORDS'; export const CLEAR_LOG_CONDITIONS = 'CLEAR_LOG_CONDITIONS'; +export const SET_LOG_ERRORS = 'SET_LOG_ERRORS'; // Event export const UPDATE_EVENTS = 'UPDATE_EVENTS'; export const SET_TOTAL_SIZE = 'SET_TOTAL_SIZE'; +export const SET_EVENT_ERRORS = 'SET_EVENT_ERRORS'; // debug export const SET_TAB_TYPE = 'SET_TAB_TYPE'; diff --git a/src/utils/tooltip.ts b/src/utils/tooltip.ts index 3ce60aa..e0e10fd 100644 --- a/src/utils/tooltip.ts +++ b/src/utils/tooltip.ts @@ -47,9 +47,7 @@ function setAttributes($inner: any, el: any) { return; } const isShow = - !popper._disabled && - (popper._visible || popper._always) && - (!popper._ellipsis || isEllipsisTooltip(el)); + !popper._disabled && (popper._visible || popper._always) && (!popper._ellipsis || isEllipsisTooltip(el)); if (popper._appendToBody) { if (isShow && popper.popper.parentNode !== document.body) { @@ -82,13 +80,11 @@ function handleClosePopper(e: any) { } } -// 添加事件 function addEvent(el: any) { el.addEventListener('mouseenter', handleShowPopper); el.addEventListener('mouseleave', handleClosePopper); } -// 移除事件 function removeEvent(el: any) { el.removeEventListener('mouseenter', handleShowPopper); el.removeEventListener('mouseleave', handleClosePopper); @@ -122,9 +118,7 @@ export default { $popper.style.display = 'none'; el.appendChild($popper); } else { - $popper.className += ` append-to-body ${ - binding.value.popperCls ? binding.value.popperCls.join(' ') : '' - }`; + $popper.className += ` append-to-body ${binding.value.popperCls ? binding.value.popperCls.join(' ') : ''}`; } } @@ -145,10 +139,7 @@ export default { if (el.popper.popper) { el.removeChild(el.popper.popper); } - } else if ( - el.popper.popper && - el.popper.popper.parentNode === document.body - ) { + } else if (el.popper.popper && el.popper.popper.parentNode === document.body) { document.body.removeChild(el.popper.popper); } }, diff --git a/src/views/components/common/alerts-content.vue b/src/views/components/common/alerts-content.vue new file mode 100644 index 0000000..9fdc638 --- /dev/null +++ b/src/views/components/common/alerts-content.vue @@ -0,0 +1,72 @@ +<!-- 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="alert-content"> + <rk-alert + v-for="(msg, index) in Object.keys(allAlerts)" + :key="msg + index" + :show.sync="allAlerts[msg]" + type="error" + :message="msg" + :description="allAlerts[msg]" + /> + </div> +</template> + +<script lang="ts"> + import { Component, Vue } from 'vue-property-decorator'; + import { State } from 'vuex-class'; + import { State as optionState } from '@/store/modules/global/selectors'; + import { State as rocketData } from '@/store/modules/dashboard/dashboard-data'; + import { State as topoState } from '@/store/modules/topology'; + import { State as profileState } from '@/store/modules/profile/profile-store'; + import { State as logState } from '@/store/modules/log'; + import { State as alarmState } from '@/store/modules/alarm'; + import { State as EventState } from '@/store/modules/event'; + import { State as traceState } from '@/store/modules/trace/index'; + + @Component + export default class AlertsContent extends Vue { + @State('rocketOption') private stateOption!: optionState; + @State('rocketData') private rocketData!: rocketData; + @State('rocketTopo') private stateTopo!: topoState; + @State('profileStore') private stateProfile!: profileState; + @State('rocketLog') private rocketLog!: logState; + @State('rocketAlarm') private rocketAlarm!: alarmState; + @State('rocketEvent') private rocketEvent!: EventState; + @State('rocketTrace') private rocketTrace!: traceState; + + private get allAlerts() { + return { + ...this.rocketEvent.eventErrors, + ...this.stateOption.selectorErrors, + ...this.rocketData.dashboardErrors, + ...this.stateTopo.topoErrors, + ...this.stateProfile.profileErrors, + ...this.rocketLog.logErrors, + ...this.rocketAlarm.alarmErrors, + ...this.rocketTrace.traceErrors, + }; + } + } +</script> +<style lang="scss" scoped> + .alert-content { + position: fixed; + top: 60px; + right: 5px; + z-index: 1000; + } +</style> diff --git a/src/components/rk-footer.vue b/src/views/components/common/rk-footer.vue similarity index 96% rename from src/components/rk-footer.vue rename to src/views/components/common/rk-footer.vue index 0b24274..8a4074c 100644 --- a/src/components/rk-footer.vue +++ b/src/views/components/common/rk-footer.vue @@ -27,9 +27,8 @@ limitations under the License. --> </template> <script lang="ts"> - import { Duration } from '@/types/global'; import { Vue, Component, Watch } from 'vue-property-decorator'; - import { State, Action, Mutation } from 'vuex-class'; + import { State, Action } from 'vuex-class'; @Component export default class Footerssd extends Vue { diff --git a/src/components/rk-header.vue b/src/views/components/common/rk-header.vue similarity index 99% rename from src/components/rk-header.vue rename to src/views/components/common/rk-header.vue index 84d9a20..842e876 100644 --- a/src/components/rk-header.vue +++ b/src/views/components/common/rk-header.vue @@ -55,7 +55,7 @@ limitations under the License. --> <script lang="ts"> import { Vue, Component } from 'vue-property-decorator'; - import { Action, State, Getter } from 'vuex-class'; + import { Action, Getter } from 'vuex-class'; import { routes } from '@/router'; import timeFormat from '@/utils/timeFormat'; diff --git a/src/views/components/dashboard/charts/chart-edit.vue b/src/views/components/dashboard/charts/chart-edit.vue index a1170f2..998243a 100755 --- a/src/views/components/dashboard/charts/chart-edit.vue +++ b/src/views/components/dashboard/charts/chart-edit.vue @@ -480,9 +480,13 @@ limitations under the License. --> return; } if (data.length > 1) { - const length = data.filter((d: { typeOfMetrics: string }) => d.typeOfMetrics !== MetricsType.REGULAR_VALUE) - .length; - if (length) { + let len = 0; + for (const d of data) { + if (d.typeOfMetrics !== MetricsType.REGULAR_VALUE) { + len++; + } + } + if (len) { this.$emit('updateStatus', 'metricType', MetricsType.UNKNOWN); return; } diff --git a/src/views/components/dashboard/dashboard-item.vue b/src/views/components/dashboard/dashboard-item.vue index 27a9177..57cb87c 100644 --- a/src/views/components/dashboard/dashboard-item.vue +++ b/src/views/components/dashboard/dashboard-item.vue @@ -173,8 +173,7 @@ limitations under the License. --> this.itemConfig = {}; return; } - this.itemConfig = params[0].config; - + this.itemConfig = params[0] && params[0].config; const { queryMetricType } = this.itemConfig; let data = params; if (queryMetricType === QueryTypes.ReadMetricsValue) { diff --git a/src/views/components/dashboard/tool-bar/tool-bar.vue b/src/views/components/dashboard/tool-bar/tool-bar.vue index 8b2eab0..7105da3 100644 --- a/src/views/components/dashboard/tool-bar/tool-bar.vue +++ b/src/views/components/dashboard/tool-bar/tool-bar.vue @@ -152,13 +152,7 @@ limitations under the License. --> private dialogAttributesVisible: boolean = false; private dashboardType = DASHBOARDTYPE; private pageEventsType = PageEventsType; - get lastKey() { - const current = this.rocketComps.tree[this.rocketComps.group].children[this.rocketComps.current].children; - if (!current.length) { - return 0; - } - return current[current.length - 1].k; - } + private selectService(i: Option) { if (!this.rocketComps.enableEvents) { this.SELECT_SERVICE({ service: i, duration: this.durationTime }); diff --git a/src/views/components/dashboard/tool-group.vue b/src/views/components/dashboard/tool-group.vue index 67588a3..a30349e 100644 --- a/src/views/components/dashboard/tool-group.vue +++ b/src/views/components/dashboard/tool-group.vue @@ -69,7 +69,6 @@ limitations under the License. --> export default class ToolGroup extends Vue { @Prop() private rocketGlobal: any; @Prop() private rocketComps: any; - @Mutation('SET_COMPS_TREE') private SET_COMPS_TREE: any; @Mutation('DELETE_COMPS_GROUP') private DELETE_COMPS_GROUP: any; @Mutation('ADD_COMPS_GROUP') private ADD_COMPS_GROUP: any; @Action('MIXHANDLE_CHANGE_GROUP') private MIXHANDLE_CHANGE_GROUP: any; diff --git a/src/views/components/profile/profile-header.vue b/src/views/components/profile/profile-header.vue index 704de77..3506de0 100644 --- a/src/views/components/profile/profile-header.vue +++ b/src/views/components/profile/profile-header.vue @@ -48,7 +48,7 @@ limitations under the License. --> <script lang="ts"> import { Duration, Option } from '@/types/global'; import { Component, Prop, Vue } from 'vue-property-decorator'; - import { Mutation } from 'vuex-class'; + import { Mutation, Action } from 'vuex-class'; import { CommonSelector } from '../common/index'; import ProfileTask from './profile-task.vue'; @@ -58,6 +58,7 @@ limitations under the License. --> @Prop() private newTaskFields: any; @Prop() private taskFieldSource: any; @Mutation('profileStore/SET_HEADER_SOURCE') private SET_HEADER_SOURCE: any; + @Action('profileStore/GET_TASK_LIST') private GET_TASK_LIST: any; private endpointName: string = ''; private dialogVisible = false; @@ -69,7 +70,7 @@ limitations under the License. --> private searchTask() { this.SET_HEADER_SOURCE({ endpointName: this.endpointName }); - this.$store.dispatch('profileStore/GET_TASK_LIST'); + this.GET_TASK_LIST(); } private created() { diff --git a/src/views/components/profile/profile-task.vue b/src/views/components/profile/profile-task.vue index 8015b21..72ea7a5 100644 --- a/src/views/components/profile/profile-task.vue +++ b/src/views/components/profile/profile-task.vue @@ -76,7 +76,7 @@ limitations under the License. --> </template> <script lang="ts"> - import { Duration, Option } from '@/types/global'; + import { Duration } from '@/types/global'; import { Component, Prop, Vue, Watch } from 'vue-property-decorator'; import { Action, Getter, Mutation, State } from 'vuex-class'; @@ -103,7 +103,7 @@ limitations under the License. --> } private createTask() { - this.CREATE_PROFILE_TASK({ startTime: this.time.getTime() }).then((res: any) => { + this.CREATE_PROFILE_TASK({ startTime: this.time.getTime() }).then((res: { errorReason?: string }) => { if (res.errorReason) { this.message = res.errorReason; return; diff --git a/src/views/components/profile/profile-trace-detail.vue b/src/views/components/profile/profile-trace-detail.vue index e6ac009..89a4158 100644 --- a/src/views/components/profile/profile-trace-detail.vue +++ b/src/views/components/profile/profile-trace-detail.vue @@ -133,11 +133,11 @@ limitations under the License. --> segmentId: this.currentSegment.segmentId, timeRanges: this.timeRange, }) - .then((result: string) => { - this.message = result; - }) - .catch((err: any) => { - throw err; + .then((result: { tip: string }) => { + if (!result) { + return; + } + this.message = result.tip; }) .finally(() => { this.loading = false; diff --git a/src/views/components/profile/task-list.vue b/src/views/components/profile/task-list.vue index c364df0..e68fe12 100644 --- a/src/views/components/profile/task-list.vue +++ b/src/views/components/profile/task-list.vue @@ -127,7 +127,6 @@ limitations under the License. --> </template> <script lang="ts"> - import { Duration, Option } from '@/types/global'; import { Component, Prop, Vue } from 'vue-property-decorator'; import { Action, Mutation } from 'vuex-class'; @@ -136,8 +135,8 @@ limitations under the License. --> @Prop() private taskListSource: any; @Prop() private segmentList: any; @Prop() private headerSource: any; - @Action('profileStore/GET_SEGMENT_LIST') private GET_SEGMENT_LIST: any; @Mutation('profileStore/SET_CURRENT_SEGMENT') private SET_CURRENT_SEGMENT: any; + @Action('profileStore/GET_SEGMENT_LIST') private GET_SEGMENT_LIST: any; @Action('profileStore/GET_SEGMENT_SPANS') private GET_SEGMENT_SPANS: any; private selectedKey: string = ''; private selectedTask: any = {}; diff --git a/src/views/components/topology/topo-service-metrics.vue b/src/views/components/topology/topo-service-metrics.vue index 292cb51..e34e7e5 100644 --- a/src/views/components/topology/topo-service-metrics.vue +++ b/src/views/components/topology/topo-service-metrics.vue @@ -60,7 +60,7 @@ limitations under the License. --> private default = DEFAULT; private type: string = ''; - private beforeMount() { + private mounted() { this.type = TopologyType.TOPOLOGY_SERVICE; this.height = document.body.clientHeight - 230; this.setServiceTemplates(); diff --git a/src/views/components/topology/topo-services.vue b/src/views/components/topology/topo-services.vue index 3071f80..5e67803 100644 --- a/src/views/components/topology/topo-services.vue +++ b/src/views/components/topology/topo-services.vue @@ -36,6 +36,7 @@ limitations under the License. --> private service = { key: '', label: 'All services' }; private groups = [{ key: '', label: 'All groups' }]; private group = { key: '', label: 'All groups' }; + private showServiceErrors: boolean = false; private created() { this.fetchData(true); diff --git a/src/views/components/trace/trace-search.vue b/src/views/components/trace/trace-search.vue index 1882460..5514353 100644 --- a/src/views/components/trace/trace-search.vue +++ b/src/views/components/trace/trace-search.vue @@ -140,24 +140,26 @@ limitations under the License. --> this.time = [this.rocketbotGlobal.durationRow.start, this.rocketbotGlobal.durationRow.end]; } private mounted() { - this.GET_SERVICES({ duration: this.durationTime }) - .then(() => { - if (this.serviceName) { - for (const s of this.rocketTrace.services) { - if (s.label === this.serviceName) { - this.service = s; - break; - } + this.GET_SERVICES({ duration: this.durationTime }).then(() => { + if (this.serviceName) { + for (const s of this.rocketTrace.services) { + if (s.label === this.serviceName) { + this.service = s; + break; } } - this.getTraceList(); - if (this.service && this.service.key) { - this.GET_INSTANCES({ - duration: this.durationTime, - serviceId: this.service.key, - }); - } - }); + } + this.getTraceList(); + if (this.service && this.service.key) { + this.getInstance(); + } + }); + } + private getInstance(serviceId?: string) { + this.GET_INSTANCES({ + duration: this.durationTime, + serviceId: serviceId || this.service.key, + }); } private globalTimeFormat(time: Date[]) { const step = 'SECOND'; @@ -180,21 +182,18 @@ limitations under the License. --> this.SET_ENDPOINTS([]); return; } - this.GET_INSTANCES({ duration: this.durationTime, serviceId: i.key }); + this.getInstance(i.key); this.SET_ENDPOINTS([]); - this.GET_ITEM_ENDPOINTS({ - serviceId: i.key, - keyword: '', - duration: this.durationTime, - }); + this.getItemEndpoints(i.key, ''); } private searchEndpoint(search: string) { + this.getItemEndpoints(this.service.key, search); + } + private getItemEndpoints(serviceId: string, keyword?: string) { this.GET_ITEM_ENDPOINTS({ - serviceId: this.service.key, - keyword: search, + serviceId, + keyword, duration: this.durationTime, - }).then((endpoints: Array<{ key: string; label: string }>) => { - this.SET_ENDPOINTS(endpoints); }); } private chooseStatus(i: Option) { diff --git a/src/views/containers/dashboard.vue b/src/views/containers/dashboard.vue index b53ecec..b973bdc 100644 --- a/src/views/containers/dashboard.vue +++ b/src/views/containers/dashboard.vue @@ -83,6 +83,7 @@ limitations under the License. --> @Mutation('SET_TEMPLATES') private SET_TEMPLATES: any; private isRouterAlive: boolean = true; + private templatesErrors: boolean = false; public reload(): void { this.isRouterAlive = false; this.$nextTick(() => { @@ -105,13 +106,13 @@ limitations under the License. --> }); } private beforeMount() { - this.GET_ALL_TEMPLATES().then((allTemplate: ITemplate[]) => { - const dashboardTemplate = allTemplate.filter((item: ITemplate) => item.type === 'DASHBOARD'); + this.GET_ALL_TEMPLATES().then((templateResp: ITemplate[]) => { + const dashboardTemplate = templateResp.filter((item: ITemplate) => item.type === 'DASHBOARD'); const templatesConfig = dashboardTemplate.map((item: ITemplate) => JSON.parse(item.configuration)).flat(1); this.SET_TEMPLATES(templatesConfig); if (window.localStorage.getItem('version') !== '8.0') { window.localStorage.removeItem('dashboard'); - const template = allTemplate.filter((item: ITemplate) => item.type === 'DASHBOARD' && item.activated); + const template = templateResp.filter((item: ITemplate) => item.type === 'DASHBOARD' && item.activated); const templatesConfiguration = template.map((item: ITemplate) => JSON.parse(item.configuration)).flat(1); this.SET_COMPS_TREE(templatesConfiguration || []); window.localStorage.setItem('version', '8.0'); diff --git a/src/views/containers/index.vue b/src/views/containers/index.vue index fa6e51d..8d6fe9c 100644 --- a/src/views/containers/index.vue +++ b/src/views/containers/index.vue @@ -17,21 +17,27 @@ limitations under the License. --> <RkHeader @reloadFooter="reloadFooter" /> <router-view></router-view> <RkFooter ref="footer" /> + <AlertsContent /> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; - import RkHeader from '@/components/rk-header.vue'; - import RkFooter from '@/components/rk-footer.vue'; + import { State } from 'vuex-class'; + import { State as optionState } from '@/store/modules/global/selectors'; + import RkHeader from '@/views/components/common/rk-header.vue'; + import RkFooter from '@/views/components/common/rk-footer.vue'; + import AlertsContent from '@/views/components/common/alerts-content.vue'; @Component({ components: { RkHeader, RkFooter, + AlertsContent, }, }) export default class RouterIndex extends Vue { + @State('rocketOption') private stateDashboardOption!: optionState; private isRouterAlive: boolean = true; public reloadFooter(timeArray: Date[]): void { const footer: any = this.$refs.footer; diff --git a/src/views/containers/profile.vue b/src/views/containers/profile.vue index d341901..c032ed7 100644 --- a/src/views/containers/profile.vue +++ b/src/views/containers/profile.vue @@ -39,8 +39,8 @@ limitations under the License. --> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; - import { State, Getter, Mutation } from 'vuex-class'; - import { DurationTime } from '@/types/global'; + import { State, Getter } from 'vuex-class'; + import { State as profileState } from '@/store/modules/profile/profile-store'; import ProfileHeader from '@/views/components/profile/profile-header.vue'; import ProfileTaskList from '@/views/components/profile/task-list.vue'; import ProfileTraceDetail from '@/views/components/profile/profile-trace-detail.vue'; @@ -49,7 +49,7 @@ limitations under the License. --> components: { ProfileHeader, ProfileTaskList, ProfileTraceDetail }, }) export default class Profile extends Vue { - @State('profileStore') private profile: any; + @State('profileStore') private profile!: profileState; @Getter('durationTime') private durationTime: any; private beforeMount() { diff --git a/src/views/containers/topology/alarm/alarm-tool.vue b/src/views/containers/topology/alarm/alarm-tool.vue index 19dd5d6..5bdb556 100644 --- a/src/views/containers/topology/alarm/alarm-tool.vue +++ b/src/views/containers/topology/alarm/alarm-tool.vue @@ -46,6 +46,8 @@ limitations under the License. --> @Prop() private total!: number; @Prop() private keyword!: string; private pageNum: number = 1; + private alarmErrors: boolean = false; + private alarmErrorsDesc: string = ''; private handleFetch(pageNum: number) { this.pageNum = pageNum; this.GET_ALARM({ diff --git a/src/views/containers/topology/endpoint-dependency/index.vue b/src/views/containers/topology/endpoint-dependency/index.vue index c064fad..80dd4b7 100644 --- a/src/views/containers/topology/endpoint-dependency/index.vue +++ b/src/views/containers/topology/endpoint-dependency/index.vue @@ -37,7 +37,7 @@ limitations under the License. --> <script lang="ts"> import Vue from 'vue'; - import { Component, Watch, Prop } from 'vue-property-decorator'; + import { Component, Prop } from 'vue-property-decorator'; import { Action, Getter, State, Mutation } from 'vuex-class'; import ToolBarSelect from '@/views/components/dashboard/tool-bar/tool-bar-select.vue'; import ToolBarEndpointSelect from '@/views/components/dashboard/tool-bar/tool-bar-endpoint-select.vue'; diff --git a/src/views/containers/trace.vue b/src/views/containers/trace.vue index 16d7842..207e42a 100644 --- a/src/views/containers/trace.vue +++ b/src/views/containers/trace.vue @@ -25,7 +25,7 @@ limitations under the License. --> <script lang="ts"> import { Option } from '@/types/global'; import { Component, Vue, Prop } from 'vue-property-decorator'; - import { State, Action, Mutation } from 'vuex-class'; + import { State, Mutation } from 'vuex-class'; import TraceSearch from '@/views/components/trace/trace-search.vue'; import TraceTable from '@/views/components/trace/trace-table.vue'; import TraceDetail from '@/views/components/trace/trace-detail.vue';