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 826b0c3 Feat: Implement service logs in ui (#417)
826b0c3 is described below
commit 826b0c368037f259a2e5f3933cdaf3c9e7d8983e
Author: Qiuxia Fan <[email protected]>
AuthorDate: Mon Jan 25 20:47:14 2021 +0800
Feat: Implement service logs in ui (#417)
---
src/assets/lang/en.ts | 14 +-
src/assets/lang/zh.ts | 14 +-
src/graph/fragments/log.ts | 45 ++--
src/graph/query/log.ts | 4 +-
src/router.ts | 2 +
src/store/index.ts | 2 +-
src/store/modules/dashboard/dashboard-data.ts | 2 -
src/store/modules/dashboard/mutation-types.ts | 1 +
.../dashboard-option.ts => global/selectors.ts} | 46 ++--
src/store/modules/log/index.ts | 147 +++++--------
src/store/mutation-types.ts | 4 +
src/{graph/query/log.ts => utils/formatJson.ts} | 13 +-
.../components/common/trace-detail-chart-table.vue | 1 -
src/views/components/dashboard/dashboard-item.vue | 2 +-
src/views/components/log/log-bar.vue | 240 ++++++++++++++-------
...log-detail-table.vue => log-browser-detail.vue} | 97 ++++-----
src/views/components/log/log-conditions.vue | 182 ++++++++++++++++
.../log.vue => components/log/log-content.vue} | 36 ++--
src/views/components/log/log-service-detail.vue | 124 +++++++++++
.../{log-item.vue => log-browser-item.vue} | 4 +-
src/views/components/log/log-table/log-constant.ts | 62 +++++-
.../components/log/log-table/log-service-item.vue | 95 ++++++++
src/views/components/log/log-table/log-table.vue | 30 ++-
src/views/components/topology/topo-group/index.vue | 1 -
.../components/trace/trace-detail-chart-list.vue | 1 -
.../components/trace/trace-detail-chart-tree.vue | 1 -
src/views/components/trace/trace-search.vue | 10 +-
src/views/containers/dashboard.vue | 3 +-
src/views/containers/log.vue | 28 +--
src/views/containers/topology/alarm/alarm-tool.vue | 1 -
.../topology/endpoint/endpoints-survey.vue | 2 +-
.../topology/instance/instances-survey.vue | 2 +-
src/views/containers/trace.vue | 3 -
33 files changed, 867 insertions(+), 352 deletions(-)
diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts
index a4fb0d2..c7201e5 100644
--- a/src/assets/lang/en.ts
+++ b/src/assets/lang/en.ts
@@ -171,10 +171,10 @@ const m = {
defaultOrder: 'Default Order',
chartType: 'Chart Type',
currentDepth: 'Current Depth',
- traceTagsTip:
+ tagsTip:
'Only tags defined in the core/default/searchableTagKeys are searchable.
Check more details on the Configuration Vocabulary page',
- traceLink: 'Configuration Vocabulary page',
- traceAddTag: 'Please add a tag',
+ tagsLink: 'Configuration Vocabulary page',
+ addTag: 'Please add a tag',
log: 'Log',
logCategory: 'Log Category',
errorCatalog: 'Error Catalog',
@@ -186,6 +186,14 @@ const m = {
errorPage: 'Error Page',
category: 'Category',
grade: 'Grade',
+ setConditions: 'More Conditions',
+ metricName: 'Metric Name',
+ keywordsOfContent: 'Keys Of Content',
+ excludingKeywordsOfContent: 'Exclude Keys Of Content',
+ return: 'Return',
+ isError: 'Error',
+ contentType: 'Content Type',
+ content: 'Content',
};
export default m;
diff --git a/src/assets/lang/zh.ts b/src/assets/lang/zh.ts
index fe8fda6..e696d0f 100644
--- a/src/assets/lang/zh.ts
+++ b/src/assets/lang/zh.ts
@@ -171,9 +171,9 @@ const m = {
defaultOrder: '默认顺序',
chartType: '图表类型',
currentDepth: '当前深度',
- traceTagsTip:
'只有core/default/searchableTagKeys中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。',
- traceLink: '配置词汇页',
- traceAddTag: '请添加标签',
+ tagsTip: '只有core/default/searchableTagKeys中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。',
+ tagsLink: '配置词汇页',
+ addTag: '请添加标签',
log: '日志',
logCategory: '日志类别',
errorCatalog: '错误类目',
@@ -185,6 +185,14 @@ const m = {
errorPage: '错误页面',
category: '类别',
grade: '等级',
+ setConditions: '更多条件',
+ metricName: '指标名称',
+ keywordsOfContent: '内容关键词',
+ excludingKeywordsOfContent: '内容不包含的关键词',
+ return: '返回',
+ isError: '错误',
+ contentType: '内容类型',
+ content: '内容',
};
export default m;
diff --git a/src/graph/fragments/log.ts b/src/graph/fragments/log.ts
index 20d6841..163c708 100644
--- a/src/graph/fragments/log.ts
+++ b/src/graph/fragments/log.ts
@@ -34,21 +34,34 @@ export const QueryBrowserErrorLogs = {
}`,
};
-export const GetProfileAnalyze = {
- variable: '$segmentId: String!, $timeRanges: [ProfileAnalyzeTimeRange!]!',
+export const QueryServiceLogs = {
+ variable: '$condition: LogQueryCondition',
query: `
- getProfileAnalyze: getProfileAnalyze(segmentId: $segmentId, timeRanges:
$timeRanges) {
- tip
- trees {
- elements {
- id
- parentId
- codeSignature
- duration
- durationChildExcluded
- count
- }
- }
- }
- `,
+ queryLogs(condition: $condition) {
+ logs {
+ serviceName
+ serviceId
+ serviceInstanceName
+ serviceInstanceId
+ endpointName
+ endpointId
+ traceId
+ timestamp
+ isError
+ statusCode
+ contentType
+ content
+ tags {
+ key
+ value
+ }
+ }
+ total
+ }`,
+};
+
+export const QueryLogsByKeywords = {
+ variable: '',
+ query: `
+ support: supportQueryLogsByKeywords`,
};
diff --git a/src/graph/query/log.ts b/src/graph/query/log.ts
index 20db18e..66ff97e 100644
--- a/src/graph/query/log.ts
+++ b/src/graph/query/log.ts
@@ -15,6 +15,8 @@
* limitations under the License.
*/
-import { QueryBrowserErrorLogs } from '../fragments/log';
+import { QueryBrowserErrorLogs, QueryServiceLogs, QueryLogsByKeywords } from
'../fragments/log';
export const queryBrowserErrorLogs = `query
queryBrowserErrorLogs(${QueryBrowserErrorLogs.variable})
{${QueryBrowserErrorLogs.query}}`;
+export const queryServiceLogs = `query queryLogs(${QueryServiceLogs.variable})
{${QueryServiceLogs.query}}`;
+export const queryLogsByKeywords = `query queryLogsByKeywords
{${QueryLogsByKeywords.query}}`;
diff --git a/src/router.ts b/src/router.ts
index fffe4dd..8250755 100644
--- a/src/router.ts
+++ b/src/router.ts
@@ -48,8 +48,10 @@ const router = new Router({
component: Dashboard,
},
{
+ name: 'trace',
path: 'trace',
component: Trace,
+ props: true,
},
{
path: 'topology',
diff --git a/src/store/index.ts b/src/store/index.ts
index ede1c32..0e907fa 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -18,7 +18,7 @@
import Vue from 'vue';
import Vuex from 'vuex';
import rocketbot, { State as RocketbotState } from './modules/global';
-import rocketOption, { State as DashboardOptionState } from
'./modules/dashboard/dashboard-option';
+import rocketOption, { State as DashboardOptionState } from
'./modules/global/selectors';
import rocketData, { State as DashboardDataState } from
'./modules/dashboard/dashboard-data';
import rocketTopo, { State as TopoState } from '@/store/modules/topology';
import rocketTopoGroup, { State as TopoGroupState } from
'@/store/modules/topology/group';
diff --git a/src/store/modules/dashboard/dashboard-data.ts
b/src/store/modules/dashboard/dashboard-data.ts
index fc4e60d..1d17125 100644
--- a/src/store/modules/dashboard/dashboard-data.ts
+++ b/src/store/modules/dashboard/dashboard-data.ts
@@ -60,7 +60,6 @@ const actions: ActionTree<State, any> = {
}
context.commit('SET_GROUP_QUERY', temp);
context.commit('SET_CURRENT_GROUP', index);
- context.dispatch('SET_CURRENT_STATE', context.state.tree[index].query);
context.dispatch('RUN_EVENTS', {}, { root: true });
},
MIXHANDLE_CHANGE_GROUP_WITH_CURRENT(
@@ -83,7 +82,6 @@ const actions: ActionTree<State, any> = {
}
context.commit('SET_GROUP_QUERY', temp);
context.commit('SET_CURRENT_GROUP_WITH_CURRENT', { index, current });
- context.dispatch('SET_CURRENT_STATE', context.state.tree[index].query);
context.dispatch('RUN_EVENTS', {}, { root: true });
},
TYPE_METRICS(context, params: { name: string }) {
diff --git a/src/store/modules/dashboard/mutation-types.ts
b/src/store/modules/dashboard/mutation-types.ts
index 110b0dd..aa18646 100644
--- a/src/store/modules/dashboard/mutation-types.ts
+++ b/src/store/modules/dashboard/mutation-types.ts
@@ -35,6 +35,7 @@ export const SET_CURRENT_INSTANCE = 'SET_CURRENT_INSTANCE';
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';
// comp
export const SET_CURRENT_GROUP = 'SET_CURRENT_GROUP';
diff --git a/src/store/modules/dashboard/dashboard-option.ts
b/src/store/modules/global/selectors.ts
similarity index 87%
rename from src/store/modules/dashboard/dashboard-option.ts
rename to src/store/modules/global/selectors.ts
index f9ac1ee..354ee72 100644
--- a/src/store/modules/dashboard/dashboard-option.ts
+++ b/src/store/modules/global/selectors.ts
@@ -16,9 +16,10 @@
*/
import { Commit, ActionTree, MutationTree, Dispatch } from 'vuex';
-import * as types from './mutation-types';
+import * as types from '../dashboard/mutation-types';
import { AxiosResponse } from 'axios';
import graph from '@/graph';
+import { Duration } from '@/types/global';
interface Options {
key: string;
@@ -34,8 +35,11 @@ export interface State {
instances: Options[];
currentInstance: Options;
updateDashboard: object;
+ pageType: string;
}
+const LOG = 'Log';
+
const initState: State = {
services: [],
currentService: { key: '', label: '' },
@@ -46,13 +50,14 @@ const initState: State = {
databases: [],
currentDatabase: { key: '', label: '' },
updateDashboard: {},
+ pageType: '',
};
// mutations
const mutations: MutationTree<State> = {
[types.SET_SERVICES](state: State, data: Options[]) {
- state.services = data;
- state.currentService = data[0] || {};
+ state.services = state.pageType === LOG ? [{ label: 'All', key: '' },
...data] : data;
+ state.currentService = state.services[0] || {};
},
[types.SET_CURRENT_SERVICE](state: State, service: Options) {
state.currentService = service;
@@ -64,24 +69,24 @@ const mutations: MutationTree<State> = {
},
[types.SET_ENDPOINTS](state: State, data: Options[]) {
- state.endpoints = data;
- if (!data.length) {
+ state.endpoints = state.pageType === LOG ? [{ label: 'All', key: '' },
...data] : data;
+ if (!state.endpoints.length) {
state.currentEndpoint = { key: '', label: '' };
return;
}
- state.currentEndpoint = data[0];
+ state.currentEndpoint = state.endpoints[0];
},
[types.SET_CURRENT_ENDPOINT](state: State, endpoint: Options) {
state.currentEndpoint = endpoint;
state.updateDashboard = endpoint;
},
[types.SET_INSTANCES](state: State, data: Options[]) {
- state.instances = data;
- if (!data.length) {
+ state.instances = state.pageType === LOG ? [{ label: 'All', key: '' },
...data] : data;
+ if (!state.instances.length) {
state.currentInstance = { key: '', label: '' };
return;
}
- state.currentInstance = data[0];
+ state.currentInstance = state.instances[0];
},
[types.SET_CURRENT_INSTANCE](state: State, instance: Options) {
state.currentInstance = instance;
@@ -99,6 +104,9 @@ const mutations: MutationTree<State> = {
state.currentDatabase = service;
state.updateDashboard = service;
},
+ [types.SET_PAGE_TYPE](state: State, type: string) {
+ state.pageType = type;
+ },
};
// actions
@@ -150,9 +158,6 @@ const actions: ActionTree<State, any> = {
});
},
SELECT_SERVICE(context: { commit: Commit; dispatch: Dispatch }, params: any)
{
- if (!params.service.key) {
- return;
- }
context.commit('SET_CURRENT_SERVICE', params.service);
context.dispatch('GET_SERVICE_ENDPOINTS', {});
context.dispatch('GET_SERVICE_INSTANCES', { duration: params.duration });
@@ -167,13 +172,16 @@ const actions: ActionTree<State, any> = {
context.commit('SET_CURRENT_DATABASE', params);
context.dispatch('RUN_EVENTS', {}, { root: true });
},
- SET_CURRENT_STATE(context: { commit: Commit }, params: any = {}) {
- context.commit(types.SET_CURRENT_SERVICE, params.service ? params.service
: {});
- context.commit(types.SET_CURRENT_DATABASE, params.database ?
params.database : {});
- context.commit(types.SET_CURRENT_ENDPOINT, params.endpoint ?
params.endpoint : {});
- context.commit(types.SET_CURRENT_INSTANCE, params.instance ?
params.instance : {});
- },
- MIXHANDLE_GET_OPTION(context: { dispatch: Dispatch; state: State }, params:
any) {
+ MIXHANDLE_GET_OPTION(
+ context: { dispatch: Dispatch; commit: Commit },
+ params: {
+ compType: string;
+ duration: Duration;
+ keywordServiceName?: string;
+ pageType?: string;
+ },
+ ) {
+ context.commit('SET_PAGE_TYPE', params.pageType);
switch (params.compType) {
case 'service':
return context
diff --git a/src/store/modules/log/index.ts b/src/store/modules/log/index.ts
index d4cedb9..3b9a66f 100644
--- a/src/store/modules/log/index.ts
+++ b/src/store/modules/log/index.ts
@@ -25,22 +25,19 @@ interface Options {
label: string;
}
export interface State {
- type: any;
- logCategories: any[];
+ type: Options;
+ logCategories: Options[];
logs: any[];
total: number;
- categories: any[];
- category: any;
+ categories: Options[];
+ category: Options;
loading: boolean;
- logServices: Options[];
- currentLogService: Options;
- logEndpoints: Options[];
- currentLogEndpoint: Options;
- logInstances: Options[];
- currentLogInstance: Options;
+ conditions: any;
+ supportQueryLogsByKeywords: boolean;
+ tagsList: string[];
}
-const categories: any = [
+const categories: Options[] = [
{ label: 'All', key: 'ALL' },
{ label: 'Ajax', key: 'AJAX' },
{ label: 'Resource', key: 'RESOURCE' },
@@ -50,23 +47,20 @@ const categories: any = [
{ label: 'Unknown', key: 'UNKNOWN' },
];
-const initState: State = {
- type: { label: 'Browser', key: 'browser' },
+const logState: State = {
+ type: { label: 'Service', key: 'service' },
logCategories: [
+ { label: 'Service', key: 'service' },
{ label: 'Browser', key: 'browser' },
- { label: 'Service', key: 'service', disabled: true },
],
logs: [],
total: 0,
categories,
category: { label: 'All', key: 'ALL' },
loading: false,
- logServices: [],
- currentLogService: { key: '', label: '' },
- logEndpoints: [],
- currentLogEndpoint: { key: '', label: '' },
- logInstances: [],
- currentLogInstance: { key: '', label: '' },
+ conditions: {},
+ supportQueryLogsByKeywords: true,
+ tagsList: localStorage.getItem('logTags') ?
JSON.parse(localStorage.getItem('logTags') || '') : [],
};
// mutations
@@ -86,39 +80,39 @@ const mutations: MutationTree<State> = {
[types.SET_LOADING](state: State, data: boolean) {
state.loading = data;
},
- [types.SET_LOG_SERVICES](state: State, data: Options[]) {
- state.logServices = [{ label: 'All', key: '' }, ...data];
- state.currentLogService = state.logServices[0];
+ [types.SET_LOG_CONDITIONS](state: State, item: Options) {
+ state.conditions = {
+ ...state.conditions,
+ [item.label]: item.key,
+ };
},
- [types.SET_LOG_ENDPOINTS](state: State, data: Options[]) {
- state.logEndpoints = [{ label: 'All', key: '' }, ...data];
- state.currentLogEndpoint = state.logEndpoints[0];
+ [types.SET_SUPPORT_QUERY_LOGS_KEYWORDS](state: State, isSupport: boolean) {
+ state.supportQueryLogsByKeywords = isSupport;
},
- [types.SET_LOG_INSTANCES](state: State, data: Options[]) {
- state.logInstances = [{ label: 'All', key: '' }, ...data];
- state.currentLogInstance = state.logInstances[0];
+ [types.CLEAR_LOG_CONDITIONS](state: State) {
+ state.conditions = {};
},
- [types.SET_CURRENT_LOG_SERVICE](state: State, service: Options) {
- state.currentLogService = service;
- },
- [types.SET_CURRENT_LOG_ENDPOINT](state: State, endpoint: Options) {
- state.currentLogEndpoint = endpoint;
- },
- [types.SET_CURRENT_LOG_INSTANCE](state: State, instance: Options) {
- state.currentLogInstance = instance;
+ [types.SET_TAG_LIST](state: State, data: string[]) {
+ state.tagsList = data;
},
};
// actions
const actions: ActionTree<State, any> = {
QUERY_LOGS(context: { commit: Commit; state: State }, params: any) {
+ context.commit('SET_LOADING', true);
switch (context.state.type.key) {
case 'browser':
- context.commit('SET_LOADING', true);
return graph
.query('queryBrowserErrorLogs')
.params(params)
.then((res: AxiosResponse<any>) => {
+ if (res.data && res.data.errors) {
+ context.commit('SET_LOGS', []);
+ context.commit('SET_LOGS_TOTAL', 0);
+
+ return;
+ }
context.commit('SET_LOGS',
res.data.data.queryBrowserErrorLogs.logs);
context.commit('SET_LOGS_TOTAL',
res.data.data.queryBrowserErrorLogs.total);
})
@@ -126,68 +120,41 @@ const actions: ActionTree<State, any> = {
context.commit('SET_LOADING', false);
});
case 'service':
- break;
+ return graph
+ .query('queryServiceLogs')
+ .params(params)
+ .then((res: AxiosResponse<any>) => {
+ if (res.data && res.data.errors) {
+ context.commit('SET_LOGS', []);
+ context.commit('SET_LOGS_TOTAL', 0);
+
+ return;
+ }
+ context.commit('SET_LOGS', res.data.data.queryLogs.logs);
+ context.commit('SET_LOGS_TOTAL', res.data.data.queryLogs.total);
+ })
+ .finally(() => {
+ context.commit('SET_LOADING', false);
+ });
default:
break;
}
},
- GET_LOG_SERVICES(context: { commit: Commit }, params: { duration: any }) {
+ QUERY_LOGS_BYKEYWORDS(context: { commit: Commit }) {
return graph
- .query('queryBrowserServices')
- .params(params)
- .then((res: AxiosResponse) => {
- context.commit(types.SET_LOG_SERVICES, res.data.data.services);
+ .query('queryLogsByKeywords')
+ .params({})
+ .then((res: AxiosResponse<any>) => {
+ if (res.data && res.data.errors) {
+ return;
+ }
+ context.commit('SET_SUPPORT_QUERY_LOGS_KEYWORDS',
res.data.data.support);
});
},
- LOG_GET_OPTION(context: { dispatch: Dispatch; state: State }, params: any) {
- context
- .dispatch('GET_LOG_SERVICES', { duration: params.duration })
- .then(() => context.dispatch('GET_LOG_ENDPOINTS', {}))
- .then(() => context.dispatch('GET_LOG_INSTANCES', { duration:
params.duration }));
- },
- GET_LOG_ENDPOINTS(context: { commit: Commit; state: any }, params: {
keyword: string }) {
- if (!context.state.currentLogEndpoint.key) {
- context.commit(types.SET_LOG_ENDPOINTS, []);
- return;
- }
- if (!params.keyword) {
- params.keyword = '';
- }
- return graph
- .query('queryEndpoints')
- .params({ serviceId: context.state.currentLogEndpoint.key || '',
...params })
- .then((res: AxiosResponse) => {
- context.commit(types.SET_LOG_ENDPOINTS, res.data.data.getEndpoints);
- });
- },
- GET_LOG_INSTANCES(context: { commit: Commit; state: any }, params: any) {
- if (!context.state.currentLogInstance.key) {
- context.commit(types.SET_LOG_INSTANCES, []);
- return;
- }
- return graph
- .query('queryInstances')
- .params({ serviceId: context.state.currentLogInstance.key || '',
...params })
- .then((res: AxiosResponse) => {
- context.commit(types.SET_LOG_INSTANCES,
res.data.data.getServiceInstances);
- });
- },
- SELECT_LOG_SERVICE(context: { commit: Commit; dispatch: Dispatch }, params:
any) {
- context.commit('SET_CURRENT_LOG_SERVICE', params.service);
- context.dispatch('GET_LOG_ENDPOINTS', {});
- context.dispatch('GET_LOG_INSTANCES', { duration: params.duration });
- },
- SELECT_LOG_ENDPOINT(context: { commit: Commit; dispatch: Dispatch; state:
any; rootState: any }, params: any) {
- context.commit('SET_CURRENT_LOG_ENDPOINT', params.endpoint);
- },
- SELECT_LOG_INSTANCE(context: { commit: Commit; dispatch: Dispatch; state:
any; rootState: any }, params: any) {
- context.commit('SET_CURRENT_LOG_INSTANCE', params.instance);
- },
};
export default {
- // namespaced: true,
- state: initState,
+ state: logState,
actions,
mutations,
};
diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts
index 603e45a..6846c00 100644
--- a/src/store/mutation-types.ts
+++ b/src/store/mutation-types.ts
@@ -122,3 +122,7 @@ export const SET_LOG_INSTANCES = 'SET_LOG_INSTANCES';
export const SET_CURRENT_LOG_SERVICE = 'SET_CURRENT_LOG_SERVICE';
export const SET_CURRENT_LOG_ENDPOINT = 'SET_CURRENT_LOG_ENDPOINT';
export const SET_CURRENT_LOG_INSTANCE = 'SET_CURRENT_LOG_INSTANCE';
+export const SET_LOG_CONDITIONS = 'SET_LOG_CONDITIONS';
+export const SET_SUPPORT_QUERY_LOGS_KEYWORDS =
'SET_SUPPORT_QUERY_LOGS_KEYWORDS';
+export const CLEAR_LOG_CONDITIONS = 'CLEAR_LOG_CONDITIONS';
+export const SET_TAG_LIST = 'SET_TAG_LIST';
diff --git a/src/graph/query/log.ts b/src/utils/formatJson.ts
similarity index 76%
copy from src/graph/query/log.ts
copy to src/utils/formatJson.ts
index 20db18e..02bda02 100644
--- a/src/graph/query/log.ts
+++ b/src/utils/formatJson.ts
@@ -14,7 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-import { QueryBrowserErrorLogs } from '../fragments/log';
-
-export const queryBrowserErrorLogs = `query
queryBrowserErrorLogs(${QueryBrowserErrorLogs.variable})
{${QueryBrowserErrorLogs.query}}`;
+const censor = (key: any, value: any) => {
+ if (typeof value === 'function') {
+ return Function.prototype.toString.call(value);
+ }
+ return value;
+};
+export const formatJson = (data: JSON) => {
+ return JSON.stringify(data, censor, 2);
+};
diff --git a/src/views/components/common/trace-detail-chart-table.vue
b/src/views/components/common/trace-detail-chart-table.vue
index 9203931..52c8048 100644
--- a/src/views/components/common/trace-detail-chart-table.vue
+++ b/src/views/components/common/trace-detail-chart-table.vue
@@ -80,7 +80,6 @@ limitations under the License. -->
</div>
</div>
</rk-sidebox>
- <v-dialog width="90%" />
</div>
</template>
<style lang="scss">
diff --git a/src/views/components/dashboard/dashboard-item.vue
b/src/views/components/dashboard/dashboard-item.vue
index 526601d..1638dc0 100644
--- a/src/views/components/dashboard/dashboard-item.vue
+++ b/src/views/components/dashboard/dashboard-item.vue
@@ -72,7 +72,7 @@ limitations under the License. -->
import { MetricsType, CalculationType } from './charts/constant';
import { uuid } from '@/utils/uuid.ts';
import { State as globalState } from '@/store/modules/global';
- import { State as optionState } from
'@/store/modules/dashboard/dashboard-option';
+ import { State as optionState } from '@/store/modules/global/selectors';
@Component({
components: { ...charts },
diff --git a/src/views/components/log/log-bar.vue
b/src/views/components/log/log-bar.vue
index bf4a5e0..1a4d14c 100644
--- a/src/views/components/log/log-bar.vue
+++ b/src/views/components/log/log-bar.vue
@@ -12,96 +12,126 @@ See the License for the specific language governing
permissions and
limitations under the License. -->
<template>
- <div class="rk-error-log-bar flex-h">
- <div class="flex-h">
- <ToolBarSelect
- @onChoose="SELECT_LOG_TYPE"
- :title="this.$t('logCategory')"
- :current="logState.type"
- :data="logState.logCategories"
- icon="chart"
- />
- <ToolBarSelect
- @onChoose="selectService"
- :title="this.$t('service')"
- :current="logState.currentLogService"
- :data="logState.logServices"
- icon="package"
- />
- <ToolBarSelect
- @onChoose="selectInstance"
- :title="this.$t('version')"
- :current="logState.currentLogInstance"
- :data="logState.logInstances"
- icon="disk"
- />
- <ToolBarSelect
- @onChoose="selectEndpoint"
- :title="this.$t('page')"
- :current="logState.currentLogEndpoint"
- :data="logState.logEndpoints"
- icon="code"
- />
- <ToolBarSelect
- @onChoose="SELECT_ERROR_CATALOG"
- :title="this.$t('errorCatalog')"
- :current="logState.category"
- :data="logState.categories"
- icon="epic"
- />
+ <div class="rk-log-nav">
+ <div class="rk-error-log-bar flex-h">
+ <div class="flex-h">
+ <ToolBarSelect
+ @onChoose="selectCategroy"
+ :title="this.$t('logCategory')"
+ :current="logState.type"
+ :data="logState.logCategories"
+ icon="chart"
+ />
+ <ToolBarSelect
+ @onChoose="selectService"
+ :title="this.$t('service')"
+ :current="rocketOption.currentService"
+ :data="rocketOption.services"
+ icon="package"
+ />
+ <ToolBarSelect
+ @onChoose="selectInstance"
+ :title="logState.type.key === cateGoryBrowser ? this.$t('version') :
this.$t('currentInstance')"
+ :current="rocketOption.currentInstance"
+ :data="rocketOption.instances"
+ icon="disk"
+ />
+ <ToolBarSelect
+ @onChoose="selectEndpoint"
+ :title="logState.type.key === cateGoryBrowser ? this.$t('page') :
this.$t('currentEndpoint')"
+ :current="rocketOption.currentEndpoint"
+ :data="rocketOption.endpoints"
+ icon="code"
+ />
+ <ToolBarSelect
+ @onChoose="SELECT_ERROR_CATALOG"
+ :title="this.$t('errorCatalog')"
+ :current="logState.category"
+ :data="logState.categories"
+ icon="epic"
+ />
+ </div>
+ <span class="flex-h rk-right">
+ <a
+ class="rk-log-search-btn bg-blue mr-10"
+ v-if="logState.type.key !== cateGoryBrowser"
+ @click="openConditionsBox"
+ >
+ <rk-icon icon="settings" class="mr-5" />
+ <span class="vm">{{ $t('setConditions') }}</span>
+ </a>
+ <a class="rk-log-search-btn bg-blue mr-10" @click="queryLogs">
+ <rk-icon icon="search" class="mr-5" />
+ <span class="vm">{{ this.$t('search') }}</span>
+ </a>
+ <a class="rk-log-clear-btn r mr-10" @click="clearSearch">
+ <rk-icon icon="clear" class="mr-5" />
+ <span class="vm">{{ this.$t('clear') }}</span>
+ </a>
+
+ <RkPage :currentSize="10" :currentPage="pageNum"
@changePage="handleRefresh" :total="logState.total" />
+ </span>
+ </div>
+ <div class="flex-h" v-show="showConditionsBox">
+ <LogConditions />
</div>
-
- <span class="flex-h rk-right">
- <a class="rk-log-clear-btn r mr-10" @click="clearSearch">
- <svg class="icon mr-5 vm">
- <use xlink:href="#clear"></use>
- </svg>
- <span class="vm">{{ this.$t('clear') }}</span>
- </a>
- <a class="rk-log-search-btn bg-blue mr-10" @click="queryLogs">
- <svg class="icon mr-5 vm">
- <use xlink:href="#search"></use>
- </svg>
- <span class="vm">{{ this.$t('search') }}</span>
- </a>
-
- <RkPage :currentSize="10" :currentPage="pageNum"
@changePage="handleRefresh" :total="logState.total" />
- </span>
</div>
</template>
<script lang="ts">
import { Duration, Option } from '@/types/global';
- import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
+ import { Component, Vue } from 'vue-property-decorator';
import { Action, Getter, Mutation, State } from 'vuex-class';
import TraceSelect from '../common/trace-select.vue';
import ToolBarSelect from '../dashboard/tool-bar-select.vue';
import ToolBarEndpointSelect from
'../dashboard/tool-bar-endpoint-select.vue';
+ import LogConditions from './log-conditions.vue';
@Component({
- components: { TraceSelect, ToolBarSelect, ToolBarEndpointSelect },
+ components: { TraceSelect, ToolBarSelect, ToolBarEndpointSelect,
LogConditions },
})
export default class Bar extends Vue {
@State('rocketLog') private logState: any;
@State('rocketOption') private rocketOption: any;
@Mutation('SELECT_LOG_TYPE') private SELECT_LOG_TYPE: any;
@Mutation('SELECT_ERROR_CATALOG') private SELECT_ERROR_CATALOG: any;
- @Action('SELECT_LOG_SERVICE') private SELECT_LOG_SERVICE: any;
- @Action('SELECT_LOG_ENDPOINT') private SELECT_LOG_ENDPOINT: any;
- @Action('SELECT_LOG_INSTANCE') private SELECT_LOG_INSTANCE: any;
- @Action('LOG_GET_OPTION') private LOG_GET_OPTION: any;
+ @Mutation('SET_EVENTS') private SET_EVENTS: any;
+ @Mutation('CLEAR_LOG_CONDITIONS') private CLEAR_LOG_CONDITIONS: any;
+ @Mutation('SET_TAG_LIST') private SET_TAG_LIST: any;
+ @Action('SELECT_SERVICE') private SELECT_SERVICE: any;
+ @Action('SELECT_ENDPOINT') private SELECT_ENDPOINT: any;
+ @Action('SELECT_INSTANCE') private SELECT_INSTANCE: any;
+ @Action('MIXHANDLE_GET_OPTION') private MIXHANDLE_GET_OPTION: any;
@Action('QUERY_LOGS') private QUERY_LOGS: any;
+ @Action('QUERY_LOGS_BYKEYWORDS') private QUERY_LOGS_BYKEYWORDS: any;
@Getter('durationTime') private durationTime: any;
private pageNum: number = 1;
+ private cateGoryBrowser = 'browser';
+ private showConditionsBox = true;
+ private logPage = 'Log';
private beforeMount() {
- this.LOG_GET_OPTION({
+ this.MIXHANDLE_GET_OPTION({
compType: this.logState.type.key,
duration: this.durationTime,
- }).then(() => {
- this.queryLogs();
- });
+ pageType: this.logPage,
+ })
+ .then(() => {
+ this.QUERY_LOGS_BYKEYWORDS();
+ })
+ .then(() => {
+ this.queryLogs();
+ });
+ this.SET_EVENTS([
+ () => {
+ this.queryLogs();
+ },
+ ]);
+ }
+
+ private beforeDestroy() {
+ this.SET_EVENTS([]);
}
private handleRefresh(pageNum: number) {
@@ -109,46 +139,90 @@ limitations under the License. -->
this.queryLogs();
}
- private selectService(i: any) {
- this.SELECT_LOG_SERVICE({ service: i, duration: this.durationTime });
+ private selectService(i: { key: string; label: string }) {
+ this.SELECT_SERVICE({ service: i, duration: this.durationTime });
}
- private selectEndpoint(i: any) {
- this.SELECT_LOG_ENDPOINT({ endpoint: i, duration: this.durationTime });
+ private selectEndpoint(i: { key: string; label: string }) {
+ this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
}
- private selectInstance(i: any) {
- this.SELECT_LOG_INSTANCE({ instance: i, duration: this.durationTime });
+ private selectInstance(i: { key: string; label: string }) {
+ this.SELECT_INSTANCE({ instance: i, duration: this.durationTime });
+ }
+
+ private selectCategroy(i: { key: string; label: string }) {
+ this.SELECT_LOG_TYPE(i);
+ this.MIXHANDLE_GET_OPTION({
+ compType: i.key,
+ duration: this.durationTime,
+ pageType: this.logPage,
+ }).then(() => {
+ this.queryLogs();
+ });
}
+
private clearSearch() {
- this.SELECT_LOG_SERVICE({ service: { label: 'All', key: '' }, duration:
this.durationTime });
+ this.SELECT_SERVICE({ service: { label: 'All', key: '' }, duration:
this.durationTime });
this.SELECT_ERROR_CATALOG({ label: 'All', key: 'ALL' });
+ this.CLEAR_LOG_CONDITIONS();
+ this.queryLogs();
+ window.localStorage.removeItem('logTags');
+ this.SET_TAG_LIST([]);
}
private queryLogs() {
- const { category, currentLogService, currentLogInstance,
currentLogEndpoint } = this.logState;
+ const { category, conditions, type } = this.logState;
+ const { currentService, currentInstance, currentEndpoint } =
this.rocketOption;
this.QUERY_LOGS({
- condition: {
- serviceId: currentLogService.key,
- serviceVersionId: currentLogInstance.key,
- pagePathId: currentLogEndpoint.key,
- category: category.key,
- paging: { pageNum: this.pageNum, pageSize: 35, needTotal: true },
- queryDuration: this.durationTime,
- },
+ condition:
+ type.key === this.cateGoryBrowser
+ ? {
+ serviceId: currentService.key,
+ serviceVersionId: currentInstance.key,
+ pagePathId: currentEndpoint.key,
+ category: category.key,
+ paging: { pageNum: this.pageNum, pageSize: 35, needTotal: true
},
+ queryDuration: this.durationTime,
+ }
+ : {
+ serviceId: currentService.key || undefined,
+ serviceInstanceId: currentInstance.key || undefined,
+ endpointId: currentEndpoint.key || undefined,
+ state: category.key,
+ excludingKeywordsOfContent:
+ this.logState.supportQueryLogsByKeywords &&
conditions.excludingKeywordsOfContent
+ ? conditions.excludingKeywordsOfContent.split(',')
+ : undefined,
+ keywordsOfContent:
+ this.logState.supportQueryLogsByKeywords &&
conditions.keywordsOfContent
+ ? conditions.keywordsOfContent.split(',')
+ : undefined,
+ relatedTrace: conditions.traceId ? { traceId:
conditions.traceId } : undefined,
+ tags: conditions.tags,
+ paging: { pageNum: this.pageNum, pageSize: 35, needTotal: true
},
+ queryDuration: conditions.traceId ? undefined :
this.durationTime,
+ },
});
}
+
+ private openConditionsBox() {
+ this.showConditionsBox = !this.showConditionsBox;
+ }
}
</script>
<style scoped lang="scss">
+ .rk-log-nav {
+ width: 100%;
+ background: #333840;
+ }
.rk-error-log-bar {
flex-shrink: 0;
background-color: #333840;
color: #eee;
width: 100%;
- padding: 8px 15px 12px;
height: 52px;
justify-content: space-between;
}
@@ -161,7 +235,6 @@ limitations under the License. -->
padding: 3px 9px;
background-color: #484b55;
border-radius: 4px;
- /*margin-top: 12px;*/
&.bg-blue {
background-color: #448dfe;
}
@@ -171,4 +244,7 @@ limitations under the License. -->
background-color: #484b55;
border-radius: 4px;
}
+ .log-condition-box {
+ color: #333840;
+ }
</style>
diff --git a/src/views/components/log/log-detail-table.vue
b/src/views/components/log/log-browser-detail.vue
similarity index 66%
rename from src/views/components/log/log-detail-table.vue
rename to src/views/components/log/log-browser-detail.vue
index 307a560..902e28e 100644
--- a/src/views/components/log/log-detail-table.vue
+++ b/src/views/components/log/log-browser-detail.vue
@@ -24,24 +24,61 @@ limitations under the License. -->
</LogTable>
<rk-sidebox :width="'50%'" :show.sync="showDetail"
:title="$t('logDetail')">
<div class="rk-log-detail">
- <div class="mb-10 clear rk-flex" v-for="(item, index) in columns">
+ <div class="mb-10 clear rk-flex" v-for="(item, index) in columns"
:key="index">
<template>
<span class="g-sm-4 grey">{{ $t(item.value) }}:</span>
<span
v-if="['message', 'stack'].includes(item.label)"
class="text"
- v-html="lineBreak(currentSpan[item.label]) || '-'"
+ v-html="lineBreak(currentLog[item.label]) || '-'"
></span>
- <span v-else-if="item.label === 'time'" class="g-sm-8 wba">{{
currentSpan[item.label] | dateformat }}</span>
- <span v-else class="g-sm-8 wba">{{ currentSpan[item.label] || '-'
}}</span>
+ <span v-else-if="item.label === 'time'" class="g-sm-8 wba">{{
currentLog[item.label] | dateformat }}</span>
+ <span v-else class="g-sm-8 wba">{{ currentLog[item.label] || '-'
}}</span>
</template>
</div>
</div>
</rk-sidebox>
-
- <v-dialog width="90%" />
</div>
</template>
+
+<script lang="ts">
+ import { Component, Prop, Vue } from 'vue-property-decorator';
+ import { Mutation, State } from 'vuex-class';
+ import LogTable from './log-table/log-table.vue';
+ import { BrowserLogConstants } from './log-table/log-constant';
+
+ @Component({
+ components: { LogTable },
+ })
+ export default class LogBrowserDetail extends Vue {
+ @State('rocketLog') private logState: any;
+ @Prop() private data: any;
+ @Prop() private loading!: true;
+ @Prop() private showBtnDetail: any;
+
+ private columns = BrowserLogConstants;
+ private showDetail = false;
+ private list = [];
+ private currentLog = {};
+ private created() {
+ this.$eventBus.$on('HANDLE-SELECT-LOG', this, this.handleSelectLog);
+ }
+ private lineBreak(str = '') {
+ const s = str
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .replace(/\r\n/g, '<br />')
+ .replace(/\n/g, '<br />');
+ return s;
+ }
+ private handleSelectLog(data: any) {
+ this.currentLog = data;
+ if (!this.showBtnDetail) {
+ this.showDetail = true;
+ }
+ }
+ }
+</script>
<style lang="scss">
.rk-tooltip-popper.log-table-tooltip .rk-tooltip-inner {
max-width: 600px;
@@ -52,54 +89,6 @@ limitations under the License. -->
border-bottom: none;
}
</style>
-
-<script lang="js">
- import LogTable from './log-table/log-table.vue';
- import { BrowserLogConstants } from './log-table/log-constant';
- /* eslint-disable */
- /* tslint:disable */
- export default {
- components: {
- LogTable,
- },
- props: ['data', 'loading', 'showBtnDetail'],
- data() {
- return {
- diaplay: true,
- columns: BrowserLogConstants,
- showDetail: false,
- list: [],
- currentSpan: {},
- };
- },
- methods: {
- lineBreak(str = '') {
- let s = str
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/\r\n/g, '<br />')
- .replace(/\n/g, '<br />');
- return s;
- },
- handleSelectSpan(data) {
- this.currentSpan = data;
- if (!this.showBtnDetail) {
- this.showDetail = true;
- }
- this.$emit('selectSpan', data);
- },
- handleViewSpan(data) {
- this.showDetail = true;
- }
- },
- created() {
- },
- mounted() {
- this.$eventBus.$on('HANDLE-SELECT-SPAN', this, this.handleSelectSpan);
- this.$eventBus.$on('HANDLE-VIEW-SPAN', this, this.handleViewSpan);
- },
- };
-</script>
<style lang="scss" scoped>
.rk-log-t-loading {
text-align: center;
diff --git a/src/views/components/log/log-conditions.vue
b/src/views/components/log/log-conditions.vue
new file mode 100644
index 0000000..4e584f1
--- /dev/null
+++ b/src/views/components/log/log-conditions.vue
@@ -0,0 +1,182 @@
+<!-- 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="rk-search-conditions flex-v">
+ <div class="flex-h">
+ <div class="mr-15">
+ <span class="sm b grey mr-10">{{ this.$t('traceID') }}:</span>
+ <input
+ type="text"
+ class="rk-trace-search-input dib"
+ @change="changeConditions($event, LogConditionsOpt.TraceID)"
+ />
+ </div>
+ <div class="mr-15">
+ <span class="sm b grey mr-10">{{ this.$t('keywordsOfContent')
}}:</span>
+ <input
+ type="text"
+ class="rk-trace-search-input dib"
+ @change="changeConditions($event,
LogConditionsOpt.KeywordsOfContent)"
+ />
+ </div>
+ <div class="mr-15">
+ <span class="sm b grey mr-10">{{ this.$t('excludingKeywordsOfContent')
}}:</span>
+ <input
+ type="text"
+ class="rk-trace-search-input dib"
+ @change="changeConditions($event,
LogConditionsOpt.ExcludingKeywordsOfContent)"
+ />
+ </div>
+ </div>
+ <div class="mr-10" style="padding-top: 10px">
+ <span class="sm grey">{{ this.$t('tags') }}: </span>
+ <span class="rk-trace-tags">
+ <span class="selected" v-for="(item, index) in rocketLog.tagsList"
:key="index">
+ <span>{{ item }}</span>
+ <span class="remove-icon" @click="removeTags(index)">×</span>
+ </span>
+ </span>
+ <input type="text" :placeholder="this.$t('addTag')" v-model="tags"
class="rk-trace-new-tag" @keyup="addLabels" />
+ <span class="trace-tips" v-tooltip:bottom="{ content: this.$t('tagsTip')
}">
+ <a
+ target="blank"
+
href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
+ >
+ {{ this.$t('tagsLink') }}
+ </a>
+ <rk-icon icon="help" class="mr-5" />
+ </span>
+ </div>
+ </div>
+</template>
+
+<script lang="ts">
+ import { Duration, Option } from '@/types/global';
+ import { Component, Vue } from 'vue-property-decorator';
+ import { Mutation, State } from 'vuex-class';
+
+ @Component({
+ components: {},
+ })
+ export default class LogConditions extends Vue {
+ @State('rocketLog') private rocketLog: any;
+ @Mutation('SET_LOG_CONDITIONS') private SET_LOG_CONDITIONS: any;
+ @Mutation('SET_TAG_LIST') private SET_TAG_LIST: any;
+
+ private tags: string = '';
+ private LogConditionsOpt = {
+ TraceID: 'traceId',
+ Tags: 'tags',
+ KeywordsOfContent: 'keywordsOfContent',
+ ExcludingKeywordsOfContent: 'excludingKeywordsOfContent',
+ };
+ private created() {
+ this.updateTags();
+ }
+ private changeConditions(item: any, type: string) {
+ item = {
+ label: type,
+ key: item.target.value,
+ };
+ this.SET_LOG_CONDITIONS(item);
+ }
+ private addLabels(event: KeyboardEvent) {
+ if (event.keyCode !== 13 || !this.tags) {
+ return;
+ }
+ const tagsList = this.rocketLog.tagsList;
+ tagsList.push(this.tags);
+ this.SET_TAG_LIST(tagsList);
+ this.tags = '';
+ this.updateTags();
+ }
+ private removeTags(index: number) {
+ const tagsList = this.rocketLog.tagsList;
+ tagsList.splice(index, 1);
+ this.SET_TAG_LIST(tagsList);
+ this.updateTags();
+ }
+ private updateTags() {
+ const tagsMap = this.rocketLog.tagsList.map((item: string) => {
+ const key = item.substring(0, item.indexOf('='));
+
+ return {
+ key,
+ value: item.substring(item.indexOf('=') + 1, item.length),
+ };
+ });
+ this.SET_LOG_CONDITIONS({
+ label: this.LogConditionsOpt.Tags,
+ key: tagsMap,
+ });
+ localStorage.setItem('logTags', JSON.stringify(this.rocketLog.tagsList));
+ }
+ }
+</script>
+
+<style scoped lang="scss">
+ .rk-search-conditions {
+ width: 100%;
+ background-color: #484b55;
+ padding: 10px;
+ border-radius: 3px;
+ margin-top: 4px;
+ position: relative;
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
+
+ &:after {
+ bottom: 100%;
+ right: 370px;
+ border: solid transparent;
+ content: ' ';
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+ border-color: rgba(0, 0, 0, 0);
+ border-bottom-color: #484b55;
+ border-width: 8px;
+ margin-right: 0px;
+ }
+ .rk-log-tag {
+ width: 30%;
+ border-style: unset;
+ outline: 0;
+ border: 1px solid #ccc;
+ height: 30px;
+ padding: 0 5px;
+ }
+ .tags-tips {
+ font-weight: normal;
+ }
+ .remove-icon {
+ display: inline-block;
+ margin-left: 3px;
+ cursor: pointer;
+ }
+ .selected {
+ display: inline-block;
+ padding: 0 3px;
+ border-radius: 3px;
+ overflow: hidden;
+ color: #eee;
+ border: 1px dashed #aaa;
+ font-size: 12px;
+ margin: 0 2px;
+ }
+ .trace-tips {
+ color: #eee;
+ }
+ }
+</style>
diff --git a/src/views/containers/log.vue
b/src/views/components/log/log-content.vue
similarity index 57%
copy from src/views/containers/log.vue
copy to src/views/components/log/log-content.vue
index 6d66473..4df6217 100644
--- a/src/views/containers/log.vue
+++ b/src/views/components/log/log-content.vue
@@ -10,42 +10,30 @@ 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="flex-v rk-log">
- <LogBar :logState="logState"></LogBar>
- <div class="log-container">
- <LogDetailTable
- :data="logState.logs"
- :loading="logState.loading"
- v-if="logState.type.key === 'browser'"
- ></LogDetailTable>
- </div>
+ <div class="log-container">
+ <LogServiceDetail :data="logState.logs || []" :loading="logState.loading"
v-if="logState.type.key === 'service'" />
+ <LogBrowserDetail :data="logState.logs || []" :loading="logState.loading"
v-else />
</div>
</template>
<script lang="ts">
- import { Component, Vue, Watch } from 'vue-property-decorator';
- import { Action, Getter, State, Mutation } from 'vuex-class';
- import LogBar from '@/views/components/log/log-bar.vue';
- import LogDetailTable from '@/views/components/log/log-detail-table.vue';
+ import { Duration, Option } from '@/types/global';
+ import { Component, Vue } from 'vue-property-decorator';
+ import { State } from 'vuex-class';
+ import LogBrowserDetail from './log-browser-detail.vue';
+ import LogServiceDetail from './log-service-detail.vue';
+
@Component({
- components: {
- LogBar,
- LogDetailTable,
- },
+ components: { LogBrowserDetail, LogServiceDetail },
})
- export default class Log extends Vue {
- @Getter('durationTime') private durationTime: any;
+ export default class LogContent extends Vue {
@State('rocketLog') private logState: any;
}
</script>
<style scoped lang="scss">
- .rk-log {
- flex-grow: 1;
- height: 100%;
- overflow: hidden;
- }
.log-container {
overflow: auto;
padding: 5px 15px 15px;
diff --git a/src/views/components/log/log-service-detail.vue
b/src/views/components/log/log-service-detail.vue
new file mode 100644
index 0000000..f16c944
--- /dev/null
+++ b/src/views/components/log/log-service-detail.vue
@@ -0,0 +1,124 @@
+<!-- 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="log-detail-chart-table">
+ <div class="rk-log-t-loading" v-show="loading">
+ <svg class="icon loading">
+ <use xlink:href="#spinner"></use>
+ </svg>
+ </div>
+ <LogTable :tableData="data" :type="`service`">
+ <div class="log-tips" v-if="!data.length">{{ $t('noData') }}</div>
+ </LogTable>
+ <rk-sidebox :width="'800px'" :show.sync="showDetail"
:title="$t('logDetail')">
+ <div class="rk-log-detail">
+ <div class="mb-10 clear rk-flex" v-for="(item, index) in columns"
:key="index">
+ <template>
+ <span class="g-sm-4 grey">{{ $t(item.value) }}:</span>
+ <span v-if="item.label === 'timestamp'" class="g-sm-8">{{
currentLog[item.label] | dateformat }}</span>
+ <textarea class="content" readonly="readonly"
v-else-if="item.label === 'content'" v-model="logContent" />
+ <span v-else-if="item.label === 'tags'" class="g-sm-8">
+ <div v-for="(d, index) in logTags" :key="index">{{ d }}</div>
+ </span>
+ <span v-else class="g-sm-8">{{ currentLog[item.label] }}</span>
+ </template>
+ </div>
+ </div>
+ </rk-sidebox>
+ </div>
+</template>
+
+<script lang="ts">
+ import { Component, Prop, Vue } 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';
+
+ @Component({
+ components: { LogTable },
+ })
+ export default class LogServiceDetail extends Vue {
+ @State('rocketLog') private logState: any;
+ @Prop() private data: any;
+ @Prop() private loading!: true;
+ @Prop() private showBtnDetail: any;
+
+ private columns = ServiceLogDetail;
+ private showDetail = false;
+ private list = [];
+ private currentLog: any = {};
+ private logContent: any = '';
+ private logTags: any = '';
+ private formatJson = formatJson;
+ private created() {
+ this.$eventBus.$on('HANDLE-SELECT-LOG', this, this.handleSelectLog);
+ }
+ private handleSelectLog(data: any) {
+ this.currentLog = data;
+ this.logTags = this.currentLog.tags.map((d: any) => {
+ return `${d.key} = ${d.value}`;
+ });
+ if (this.currentLog.contentType === 'JSON') {
+ this.logContent = formatJson(JSON.parse(this.currentLog.content));
+ } else if (this.currentLog.contentType === 'TEXT') {
+ this.logContent = this.currentLog.content;
+ } else {
+ this.logContent = this.currentLog.content;
+ }
+ if (!this.showBtnDetail) {
+ this.showDetail = true;
+ }
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ .rk-log-t-loading {
+ text-align: center;
+ position: absolute;
+ width: 100%;
+ height: 70px;
+ margin-top: 40px;
+ line-height: 88px;
+ overflow: hidden;
+ .icon {
+ width: 30px;
+ height: 30px;
+ }
+ }
+ .dialog-c-text {
+ white-space: pre;
+ overflow: auto;
+ font-family: monospace;
+ }
+ .log-tips {
+ width: 100%;
+ text-align: center;
+ margin-top: 10px;
+ }
+ .rk-flex {
+ display: flex;
+ }
+ .g-sm-4.grey {
+ flex-shrink: 0;
+ }
+ .content {
+ width: 500px;
+ height: 500px;
+ border: none;
+ outline: none;
+ color: #3d444f;
+ }
+</style>
diff --git a/src/views/components/log/log-table/log-item.vue
b/src/views/components/log/log-table/log-browser-item.vue
similarity index 97%
rename from src/views/components/log/log-table/log-item.vue
rename to src/views/components/log/log-table/log-browser-item.vue
index ae7b636..1df1b0b 100644
--- a/src/views/components/log/log-table/log-item.vue
+++ b/src/views/components/log/log-table/log-browser-item.vue
@@ -37,7 +37,7 @@ limitations under the License. -->
export default {
name: 'item',
- props: ['data', 'type', 'method'],
+ props: ['data', 'method'],
watch: {
data: {
handler() {
@@ -85,7 +85,7 @@ limitations under the License. -->
item.style.background = '#fff';
}
this.$refs.logItem.style.background = 'rgba(0, 0, 0, 0.1)';
- this.$eventBus.$emit('HANDLE-SELECT-SPAN', this.data);
+ this.$eventBus.$emit('HANDLE-SELECT-LOG', this.data);
},
},
};
diff --git a/src/views/components/log/log-table/log-constant.ts
b/src/views/components/log/log-table/log-constant.ts
index 1261fc6..c191b77 100644
--- a/src/views/components/log/log-table/log-constant.ts
+++ b/src/views/components/log/log-table/log-constant.ts
@@ -17,8 +17,66 @@
export const ServiceLogConstants = [
{
- label: '',
- value: '',
+ label: 'serviceName',
+ value: 'currentService',
+ },
+ {
+ label: 'serviceInstanceName',
+ value: 'currentInstance',
+ },
+ {
+ label: 'timestamp',
+ value: 'time',
+ },
+ {
+ label: 'contentType',
+ value: 'contentType',
+ },
+ {
+ label: 'isError',
+ value: 'isError',
+ },
+ {
+ label: 'content',
+ value: 'content',
+ },
+ {
+ label: 'traceId',
+ value: 'traceID',
+ },
+];
+export const ServiceLogDetail = [
+ {
+ label: 'serviceName',
+ value: 'currentService',
+ },
+ {
+ label: 'serviceInstanceName',
+ value: 'currentInstance',
+ },
+ {
+ label: 'timestamp',
+ value: 'time',
+ },
+ {
+ label: 'contentType',
+ value: 'contentType',
+ },
+ {
+ label: 'isError',
+ value: 'isError',
+ },
+ {
+ label: 'traceId',
+ value: 'traceID',
+ },
+ {
+ label: 'tags',
+ value: 'tags',
+ },
+ {
+ label: 'content',
+ value: 'content',
},
];
// The order of columns should be time, service, error, stack, version, url,
catalog, and grade.
diff --git a/src/views/components/log/log-table/log-service-item.vue
b/src/views/components/log/log-table/log-service-item.vue
new file mode 100644
index 0000000..a24f63f
--- /dev/null
+++ b/src/views/components/log/log-table/log-service-item.vue
@@ -0,0 +1,95 @@
+<!-- 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 @click="showSelectSpan" class="log-item">
+ <div v-for="(item, index) in columns" :key="index" :class="item.label">
+ <span v-if="item.label === 'timestamp'">
+ {{ data.time | dateformat }}
+ </span>
+ <router-link v-if="item.label === 'traceId'" :to="{ name: 'trace',
query: { traceid: data[item.label] } }">
+ <span>{{ data[item.label] }}</span>
+ </router-link>
+ <span v-else>{{ data[item.label] }}</span>
+ </div>
+ </div>
+</template>
+<script lang="ts">
+ import { Component, Prop, Vue } from 'vue-property-decorator';
+ import { ServiceLogConstants } from './log-constant';
+
+ @Component
+ export default class ServiceItem extends Vue {
+ @Prop() private data: any;
+ private columns = ServiceLogConstants;
+ private showSelectSpan() {
+ this.$eventBus.$emit('HANDLE-SELECT-LOG', this.data);
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ .log-item {
+ white-space: nowrap;
+ position: relative;
+ cursor: pointer;
+ .traceId {
+ width: 390px;
+ color: #448dfe;
+ cursor: pointer;
+ span {
+ display: inline-block;
+ width: 100%;
+ line-height: 30px;
+ }
+ }
+ .content {
+ width: 300px;
+ }
+ .serviceInstanceName,
+ .serviceName {
+ width: 200px;
+ }
+ }
+
+ .log-item:hover {
+ background: rgba(0, 0, 0, 0.04);
+ }
+
+ .log-item > div {
+ line-height: 1.3;
+ width: 140px;
+ padding: 0 5px;
+ display: inline-block;
+ border: 1px solid transparent;
+ border-right: 1px dotted silver;
+ overflow: hidden;
+ line-height: 30px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .log-item .text {
+ width: 100%;
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .log-item > div.method {
+ height: 100%;
+ padding: 3px 8px;
+ }
+</style>
diff --git a/src/views/components/log/log-table/log-table.vue
b/src/views/components/log/log-table/log-table.vue
index 3a526cc..8795e88 100644
--- a/src/views/components/log/log-table/log-table.vue
+++ b/src/views/components/log/log-table/log-table.vue
@@ -19,9 +19,7 @@ limitations under the License. -->
<template v-for="(item, index) in columns">
<div class="method" :style="`width: ${item.method}px`"
v-if="item.drag" :key="index">
<span class="r cp" ref="dragger" :data-index="index">
- <svg class="icon">
- <use xlink:href="#settings_ethernet"></use>
- </svg>
+ <rk-icon icon="settings_ethernet" />
</span>
{{ $t(item.value) }}
</div>
@@ -30,22 +28,28 @@ limitations under the License. -->
</div>
</template>
</div>
- <Item :method="method" v-for="(item, index) in tableData" :data="item"
:key="'key' + index" :type="type" />
+ <div v-if="type === 'browser'">
+ <BrowserItem :method="method" v-for="(item, index) in tableData"
:data="item" :key="'key' + index" />
+ </div>
+ <div v-else>
+ <ServiceItem v-for="(item, index) in tableData" :data="item" :key="'key'
+ index" />
+ </div>
<slot></slot>
</div>
</template>
<script lang="js">
import { ServiceLogConstants, BrowserLogConstants } from './log-constant';
- import Item from './log-item';
+ import BrowserItem from './log-browser-item';
+ import ServiceItem from './log-service-item';
export default {
- components: { Item },
+ components: { ServiceItem, BrowserItem },
name: 'LogContainer',
props: ['type', 'tableData'],
data() {
return {
method: 380,
- columns: BrowserLogConstants,
+ columns: this.type === 'browser' ? BrowserLogConstants :
ServiceLogConstants,
};
},
created() {
@@ -61,7 +65,7 @@ limitations under the License. -->
}
},
mounted() {
- const drags = this.$refs.dragger;
+ const drags = this.$refs.dragger || [];
drags.forEach((drag) => {
drag.onmousedown = (event) => {
const diffX = event.clientX;
@@ -100,6 +104,16 @@ limitations under the License. -->
border-right: 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
/*background-color: #f3f4f9;*/
+ .traceId {
+ width: 390px;
+ }
+ .content {
+ width: 300px;
+ }
+ .serviceInstanceName,
+ .serviceName {
+ width: 200px;
+ }
}
.log-header div {
diff --git a/src/views/components/topology/topo-group/index.vue
b/src/views/components/topology/topo-group/index.vue
index 6508a67..b55269f 100644
--- a/src/views/components/topology/topo-group/index.vue
+++ b/src/views/components/topology/topo-group/index.vue
@@ -59,7 +59,6 @@ limitations under the License. -->
@Mutation('rocketTopoGroup/INIT_GROUPS') private INIT_GROUPS: any;
@Mutation('rocketTopoGroup/DELETE_GROUP') private DELETE_GROUP: any;
@Mutation('rocketTopoGroup/SELECT_GROUP') private SELECT_GROUP: any;
- @Mutation('SET_EVENTS') private SET_EVENTS: any;
@Action('rocketTopo/GET_TOPO') private GET_TOPO: any;
private servicesMap = [];
private currentPage = 1;
diff --git a/src/views/components/trace/trace-detail-chart-list.vue
b/src/views/components/trace/trace-detail-chart-list.vue
index 0d5e7fb..286f4b3 100644
--- a/src/views/components/trace/trace-detail-chart-list.vue
+++ b/src/views/components/trace/trace-detail-chart-list.vue
@@ -85,7 +85,6 @@ limitations under the License. -->
</div>
</div>
</rk-sidebox>
- <v-dialog width="90%" />
<div class="trace-list">
<div ref="traceList"></div>
</div>
diff --git a/src/views/components/trace/trace-detail-chart-tree.vue
b/src/views/components/trace/trace-detail-chart-tree.vue
index 046f839..8f0601c 100644
--- a/src/views/components/trace/trace-detail-chart-tree.vue
+++ b/src/views/components/trace/trace-detail-chart-tree.vue
@@ -84,7 +84,6 @@ limitations under the License. -->
</div>
</div>
</rk-sidebox>
- <v-dialog width="90%" />
<div class="trace-tree" style="height:100%">
<div class="trace-tree-inner" ref="traceTree"></div>
</div>
diff --git a/src/views/components/trace/trace-search.vue
b/src/views/components/trace/trace-search.vue
index 6976c1c..709ee7b 100644
--- a/src/views/components/trace/trace-search.vue
+++ b/src/views/components/trace/trace-search.vue
@@ -89,21 +89,19 @@ limitations under the License. -->
</span>
<input
type="text"
- :placeholder="this.$t('traceAddTag')"
+ :placeholder="this.$t('addTag')"
v-model="tags"
class="rk-trace-new-tag"
@keyup="addLabels"
/>
- <span class="trace-tips" v-tooltip:bottom="{ content:
this.$t('traceTagsTip') }">
+ <span class="trace-tips" v-tooltip:bottom="{ content:
this.$t('tagsTip') }">
<a
target="blank"
href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
>
- {{ this.$t('traceLink') }}
+ {{ this.$t('tagsLink') }}
</a>
- <svg class="icon mr-5 vm">
- <use xlink:href="#help"></use>
- </svg>
+ <rk-icon icon="help" class="mr-5" />
</span>
</div>
</div>
diff --git a/src/views/containers/dashboard.vue
b/src/views/containers/dashboard.vue
index 134e694..ecaffbb 100644
--- a/src/views/containers/dashboard.vue
+++ b/src/views/containers/dashboard.vue
@@ -40,7 +40,6 @@ limitations under the License. -->
+ Add An Item
</div>
</div>
- <v-dialog width="300px" />
</div>
</template>
@@ -53,7 +52,7 @@ limitations under the License. -->
import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
import { ObjectsType } from '../../constants/constant';
import { State as globalState } from '@/store/modules/global';
- import { State as optionState } from
'@/store/modules/dashboard/dashboard-option';
+ import { State as optionState } from '@/store/modules/global/selectors';
import { State as dataState } from
'@/store/modules/dashboard/dashboard-data';
interface ITemplate {
diff --git a/src/views/containers/log.vue b/src/views/containers/log.vue
index 6d66473..6c9f360 100644
--- a/src/views/containers/log.vue
+++ b/src/views/containers/log.vue
@@ -12,32 +12,22 @@ See the License for the specific language governing
permissions and
limitations under the License. -->
<template>
<div class="flex-v rk-log">
- <LogBar :logState="logState"></LogBar>
- <div class="log-container">
- <LogDetailTable
- :data="logState.logs"
- :loading="logState.loading"
- v-if="logState.type.key === 'browser'"
- ></LogDetailTable>
- </div>
+ <LogBar />
+ <LogContent />
</div>
</template>
<script lang="ts">
- import { Component, Vue, Watch } from 'vue-property-decorator';
- import { Action, Getter, State, Mutation } from 'vuex-class';
+ import { Component, Vue } from 'vue-property-decorator';
import LogBar from '@/views/components/log/log-bar.vue';
- import LogDetailTable from '@/views/components/log/log-detail-table.vue';
+ import LogContent from '@/views/components/log/log-content.vue';
@Component({
components: {
LogBar,
- LogDetailTable,
+ LogContent,
},
})
- export default class Log extends Vue {
- @Getter('durationTime') private durationTime: any;
- @State('rocketLog') private logState: any;
- }
+ export default class Log extends Vue {}
</script>
<style scoped lang="scss">
@@ -46,10 +36,4 @@ limitations under the License. -->
height: 100%;
overflow: hidden;
}
- .log-container {
- overflow: auto;
- padding: 5px 15px 15px;
- height: 100%;
- flex-grow: 1;
- }
</style>
diff --git a/src/views/containers/topology/alarm/alarm-tool.vue
b/src/views/containers/topology/alarm/alarm-tool.vue
index 282ebf9..19dd5d6 100644
--- a/src/views/containers/topology/alarm/alarm-tool.vue
+++ b/src/views/containers/topology/alarm/alarm-tool.vue
@@ -42,7 +42,6 @@ limitations under the License. -->
@Component
export default class AlarmTool extends Vue {
@Getter('durationTime') private durationTime: any;
- @Mutation('SET_EVENTS') private SET_EVENTS: any;
@Action('rocketAlarm/GET_ALARM') private GET_ALARM: any;
@Prop() private total!: number;
@Prop() private keyword!: string;
diff --git a/src/views/containers/topology/endpoint/endpoints-survey.vue
b/src/views/containers/topology/endpoint/endpoints-survey.vue
index 6c9551d..c688f5d 100644
--- a/src/views/containers/topology/endpoint/endpoints-survey.vue
+++ b/src/views/containers/topology/endpoint/endpoints-survey.vue
@@ -35,7 +35,7 @@ limitations under the License. -->
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
import { State, Mutation } from 'vuex-class';
- import { State as optionState } from
'@/store/modules/dashboard/dashboard-option';
+ import { State as optionState } from '@/store/modules/global/selectors';
import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
@Component({
diff --git a/src/views/containers/topology/instance/instances-survey.vue
b/src/views/containers/topology/instance/instances-survey.vue
index 6d99852..029bc83 100644
--- a/src/views/containers/topology/instance/instances-survey.vue
+++ b/src/views/containers/topology/instance/instances-survey.vue
@@ -35,7 +35,7 @@ limitations under the License. -->
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
import { State, Mutation } from 'vuex-class';
- import { State as optionState } from
'@/store/modules/dashboard/dashboard-option';
+ import { State as optionState } from '@/store/modules/global/selectors';
import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
@Component({
diff --git a/src/views/containers/trace.vue b/src/views/containers/trace.vue
index e4e10e7..16d7842 100644
--- a/src/views/containers/trace.vue
+++ b/src/views/containers/trace.vue
@@ -45,9 +45,6 @@ limitations under the License. -->
private service!: Option;
@Prop({ default: false, type: Boolean })
- private inTopo!: boolean;
-
- private show: boolean = true;
private beforeMount() {
this.SET_EVENTS([]);
}