You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2021/04/06 03:43:39 UTC
[skywalking-rocketbot-ui] branch master updated: feat: implement
Events in dashboard (#452)
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 d339675 feat: implement Events in dashboard (#452)
d339675 is described below
commit d339675c61ff0444f101edaedb92bd8a7bbca5b0
Author: Qiuxia Fan <fi...@outlook.com>
AuthorDate: Tue Apr 6 11:43:32 2021 +0800
feat: implement Events in dashboard (#452)
---
src/assets/lang/en.ts | 17 +-
src/assets/lang/zh.ts | 17 +-
src/components/rk-select.vue | 3 +-
src/constants/constant.ts | 10 +
src/graph/fragments/dashboard.ts | 25 ++
src/graph/query/dashboard.ts | 3 +
src/main.ts | 1 +
src/store/modules/dashboard/dashboard-data.ts | 108 ++++-
src/store/modules/dashboard/mutation-types.ts | 9 +
src/store/modules/global/index.ts | 40 +-
src/store/modules/global/selectors.ts | 110 +++--
src/types/dashboard.d.ts | 35 +-
src/utils/{dateFormatStep.ts => dateFormat.ts} | 37 ++
.../components/dashboard/charts/chart-bar.vue | 41 ++
.../charts/{chart-bar.vue => chart-heap.vue} | 101 ++---
.../components/dashboard/charts/chart-heatmap.vue | 1 +
.../components/dashboard/charts/chart-line.vue | 41 ++
.../components/dashboard/charts/chart-sankey.vue | 67 +++
src/views/components/dashboard/constant.ts | 22 +
src/views/components/dashboard/dashboard-comp.vue | 2 +-
src/views/components/dashboard/dashboard-item.vue | 69 ++-
.../dashboard/tool-bar/dashboard-events.vue | 490 +++++++++++++++++++++
.../dashboard/tool-bar/tool-bar-btns.vue | 75 ++--
.../components/dashboard/tool-bar/tool-bar.vue | 201 ++++++---
src/views/components/dashboard/tool-group.vue | 4 +-
src/views/components/dashboard/tool-nav.vue | 55 +--
src/views/components/log/log-bar.vue | 7 +-
src/views/components/log/log-conditions.vue | 2 +-
src/views/components/log/log-service-detail.vue | 1 -
src/views/components/profile/profile-task.vue | 5 +-
src/views/components/topology/topo-aside.vue | 6 +-
.../topology/topo-endpoint-dependency.vue | 2 +-
src/views/components/trace/trace-search.vue | 2 +-
src/views/containers/dashboard.vue | 14 +-
src/views/containers/topology/endpoint/index.vue | 85 ++--
src/views/containers/topology/instance/index.vue | 98 +++--
vue.config.js | 1 -
37 files changed, 1426 insertions(+), 381 deletions(-)
diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts
index 645d8c1..04b36fe 100644
--- a/src/assets/lang/en.ts
+++ b/src/assets/lang/en.ts
@@ -99,7 +99,7 @@ const m = {
range: 'Range',
timeRange: 'Time Range',
duration: 'Duration',
- startTime: 'startTime',
+ startTime: 'Start Time',
start: 'Start',
spans: 'Spans',
spanInfo: 'Span Info',
@@ -199,7 +199,22 @@ const m = {
logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable.
Check more details on the Configuration Vocabulary page`,
keywordsOfContentLogTips: 'Current storage of SkyWalking OAP server does not support this.',
+ setEvent: 'Set Event',
instanceAttributes: 'Instance Attributes',
+ serviceEvents: 'Service Events',
+ select: 'Select',
+ eventID: 'Event ID',
+ eventName: 'Event Name',
+ endTime: 'End Time',
+ instanceEvents: 'Instance Events',
+ endpointEvents: 'Endpoint Events',
+ enableEvents: 'Enable Events',
+ disableEvents: 'Disable Events',
+ eventSeries: 'Events Series',
+ eventsType: 'Event Type',
+ eventsMessage: 'Event Message',
+ eventsParameters: 'Event Parameters',
+ eventDetail: 'Event Detail',
value: 'Value',
tableHeader: 'Header Names',
tableValues: 'Table Values',
diff --git a/src/assets/lang/zh.ts b/src/assets/lang/zh.ts
index f222588..7b4a3d7 100644
--- a/src/assets/lang/zh.ts
+++ b/src/assets/lang/zh.ts
@@ -197,7 +197,22 @@ const m = {
viewLogs: '查看日志',
logsTagsTip: '只有core/default/searchableLogsTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。',
keywordsOfContentLogTips: 'SkyWalking OAP服务器的当前存储不支持此操作',
- instanceAttributes: '查看实例属性',
+ setEvent: '设置事件',
+ instanceAttributes: '实例属性',
+ serviceEvents: '服务事件',
+ select: '选择',
+ eventID: '事件ID',
+ eventName: '事件名称',
+ endTime: '结束事件',
+ instanceEvents: '实例事件',
+ endpointEvents: '端点事件',
+ enableEvents: '启动事件',
+ disableEvents: '禁用事件',
+ eventSeries: '事件系列',
+ eventsType: '事件类型',
+ eventsMessage: '事件消息',
+ eventsParameters: '事件参数',
+ eventDetail: '事件详情',
value: '数值',
tableHeader: '表头名称',
tableValues: '表值',
diff --git a/src/components/rk-select.vue b/src/components/rk-select.vue
index 4b69653..528c05a 100644
--- a/src/components/rk-select.vue
+++ b/src/components/rk-select.vue
@@ -46,7 +46,7 @@ limitations under the License. -->
<use xlink:href="#clear"></use>
</svg>
</div>
- <div class="rk-opt-wrapper scroll_bar_style">
+ <div class="rk-opt-wrapper">
<div
class="rk-opt ell"
@click="handleSelect(i)"
@@ -104,7 +104,6 @@ limitations under the License. -->
<style lang="scss" scoped>
.rk-bar-select {
position: relative;
- height: 30px;
justify-content: space-between;
border: 1px solid #ddd;
background: #fff;
diff --git a/src/constants/constant.ts b/src/constants/constant.ts
index 022719c..f67961e 100644
--- a/src/constants/constant.ts
+++ b/src/constants/constant.ts
@@ -31,3 +31,13 @@ export enum TimeType {
HOUR_TIME = 'HOUR',
DAY_TIME = 'DAY',
}
+
+export enum PageEventsType {
+ DASHBOARD_EVENTS = 'dashboardEvents',
+ TOPO_ENDPOINT_EVENTS = 'topoEndpointEvents',
+ TOPO_INSTANCE_EVENTS = 'topoInstanceEvents',
+}
+export enum PageTypes {
+ DASHBOARD = 'Dashboard',
+ LOG = 'Log',
+}
diff --git a/src/graph/fragments/dashboard.ts b/src/graph/fragments/dashboard.ts
index 2b762d7..2b46e60 100644
--- a/src/graph/fragments/dashboard.ts
+++ b/src/graph/fragments/dashboard.ts
@@ -42,6 +42,31 @@ export const addTemplate = {
`,
};
+export const fetchEvents = {
+ variable: ['$condition: EventQueryCondition'],
+ query: `
+ fetchEvents: queryEvents(condition: $condition) {
+ events {
+ uuid
+ source {
+ service
+ serviceInstance
+ endpoint
+ }
+ name
+ type
+ message
+ parameters {
+ key
+ value
+ }
+ startTime
+ endTime
+ }
+ total
+ }`,
+};
+
export const changeTemplate = {
variable: '$setting: DashboardSetting!',
query: `
diff --git a/src/graph/query/dashboard.ts b/src/graph/query/dashboard.ts
index 219577e..d95f6c1 100644
--- a/src/graph/query/dashboard.ts
+++ b/src/graph/query/dashboard.ts
@@ -27,6 +27,7 @@ import {
querySortMetrics,
queryMetricsValue,
queryMetricsValues,
+ fetchEvents,
} from '../fragments/dashboard';
export const queryTypeOfMetrics = `query queryTypeOfMetrics(${TypeOfMetrics.variable}) {${TypeOfMetrics.query}}`;
@@ -53,3 +54,5 @@ export const sortMetrics = `query queryData(${querySortMetrics.variable}) {${que
export const readMetricsValue = `query queryData(${queryMetricsValue.variable}) {${queryMetricsValue.query}}`;
export const readMetricsValues = `query queryData(${queryMetricsValues.variable}) {${queryMetricsValues.query}}`;
+
+export const queryEvents = `query queryData(${fetchEvents.variable}) {${fetchEvents.query}}`;
diff --git a/src/main.ts b/src/main.ts
index 1ee8746..0b4c5e2 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -33,6 +33,7 @@ import 'echarts/lib/chart/heatmap';
import 'echarts/lib/chart/sankey';
import 'echarts/lib/component/legend';
import 'echarts/lib/component/tooltip';
+import 'echarts/lib/component/markArea';
import VModal from 'vue-js-modal';
import { queryOAPTimeInfo } from './utils/localtime';
import './assets';
diff --git a/src/store/modules/dashboard/dashboard-data.ts b/src/store/modules/dashboard/dashboard-data.ts
index 1d17125..298a96c 100644
--- a/src/store/modules/dashboard/dashboard-data.ts
+++ b/src/store/modules/dashboard/dashboard-data.ts
@@ -16,25 +16,112 @@
*/
import { ActionTree, MutationTree, Commit, Dispatch } from 'vuex';
-import { CompsTree } from '@/types/dashboard';
+import { CompsTree, Event } from '@/types/dashboard';
import { AxiosResponse } from 'axios';
import graph from '@/graph';
import dashboardLayout from './dashboard-data-layout';
import dashboardQuery from './dashboard-data-query';
+import { QueryEventCondition } from '../../../types/dashboard';
+import { dateFormatTime } from '@/utils/dateFormat';
+import { DurationTime, Option } from '@/types/global';
+import * as types from './mutation-types';
+import { PageEventsType } from '@/constants/constant';
+const EntityType = ['Service', 'ServiceInstance', 'Endpoint'];
export interface State {
current: number;
group: number;
tree: CompsTree[];
+ serviceEvents: Event[];
+ serviceInstanceEvents: Event[];
+ endpointEvents: Event[];
+ enableEvents: boolean;
+ eventsPageType: string;
+ currentSeriesType: Option[];
}
const initState: State = {
+ serviceEvents: [],
+ endpointEvents: [],
+ serviceInstanceEvents: [],
+ enableEvents: false,
+ eventsPageType: PageEventsType.DASHBOARD_EVENTS,
+ currentSeriesType: [],
...dashboardLayout.state,
};
// mutations
const mutations: MutationTree<any> = {
...dashboardLayout.mutations,
+ [types.SET_DASHBOARD_EVENTS](state: State, param: { events: Event[]; type: string; duration: DurationTime }) {
+ const events = param.events.map((d: Event, index: number) => {
+ d.entityType = param.type;
+ d.startTime = dateFormatTime(new Date(Number(d.startTime)), param.duration.step);
+ d.endTime = dateFormatTime(new Date(Number(d.endTime)), param.duration.step);
+ if (index > 2) {
+ return d;
+ }
+ for (const item of state.currentSeriesType) {
+ if (item.key === param.type) {
+ d.checked = true;
+ }
+ }
+ return d;
+ });
+ if (param.type === EntityType[0]) {
+ state.serviceEvents = events;
+ } else if (param.type === EntityType[1]) {
+ state.serviceInstanceEvents = events;
+ } else {
+ state.endpointEvents = events;
+ }
+ },
+ [types.SET_CHECKED_EVENTS](state: State, selectedEvents: Event[]) {
+ for (const event of selectedEvents) {
+ if (event.entityType === EntityType[0]) {
+ for (const item of state.serviceEvents) {
+ if (event.uuid === item.uuid && event.entityType === item.entityType) {
+ item.checked = event.checked;
+ break;
+ }
+ }
+ }
+ if (event.entityType === EntityType[1]) {
+ for (const item of state.serviceInstanceEvents) {
+ if (event.uuid === item.uuid && event.entityType === item.entityType) {
+ item.checked = event.checked;
+ break;
+ }
+ }
+ }
+ if (event.entityType === EntityType[2]) {
+ for (const item of state.endpointEvents) {
+ if (event.uuid === item.uuid && event.entityType === item.entityType) {
+ item.checked = event.checked;
+ break;
+ }
+ }
+ }
+ }
+ },
+ [types.SET_ENABLE_EVENTS](state: State, enable: boolean) {
+ state.enableEvents = enable;
+ },
+ [types.SET_EVENTS_PAGE_TYPE](state: State, type: string) {
+ state.eventsPageType = type;
+ },
+ [types.SET_CURRENT_SERIES_TYPE](state: State, data: { item: Option; index: number }) {
+ if (data.index > -1) {
+ state.currentSeriesType.splice(data.index, 1);
+ } else {
+ state.currentSeriesType.push(data.item);
+ }
+ },
+ [types.SET_CLEAR_SELECTED_EVENTS](state: State) {
+ for (const item of [...state.serviceEvents, ...state.serviceInstanceEvents, ...state.endpointEvents]) {
+ item.checked = false;
+ }
+ },
};
// actions
@@ -108,15 +195,22 @@ const actions: ActionTree<State, any> = {
return res.data.data.getAllTemplates || [];
});
},
- ADD_TEMPLATE(context, params) {
+ GET_EVENT(context: { commit: Commit }, params: { condition: QueryEventCondition; type: string }) {
return graph
- .query('mutationAddTemplate')
- .params({ setting: params })
+ .query('queryEvents')
+ .params({ condition: params.condition })
.then((res: AxiosResponse) => {
- if (!res.data.data) {
- return;
+ if (!(res.data.data && res.data.data.fetchEvents)) {
+ context.commit('SET_DASHBOARD_EVENTS', { events: [], type: params.type, duration: params.condition.time });
+ return [];
}
- return res.data.data.addTemplate || [];
+ context.commit('SET_DASHBOARD_EVENTS', {
+ events: res.data.data.fetchEvents.events,
+ type: params.type,
+ duration: params.condition.time,
+ });
+
+ return res.data.data.fetchEvents.events || [];
});
},
};
diff --git a/src/store/modules/dashboard/mutation-types.ts b/src/store/modules/dashboard/mutation-types.ts
index aa18646..eef9b1c 100644
--- a/src/store/modules/dashboard/mutation-types.ts
+++ b/src/store/modules/dashboard/mutation-types.ts
@@ -36,6 +36,12 @@ export const SET_INSTANCE_INFO = 'SET_INSTANCE_INFO';
export const SET_TEMPLATES = 'SET_TEMPLATES';
export const UPDATE_DASHBOARD = 'UPDATE_DASHBOARD';
export const SET_PAGE_TYPE = 'SET_PAGE_TYPE';
+export const SET_ALL_ENDPOINT_EVENTS = 'SET_ALL_ENDPOINT_EVENTS';
+export const SET_ALL_SERVICE_EVENTS = 'SET_ALL_SERVICE_EVENTS';
+export const SET_ALL_INSTANCE_EVENTS = 'SET_ALL_INSTANCE_EVENTS';
+export const SET_EVENTS_PAGE_TYPE = 'SET_EVENTS_PAGE_TYPE';
+export const SET_CURRENT_SERIES_TYPE = 'SET_CURRENT_SERIES_TYPE';
+export const SET_CLEAR_SELECTED_EVENTS = 'SET_CLEAR_SELECTED_EVENTS';
// comp
export const SET_CURRENT_GROUP = 'SET_CURRENT_GROUP';
@@ -55,3 +61,6 @@ export const SWICH_CURRENTCOMP = 'SWICH_CURRENTCOMP';
export const SET_GROUP_QUERY = 'SET_GROUP_QUERY';
export const EDIT_COMP_CONFIG = 'EDIT_COMP_CONFIG';
export const SET_COMPS_ID = 'SET_COMPS_ID';
+export const SET_DASHBOARD_EVENTS = 'SET_DASHBOARD_EVENTS';
+export const SET_CHECKED_EVENTS = 'SET_CHECKED_EVENTS';
+export const SET_ENABLE_EVENTS = 'SET_ENABLE_EVENTS';
diff --git a/src/store/modules/global/index.ts b/src/store/modules/global/index.ts
index 68f91a3..0d7cf44 100644
--- a/src/store/modules/global/index.ts
+++ b/src/store/modules/global/index.ts
@@ -19,48 +19,10 @@ import * as types from '@/store/mutation-types';
import { Duration, DurationTime } from '@/types/global';
import getDurationRow from '@/utils/datetime';
import getLocalTime from '@/utils/localtime';
-import dateFormatStep from '@/utils/dateFormatStep';
+import dateFormatStep, { dateFormatTime } from '@/utils/dateFormat';
import { ActionTree, Commit, MutationTree } from 'vuex';
let timer: any = null;
-
-const dateFormatTime = (date: Date, step: string): string => {
- const year = date.getFullYear();
- const monthTemp = date.getMonth() + 1;
- let month: string = `${monthTemp}`;
- if (monthTemp < 10) {
- month = `0${monthTemp}`;
- }
- if (step === 'MONTH') {
- return `${year}-${month}`;
- }
- const dayTemp = date.getDate();
- let day: string = `${dayTemp}`;
- if (dayTemp < 10) {
- day = `0${dayTemp}`;
- }
- if (step === 'DAY') {
- return `${month}-${day}`;
- }
- const hourTemp = date.getHours();
- let hour: string = `${hourTemp}`;
- if (hourTemp < 10) {
- hour = `0${hourTemp}`;
- }
- if (step === 'HOUR') {
- return `${month}-${day} ${hour}`;
- }
- const minuteTemp = date.getMinutes();
- let minute: string = `${minuteTemp}`;
- if (minuteTemp < 10) {
- minute = `0${minuteTemp}`;
- }
- if (step === 'MINUTE') {
- return `${hour}:${minute}\n${month}-${day}`;
- }
- return '';
-};
-
export interface State {
durationRow: Duration;
eventStack: any;
diff --git a/src/store/modules/global/selectors.ts b/src/store/modules/global/selectors.ts
index 84eecfb..72832f2 100644
--- a/src/store/modules/global/selectors.ts
+++ b/src/store/modules/global/selectors.ts
@@ -19,22 +19,20 @@ import { Commit, ActionTree, MutationTree, Dispatch } from 'vuex';
import * as types from '../dashboard/mutation-types';
import { AxiosResponse } from 'axios';
import graph from '@/graph';
-import { Duration } from '@/types/global';
+import { Duration, DurationTime, Option } from '@/types/global';
+import { PageTypes } from '@/constants/constant';
-interface Options {
- key: string;
- label: string;
-}
+const EntityType = ['Service', 'ServiceInstance', 'Endpoint'];
export interface State {
- services: Options[];
- currentService: Options;
- databases: Options[];
- currentDatabase: Options;
- endpoints: Options[];
- currentEndpoint: Options;
- instances: Options[];
- currentInstance: Options;
- updateDashboard: object;
+ services: Option[];
+ currentService: Option;
+ databases: Option[];
+ currentDatabase: Option;
+ endpoints: Option[];
+ currentEndpoint: Option;
+ instances: Option[];
+ currentInstance: Option;
+ updateDashboard: { key: string; label?: string | undefined };
pageType: string;
}
@@ -49,26 +47,28 @@ const initState: State = {
currentInstance: { key: '', label: '' },
databases: [],
currentDatabase: { key: '', label: '' },
- updateDashboard: {},
+ updateDashboard: { key: '' },
pageType: '',
};
// mutations
const mutations: MutationTree<State> = {
- [types.SET_SERVICES](state: State, data: Options[]) {
+ [types.SET_SERVICES](state: State, data: Option[]) {
state.services = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data;
state.currentService = state.services[0] || {};
},
- [types.SET_CURRENT_SERVICE](state: State, service: Options) {
+ [types.SET_CURRENT_SERVICE](state: State, service: Option) {
state.currentService = service;
- state.updateDashboard = service;
+ if (state.pageType !== PageTypes.DASHBOARD) {
+ state.updateDashboard = service;
+ }
},
- [types.UPDATE_DASHBOARD](state: State) {
- state.updateDashboard = { key: new Date().getTime() };
+ [types.UPDATE_DASHBOARD](state: State, param?: { key: string }) {
+ state.updateDashboard = param || { key: String(new Date().getTime()) };
},
- [types.SET_ENDPOINTS](state: State, data: Options[]) {
+ [types.SET_ENDPOINTS](state: State, data: Option[]) {
state.endpoints = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data;
if (!state.endpoints.length) {
state.currentEndpoint = { key: '', label: '' };
@@ -76,11 +76,11 @@ const mutations: MutationTree<State> = {
}
state.currentEndpoint = state.endpoints[0];
},
- [types.SET_CURRENT_ENDPOINT](state: State, endpoint: Options) {
+ [types.SET_CURRENT_ENDPOINT](state: State, endpoint: Option) {
state.currentEndpoint = endpoint;
state.updateDashboard = endpoint;
},
- [types.SET_INSTANCES](state: State, data: Options[]) {
+ [types.SET_INSTANCES](state: State, data: Option[]) {
state.instances = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data;
if (!state.instances.length) {
state.currentInstance = { key: '', label: '' };
@@ -88,11 +88,11 @@ const mutations: MutationTree<State> = {
}
state.currentInstance = state.instances[0];
},
- [types.SET_CURRENT_INSTANCE](state: State, instance: Options) {
+ [types.SET_CURRENT_INSTANCE](state: State, instance: Option) {
state.currentInstance = instance;
state.updateDashboard = instance;
},
- [types.SET_DATABASES](state: State, data: Options[]) {
+ [types.SET_DATABASES](state: State, data: Option[]) {
state.databases = data;
if (!data.length) {
state.currentDatabase = { key: '', label: '' };
@@ -100,7 +100,7 @@ const mutations: MutationTree<State> = {
}
state.currentDatabase = data[0];
},
- [types.SET_CURRENT_DATABASE](state: State, service: Options) {
+ [types.SET_CURRENT_DATABASE](state: State, service: Option) {
state.currentDatabase = service;
state.updateDashboard = service;
},
@@ -111,7 +111,7 @@ const mutations: MutationTree<State> = {
// actions
const actions: ActionTree<State, any> = {
- GET_SERVICES(context: { commit: Commit }, params: { duration: any; keyword: string }) {
+ GET_SERVICES(context: { commit: Commit }, params: { duration: DurationTime; keyword: string }) {
if (!params.keyword) {
params.keyword = '';
}
@@ -123,7 +123,7 @@ const actions: ActionTree<State, any> = {
});
},
GET_SERVICE_ENDPOINTS(
- context: { commit: Commit; state: any },
+ context: { commit: Commit; state: State },
params: { keyword: string; currentService?: { key: string; label: string } },
) {
if (!context.state.currentService.key) {
@@ -143,7 +143,7 @@ const actions: ActionTree<State, any> = {
context.commit(types.SET_ENDPOINTS, res.data.data.getEndpoints);
});
},
- GET_SERVICE_INSTANCES(context: { commit: Commit; state: any }, params: any) {
+ GET_SERVICE_INSTANCES(context: { commit: Commit; state: State }, params: any) {
if (!context.state.currentService.key) {
context.commit(types.SET_INSTANCES, []);
return;
@@ -163,15 +163,55 @@ const actions: ActionTree<State, any> = {
context.commit(types.SET_DATABASES, res.data.data.services);
});
},
- SELECT_SERVICE(context: { commit: Commit; dispatch: Dispatch }, params: any) {
+ SELECT_SERVICE(
+ context: { commit: Commit; dispatch: Dispatch; state: State },
+ params: { service: Option; duration: DurationTime; callback?: any },
+ ) {
context.commit('SET_CURRENT_SERVICE', params.service);
- context.dispatch('GET_SERVICE_ENDPOINTS', {});
- context.dispatch('GET_SERVICE_INSTANCES', { duration: params.duration });
+ context.dispatch('GET_SERVICE_ENDPOINTS', {}).then(() => {
+ if (context.state.pageType !== PageTypes.DASHBOARD || !params.callback) {
+ return;
+ }
+ params.callback({
+ condition: {
+ time: params.duration,
+ size: 20,
+ source: {
+ service: params.service.label,
+ endpoint: context.state.currentEndpoint.label,
+ },
+ },
+ type: EntityType[2],
+ });
+ });
+ context.dispatch('GET_SERVICE_INSTANCES', { duration: params.duration }).then(() => {
+ if (context.state.pageType === PageTypes.DASHBOARD && !params.callback) {
+ context.commit('UPDATE_DASHBOARD', params.service);
+ }
+ if (context.state.pageType !== PageTypes.DASHBOARD || !params.callback) {
+ return;
+ }
+ params
+ .callback({
+ condition: {
+ time: params.duration,
+ size: 20,
+ source: {
+ service: params.service.label,
+ serviceInstance: context.state.currentInstance.label,
+ },
+ },
+ type: EntityType[1],
+ })
+ .then(() => {
+ context.commit('UPDATE_DASHBOARD', params.service);
+ });
+ });
},
- SELECT_ENDPOINT(context: { commit: Commit; dispatch: Dispatch; state: any; rootState: any }, params: any) {
+ SELECT_ENDPOINT(context: { commit: Commit; dispatch: Dispatch; state: State; rootState: any }, params: any) {
context.commit('SET_CURRENT_ENDPOINT', params.endpoint);
},
- SELECT_INSTANCE(context: { commit: Commit; dispatch: Dispatch; state: any; rootState: any }, params: any) {
+ SELECT_INSTANCE(context: { commit: Commit; dispatch: Dispatch; state: State; rootState: any }, params: any) {
context.commit('SET_CURRENT_INSTANCE', params.instance);
},
SELECT_DATABASE(context: { commit: Commit; dispatch: Dispatch }, params: any) {
@@ -229,7 +269,7 @@ const actions: ActionTree<State, any> = {
return res.data.data.getServiceInstances;
});
},
- GET_ITEM_SERVICES(context, params: { duration: any; keyword: string }) {
+ GET_ITEM_SERVICES(context, params: { duration: DurationTime; keyword: string }) {
if (!params.keyword) {
params.keyword = '';
}
diff --git a/src/types/dashboard.d.ts b/src/types/dashboard.d.ts
index ace8a2f..a96a432 100644
--- a/src/types/dashboard.d.ts
+++ b/src/types/dashboard.d.ts
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Option } from './global';
+import { Duration } from './global';
export interface Value {
value: number;
}
@@ -67,3 +67,36 @@ export interface DashboardTemplate {
activated: boolean;
disabled: boolean;
}
+
+export interface QueryEventCondition {
+ uuid: string;
+ source: SourceInput;
+ name: string;
+ type: EventType;
+ time: Duration;
+ order: string;
+ size: number;
+}
+
+type SourceInput = {
+ service: String;
+ serviceInstance: String;
+ endpoint: String;
+};
+export enum EventType {
+ Normal,
+ Error,
+}
+
+export type Event = {
+ uuid: string;
+ source: SourceInput;
+ name: string;
+ type: string;
+ message: string;
+ parameters: { key: string; value: string }[];
+ startTime: number | string;
+ endTime: number | string;
+ entityType?: string;
+ checked?: boolean;
+};
diff --git a/src/utils/dateFormatStep.ts b/src/utils/dateFormat.ts
similarity index 66%
rename from src/utils/dateFormatStep.ts
rename to src/utils/dateFormat.ts
index 90967d9..3ad6952 100644
--- a/src/utils/dateFormatStep.ts
+++ b/src/utils/dateFormat.ts
@@ -51,3 +51,40 @@ export default function dateFormatStep(date: Date, step: string, monthDayDiff?:
}
return '';
}
+
+export const dateFormatTime = (date: Date, step: string): string => {
+ const year = date.getFullYear();
+ const monthTemp = date.getMonth() + 1;
+ let month: string = `${monthTemp}`;
+ if (monthTemp < 10) {
+ month = `0${monthTemp}`;
+ }
+ if (step === 'MONTH') {
+ return `${year}-${month}`;
+ }
+ const dayTemp = date.getDate();
+ let day: string = `${dayTemp}`;
+ if (dayTemp < 10) {
+ day = `0${dayTemp}`;
+ }
+ if (step === 'DAY') {
+ return `${month}-${day}`;
+ }
+ const hourTemp = date.getHours();
+ let hour: string = `${hourTemp}`;
+ if (hourTemp < 10) {
+ hour = `0${hourTemp}`;
+ }
+ if (step === 'HOUR') {
+ return `${month}-${day} ${hour}`;
+ }
+ const minuteTemp = date.getMinutes();
+ let minute: string = `${minuteTemp}`;
+ if (minuteTemp < 10) {
+ minute = `0${minuteTemp}`;
+ }
+ if (step === 'MINUTE') {
+ return `${hour}:${minute}\n${month}-${day}`;
+ }
+ return '';
+};
diff --git a/src/views/components/dashboard/charts/chart-bar.vue b/src/views/components/dashboard/charts/chart-bar.vue
index b438f81..16dbb49 100644
--- a/src/views/components/dashboard/charts/chart-bar.vue
+++ b/src/views/components/dashboard/charts/chart-bar.vue
@@ -18,17 +18,40 @@ limitations under the License. -->
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator';
+ import { Event } from '@/types/dashboard';
@Component
export default class ChartBar extends Vue {
@Prop() private data!: any;
@Prop() private intervalTime!: any;
+ @Prop() private itemEvents!: Event[];
public resize() {
const chart: any = this.$refs.chart;
chart.myChart.resize();
}
get option() {
const keys = Object.keys(this.data || {}).filter((i: any) => Array.isArray(this.data[i]) && this.data[i].length);
+ const startP = keys.length > 1 ? 50 : 15;
+ const diff = 15;
+ const markAreas = (this.itemEvents || []).map((event: Event, index: number) => {
+ return [
+ {
+ name: `${event.name}:${event.type}`,
+ xAxis: event.startTime,
+ y: startP + diff * index,
+ itemStyle: {
+ borderWidth: 2,
+ borderColor: event.type === 'Normal' ? '#5dc859' : '#FF0087',
+ color: event.type === 'Normal' ? '#5dc859' : '#FF0087',
+ },
+ },
+ {
+ name: event.message,
+ xAxis: event.endTime,
+ y: startP + diff * (index + 1),
+ },
+ ];
+ });
const temp = keys.map((i: string, index: number) => {
return {
data: this.data[i].map((item: any, itemIndex: number) => [this.intervalTime[itemIndex], item]),
@@ -41,6 +64,23 @@ limitations under the License. -->
width: 1.5,
type: 'dotted',
},
+ markArea:
+ index === 0
+ ? {
+ silent: false,
+ data: markAreas,
+ label: {
+ show: false,
+ width: 60,
+ },
+ emphasis: {
+ label: {
+ position: 'bottom',
+ show: true,
+ },
+ },
+ }
+ : undefined,
};
});
let color: string[] = [];
@@ -79,6 +119,7 @@ limitations under the License. -->
backgroundColor: 'rgb(50,50,50)',
textStyle: {
fontSize: 13,
+ color: '#ccc',
},
enterable: true,
extraCssText: 'max-height: 300px; overflow: auto;',
diff --git a/src/views/components/dashboard/charts/chart-bar.vue b/src/views/components/dashboard/charts/chart-heap.vue
similarity index 52%
copy from src/views/components/dashboard/charts/chart-bar.vue
copy to src/views/components/dashboard/charts/chart-heap.vue
index b438f81..a38025f 100644
--- a/src/views/components/dashboard/charts/chart-bar.vue
+++ b/src/views/components/dashboard/charts/chart-heap.vue
@@ -14,85 +14,39 @@ See the License for the specific language governing permissions and
limitations under the License. -->
<template>
- <RkEcharts ref="chart" :option="option" :autoResize="true" />
+ <rk-panel :title="title">
+ <RkEcharts height="215px" :option="responseConfig" />
+ </rk-panel>
</template>
+
<script lang="ts">
- import { Vue, Component, Prop } from 'vue-property-decorator';
+ import Vue from 'vue';
+ import { Component, Prop } from 'vue-property-decorator';
@Component
- export default class ChartBar extends Vue {
- @Prop() private data!: any;
+ export default class ChartHeap extends Vue {
+ @Prop() private title!: string;
+ @Prop() private stateDashboard!: any;
@Prop() private intervalTime!: any;
- public resize() {
- const chart: any = this.$refs.chart;
- chart.myChart.resize();
- }
- get option() {
- const keys = Object.keys(this.data || {}).filter((i: any) => Array.isArray(this.data[i]) && this.data[i].length);
- const temp = keys.map((i: string, index: number) => {
- return {
- data: this.data[i].map((item: any, itemIndex: number) => [this.intervalTime[itemIndex], item]),
- name: i,
- type: 'bar',
- symbol: 'none',
- barMaxWidth: 10,
- stack: '总量',
- lineStyle: {
- width: 1.5,
- type: 'dotted',
- },
- };
- });
- let color: string[] = [];
- switch (keys.length) {
- case 2:
- color = ['#FF6A84', '#a0b1e6'];
- break;
- case 1:
- color = ['#3f96e3'];
- break;
- default:
- color = [
- '#30A4EB',
- '#45BFC0',
- '#FFCC55',
- '#FF6A84',
- '#a0a7e6',
- '#c23531',
- '#2f4554',
- '#61a0a8',
- '#d48265',
- '#91c7ae',
- '#749f83',
- '#ca8622',
- '#bda29a',
- '#6e7074',
- '#546570',
- '#c4ccd3',
- ];
- break;
- }
+ get responseConfig() {
return {
- color,
+ color: ['#3f96e3', '#3fbde3'],
tooltip: {
trigger: 'axis',
backgroundColor: 'rgb(50,50,50)',
textStyle: {
fontSize: 13,
+ color: '#ccc',
},
- enterable: true,
- extraCssText: 'max-height: 300px; overflow: auto;',
},
legend: {
- type: 'scroll',
- show: keys.length === 1 ? false : true,
icon: 'circle',
top: 0,
left: 0,
itemWidth: 12,
},
grid: {
- top: keys.length === 1 ? 15 : 40,
+ top: 10,
left: 0,
right: 10,
bottom: 5,
@@ -115,7 +69,34 @@ limitations under the License. -->
splitLine: { lineStyle: { color: '#c1c5ca41', type: 'dashed' } },
axisLabel: { color: '#9da5b2', fontSize: '11' },
},
- series: temp,
+ series: [
+ {
+ data: this.stateDashboard.instanceInfo.heap.map((i: any, index: number) => [
+ this.intervalTime[index],
+ (i.value / 1048576).toFixed(2),
+ ]),
+ name: this.stateDashboard.instanceInfo.heap.length ? 'Value' : null,
+ type: 'line',
+ symbol: 'none',
+ areaStyle: {},
+ lineStyle: {
+ width: 1.5,
+ },
+ },
+ {
+ data: this.stateDashboard.instanceInfo.heap.map((i: any, index: number) => [
+ this.intervalTime[index],
+ ((this.stateDashboard.instanceInfo.maxHeap[index].value - i.value) / 1048576).toFixed(2),
+ ]),
+ name: this.stateDashboard.instanceInfo.heap.length ? 'Free' : null,
+ type: 'line',
+ symbol: 'none',
+ areaStyle: {},
+ lineStyle: {
+ width: 1.5,
+ },
+ },
+ ],
};
}
}
diff --git a/src/views/components/dashboard/charts/chart-heatmap.vue b/src/views/components/dashboard/charts/chart-heatmap.vue
index 5d95b9c..27d6c2f 100644
--- a/src/views/components/dashboard/charts/chart-heatmap.vue
+++ b/src/views/components/dashboard/charts/chart-heatmap.vue
@@ -64,6 +64,7 @@ limitations under the License. -->
formatter: (a: any) => `${a.data[1] * 100}${this.item.unit} [ ${a.data[2]} ]`,
textStyle: {
fontSize: 13,
+ color: '#ccc',
},
},
grid: {
diff --git a/src/views/components/dashboard/charts/chart-line.vue b/src/views/components/dashboard/charts/chart-line.vue
index feef6a4..1ba0622 100644
--- a/src/views/components/dashboard/charts/chart-line.vue
+++ b/src/views/components/dashboard/charts/chart-line.vue
@@ -18,18 +18,41 @@ limitations under the License. -->
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator';
+ import { Event } from '@/types/dashboard';
@Component
export default class ChartLine extends Vue {
@Prop() private data!: any;
@Prop() private type!: string;
@Prop() private intervalTime!: any;
+ @Prop() private itemEvents!: Event[];
public resize() {
const chart: any = this.$refs.chart;
chart.myChart.resize();
}
get option() {
const keys = Object.keys(this.data || {}).filter((i: any) => Array.isArray(this.data[i]) && this.data[i].length);
+ const startP = keys.length > 1 ? 50 : 15;
+ const diff = 10;
+ const markAreas = (this.itemEvents || []).map((event: Event, index: number) => {
+ return [
+ {
+ name: `${event.name}:${event.type}`,
+ xAxis: event.startTime,
+ y: startP + diff * index,
+ itemStyle: {
+ borderWidth: 2,
+ borderColor: event.type === 'Normal' ? '#5dc859' : '#FF0087',
+ color: event.type === 'Normal' ? '#5dc859' : '#FF0087',
+ },
+ },
+ {
+ name: event.message,
+ xAxis: event.endTime,
+ y: startP + diff * (index + 1),
+ },
+ ];
+ });
const temp = keys.map((i: any, index: number) => {
const serie: any = {
data: this.data[i].map((item: any, itemIndex: number) => [this.intervalTime[itemIndex], item]),
@@ -41,6 +64,23 @@ limitations under the License. -->
width: 1.5,
type: 'solid',
},
+ markArea:
+ index === 0
+ ? {
+ silent: false,
+ data: markAreas,
+ label: {
+ show: false,
+ width: 60,
+ },
+ emphasis: {
+ label: {
+ position: 'bottom',
+ show: true,
+ },
+ },
+ }
+ : undefined,
};
if (this.type === 'areaChart') {
serie.areaStyle = {
@@ -85,6 +125,7 @@ limitations under the License. -->
backgroundColor: 'rgb(50,50,50)',
textStyle: {
fontSize: 13,
+ color: '#ccc',
},
enterable: true,
extraCssText: 'max-height: 300px; overflow: auto;',
diff --git a/src/views/components/dashboard/charts/chart-sankey.vue b/src/views/components/dashboard/charts/chart-sankey.vue
new file mode 100644
index 0000000..13cd062
--- /dev/null
+++ b/src/views/components/dashboard/charts/chart-sankey.vue
@@ -0,0 +1,67 @@
+<!-- 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>
+ <RkEcharts ref="chart" :option="option" :autoResize="true" />
+</template>
+
+<script lang="ts">
+ import Vue from 'vue';
+ import { Component, Prop } from 'vue-property-decorator';
+
+ @Component
+ export default class ChartSankey extends Vue {
+ @Prop() private title!: string;
+ @Prop() private data!: any;
+ @Prop() private intervalTime!: any;
+ get option() {
+ return {
+ tooltip: {
+ trigger: 'item',
+ triggerOn: 'mousemove',
+ backgroundColor: 'rgb(50,50,50)',
+ textStyle: {
+ fontSize: 13,
+ color: '#ccc',
+ },
+ formatter: (a: any) => a.data.tip,
+ },
+ series: [
+ {
+ type: 'sankey',
+ left: '30px',
+ top: '20px',
+ bottom: '20px',
+ label: {
+ formatter: (a: any) => a.data.content,
+ },
+ animation: false,
+ color: ['#bf99f8', '#3fe1da', '#6be6c1', '#3fcfdc', '#626c91', '#3fbcde', '#a0a7e6', '#3fa9e1', '#96dee8'],
+ data: this.data.nodes,
+ links: this.data.calls,
+ itemStyle: {
+ borderWidth: 0,
+ },
+ lineStyle: {
+ color: 'source',
+ opacity: 0.12,
+ },
+ },
+ ],
+ visualMap: this.data.visualMap,
+ };
+ }
+ }
+</script>
diff --git a/src/views/components/dashboard/constant.ts b/src/views/components/dashboard/constant.ts
index fcd3950..e104c49 100644
--- a/src/views/components/dashboard/constant.ts
+++ b/src/views/components/dashboard/constant.ts
@@ -29,3 +29,25 @@ export enum QueryTypes {
READHEATMAP = 'readHeatMap',
ReadSampledRecords = 'readSampledRecords',
}
+export const UpdateDashboardEvents = 'UpdateDashboardEvents';
+export const SeriesTypes = [
+ { key: 'Service', label: 'Service Events' },
+ { key: 'Endpoint', label: 'Service Endpoint Events' },
+ { key: 'ServiceInstance', label: 'Service Instance Events' },
+];
+export const EventsHeaders = [
+ { text: 'eventID', class: 'uuid' },
+ { text: 'eventName', class: 'name' },
+ { text: 'eventsType', class: 'type' },
+ { text: 'startTime', class: 'startTime' },
+ { text: 'endTime', class: 'endTime' },
+];
+export const EventsDetailHeaders = [
+ { text: 'eventID', class: 'uuid' },
+ { text: 'eventName', class: 'name' },
+ { text: 'eventsType', class: 'type' },
+ { text: 'startTime', class: 'startTime' },
+ { text: 'endTime', class: 'endTime' },
+ { text: 'eventsMessage', class: 'message' },
+ { text: 'eventsParameters', class: 'parameters' },
+];
diff --git a/src/views/components/dashboard/dashboard-comp.vue b/src/views/components/dashboard/dashboard-comp.vue
index d03d57d..6614a5f 100644
--- a/src/views/components/dashboard/dashboard-comp.vue
+++ b/src/views/components/dashboard/dashboard-comp.vue
@@ -17,7 +17,7 @@ limitations under the License. -->
<nav class="rk-dashboard-comp-nav mb-15">
<a
class="rk-dashboard-comp-nav-i b mr-20"
- v-if="value.length"
+ v-show="value.length"
@click="
current = key;
configMode = false;
diff --git a/src/views/components/dashboard/dashboard-item.vue b/src/views/components/dashboard/dashboard-item.vue
index 8df84fc..dabf924 100644
--- a/src/views/components/dashboard/dashboard-item.vue
+++ b/src/views/components/dashboard/dashboard-item.vue
@@ -15,23 +15,21 @@ limitations under the License. -->
<template>
<div class="rk-dashboard-item" :class="`g-sm-${width}`" :style="`height:${height}px;`">
<div class="rk-dashboard-item-title ell">
- <svg class="icon cp red r" v-show="rocketGlobal.edit" @click="deleteItem(index)">
- <use xlink:href="#file-deletion"></use>
- </svg>
+ <span v-show="rocketGlobal.edit" @click="deleteItem(index)">
+ <rk-icon class="r edit red" icon="file-deletion" />
+ </span>
<span>{{ title }}</span>
<span v-show="unit"> ( {{ unit }} ) </span>
<span v-show="status === 'UNKNOWN'" class="item-status">( {{ $t('unknownMetrics') }} )</span>
<span v-show="!rocketGlobal.edit && !pageTypes.includes(type)" @click="editComponentConfig">
- <svg class="icon cp r">
- <use xlink:href="#lock"></use>
- </svg>
+ <rk-icon class="r edit" icon="keyboard_control" v-tooltip:bottom="{ content: $t('editConfig') }" />
</span>
<span v-show="!rocketGlobal.edit && itemConfig.chartType === 'ChartTable'" @click="copyTable">
<rk-icon class="r cp" icon="review-list" />
</span>
</div>
- <div class="rk-dashboard-item-body">
- <div style="height:100%; width:100%">
+ <div class="rk-dashboard-item-body" ref="chartBody">
+ <div style="height:100%;width:100%">
<component
:is="rocketGlobal.edit ? 'ChartEdit' : itemConfig.chartType"
ref="chart"
@@ -40,6 +38,7 @@ limitations under the License. -->
:intervalTime="intervalTime"
:data="chartSource"
:type="type"
+ :itemEvents="itemEvents"
@updateStatus="(type, value) => setStatus(type, value)"
></component>
</div>
@@ -70,11 +69,14 @@ limitations under the License. -->
import charts from './charts';
import dayjs from 'dayjs';
- import { QueryTypes } from './constant';
+ import { QueryTypes, UpdateDashboardEvents } from './constant';
import { TopologyType, ObjectsType } from '../../../constants/constant';
import { CalculationType } from './charts/constant';
import { State as globalState } from '@/store/modules/global';
import { State as optionState } from '@/store/modules/global/selectors';
+ import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
+ import { Event } from '@/types/dashboard';
+ import { EntityType } from './charts/constant';
import copy from '@/utils/copy';
@Component({
@@ -82,6 +84,7 @@ limitations under the License. -->
})
export default class DashboardItem extends Vue {
@State('rocketbot') private rocketGlobal!: globalState;
+ @State('rocketData') private rocketData!: rocketData;
@Mutation('EDIT_COMP_CONFIG') private EDIT_COMP_CONFIG: any;
@Mutation('DELETE_COMP') private DELETE_COMP: any;
@Mutation('rocketTopo/DELETE_TOPO_ENDPOINT') private DELETE_TOPO_ENDPOINT: any;
@@ -95,7 +98,7 @@ limitations under the License. -->
@Prop() private updateObjects!: string;
@Prop() private rocketOption!: optionState;
- private pageTypes = [TopologyType.TOPOLOGY_ENDPOINT, TopologyType.TOPOLOGY_INSTANCE] as any[];
+ private pageTypes = [TopologyType.TOPOLOGY_ENDPOINT, TopologyType.TOPOLOGY_INSTANCE] as string[];
private dialogConfigVisible = false;
private status = 'UNKNOWN';
private title = 'Title';
@@ -104,6 +107,7 @@ limitations under the License. -->
private height = 300;
private chartSource: any = {};
private itemConfig: any = {};
+ private itemEvents: Event[] = [];
private created() {
this.status = this.item.metricType;
@@ -112,6 +116,7 @@ limitations under the License. -->
this.height = this.item.height;
this.unit = this.item.unit;
this.itemConfig = this.item;
+ this.itemEvents = this.eventsFilter();
const types = [
ObjectsType.UPDATE_INSTANCES,
ObjectsType.UPDATE_ENDPOINTS,
@@ -339,8 +344,49 @@ limitations under the License. -->
}
}
+ private eventsFilter() {
+ const allEvents = [
+ ...this.rocketData.serviceEvents,
+ ...this.rocketData.serviceInstanceEvents,
+ ...this.rocketData.endpointEvents,
+ ];
+
+ let events = allEvents.filter(
+ (item) =>
+ this.itemConfig.entityType === item.entityType &&
+ item.checked &&
+ ((item.source.service === this.rocketOption.currentService.label &&
+ (item.source.serviceInstance === this.rocketOption.currentInstance.label ||
+ item.source.endpoint === this.rocketOption.currentEndpoint.label)) ||
+ (item.entityType === EntityType[0].key && item.source.service === this.rocketOption.currentService.label)),
+ );
+ events = events.filter((d: Event, index: number) => index < this.setEventsLength());
+
+ return events;
+ }
+
+ private setEventsLength() {
+ const body: any = this.$refs.chartBody;
+ if (!body) {
+ return 0;
+ }
+ const keys = Object.keys(this.chartSource || {}).filter(
+ (i: any) => Array.isArray(this.chartSource[i]) && this.chartSource[i].length,
+ );
+ const startP = keys.length > 1 ? 50 : 15;
+ const endP = keys.length > 1 ? 0 : 40;
+ const eventNum = parseInt(String((body.offsetHeight - startP - endP) / 10), 10);
+
+ return eventNum;
+ }
+
+ // watch selectors and events
@Watch('rocketOption.updateDashboard')
private watchCurrentSelectors() {
+ this.itemEvents = this.eventsFilter();
+ if (this.rocketOption.updateDashboard.key.includes(UpdateDashboardEvents)) {
+ return;
+ }
setTimeout(() => {
this.chartRender();
}, 1000);
@@ -362,6 +408,9 @@ limitations under the License. -->
flex-direction: column;
padding-left: 5px;
padding-right: 5px;
+ .edit {
+ cursor: pointer;
+ }
}
.dashboard-item-shadow {
background-color: #448dfe15;
diff --git a/src/views/components/dashboard/tool-bar/dashboard-events.vue b/src/views/components/dashboard/tool-bar/dashboard-events.vue
new file mode 100644
index 0000000..2c271da
--- /dev/null
+++ b/src/views/components/dashboard/tool-bar/dashboard-events.vue
@@ -0,0 +1,490 @@
+<!-- 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="event-list flex-h">
+ <div class="rk-dashboard-tool-btn" @click="viewEventsList" v-show="enableEvents">
+ <rk-icon class="lg" icon="settings" v-tooltip:left="{ content: $t('setEvent') }" />
+ </div>
+ <div class="rk-dashboard-tool-btn" @click="setEnbleEvents">
+ <rk-icon
+ class="lg"
+ :class="enableEvents ? 'blue' : ''"
+ icon="format_indent_increase"
+ v-tooltip:left="{ content: enableEvents ? $t('disableEvents') : $t('enableEvents') }"
+ />
+ </div>
+ <rk-sidebox width="1000px" :fixed="true" :show.sync="dialogEventVisible" @closeSideboxCallback="updateEvents">
+ <div class="config-box">
+ <div class="series-type" v-show="type === pageEventsType.DASHBOARD_EVENTS">
+ <label class="title">{{ $t('eventSeries') }}</label>
+ <RkSelect
+ :mode="'multiple'"
+ :current="rocketComps.currentSeriesType"
+ :data="seriesTypes"
+ @onChoose="(item) => changeSeriesType(item)"
+ />
+ </div>
+ <div v-show="type === pageEventsType.DASHBOARD_EVENTS">
+ <div class="title">{{ $t('serviceEvents') }}</div>
+ <ul>
+ <li class="header">
+ <span class="check">
+ <input type="checkbox" v-model="checkAllServiceEvents" @click="checkServiceEvents" />
+ </span>
+ <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="item.class + index">{{
+ $t(item.text)
+ }}</span>
+ </li>
+ <li v-show="!rocketComps.serviceEvents.length">{{ $t('noData') }}</li>
+ <li v-for="event in rocketComps.serviceEvents" :key="event.uuid" @click="viewEventDetail(event)">
+ <span class="check">
+ <input type="checkbox" :checked="!!event.checked" @click="selectEvents(event)" />
+ </span>
+ <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="event.uuid + index">{{
+ event[item.class]
+ }}</span>
+ </li>
+ </ul>
+ </div>
+ <div v-show="type !== pageEventsType.TOPO_ENDPOINT_EVENTS">
+ <div class="title">{{ $t('instanceEvents') }}</div>
+ <ul>
+ <li class="header">
+ <span class="check">
+ <input type="checkbox" v-model="checkAllInstanceEvents" @click="checkInstanceEvents" />
+ </span>
+ <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="item.class + index">{{
+ $t(item.text)
+ }}</span>
+ </li>
+ <li v-show="!rocketComps.serviceInstanceEvents.length">{{ $t('noData') }}</li>
+ <li v-for="event in rocketComps.serviceInstanceEvents" :key="event.uuid" @click="viewEventDetail(event)">
+ <span class="check">
+ <input type="checkbox" :checked="!!event.checked" @click="selectEvents(event)" />
+ </span>
+ <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="event.uuid + index">{{
+ event[item.class]
+ }}</span>
+ </li>
+ </ul>
+ </div>
+ <div v-show="type !== pageEventsType.TOPO_INSTANCE_EVENTS">
+ <div class="title">{{ $t('endpointEvents') }}</div>
+ <ul>
+ <li class="header">
+ <span class="check">
+ <input type="checkbox" v-model="checkAllEndpointEvents" @click="checkEndpointEvents" />
+ </span>
+ <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="item.class + index">{{
+ $t(item.text)
+ }}</span>
+ </li>
+ <li v-show="!rocketComps.endpointEvents.length">{{ $t('noData') }}</li>
+ <li v-for="event in rocketComps.endpointEvents" :key="event.uuid" @click="viewEventDetail(event)">
+ <span class="check">
+ <input type="checkbox" :checked="!!event.checked" @click="selectEvents(event)" />
+ </span>
+ <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="event.uuid + index">{{
+ event[item.class]
+ }}</span>
+ </li>
+ </ul>
+ </div>
+ <div class="save-btn bg-blue" @click="updateEvents">{{ $t('setEvent') }}</div>
+ </div>
+ </rk-sidebox>
+ <rk-sidebox :width="'1000px'" :show.sync="showEventDetail" :title="$t('eventDetail')">
+ <div class="event-detail">
+ <div class="mb-10 rk-flex" v-for="(item, index) in eventsDetailHeaders" :key="index">
+ <span>{{ $t(item.text) }}: </span>
+ <span v-if="item.class === 'parameters'">
+ <span v-for="(item, index) of currentEvent[item.class]" :key="index"
+ >{{ item.key }}={{ item.value }};
+ </span>
+ </span>
+ <span v-else>{{ currentEvent[item.class] }}</span>
+ </div>
+ </div>
+ </rk-sidebox>
+ </div>
+</template>
+<script lang="ts">
+ import { Mutation, Action } from 'vuex-class';
+ import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
+ import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
+ import { Event } from '@/types/dashboard';
+ import { DurationTime, Option } from '@/types/global';
+ import { UpdateDashboardEvents, SeriesTypes, EventsHeaders, EventsDetailHeaders } from '../constant';
+ import { EntityType } from '../charts/constant';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import { PageEventsType } from '@/constants/constant';
+
+ @Component
+ export default class DashboardEvent extends Vue {
+ @Prop() private rocketComps!: rocketData;
+ @Prop() private stateDashboard!: optionState;
+ @Prop() private durationTime!: DurationTime;
+ @Prop() private type!: string;
+ @Mutation('SET_CHECKED_EVENTS') private SET_CHECKED_EVENTS: any;
+ @Mutation('UPDATE_DASHBOARD') private UPDATE_DASHBOARD: any;
+ @Mutation('SET_ENABLE_EVENTS') private SET_ENABLE_EVENTS: any;
+ @Mutation('SET_DASHBOARD_EVENTS') private SET_DASHBOARD_EVENTS: any;
+ @Mutation('SET_EVENTS_PAGE_TYPE') private SET_EVENTS_PAGE_TYPE!: (type: string) => void;
+ @Mutation('SET_CURRENT_SERIES_TYPE') private SET_CURRENT_SERIES_TYPE!: (data: {
+ item: Option;
+ index: number;
+ }) => void;
+ @Mutation('SET_CLEAR_SELECTED_EVENTS') private SET_CLEAR_SELECTED_EVENTS!: () => void;
+ @Mutation('SET_EVENTS') private SET_EVENTS: any;
+ @Action('GET_EVENT') private GET_EVENT: any;
+
+ private dialogEventVisible: boolean = false;
+ private enableEvents: boolean = false;
+ private selectedEvents: Event[] = [];
+ private checkAllServiceEvents: boolean = false;
+ private checkAllInstanceEvents: boolean = false;
+ private checkAllEndpointEvents: boolean = false;
+ private showEventDetail: boolean = false;
+ private currentEvent: Event | {} = {};
+ private pageEventsType = PageEventsType;
+ private seriesTypes = SeriesTypes;
+ private eventsHeaders = EventsHeaders;
+ private eventsDetailHeaders = EventsDetailHeaders;
+
+ private created() {
+ this.initEvents();
+ this.SET_EVENTS([
+ () => {
+ if (!this.enableEvents) {
+ return;
+ }
+ this.fetchEvents();
+ },
+ ]);
+ }
+
+ private initEvents() {
+ this.SET_EVENTS_PAGE_TYPE(this.type);
+ if (this.type === this.pageEventsType.DASHBOARD_EVENTS) {
+ this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[0], index: -1 });
+ this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[2], index: -1 });
+ } else if (this.type === this.pageEventsType.TOPO_ENDPOINT_EVENTS) {
+ this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[1], index: -1 });
+ } else {
+ this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[2], index: -1 });
+ }
+ this.updateAllChecked();
+ }
+
+ private viewEventsList() {
+ this.dialogEventVisible = true;
+ this.updateAllChecked();
+ }
+
+ private updateAllChecked() {
+ this.checkAllServiceEvents = this.checkAllEvents(this.rocketComps.serviceEvents);
+ this.checkAllEndpointEvents = this.checkAllEvents(this.rocketComps.endpointEvents);
+ this.checkAllInstanceEvents = this.checkAllEvents(this.rocketComps.serviceInstanceEvents);
+ }
+
+ private checkAllEvents(events: Event[]) {
+ if (!events.length) {
+ return false;
+ }
+ const selectedServiceEvents = events.filter((item: Event) => item.checked);
+ if (selectedServiceEvents.length === events.length) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private viewEventDetail(event: Event) {
+ this.showEventDetail = true;
+ this.currentEvent = event;
+ }
+
+ private changeSeriesType(item: Option) {
+ const index = this.rocketComps.currentSeriesType.findIndex((d: Option) => item.key === d.key);
+
+ this.SET_CURRENT_SERIES_TYPE({ item, index });
+ this.SET_CLEAR_SELECTED_EVENTS();
+ const selectedEvents: Event[] = [];
+ for (const type of this.rocketComps.currentSeriesType) {
+ if (type.key === this.seriesTypes[0].key) {
+ selectedEvents.push(...this.rocketComps.serviceEvents.slice(0, 3));
+ } else if (type.key === this.seriesTypes[1].key) {
+ selectedEvents.push(...this.rocketComps.endpointEvents.slice(0, 3));
+ } else {
+ selectedEvents.push(...this.rocketComps.serviceInstanceEvents.slice(0, 3));
+ }
+ }
+ this.selectedEvents = selectedEvents.map((d: Event) => {
+ d.checked = true;
+ return d;
+ });
+ this.SET_CHECKED_EVENTS(this.selectedEvents);
+ this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() });
+ this.selectedEvents = [];
+ this.updateAllChecked();
+ }
+
+ private setEnbleEvents() {
+ this.enableEvents = !this.enableEvents;
+ this.SET_ENABLE_EVENTS(this.enableEvents);
+ if (!this.enableEvents) {
+ this.clearAllEvents();
+ this.checkAllServiceEvents = false;
+ this.checkAllInstanceEvents = false;
+ this.checkAllEndpointEvents = false;
+ this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() });
+ return;
+ }
+ this.fetchEvents();
+ }
+
+ private clearAllEvents() {
+ this.SET_DASHBOARD_EVENTS({ events: [], type: EntityType[0].key });
+ this.SET_DASHBOARD_EVENTS({ events: [], type: EntityType[2].key });
+ this.SET_DASHBOARD_EVENTS({ events: [], type: EntityType[3].key });
+ }
+
+ private fetchEvents() {
+ if (this.type === PageEventsType.DASHBOARD_EVENTS) {
+ Promise.all([this.fetchServiceEvents(), this.fetchInstanceEvents(), this.fetchEndpointEvents()]).then(() => {
+ this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() });
+ });
+ return;
+ }
+ if (this.type === PageEventsType.TOPO_INSTANCE_EVENTS) {
+ this.fetchInstanceEvents().then(() => {
+ this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() });
+ });
+ return;
+ }
+ if (this.type === PageEventsType.TOPO_ENDPOINT_EVENTS) {
+ this.fetchEndpointEvents().then(() => {
+ this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() });
+ });
+ }
+ }
+
+ private fetchServiceEvents() {
+ return this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: this.stateDashboard.currentService.label,
+ },
+ },
+ type: EntityType[0].key,
+ });
+ }
+
+ private fetchInstanceEvents() {
+ return this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: this.stateDashboard.currentService.label,
+ serviceInstance: this.stateDashboard.currentInstance.label,
+ },
+ },
+ type: EntityType[3].key,
+ });
+ }
+
+ private fetchEndpointEvents() {
+ return this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: this.stateDashboard.currentService.label,
+ endpoint: this.stateDashboard.currentEndpoint.label,
+ },
+ },
+ type: EntityType[2].key,
+ }).then(() => {
+ if (this.type === PageEventsType.DASHBOARD_EVENTS) {
+ return;
+ }
+ this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() });
+ });
+ }
+
+ private selectEvents(data: Event, e: any) {
+ window.event ? (window.event.cancelBubble = true) : e.stopPropagation();
+ const index = this.selectedEvents.findIndex(
+ (item: Event) => item.uuid === data.uuid && item.entityType === data.entityType,
+ );
+
+ data.checked = !data.checked;
+ if (index > -1) {
+ this.selectedEvents[index].checked = data.checked;
+ } else {
+ this.selectedEvents.push(data);
+ }
+ }
+
+ private updateEvents() {
+ this.SET_CHECKED_EVENTS(this.selectedEvents);
+ this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() });
+ this.selectedEvents = [];
+ this.dialogEventVisible = false;
+ }
+
+ private checkServiceEvents() {
+ for (const event of this.rocketComps.serviceEvents) {
+ if (this.checkAllServiceEvents) {
+ event.checked = false;
+ } else {
+ event.checked = true;
+ }
+ this.selectedEvents = this.selectedEvents.filter(
+ (item: Event) => !(item.entityType === EntityType[0].label && item.uuid === event.uuid),
+ );
+ }
+ if (!this.checkAllServiceEvents) {
+ this.selectedEvents.push(...this.rocketComps.serviceEvents);
+ }
+ }
+
+ private checkInstanceEvents() {
+ for (const event of this.rocketComps.serviceInstanceEvents) {
+ if (this.checkAllInstanceEvents) {
+ event.checked = false;
+ } else {
+ event.checked = true;
+ }
+ this.selectedEvents = this.selectedEvents.filter(
+ (item: Event) => !(item.entityType === EntityType[3].label && item.uuid === event.uuid),
+ );
+ }
+ if (!this.checkAllInstanceEvents) {
+ this.selectedEvents.push(...this.rocketComps.serviceInstanceEvents);
+ }
+ }
+
+ private checkEndpointEvents() {
+ for (const event of this.rocketComps.endpointEvents) {
+ if (this.checkAllEndpointEvents) {
+ event.checked = false;
+ } else {
+ event.checked = true;
+ }
+ this.selectedEvents = this.selectedEvents.filter(
+ (item: Event) => !(item.entityType === EntityType[2].label && item.uuid === event.uuid),
+ );
+ }
+ if (!this.checkAllEndpointEvents) {
+ this.selectedEvents.push(...this.rocketComps.endpointEvents);
+ }
+ }
+
+ private beforeDestroy() {
+ this.clearAllEvents();
+ this.SET_ENABLE_EVENTS(false);
+ this.SET_EVENTS([]);
+ }
+
+ @Watch('durationTime')
+ private watchDurationTime() {
+ if (!this.enableEvents) {
+ return;
+ }
+ this.fetchEvents();
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ .event-list {
+ color: #444;
+ }
+ .rk-dashboard-tool-btn {
+ background-color: rgba(255, 255, 255, 0.07);
+ border-radius: 4px;
+ margin-left: 5px;
+ padding: 3px;
+ color: #efefef;
+ cursor: pointer;
+ }
+ .rk-sidebox-title {
+ color: #444;
+ }
+ .config-box {
+ color: #444;
+ .series-type {
+ margin-bottom: 20px;
+ width: 400px;
+ }
+ .title {
+ font-size: 14px;
+ font-weight: bold;
+ }
+ .save-btn {
+ width: 120px;
+ height: 30px;
+ line-height: 30px;
+ text-align: center;
+ border-radius: 4px;
+ color: #fff;
+ cursor: pointer;
+ }
+ ul {
+ max-height: 200px;
+ min-height: 100px;
+ overflow: auto;
+ margin-bottom: 20px;
+ .header {
+ font-weight: bold;
+ }
+ .check {
+ width: 30px;
+ input {
+ cursor: pointer;
+ }
+ }
+ .starTime,
+ .endTime {
+ width: 150px;
+ }
+ .uuid,
+ .parameters {
+ width: 280px;
+ }
+ .message {
+ width: 220px;
+ }
+ }
+ li {
+ cursor: pointer;
+ span {
+ width: 150px;
+ height: 20px;
+ line-height: 20px;
+ text-align: center;
+ display: inline-block;
+ border-bottom: 1px solid #ccc;
+ overflow: hidden;
+ }
+ }
+ }
+ .event-detail {
+ color: #444;
+ }
+</style>
diff --git a/src/views/components/dashboard/tool-bar/tool-bar-btns.vue b/src/views/components/dashboard/tool-bar/tool-bar-btns.vue
index 28e9b40..8d1f5ad 100644
--- a/src/views/components/dashboard/tool-bar/tool-bar-btns.vue
+++ b/src/views/components/dashboard/tool-bar/tool-bar-btns.vue
@@ -15,39 +15,25 @@ limitations under the License. -->
<template>
<div class="flex-h btn-box">
- <div class="rk-dashboard-bar-btn">
- <span v-tooltip:bottom="{ content: rocketGlobal.edit ? 'view' : 'edit' }">
- <svg
- class="icon lg vm cp rk-btn ghost"
- :style="`color:${!rocketGlobal.edit ? '' : '#ffc107'}`"
- @click="handleSetEdit"
- >
- <use :xlink:href="!rocketGlobal.edit ? '#lock' : '#lock-open'"></use>
- </svg>
- </span>
+ <div class="rk-dashboard-bar-btn" @click="handleSetEdit">
+ <rk-icon
+ class="lg"
+ :style="`color:${!rocketGlobal.edit ? '' : '#ffc107'}`"
+ :icon="!rocketGlobal.edit ? 'lock' : 'lock-open'"
+ v-tooltip:bottom="{ content: rocketGlobal.edit ? 'view' : 'edit' }"
+ />
</div>
- <div class="rk-dashboard-bar-btn">
- <span v-tooltip:bottom="{ content: 'import' }">
- <input id="tool-bar-file" type="file" name="file" title="" accept=".json" @change="importData" />
- <label class="rk-btn ghost input-label" for="tool-bar-file">
- <svg class="icon lg vm cp " :style="`marginTop: 0px`">
- <use :xlink:href="'#folder_open'"></use>
- </svg>
- </label>
- </span>
+ <div class="rk-dashboard-bar-btn" v-tooltip:bottom="{ content: 'import' }">
+ <input id="tool-bar-file" type="file" name="file" title="" accept=".json" @change="importData" />
+ <label for="tool-bar-file">
+ <rk-icon class="lg import" icon="folder_open" />
+ </label>
</div>
- <div class="rk-dashboard-bar-btn">
- <span v-tooltip:bottom="{ content: 'export' }">
- <svg class="icon lg vm cp rk-btn ghost" @click="exportData">
- <use :xlink:href="'#save_alt'"></use>
- </svg>
- </span>
+ <div class="rk-dashboard-bar-btn" @click="exportData">
+ <rk-icon class="lg" icon="save_alt" v-tooltip:bottom="{ content: 'export' }" />
</div>
-
- <div class="rk-dashboard-bar-btn">
- <svg class="icon lg vm cp rk-btn ghost" @click="handleOption">
- <use xlink:href="#retry"></use>
- </svg>
+ <div class="rk-dashboard-bar-btn" @click="handleOption">
+ <rk-icon class="lg" icon="retry" v-tooltip:bottom="{ content: 'auto' }" />
</div>
</div>
</template>
@@ -57,15 +43,17 @@ limitations under the License. -->
import { Action, Mutation } from 'vuex-class';
import { readFile } from '@/utils/readFile';
import { saveFile } from '@/utils/saveFile';
- @Component({})
+ import { DurationTime } from '@/types/global';
+ import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
+ import { State as rocketGlobal } from '@/store/modules/global';
+ import { PageTypes } from '@/constants/constant';
+
+ @Component
export default class ToolBarBtns extends Vue {
- @Prop() private compType!: any;
- @Prop() private dashboardType!: any;
- @Prop() private rocketGlobal!: any;
- @Prop() private rocketComps!: any;
- @Prop() private durationTime!: any;
- @Prop() private rocketOption: any;
- @Mutation('SET_COMPS_TREE') private SET_COMPS_TREE: any;
+ @Prop() private compType!: string;
+ @Prop() private rocketGlobal!: rocketGlobal;
+ @Prop() private rocketComps!: rocketData;
+ @Prop() private durationTime!: DurationTime;
@Mutation('IMPORT_TREE') private IMPORT_TREE: any;
@Action('SET_EDIT') private SET_EDIT: any;
@Action('MIXHANDLE_GET_OPTION') private MIXHANDLE_GET_OPTION: any;
@@ -74,13 +62,16 @@ limitations under the License. -->
return this.MIXHANDLE_GET_OPTION({
compType: this.compType,
duration: this.durationTime,
+ pageType: PageTypes.DASHBOARD,
keywordServiceName:
this.rocketComps.tree[this.rocketComps.group] && this.rocketComps.tree[this.rocketComps.group].serviceGroup,
});
}
+
private handleSetEdit() {
this.SET_EDIT(!this.rocketGlobal.edit);
}
+
private async importData(event: any) {
try {
const data: any = await readFile(event);
@@ -110,9 +101,10 @@ limitations under the License. -->
<style lang="scss" scoped>
.rk-dashboard-bar-btn {
- padding: 0 5px;
+ padding: 0 8px;
border-right: 2px solid #252a2f;
height: 19px;
+ cursor: pointer;
}
#tool-bar-file {
display: none;
@@ -120,8 +112,13 @@ limitations under the License. -->
.input-label {
display: inline;
line-height: inherit;
+ cursor: pointer;
}
.btn-box {
height: 58px;
}
+ .import {
+ margin-top: 0;
+ cursor: pointer;
+ }
</style>
diff --git a/src/views/components/dashboard/tool-bar/tool-bar.vue b/src/views/components/dashboard/tool-bar/tool-bar.vue
index 3d67af7..6708612 100644
--- a/src/views/components/dashboard/tool-bar/tool-bar.vue
+++ b/src/views/components/dashboard/tool-bar/tool-bar.vue
@@ -18,59 +18,69 @@ limitations under the License. -->
:rocketGlobal="rocketGlobal"
:rocketComps="rocketComps"
:compType="compType"
- :dashboardType="dashboardType"
:durationTime="durationTime"
- :rocketOption="rocketOption"
/>
- <div class="flex-h" v-if="compType === dashboardType.SERVICE">
- <div class="sm grey service-search">
- <div>{{ $t('serviceGroup') }}</div>
- <input
- type="text"
- :value="rocketComps.tree[rocketComps.group].serviceGroup"
- @change="searchServices($event.target.value)"
+ <div class="dashboard-selectors flex-h" v-if="compType === dashboardType.SERVICE">
+ <div class="flex-h">
+ <div class="sm grey service-search">
+ <div>{{ $t('serviceGroup') }}</div>
+ <input
+ type="text"
+ :value="rocketComps.tree[rocketComps.group].serviceGroup"
+ @change="searchServices($event.target.value)"
+ />
+ </div>
+ <ToolBarSelect
+ @onChoose="selectService"
+ :title="$t('currentService')"
+ :current="stateDashboard.currentService"
+ :data="stateDashboard.services"
+ icon="package"
+ />
+ <ToolBarEndpointSelect
+ @onChoose="selectEndpoint"
+ :title="$t('currentEndpoint')"
+ :current="stateDashboard.currentEndpoint"
+ :data="stateDashboard.endpoints"
+ :currentService="stateDashboard.currentService"
+ icon="code"
+ />
+ <ToolBarSelect
+ @onChoose="selectInstance"
+ :title="$t('currentInstance')"
+ :current="stateDashboard.currentInstance"
+ :data="stateDashboard.instances"
+ icon="disk"
/>
+ <a
+ class="rk-view-instance-attributes r"
+ @click="() => (dialogAttributesVisible = true)"
+ v-tooltip:bottom="{ content: $t('instanceAttributes') }"
+ >
+ <rk-icon icon="info_outline" />
+ </a>
+ <rk-sidebox
+ width="600px"
+ :fixed="true"
+ :title="`${$t('instanceAttributes')} of ${stateDashboard.currentInstance.label}`"
+ :show.sync="dialogAttributesVisible"
+ class="instance-attributes-box"
+ >
+ <div
+ class="instance-attr"
+ v-for="(attr, index) in stateDashboard.currentInstance.attributes"
+ :key="attr.name + index"
+ >
+ {{ attr.name + ' : ' + attr.value }}
+ </div>
+ </rk-sidebox>
</div>
- <ToolBarSelect
- @onChoose="selectService"
- :title="$t('currentService')"
- :current="stateDashboard.currentService"
- :data="stateDashboard.services"
- icon="package"
- />
- <ToolBarEndpointSelect
- @onChoose="selectEndpoint"
- :title="$t('currentEndpoint')"
- :current="stateDashboard.currentEndpoint"
- :data="stateDashboard.endpoints"
- :currentService="stateDashboard.currentService"
- icon="code"
+ <DashboardEvent
+ :rocketComps="rocketComps"
+ :stateDashboard="stateDashboard"
+ :durationTime="durationTime"
+ :type="pageEventsType.DASHBOARD_EVENTS"
/>
- <ToolBarSelect
- @onChoose="selectInstance"
- :title="$t('currentInstance')"
- :current="stateDashboard.currentInstance"
- :data="stateDashboard.instances"
- icon="disk"
- />
- <a class="rk-view-instance-attributes r" @click="() => (dialogAttributesVisible = true)">
- <span class="vm">{{ $t('instanceAttributes') }}</span>
- </a>
- <rk-sidebox
- width="50%"
- :fixed="true"
- :title="`${$t('instanceAttributes')} of ${stateDashboard.currentInstance.label}`"
- :show.sync="dialogAttributesVisible"
- class="instance-attributes-box"
- >
- <div
- class="instance-attr"
- v-for="(attr, index) in stateDashboard.currentInstance.attributes"
- :key="attr.name + index"
- >
- {{ attr.name + ' : ' + attr.value }}
- </div>
- </rk-sidebox>
</div>
<div class="flex-h" v-else-if="compType === dashboardType.BROWSER">
<ToolBarSelect
@@ -113,18 +123,23 @@ limitations under the License. -->
import ToolBarSelect from './tool-bar-select.vue';
import ToolBarEndpointSelect from './tool-bar-endpoint-select.vue';
import ToolBarBtns from './tool-bar-btns.vue';
- import { State, Action, Mutation } from 'vuex-class';
+ import { Action, Mutation } from 'vuex-class';
+ import { EntityType } from '../charts/constant';
+ import { DurationTime, Option } from '@/types/global';
+ import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
+ import { State as rocketGlobal } from '@/store/modules/global';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import DashboardEvent from './dashboard-events.vue';
import { DASHBOARDTYPE } from '../constant';
+ import { PageEventsType, PageTypes } from '@/constants/constant';
- @Component({ components: { ToolBarSelect, ToolBarBtns, ToolBarEndpointSelect } })
+ @Component({ components: { ToolBarSelect, ToolBarBtns, ToolBarEndpointSelect, DashboardEvent } })
export default class ToolBar extends Vue {
- @Prop() private compType!: any;
- @Prop() private stateDashboard!: any;
- @Prop() private rocketGlobal!: any;
- @Prop() private rocketComps!: any;
- @Prop() private durationTime!: any;
- @State('rocketOption') private rocketOption: any;
- @Mutation('ADD_COMP') private ADD_COMP: any;
+ @Prop() private compType!: string;
+ @Prop() private stateDashboard!: optionState;
+ @Prop() private rocketGlobal!: rocketGlobal;
+ @Prop() private rocketComps!: rocketData;
+ @Prop() private durationTime!: DurationTime;
@Mutation('SET_CURRENT_SERVICE_GROUP') private SET_CURRENT_SERVICE_GROUP: any;
@Mutation('UPDATE_DASHBOARD') private UPDATE_DASHBOARD: any;
@Action('SELECT_SERVICE') private SELECT_SERVICE: any;
@@ -132,8 +147,10 @@ limitations under the License. -->
@Action('SELECT_ENDPOINT') private SELECT_ENDPOINT: any;
@Action('SELECT_INSTANCE') private SELECT_INSTANCE: any;
@Action('MIXHANDLE_GET_OPTION') private MIXHANDLE_GET_OPTION: any;
+ @Action('GET_EVENT') private GET_EVENT: any;
+ private dialogAttributesVisible: boolean = false;
private dashboardType = DASHBOARDTYPE;
- private dialogAttributesVisible = false;
+ private pageEventsType = PageEventsType;
get lastKey() {
const current = this.rocketComps.tree[this.rocketComps.group].children[this.rocketComps.current].children;
if (!current.length) {
@@ -141,14 +158,60 @@ limitations under the License. -->
}
return current[current.length - 1].k;
}
- private selectService(i: any) {
- this.SELECT_SERVICE({ service: i, duration: this.durationTime });
+ private selectService(i: Option) {
+ if (!this.rocketComps.enableEvents) {
+ this.SELECT_SERVICE({ service: i, duration: this.durationTime });
+ return;
+ }
+ this.SELECT_SERVICE({ service: i, duration: this.durationTime, callback: this.GET_EVENT });
+ this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: i.label,
+ },
+ },
+ type: EntityType[0].key,
+ });
}
- private selectEndpoint(i: any) {
- this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
+ private selectEndpoint(i: Option) {
+ if (!this.rocketComps.enableEvents) {
+ this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
+ return;
+ }
+ this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: this.stateDashboard.currentService.label,
+ endpoint: i.label,
+ },
+ },
+ type: EntityType[2].key,
+ }).then(() => {
+ this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
+ });
}
- private selectInstance(i: any) {
- this.SELECT_INSTANCE({ instance: i, duration: this.durationTime });
+ private selectInstance(i: Option) {
+ if (!this.rocketComps.enableEvents) {
+ this.SELECT_INSTANCE({ instance: i, duration: this.durationTime });
+ return;
+ }
+ this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: this.stateDashboard.currentService.label,
+ serviceInstance: i.label,
+ },
+ },
+ type: EntityType[3].key,
+ }).then(() => {
+ this.SELECT_INSTANCE({ instance: i, duration: this.durationTime });
+ });
}
private searchServices(value: string) {
this.SET_CURRENT_SERVICE_GROUP(value);
@@ -156,6 +219,7 @@ limitations under the License. -->
compType: this.dashboardType.SERVICE,
duration: this.durationTime,
keywordServiceName: value,
+ pageType: PageTypes.DASHBOARD,
}).then(() => {
this.UPDATE_DASHBOARD();
});
@@ -168,6 +232,10 @@ limitations under the License. -->
flex-shrink: 0;
color: #efefef;
background-color: #333840;
+ .dashboard-selectors {
+ width: calc(100% - 150px);
+ justify-content: space-between;
+ }
.instance-attributes-box {
color: #252a2f;
}
@@ -190,10 +258,11 @@ limitations under the License. -->
}
}
.rk-view-instance-attributes {
- background-color: #484b55;
+ background-color: rgba(255, 255, 255, 0.07);
border-radius: 4px;
margin-left: 5px;
- padding: 5px 10px;
+ padding: 3px;
+ color: #efefef;
}
}
</style>
diff --git a/src/views/components/dashboard/tool-group.vue b/src/views/components/dashboard/tool-group.vue
index 7e6c105..67588a3 100644
--- a/src/views/components/dashboard/tool-group.vue
+++ b/src/views/components/dashboard/tool-group.vue
@@ -63,8 +63,7 @@ limitations under the License. -->
import { Component, Prop } from 'vue-property-decorator';
import { Mutation, Action, Getter } from 'vuex-class';
import { DASHBOARDTYPE } from './constant';
- import { readFile } from '@/utils/readFile';
- import { saveFile } from '@/utils/saveFile';
+ import { PageTypes } from '@/constants/constant';
@Component({})
export default class ToolGroup extends Vue {
@@ -118,6 +117,7 @@ limitations under the License. -->
compType: this.compType,
duration: this.durationTime,
keywordServiceName: serviceGroup,
+ pageType: PageTypes.DASHBOARD,
});
}
private handleHide() {
diff --git a/src/views/components/dashboard/tool-nav.vue b/src/views/components/dashboard/tool-nav.vue
index 99b008c..58f903e 100644
--- a/src/views/components/dashboard/tool-nav.vue
+++ b/src/views/components/dashboard/tool-nav.vue
@@ -19,15 +19,9 @@ limitations under the License. -->
:key="index"
class="mr-20"
>
- <a
- class="rk-dashboard-nav-i b"
- @click="
- SET_CURRENT_COMPS(index);
- RUN_EVENTS({});
- "
- :class="{ active: rocketComps.current == index }"
- >{{ i.name }}</a
- >
+ <a class="rk-dashboard-nav-i b" @click="changeComps(index)" :class="{ active: rocketComps.current == index }">{{
+ i.name
+ }}</a>
<svg
v-if="rocketGlobal.edit && rocketComps.current !== index"
class="ml-5 icon cp red vm"
@@ -44,50 +38,28 @@ limitations under the License. -->
<div class="mb-10 vm">{{ $t('createTab') }}</div>
<div class="sm grey mb-5 mr-10">{{ $t('tabName') }}</div>
<input class="mb-5 rk-dashboard-nav-input" type="text" v-model="name" />
- <!-- <div class="sm grey mb-5 mr-10">{{ $t('template') }}</div>
- <label class="dib mb-5 mr-10 sm"
- ><input type="radio" v-model="template" value="nouse" />{{ $t('nouse') }}</label
- >
- <label class="dib mb-5 mr-10 sm"
- ><input type="radio" v-model="template" value="global" />{{ $t('global') }}</label
- >
- <label class="dib mb-5 mr-10 sm" v-if="type === 'service'"
- ><input type="radio" v-model="template" value="service" />{{ $t('service') }}</label
- >
- <label class="dib mb-5 mr-10 sm" v-if="type === 'service'"
- ><input type="radio" v-model="template" value="endpoint" />{{ $t('endpoint') }}</label
- >
- <label class="dib mb-5 mr-10 sm" v-if="type === 'service'"
- ><input type="radio" v-model="template" value="instance" />{{ $t('instance') }}</label
- >
- <label class="dib mb-5 mr-10 sm" v-if="type === 'database'"
- ><input type="radio" v-model="template" value="database" />{{ $t('database') }}</label
- > -->
<a class="rk-btn r vm long tc confirm" @click="handleCreate">{{ $t('confirm') }}</a>
</div>
</a>
<a class="rk-dashboard-import mr-10">
<input id="tool-nav-file" class="ipt" type="file" name="file" title="" accept=".json" @change="importData" />
<label for="tool-nav-file" class="input-label">
- <svg class="icon open vm">
- <use xlink:href="#folder_open"></use>
- </svg>
+ <rk-icon class="open vm" icon="folder_open" />
</label>
</a>
- <a>
- <svg class="icon vm" @click="exportData">
- <use xlink:href="#save_alt"></use>
- </svg>
+ <a class="mr-10" @click="exportData">
+ <rk-icon icon="save_alt" />
</a>
</nav>
</template>
<script lang="ts">
import Vue from 'vue';
- import { Component, Prop, Model } from 'vue-property-decorator';
- import { State, Mutation, Action } from 'vuex-class';
+ import { Component, Prop } from 'vue-property-decorator';
+ import { Getter, Mutation, Action } from 'vuex-class';
import { readFile } from '@/utils/readFile';
import { saveFile } from '@/utils/saveFile';
+ import { DASHBOARDTYPE } from './constant';
@Component
export default class ToolNav extends Vue {
@@ -98,9 +70,11 @@ limitations under the License. -->
@Mutation('DELETE_COMPS_TREE') private DELETE_COMPS_TREE: any;
@Mutation('ADD_COMPS_TREE') private ADD_COMPS_TREE: any;
@Action('RUN_EVENTS') private RUN_EVENTS: any;
+ @Getter('durationTime') private durationTime: any;
private name: string = '';
- // private template: string = 'nouse';
private show: boolean = false;
+ private dashboardType = DASHBOARDTYPE;
+
get type() {
return this.rocketComps.tree[this.rocketComps.group].type;
}
@@ -114,7 +88,10 @@ limitations under the License. -->
}
this.ADD_COMPS_TREE({ name: this.name });
this.handleHide();
- // this.template = 'nouse';
+ }
+ private changeComps(index: number) {
+ this.SET_CURRENT_COMPS(index);
+ this.RUN_EVENTS({});
}
private async importData(event: any) {
try {
diff --git a/src/views/components/log/log-bar.vue b/src/views/components/log/log-bar.vue
index 1e54f64..7de635a 100644
--- a/src/views/components/log/log-bar.vue
+++ b/src/views/components/log/log-bar.vue
@@ -76,7 +76,6 @@ limitations under the License. -->
</template>
<script lang="ts">
- import { Duration, Option } from '@/types/global';
import { Component, Vue } from 'vue-property-decorator';
import { Action, Getter, Mutation, State } from 'vuex-class';
import TraceSelect from '../common/trace-select.vue';
@@ -85,6 +84,7 @@ limitations under the License. -->
import LogConditions from './log-conditions.vue';
import { State as logState } from '@/store/modules/log/index';
import { State as optionState } from '@/store/modules/global/selectors';
+ import { PageTypes } from '@/constants/constant';
@Component({
components: { TraceSelect, ToolBarSelect, ToolBarEndpointSelect, LogConditions },
@@ -107,14 +107,13 @@ limitations under the License. -->
private pageNum: number = 1;
private cateGoryBrowser = 'browser';
private showConditionsBox = true;
- private logPage = 'Log';
private pageSize = 20;
private beforeMount() {
this.MIXHANDLE_GET_OPTION({
compType: this.logState.type.key,
duration: this.durationTime,
- pageType: this.logPage,
+ pageType: PageTypes.LOG,
})
.then(() => {
this.QUERY_LOGS_BYKEYWORDS();
@@ -146,7 +145,7 @@ limitations under the License. -->
this.MIXHANDLE_GET_OPTION({
compType: i.key,
duration: this.durationTime,
- pageType: this.logPage,
+ pageType: PageTypes.LOG,
}).then(() => {
this.queryLogs();
});
diff --git a/src/views/components/log/log-conditions.vue b/src/views/components/log/log-conditions.vue
index 5035275..529743e 100644
--- a/src/views/components/log/log-conditions.vue
+++ b/src/views/components/log/log-conditions.vue
@@ -116,7 +116,7 @@ limitations under the License. -->
import { Mutation, State } from 'vuex-class';
import { State as globalState } from '@/store/modules/global/index';
import { State as logState } from '@/store/modules/log/index';
- import dateFormatStep from '@/utils/dateFormatStep';
+ import dateFormatStep from '@/utils/dateFormat';
@Component({
components: {},
diff --git a/src/views/components/log/log-service-detail.vue b/src/views/components/log/log-service-detail.vue
index 08c1515..0a521a6 100644
--- a/src/views/components/log/log-service-detail.vue
+++ b/src/views/components/log/log-service-detail.vue
@@ -42,7 +42,6 @@ limitations under the License. -->
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
- import { Mutation, State } from 'vuex-class';
import LogTable from './log-table/log-table.vue';
import { ServiceLogDetail } from './log-table/log-constant';
import { formatJson } from '../../../utils/formatJson';
diff --git a/src/views/components/profile/profile-task.vue b/src/views/components/profile/profile-task.vue
index 343c3a7..8015b21 100644
--- a/src/views/components/profile/profile-task.vue
+++ b/src/views/components/profile/profile-task.vue
@@ -125,10 +125,7 @@ limitations under the License. -->
}
</script>
-<style lang="scss">
- .rk-profile-task {
- margin: 20px;
- }
+<style lang="scss" scoped>
label {
display: inline-block;
margin: 10px 0;
diff --git a/src/views/components/topology/topo-aside.vue b/src/views/components/topology/topo-aside.vue
index 22f2964..83c883e 100644
--- a/src/views/components/topology/topo-aside.vue
+++ b/src/views/components/topology/topo-aside.vue
@@ -16,7 +16,11 @@ limitations under the License. -->
<template>
<aside class="link-topo-aside">
<Radial v-if="radioStatus" :datas="{ nodes: stateTopo.nodes, calls: stateTopo.calls }" />
- <svg class="link-topo-aside-btn icon cp lg" @click="showRadial()" :style="`position:absolute;left:580px;${radioStatus ? 'background-color: #357de9;' : ''}`">
+ <svg
+ class="link-topo-aside-btn icon cp lg"
+ @click="showRadial()"
+ :style="`position:absolute;left:580px;${radioStatus ? 'background-color: #357de9;' : ''}`"
+ >
<use xlink:href="#issues" />
</svg>
<svg
diff --git a/src/views/components/topology/topo-endpoint-dependency.vue b/src/views/components/topology/topo-endpoint-dependency.vue
index 54839b1..97db853 100644
--- a/src/views/components/topology/topo-endpoint-dependency.vue
+++ b/src/views/components/topology/topo-endpoint-dependency.vue
@@ -100,7 +100,7 @@ limitations under the License. -->
height: 100%;
display: flex;
flex-direction: column;
- overflow: scroll;
+ overflow: auto;
.endpoint-dependency-chart {
height: 80%;
min-height: 500px;
diff --git a/src/views/components/trace/trace-search.vue b/src/views/components/trace/trace-search.vue
index 526c1e9..c144176 100644
--- a/src/views/components/trace/trace-search.vue
+++ b/src/views/components/trace/trace-search.vue
@@ -110,7 +110,7 @@ limitations under the License. -->
import TraceSelect from '../common/trace-select.vue';
import { State as traceState } from '@/store/modules/trace/index';
import { State as globalState } from '@/store/modules/global/index';
- import dateFormatStep from '@/utils/dateFormatStep';
+ import dateFormatStep from '@/utils/dateFormat';
@Component({ components: { TraceSelect } })
export default class TraceSearch extends Vue {
diff --git a/src/views/containers/dashboard.vue b/src/views/containers/dashboard.vue
index 51f2866..ee65932 100644
--- a/src/views/containers/dashboard.vue
+++ b/src/views/containers/dashboard.vue
@@ -44,7 +44,7 @@ limitations under the License. -->
</template>
<script lang="ts">
- import { Component, Vue, Watch } from 'vue-property-decorator';
+ import { Component, Vue } from 'vue-property-decorator';
import { Action, Getter, State, Mutation } from 'vuex-class';
import ToolBar from '@/views/components/dashboard/tool-bar/tool-bar.vue';
import ToolGroup from '@/views/components/dashboard/tool-group.vue';
@@ -54,6 +54,7 @@ limitations under the License. -->
import { State as globalState } from '@/store/modules/global';
import { State as optionState } from '@/store/modules/global/selectors';
import { State as dataState } from '@/store/modules/dashboard/dashboard-data';
+ import { PageTypes } from '@/constants/constant';
interface ITemplate {
name: string;
@@ -76,7 +77,7 @@ limitations under the License. -->
@State('rocketData') private rocketComps!: dataState;
@Action('MIXHANDLE_GET_OPTION') private MIXHANDLE_GET_OPTION: any;
@Action('GET_ALL_TEMPLATES') private GET_ALL_TEMPLATES: any;
- // @Action('ADD_TEMPLATE') private ADD_TEMPLATE: any;
+ @Action('GET_EVENT') private GET_EVENT: any;
@Getter('durationTime') private durationTime: any;
@Mutation('SET_COMPS_TREE') private SET_COMPS_TREE: any;
@Mutation('ADD_COMP') private ADD_COMP: any;
@@ -104,17 +105,10 @@ limitations under the License. -->
duration: this.durationTime,
keywordServiceName:
this.rocketComps.tree[this.rocketComps.group] && this.rocketComps.tree[this.rocketComps.group].serviceGroup,
+ pageType: PageTypes.DASHBOARD,
});
}
private beforeMount() {
- // this.ADD_TEMPLATE({
- // name: 'Topology Instance',
- // type: 'TOPOLOGY_INSTANCE',
- // active: true,
- // configuration: JSON.stringify(TopologyInstanceTemp),
- // }).then((data: any) => {
- // console.log(data);
- // });
this.GET_ALL_TEMPLATES().then((allTemplate: ITemplate[]) => {
const dashboardTemplate = allTemplate.filter((item: ITemplate) => item.type === 'DASHBOARD');
const templatesConfig = dashboardTemplate.map((item: ITemplate) => JSON.parse(item.configuration)).flat(1);
diff --git a/src/views/containers/topology/endpoint/index.vue b/src/views/containers/topology/endpoint/index.vue
index 10afc9f..4cc39bf 100644
--- a/src/views/containers/topology/endpoint/index.vue
+++ b/src/views/containers/topology/endpoint/index.vue
@@ -45,14 +45,24 @@ limitations under the License. -->
</span>
</div>
</span>
- <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" />
- <ToolBarEndpointSelect
- @onChoose="selectEndpoint"
- :title="$t('currentEndpoint')"
- :current="stateDashboardOption.currentEndpoint"
- :data="stateDashboardOption.endpoints"
- icon="code"
- />
+ <div class="rk-dashboard-bar-tool flex-h">
+ <div class="flex-h">
+ <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" />
+ <ToolBarEndpointSelect
+ @onChoose="selectEndpoint"
+ :title="$t('currentEndpoint')"
+ :current="stateDashboardOption.currentEndpoint"
+ :data="stateDashboardOption.endpoints"
+ icon="code"
+ />
+ </div>
+ <DashboardEvent
+ :rocketComps="rocketComps"
+ :stateDashboard="stateDashboardOption"
+ :durationTime="durationTime"
+ :type="pageEventsType.TOPO_ENDPOINT_EVENTS"
+ />
+ </div>
</div>
<endpoints-survey :endpointComps="endpointComps" :updateObjects="updateObjects" />
</div>
@@ -60,7 +70,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 EndpointsSurvey from './endpoints-survey.vue';
import ToolBarSelect from '@/views/components/dashboard/tool-bar/tool-bar-select.vue';
@@ -68,36 +78,57 @@ limitations under the License. -->
import { readFile } from '@/utils/readFile';
import { saveFile } from '@/utils/saveFile';
import { ObjectsType } from '../../../../constants/constant';
-
- interface Endpoint {
- label: string;
- key: string;
- name?: string;
- }
+ import DashboardEvent from '@/views/components/dashboard/tool-bar/dashboard-events.vue';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
+ import { State as rocketbotGlobal } from '@/store/modules/global';
+ import { DurationTime, Option } from '@/types/global';
+ import { EntityType } from '@/views/components/dashboard/charts/constant';
+ import { PageEventsType } from '@/constants/constant';
@Component({
components: {
EndpointsSurvey,
ToolBarSelect,
ToolBarEndpointSelect,
+ DashboardEvent,
},
})
export default class WindowEndpoint extends Vue {
- @State('rocketOption') private stateDashboardOption!: any;
- @State('rocketData') private rocketComps!: any;
- @State('rocketbot') private rocketGlobal: any;
- @Getter('durationTime') private durationTime: any;
+ @Prop() private current!: { key: number | string; label: number | string };
+ @Prop() private endpointComps: any;
+ @Prop() private updateObjects!: string;
+ @State('rocketOption') private stateDashboardOption!: optionState;
+ @State('rocketData') private rocketComps!: rocketData;
+ @State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @Getter('durationTime') private durationTime!: DurationTime;
@Action('SELECT_ENDPOINT') private SELECT_ENDPOINT: any;
@Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any;
@Mutation('SET_EDIT') private SET_EDIT: any;
@Action('GET_SERVICE_ENDPOINTS') private GET_SERVICE_ENDPOINTS: any;
@Action('MIXHANDLE_CHANGE_GROUP_WITH_CURRENT') private MIXHANDLE_CHANGE_GROUP_WITH_CURRENT: any;
- @Prop() private current!: { key: number | string; label: number | string };
- @Prop() private endpointComps: any;
- @Prop() private updateObjects!: string;
+ @Action('GET_EVENT') private GET_EVENT: any;
+
+ private pageEventsType = PageEventsType;
- private selectEndpoint(i: any) {
- this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
+ private selectEndpoint(i: Option) {
+ if (!this.rocketComps.enableEvents) {
+ this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
+ return;
+ }
+ this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: this.stateDashboardOption.currentService.label,
+ endpoint: i.label,
+ },
+ },
+ type: EntityType[2].key,
+ }).then(() => {
+ this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
+ });
}
private beforeMount() {
@@ -135,7 +166,11 @@ limitations under the License. -->
}
</script>
-<style lang="scss">
+<style lang="scss" scoped>
+ .rk-dashboard-bar-tool {
+ width: calc(100% - 160px);
+ justify-content: space-between;
+ }
.rk-dashboard-bar {
flex-shrink: 0;
color: #efefef;
diff --git a/src/views/containers/topology/instance/index.vue b/src/views/containers/topology/instance/index.vue
index f73ab20..b0fae5b 100644
--- a/src/views/containers/topology/instance/index.vue
+++ b/src/views/containers/topology/instance/index.vue
@@ -16,7 +16,7 @@ limitations under the License. -->
<template>
<div style="height: 100%">
<div class="rk-dashboard-bar flex-h">
- <span class="flex-h">
+ <div class="flex-h">
<div class="rk-dashboard-bar-btn">
<span v-tooltip:bottom="{ content: rocketGlobal.edit ? 'view' : 'edit' }">
<svg
@@ -45,60 +45,91 @@ limitations under the License. -->
</svg>
</span>
</div>
- </span>
- <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" />
- <ToolBarSelect
- @onChoose="selectInstance"
- :title="$t('currentInstance')"
- :current="stateDashboardOption.currentInstance"
- :data="stateDashboardOption.instances"
- icon="disk"
- />
+ </div>
+ <div class="rk-dashboard-bar-tool flex-h">
+ <div class="flex-h">
+ <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" />
+ <ToolBarSelect
+ @onChoose="selectInstance"
+ :title="$t('currentInstance')"
+ :current="stateDashboardOption.currentInstance"
+ :data="stateDashboardOption.instances"
+ icon="disk"
+ />
+ </div>
+ <DashboardEvent
+ :rocketComps="rocketComps"
+ :stateDashboard="stateDashboardOption"
+ :durationTime="durationTime"
+ :type="pageEventsType.TOPO_INSTANCE_EVENTS"
+ />
+ </div>
</div>
<instances-survey :instanceComps="instanceComps" :updateObjects="updateObjects" />
</div>
</template>
<script lang="ts">
+ import Vue from 'vue';
+ import { Component, Prop } from 'vue-property-decorator';
+ import { Action, Getter, State, Mutation } from 'vuex-class';
import InstancesSurvey from './instances-survey.vue';
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';
- import Vue from 'vue';
- import { Component, PropSync, Watch, Prop } from 'vue-property-decorator';
- import { Action, Getter, State, Mutation } from 'vuex-class';
import { readFile } from '@/utils/readFile';
import { saveFile } from '@/utils/saveFile';
- import { ObjectsType } from '../../../../constants/constant';
-
- interface Instance {
- label: string;
- key: string;
- name?: string;
- }
+ import { ObjectsType } from '@/constants/constant';
+ import { EntityType } from '@/views/components/dashboard/charts/constant';
+ import { DurationTime, Option } from '@/types/global';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
+ import { State as rocketbotGlobal } from '@/store/modules/global';
+ import DashboardEvent from '@/views/components/dashboard/tool-bar/dashboard-events.vue';
+ import { PageEventsType } from '@/constants/constant';
@Component({
components: {
InstancesSurvey,
ToolBarSelect,
ToolBarEndpointSelect,
+ DashboardEvent,
},
})
export default class WindowInstance extends Vue {
- @State('rocketOption') private stateDashboardOption!: any;
- @State('rocketData') private rocketComps!: any;
- @State('rocketbot') private rocketGlobal: any;
- @Getter('durationTime') private durationTime: any;
+ @Prop() private current!: { key: number | string; label: number | string };
+ @Prop() private instanceComps: any;
+ @Prop() private updateObjects!: string;
+ @State('rocketOption') private stateDashboardOption!: optionState;
+ @State('rocketData') private rocketComps!: rocketData;
+ @State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @Getter('durationTime') private durationTime!: DurationTime;
@Action('SELECT_INSTANCE') private SELECT_INSTANCE: any;
@Action('GET_SERVICE_INSTANCES') private GET_SERVICE_INSTANCES: any;
@Action('MIXHANDLE_CHANGE_GROUP_WITH_CURRENT') private MIXHANDLE_CHANGE_GROUP_WITH_CURRENT: any;
+ @Action('GET_EVENT') private GET_EVENT: any;
@Mutation('SET_EDIT') private SET_EDIT: any;
@Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any;
- @Prop() private current!: { key: number | string; label: number | string };
- @Prop() private instanceComps: any;
- @Prop() private updateObjects!: string;
- private selectInstance(i: any) {
- this.SELECT_INSTANCE({ instance: i, duration: this.durationTime });
+ private pageEventsType = PageEventsType;
+
+ private selectInstance(i: Option) {
+ if (!this.rocketComps.enableEvents) {
+ this.SELECT_INSTANCE({ instance: i, duration: this.durationTime });
+ return;
+ }
+ this.GET_EVENT({
+ condition: {
+ time: this.durationTime,
+ size: 20,
+ source: {
+ service: this.stateDashboardOption.currentService.label,
+ serviceInstance: i.label,
+ },
+ },
+ type: EntityType[3].key,
+ }).then(() => {
+ this.SELECT_INSTANCE({ instance: i, duration: this.durationTime });
+ });
}
private beforeMount() {
@@ -136,6 +167,15 @@ limitations under the License. -->
</script>
<style lang="scss" scoped>
+ .rk-dashboard-bar-tool {
+ width: calc(100% - 160px);
+ justify-content: space-between;
+ }
+ .rk-dashboard-bar {
+ flex-shrink: 0;
+ color: #efefef;
+ background-color: #333840;
+ }
.rk-dashboard-bar-btn {
padding: 0 5px;
border-right: 2px solid #252a2f;
diff --git a/vue.config.js b/vue.config.js
index 7fa74f0..ee2b28d 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -21,7 +21,6 @@ module.exports = {
proxy: {
'/graphql': {
target: `${process.env.SW_PROXY_TARGET || 'http://127.0.0.1:12800'}`,
-
changeOrigin: true,
},
},