feat: Implement the Log Analysis Language text regexp debugger (#536)
diff --git a/package-lock.json b/package-lock.json
index 603d6c5..2ba8688 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6642,12 +6642,12 @@
"dev": true
},
"json5": {
- "version": "2.1.0",
- "resolved": "http://registry.npm.taobao.org/json5/download/json5-2.1.0.tgz",
- "integrity": "sha1-56DGLEgoXGKNIKELhcibuAfDKFA=",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+ "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"dev": true,
"requires": {
- "minimist": "^1.2.0"
+ "minimist": "^1.2.5"
}
},
"jsonfile": {
@@ -7602,9 +7602,9 @@
}
},
"minimist": {
- "version": "1.2.0",
- "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"mississippi": {
@@ -7669,6 +7669,39 @@
}
}
},
+ "monaco-editor": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.27.0.tgz",
+ "integrity": "sha512-UhwP78Wb8w0ZSYoKXQNTV/0CHObp6NS3nCt51QfKE6sKyBo5PBsvuDOHoI2ooBakc6uIwByRLHVeT7+yXQe2fQ=="
+ },
+ "monaco-editor-webpack-plugin": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.1.2.tgz",
+ "integrity": "sha512-snmHecygICKT0UlHhva+Cs2WaLPpxy3111xbvInhjjTr5m0xQTFHlmJ2QQDcB14Vzmm7f07uc1TtbvOpmL50BA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^2.0.0"
+ },
+ "dependencies": {
+ "emojis-list": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+ "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ }
+ }
+ }
+ },
"move-concurrently": {
"version": "1.0.1",
"resolved": "http://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
@@ -9629,15 +9662,6 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
- "json5": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
- "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
@@ -9649,12 +9673,6 @@
"json5": "^2.1.2"
}
},
- "minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
- "dev": true
- },
"neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
diff --git a/package.json b/package.json
index acf78b9..b0fb897 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"dayjs": "^1.8.8",
"echarts": "^5.0.2",
"lodash": "^4.17.15",
+ "monaco-editor": "^0.27.0",
"noty": "^3.2.0-beta",
"popper.js": "^1.14.7",
"vue": "^2.6.6",
@@ -45,6 +46,7 @@
"@vue/cli-service": "^3.4.1",
"husky": "^4.0.9",
"lint-staged": "^9.5.0",
+ "monaco-editor-webpack-plugin": "^4.1.2",
"prettier": "^1.19.1",
"sass": "^1.27.0",
"sass-loader": "^10.0.4",
diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts
index 0e0ced9..6f34e8e 100644
--- a/src/assets/lang/en.ts
+++ b/src/assets/lang/en.ts
@@ -96,7 +96,7 @@
search: 'Search',
clear: 'Clear',
more: 'More',
- traceID: 'TraceID',
+ traceID: 'Trace ID',
range: 'Range',
timeRange: 'Time Range',
duration: 'Duration',
@@ -232,6 +232,23 @@
eventSource: 'Event Source',
modalTitle: 'Inspection',
selectRedirectPage: 'Do you want to inspect Traces or Logs of %s service?',
+ logAnalysis: 'Log Analysis Language',
+ logDataBody: 'The content of the log',
+ addType: 'Please input a type',
+ traceContext: 'Logs with trace context',
+ traceSegmentId: 'Trace Segment ID',
+ spanId: 'Span ID',
+ inputTraceSegmentId: 'Please input the trace segment ID',
+ inputSpanId: 'Please input the span ID',
+ inputTraceId: 'Please input the trace ID',
+ dsl: 'Script input for LAL',
+ logContentType: 'The type of the log content',
+ logRespContent: 'Log Content',
+ analysis: 'Analysis',
+ waitLoading: 'Loading',
+ dslEmpty: 'Script input of LAL should not be empty',
+ logContentEmpty: 'The content of the log should not not be empty.',
+ debug: 'Debug',
};
export default m;
diff --git a/src/assets/lang/zh.ts b/src/assets/lang/zh.ts
index 5e13722..5957867 100644
--- a/src/assets/lang/zh.ts
+++ b/src/assets/lang/zh.ts
@@ -230,6 +230,23 @@
eventSource: '事件资源',
modalTitle: '查看',
selectRedirectPage: '查看 %s 服务的追踪或日志?',
+ logAnalysis: '日志分析语言',
+ logDataBody: '日志数据的内容',
+ addType: '请输入一个类型',
+ traceContext: '具有跟踪上下文的日志',
+ traceSegmentId: '跟踪段ID',
+ spanId: '跨度ID',
+ inputTraceSegmentId: '请输入跟踪段ID',
+ inputSpanId: '请输入跨度ID',
+ inputTraceId: '请输入跟踪ID',
+ dsl: 'LAL的脚本输入',
+ logContentType: '日志内容的类型',
+ logRespContent: '日志内容',
+ analysis: '分析',
+ waitLoading: '加载中',
+ dslEmpty: 'LAL的脚本输入不应该是空',
+ logContentEmpty: '日志数据的内容不应该是空。',
+ debug: '调试',
};
export default m;
diff --git a/src/components/rk-date.vue b/src/components/rk-date.vue
index cf9d311..6d8c340 100755
--- a/src/components/rk-date.vue
+++ b/src/components/rk-date.vue
@@ -368,7 +368,6 @@
}
.datepicker-popup {
- // right: 0px;
border-radius: 4px;
position: absolute;
transition: all 200ms ease;
@@ -398,7 +397,7 @@
transform-origin: center top;
}
&.right {
- right: 0;
+ right: -80px;
top: 30px;
transform-origin: center top;
}
diff --git a/src/components/rk-sidebox.vue b/src/components/rk-sidebox.vue
index 5720c86..55b23a6 100644
--- a/src/components/rk-sidebox.vue
+++ b/src/components/rk-sidebox.vue
@@ -103,7 +103,7 @@
right: 10px;
top: 0;
cursor: pointer;
- color: #d8d8d8;
+ color: #666;
transition: color 0.3s;
.icon {
width: 18px;
diff --git a/src/graph/fragments/debug.ts b/src/graph/fragments/debug.ts
new file mode 100644
index 0000000..155d786
--- /dev/null
+++ b/src/graph/fragments/debug.ts
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+
+export const QueryLogTest = {
+ variable: '$requests: LogTestRequest!',
+ query: `test(requests: $requests) { log { content, serviceName, serviceInstanceName, endpointName,
+ traceId, timestamp, contentType, content, tags { key, value }}
+ metrics { name, value, timestamp, tags { key, value }} }`,
+};
diff --git a/src/graph/fragments/profile.ts b/src/graph/fragments/profile.ts
index f4e2da3..7b5d247 100644
--- a/src/graph/fragments/profile.ts
+++ b/src/graph/fragments/profile.ts
@@ -35,8 +35,10 @@
key value
}
logs {
- time data {
- key value
+ time
+ data {
+ key
+ value
}
}
}
diff --git a/src/graph/index.ts b/src/graph/index.ts
index 6e2d922..e6fa409 100644
--- a/src/graph/index.ts
+++ b/src/graph/index.ts
@@ -24,6 +24,7 @@
import * as profile from './query/profile';
import * as dashboard from './query/dashboard';
import * as errorLog from './query/log';
+import * as logDebug from './query/debug';
const query: any = {
...errorLog,
@@ -33,6 +34,7 @@
...alarm,
...profile,
...dashboard,
+ ...logDebug,
};
class Graph {
diff --git a/src/graph/query/debug.ts b/src/graph/query/debug.ts
new file mode 100644
index 0000000..a9ed73c
--- /dev/null
+++ b/src/graph/query/debug.ts
@@ -0,0 +1,20 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { QueryLogTest } from '../fragments/debug';
+
+export const queryLogTest = `query test(${QueryLogTest.variable}) {${QueryLogTest.query}}`;
diff --git a/src/router.ts b/src/router.ts
index 5eff998..a5b1afe 100644
--- a/src/router.ts
+++ b/src/router.ts
@@ -70,6 +70,11 @@
component: () => import('./views/containers/event.vue'),
meta: { icon: 'storage', title: 'event', exact: false },
},
+ {
+ path: 'debug',
+ component: () => import('./views/containers/debug.vue'),
+ meta: { icon: 'library_books', title: 'debug', exact: false },
+ },
],
},
];
diff --git a/src/store/index.ts b/src/store/index.ts
index 0610eee..7ad1a68 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -27,6 +27,7 @@
import profileStore, { State as ProfileState } from '@/store/modules/profile/profile-store';
import rocketLog, { State as LogState } from '@/store/modules/log';
import rocketEvent, { State as EventState } from '@/store/modules/event';
+import rocketDebugLAL, { State as logLALState } from '@/store/modules/debug/log-lal';
Vue.use(Vuex);
@@ -41,6 +42,7 @@
profileStore: ProfileState;
logStore: LogState;
eventStore: EventState;
+ logLALStore: logLALState;
}
export default new Vuex.Store({
@@ -55,5 +57,6 @@
profileStore,
rocketLog,
rocketEvent,
+ rocketDebugLAL,
},
});
diff --git a/src/store/modules/debug/log-lal.ts b/src/store/modules/debug/log-lal.ts
new file mode 100644
index 0000000..4082170
--- /dev/null
+++ b/src/store/modules/debug/log-lal.ts
@@ -0,0 +1,164 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Commit, ActionTree, MutationTree } from 'vuex';
+import * as types from '@/store/mutation-types';
+import { LogTestOptions, LogTestMetrics } from '@/types/debug';
+import graph from '@/graph';
+import { AxiosResponse } from 'axios';
+import { DurationTime, Option } from '@/types/global';
+
+export interface State {
+ logTestFields: LogTestOptions | any;
+ services: Option[];
+ instances: Option[];
+ endpoints: Option[];
+ selectedService: Option;
+ selectedEndpoint: Option;
+ selectedInstance: Option;
+ dsl: string;
+ logTestResp: { log: { content: string }; metrics: LogTestMetrics[] };
+ tabType: string;
+}
+
+const logAnaState: State = {
+ logTestFields: {},
+ services: [],
+ selectedService: { key: '', label: '' },
+ instances: [],
+ selectedInstance: { key: '', label: '' },
+ endpoints: [],
+ selectedEndpoint: { key: '', label: '' },
+ dsl: '',
+ logTestResp: { log: { content: '' }, metrics: [] },
+ tabType: 'LAL',
+};
+
+// mutations
+const mutations: MutationTree<State> = {
+ [types.SET_LOG_TEST_FIELDS](state, item: Option) {
+ state.logTestFields = {
+ ...state.logTestFields,
+ [item.label]: item.key,
+ };
+ },
+ [types.SET_LOG_ANA_SERVICES](state, items: Option[]) {
+ state.services = items;
+ state.selectedService = items[0] || state.selectedService;
+ state.logTestFields.service = state.selectedService.label || undefined;
+ },
+ [types.SET_LOG_ANA_ENDPOINTS](state, items: Option[]) {
+ state.endpoints = [{ key: '', label: 'None' }, ...items];
+ state.selectedEndpoint = state.endpoints[0];
+ state.logTestFields.endpoint = state.selectedEndpoint.key ? state.selectedEndpoint.label : undefined;
+ },
+ [types.SET_LOG_ANA_INSTANCES](state, items: Option[]) {
+ state.instances = [{ key: '', label: 'None' }, ...items];
+ state.selectedInstance = state.instances[0];
+ state.logTestFields.serviceInstance = state.selectedInstance.key ? state.selectedInstance.label : undefined;
+ },
+ [types.SET_SELECTED_SERVICE](state, item: Option) {
+ state.selectedService = item;
+ },
+ [types.SET_SELECTED_ENDPOINT](state, item: Option) {
+ state.selectedEndpoint = item;
+ },
+ [types.SET_SELECTED_INSTANCE](state, item: Option) {
+ state.selectedInstance = item;
+ },
+ [types.SET_DSL](state, content: string) {
+ state.dsl = content;
+ },
+ [types.SET_LOG_TEST_RESPONSE](state, resp: { log: { content: string }; metrics: LogTestMetrics[] }) {
+ state.logTestResp = resp;
+ },
+ [types.SET_TAB_TYPE](state, type: string) {
+ state.tabType = type;
+ },
+};
+
+// actions
+const actions: ActionTree<State, any> = {
+ GET_LOG_ANA_SERVICES(context: { commit: Commit }, params: { duration: DurationTime; keyword: string }) {
+ if (!params.keyword) {
+ params.keyword = '';
+ }
+ return graph
+ .query('queryServices')
+ .params(params)
+ .then((res: AxiosResponse) => {
+ context.commit(types.SET_LOG_ANA_SERVICES, res.data.data.services);
+ });
+ },
+ GET_LOG_ANA_ENDPOINTS(
+ context: { commit: Commit; state: State },
+ params: { keyword: string; currentService?: { key: string; label: string } },
+ ) {
+ if (!context.state.selectedService.key) {
+ context.commit(types.SET_LOG_ANA_ENDPOINTS, []);
+ return;
+ }
+ if (!params.keyword) {
+ params.keyword = '';
+ }
+ return graph
+ .query('queryEndpoints')
+ .params({
+ serviceId: context.state.selectedService.key || '',
+ ...params,
+ })
+ .then((res: AxiosResponse) => {
+ context.commit(types.SET_LOG_ANA_ENDPOINTS, res.data.data.getEndpoints);
+ });
+ },
+ GET_LOG_ANA_INSTANCES(context: { commit: Commit; state: State }, params: any) {
+ if (!context.state.selectedService.key) {
+ context.commit(types.SET_LOG_ANA_INSTANCES, []);
+ return;
+ }
+ return graph
+ .query('queryInstances')
+ .params({ serviceId: context.state.selectedService.key || '', ...params })
+ .then((res: AxiosResponse) => {
+ context.commit(types.SET_LOG_ANA_INSTANCES, res.data.data.getServiceInstances);
+ });
+ },
+ LOG_ANA_QUERY(context: { commit: Commit; state: State }) {
+ const requests = {
+ dsl: context.state.dsl,
+ log: JSON.stringify(context.state.logTestFields),
+ };
+ const params = { requests };
+
+ return graph
+ .query('queryLogTest')
+ .params(params)
+ .then((res: AxiosResponse) => {
+ if (res.data.errors) {
+ context.commit(types.SET_LOG_TEST_RESPONSE, { log: {}, metrics: [] });
+ return res.data.errors;
+ }
+ context.commit(types.SET_LOG_TEST_RESPONSE, res.data.data.test);
+ });
+ },
+};
+
+export default {
+ state: logAnaState,
+ actions,
+ mutations,
+};
diff --git a/src/store/modules/log/index.ts b/src/store/modules/log/index.ts
index 07c437f..2890f1d 100644
--- a/src/store/modules/log/index.ts
+++ b/src/store/modules/log/index.ts
@@ -15,28 +15,24 @@
* limitations under the License.
*/
-import { Commit, ActionTree, MutationTree, Dispatch } from 'vuex';
+import { Commit, ActionTree, MutationTree } from 'vuex';
import * as types from '@/store/mutation-types';
import { AxiosResponse } from 'axios';
import graph from '@/graph';
-
-interface Options {
- key: string;
- label: string;
-}
+import { Option } from '@/types/global';
export interface State {
- type: Options;
- logCategories: Options[];
+ type: Option;
+ logCategories: Option[];
logs: any[];
total: number;
- categories: Options[];
- category: Options;
+ categories: Option[];
+ category: Option;
loading: boolean;
conditions: any;
supportQueryLogsByKeywords: boolean;
}
-const categories: Options[] = [
+const categories: Option[] = [
{ label: 'All', key: 'ALL' },
{ label: 'Ajax', key: 'AJAX' },
{ label: 'Resource', key: 'RESOURCE' },
@@ -71,10 +67,10 @@
// mutations
const mutations: MutationTree<State> = {
- [types.SELECT_LOG_TYPE](state: State, data: Options) {
+ [types.SELECT_LOG_TYPE](state: State, data: Option) {
state.type = data;
},
- [types.SELECT_ERROR_CATALOG](state: State, data: Options) {
+ [types.SELECT_ERROR_CATALOG](state: State, data: Option) {
state.category = data;
},
[types.SET_LOGS](state: State, data: any[]) {
@@ -86,7 +82,7 @@
[types.SET_LOADING](state: State, data: boolean) {
state.loading = data;
},
- [types.SET_LOG_CONDITIONS](state: State, item: Options) {
+ [types.SET_LOG_CONDITIONS](state: State, item: Option) {
state.conditions = {
...state.conditions,
[item.label]: item.key,
diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts
index f7baa67..a348f5e 100644
--- a/src/store/mutation-types.ts
+++ b/src/store/mutation-types.ts
@@ -153,3 +153,15 @@
// Event
export const UPDATE_EVENTS = 'UPDATE_EVENTS';
export const SET_TOTAL_SIZE = 'SET_TOTAL_SIZE';
+
+// debug
+export const SET_TAB_TYPE = 'SET_TAB_TYPE';
+export const SET_LOG_TEST_FIELDS = 'SET_LOG_TEST_FIELDS';
+export const SET_LOG_ANA_SERVICES = 'SET_LOG_ANA_SERVICES';
+export const SET_LOG_ANA_ENDPOINTS = 'SET_LOG_ANA_ENDPOINTS';
+export const SET_LOG_ANA_INSTANCES = 'SET_LOG_ANA_INSTANCES';
+export const SET_SELECTED_INSTANCE = 'SET_SELECTED_INSTANCE';
+export const SET_SELECTED_SERVICE = 'SET_SELECTED_SERVICE';
+export const SET_SELECTED_ENDPOINT = 'SET_SELECTED_ENDPOINT';
+export const SET_DSL = 'SET_DSL';
+export const SET_LOG_TEST_RESPONSE = 'SET_LOG_TEST_RESPONSE';
diff --git a/src/types.d.ts b/src/types.d.ts
index 6f8ac8d..26b79cf 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -17,3 +17,4 @@
declare module '*.js';
declare module 'echarts/lib/echarts';
+declare module 'monaco-editor/esm/vs/editor/editor.main.js';
diff --git a/src/types/debug.d.ts b/src/types/debug.d.ts
new file mode 100644
index 0000000..1fd9396
--- /dev/null
+++ b/src/types/debug.d.ts
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+export interface LogTestOptions {
+ service: string;
+ serviceInstance: string;
+ endpoint: string;
+ timestamp: number;
+ body: LogDataBody;
+ traceContext: TraceContext;
+ tags: LogTags;
+}
+
+interface LogDataBody {
+ type: string;
+ content: string;
+}
+
+interface TraceContext {
+ traceId: string;
+ traceSegmentId: string;
+ spanId: number;
+}
+
+interface LogTags {
+ data: { key: string; value: string };
+}
+export interface LogTestMetrics {
+ name: String;
+ tags: { key: string; value: string };
+ value: number;
+ timestamp: number;
+}
diff --git a/src/views/components/common/condition-tags.vue b/src/views/components/common/condition-tags.vue
index b27fc18..f0623bf 100644
--- a/src/views/components/common/condition-tags.vue
+++ b/src/views/components/common/condition-tags.vue
@@ -13,9 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
- <div class="flex-h">
+ <div class="flex-h" :class="{ light: theme === 'light' }">
<div class="mr-10 pt-5">
- <span class="sm grey">{{ $t('tags') }}: </span>
+ <span class="sm grey" v-show="theme === 'dark'">{{ $t('tags') }}: </span>
<span class="rk-trace-tags">
<span class="selected" v-for="(item, index) in tagsList" :key="index">
<span>{{ item }}</span>
@@ -41,6 +41,7 @@
export default class ConditionTags extends Vue {
@Prop() private type!: string;
@Prop() private clearTags!: boolean;
+ @Prop({ default: 'dark' }) private theme!: string;
private tagsList: string[] = [];
private tags: string = '';
@@ -129,4 +130,13 @@
.tags-tip {
color: #a7aebb;
}
+ .light {
+ color: #3d444f;
+ input {
+ border: 1px solid #ccc;
+ }
+ .selected {
+ color: #3d444f;
+ }
+ }
</style>
diff --git a/src/views/components/debug/debug-constant.ts b/src/views/components/debug/debug-constant.ts
new file mode 100644
index 0000000..2af4458
--- /dev/null
+++ b/src/views/components/debug/debug-constant.ts
@@ -0,0 +1,62 @@
+/**
+ * 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.
+ */
+
+export enum LogTestConstants {
+ Timestamp = 'timestamp',
+ Service = 'service',
+ ServiceInstance = 'serviceInstance',
+ Endpoint = 'endpoint',
+ Body = 'body',
+ TraceContext = 'traceContext',
+ Tags = 'tags',
+ DSL = 'dsl',
+ Type = 'type',
+}
+
+export const TypeList = [
+ {
+ label: 'Text',
+ value: 'text',
+ },
+ {
+ label: 'Json',
+ value: 'json',
+ },
+ {
+ label: 'YAML',
+ value: 'yaml',
+ },
+];
+
+export const LogMetricsHeader = [
+ {
+ label: 'name',
+ value: 'name',
+ },
+ {
+ label: 'time',
+ value: 'timestamp',
+ },
+ {
+ label: 'value',
+ value: 'value',
+ },
+ {
+ label: 'tags',
+ value: 'tags',
+ },
+];
diff --git a/src/views/components/debug/log-lal.vue b/src/views/components/debug/log-lal.vue
new file mode 100644
index 0000000..d2b4d9b
--- /dev/null
+++ b/src/views/components/debug/log-lal.vue
@@ -0,0 +1,379 @@
+<!-- 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-lal">
+ <div class="lal-conditions">
+ <div class="flex-v">
+ <div>
+ <label>{{ $t('service') }}<b class="require"> *</b></label>
+ <RkSelect
+ class="mb-5"
+ :current="rocketLogLAL.selectedService"
+ :data="rocketLogLAL.services"
+ @onChoose="(item) => changeLogAnaOptions(logTestConstants.Service, item)"
+ />
+ </div>
+ <div>
+ <label>{{ $t('serviceinstance') }}</label>
+ <RkSelect
+ class="mb-5"
+ :current="rocketLogLAL.selectedInstance"
+ :data="rocketLogLAL.instances"
+ @onChoose="(item) => changeLogAnaOptions(logTestConstants.ServiceInstance, item)"
+ />
+ </div>
+ <div>
+ <label>{{ $t('endpoint') }}</label>
+ <RkSelect
+ class="mb-5"
+ :current="rocketLogLAL.selectedEndpoint"
+ :data="rocketLogLAL.endpoints"
+ @onChoose="(item) => changeLogAnaOptions(logTestConstants.Endpoint, item)"
+ />
+ </div>
+ <div>
+ <label>{{ $t('time') }}<b class="require"> *</b></label>
+ <div>
+ <span>
+ <RkDate class="sm" v-model="time" position="right" format="YYYY-MM-DD HH:mm:ss" />
+ </span>
+ </div>
+ </div>
+ <div>
+ <label>{{ $t('tags') }}</label>
+ <ConditionTags :theme="'light'" :clearTags="false" @updateTags="updateTags" />
+ </div>
+ <div>
+ <label>{{ $t('logContentType') }}</label>
+ <RkSelect
+ class="mb-5"
+ :current="currentType"
+ :data="typeList"
+ @onChoose="(item) => changeLogAnaOptions(logTestConstants.Type, item)"
+ />
+ </div>
+ <div class="logDataBody">
+ <label>{{ $t('logDataBody') }}<b class="require"> *</b></label>
+ <textarea v-model="logContent" @change="changeLogAnaOptions(logTestConstants.Body)" />
+ </div>
+ <div>
+ <label>{{ $t('traceID') }}</label>
+ <input
+ type="text"
+ :placeholder="$t('inputTraceId')"
+ v-model="traceID"
+ @change="changeLogAnaOptions(logTestConstants.TraceContext)"
+ />
+ </div>
+ <div>
+ <label>{{ $t('traceSegmentId') }}</label>
+ <input
+ type="text"
+ :placeholder="$t('inputTraceSegmentId')"
+ v-model="segmentID"
+ @change="changeLogAnaOptions(logTestConstants.TraceContext)"
+ />
+ </div>
+ <div>
+ <label>{{ $t('spanId') }}</label>
+ <input
+ type="number"
+ :placeholder="$t('inputSpanId')"
+ v-model="spanID"
+ @change="changeLogAnaOptions(logTestConstants.TraceContext)"
+ />
+ </div>
+ <div>
+ <label>{{ $t('dsl') }}<b class="require"> *</b></label>
+ <div ref="dslContent" id="dsl" contenteditable="true" />
+ </div>
+ </div>
+ </div>
+ <div class="log-analysis">
+ <div class="error-tips">{{ errorCnt }}</div>
+ <div class="log-ana-btn bg-blue" @click="logAnalysis">{{ isLoading ? $t('waitLoading') : $t('analysis') }}</div>
+ </div>
+ <div class="lal-resp">
+ <div class="log-metrics">
+ <label>{{ $t('metrics') }}</label>
+ <ul>
+ <li>
+ <span v-for="item of logMetricsHeader" :class="item.value" :key="item.value">
+ {{ $t(item.label) }}
+ </span>
+ </li>
+ <li class="no-data" v-show="!rocketLogLAL.logTestResp.metrics.length">{{ $t('noData') }}</li>
+ <li v-for="metric in rocketLogLAL.logTestResp.metrics" :key="metric.name">
+ <span v-for="(item, index) of logMetricsHeader" :class="item.value" :key="item.value + index">
+ <b v-if="item.value === 'tags'">
+ <a v-for="t of metric.tags" :key="t.key">{{ `${t.key}=${t.value};` }} </a>
+ </b>
+ <b v-else-if="item.value === 'timestamp'">{{ metric[item.value] | dateformat }}</b>
+ <b v-else>{{ metric[item.value] }}</b>
+ </span>
+ </li>
+ </ul>
+ </div>
+ <div>
+ <label class="log-detail">{{ $t('log') }}</label>
+ <LogServiceDetailContent :currentLog="rocketLogLAL.logTestResp.log" />
+ </div>
+ <div class="error-tips">
+ <i v-for="err of errorsMessage" :key="err.message">{{ err.message }}</i>
+ </div>
+ </div>
+ </div>
+</template>
+<script lang="ts">
+ import { Component, Vue } from 'vue-property-decorator';
+ import { Action, Getter, Mutation, State } from 'vuex-class';
+ import { State as rocketLogAnaState } from '@/store/modules/debug/log-lal';
+ import { LogTestConstants, TypeList, LogMetricsHeader } from './debug-constant';
+ import { Option } from '@/types/global';
+ import { ConditionTags } from '../common/index';
+ import LogServiceDetailContent from '../log/log-detail-content.vue';
+
+ @Component({ components: { ConditionTags, LogServiceDetailContent } })
+ export default class LogLAL extends Vue {
+ @State('rocketDebugLAL') private rocketLogLAL!: rocketLogAnaState;
+ @State('rocketbot') private rocketbotGlobal: any;
+ @Getter('durationTime') private durationTime: any;
+ @Mutation('SET_SELECTED_SERVICE') private SET_SELECTED_SERVICE: any;
+ @Mutation('SET_SELECTED_ENDPOINT') private SET_SELECTED_ENDPOINT: any;
+ @Mutation('SET_SELECTED_INSTANCE') private SET_SELECTED_INSTANCE: any;
+ @Mutation('SET_LOG_TEST_FIELDS') private SET_LOG_TEST_FIELDS: any;
+ @Mutation('SET_DSL') private SET_DSL: any;
+ @Mutation('SET_LOG_TEST_RESPONSE') private SET_LOG_TEST_RESPONSE: any;
+ @Action('GET_LOG_ANA_ENDPOINTS') private GET_LOG_ANA_ENDPOINTS: any;
+ @Action('GET_LOG_ANA_INSTANCES') private GET_LOG_ANA_INSTANCES: any;
+ @Action('LOG_ANA_QUERY') private LOG_ANA_QUERY: any;
+ @Action('GET_LOG_ANA_SERVICES') private GET_LOG_ANA_SERVICES: any;
+
+ private logTestConstants = LogTestConstants;
+ private time!: Date;
+ private logContent: string = '';
+ private traceID: string = '';
+ private segmentID: string = '';
+ private spanID: string = '';
+ private typeList = TypeList;
+ private logMetricsHeader = LogMetricsHeader;
+ private currentType = {
+ label: 'Text',
+ value: 'text',
+ };
+ private logRespContent: string = '';
+ private showLALResp: boolean = false;
+ private isLoading: boolean = false;
+ private monacoInstance: any;
+ private errorCnt: string = '';
+ private errorsMessage: Array<{ message: string }> = [];
+
+ private created() {
+ this.time = this.rocketbotGlobal.durationRow.start;
+ this.GET_LOG_ANA_SERVICES({ duration: this.durationTime }).then(() => {
+ this.GET_LOG_ANA_INSTANCES({ duration: this.durationTime });
+ this.GET_LOG_ANA_ENDPOINTS({ duration: this.durationTime });
+ });
+ }
+
+ private mounted() {
+ import('monaco-editor/esm/vs/editor/editor.main.js').then((monaco) => {
+ this.monacoInstanceGen(monaco);
+ });
+ }
+
+ private monacoInstanceGen(monaco: any) {
+ this.monacoInstance = monaco.editor.create(this.$refs.dslContent, {
+ value: '',
+ language: 'java',
+ });
+ this.monacoInstance.onDidChangeModelContent((event: any) => {
+ this.SET_DSL(this.monacoInstance.getValue());
+ });
+ }
+
+ private changeLogAnaOptions(type: string, item: Option | any) {
+ if (type === this.logTestConstants.Body) {
+ const contentType = this.typeList.filter(
+ (d: { value: string; label: string }) => d.value === this.currentType.value,
+ )[0];
+ const val = {
+ [contentType.value]: { [contentType.value]: this.logContent },
+ };
+ this.SET_LOG_TEST_FIELDS({ label: type, key: val });
+ return;
+ }
+ if (type === this.logTestConstants.TraceContext) {
+ const val = {
+ traceId: this.traceID,
+ traceSegmentId: this.segmentID,
+ spanId: this.spanID,
+ };
+ this.SET_LOG_TEST_FIELDS({ label: type, key: val });
+ return;
+ }
+ if (type === this.logTestConstants.Type) {
+ this.currentType = { value: item.key, label: item.label };
+ return;
+ }
+ if (type === this.logTestConstants.Service) {
+ this.SET_SELECTED_SERVICE(item);
+ this.GET_LOG_ANA_INSTANCES({ duration: this.durationTime });
+ this.GET_LOG_ANA_ENDPOINTS({ duration: this.durationTime });
+ }
+ if (type === this.logTestConstants.ServiceInstance) {
+ this.SET_SELECTED_INSTANCE(item);
+ }
+ if (type === this.logTestConstants.Endpoint) {
+ this.SET_SELECTED_ENDPOINT(item);
+ }
+ this.SET_LOG_TEST_FIELDS({ label: type, key: item.label });
+ }
+
+ private updateTags(data: { tagsMap: Array<{ key: string; value: string }>; tagsList: string[] }) {
+ this.SET_LOG_TEST_FIELDS({ label: this.logTestConstants.Tags, key: { data: data.tagsMap } });
+ }
+
+ private logAnalysis() {
+ this.SET_LOG_TEST_RESPONSE({ log: {}, metrics: [] });
+ if (this.isLoading) {
+ return;
+ }
+ this.isLoading = true;
+ this.SET_LOG_TEST_FIELDS({ label: this.logTestConstants.Timestamp, key: this.time.getTime() });
+ if (!this.rocketLogLAL.dsl) {
+ this.isLoading = false;
+ this.errorCnt = this.$t('dslEmpty') as string;
+ return;
+ }
+ if (!this.rocketLogLAL.logTestFields.body) {
+ this.isLoading = false;
+ this.errorCnt = this.$t('logContentEmpty') as string;
+ return;
+ }
+ this.LOG_ANA_QUERY().then((errors: Array<{ message: string }>) => {
+ this.showLALResp = true;
+ this.isLoading = false;
+ this.errorsMessage = errors || [];
+ });
+ }
+
+ private unmounted() {
+ this.monacoInstance.dispose();
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ .log-lal {
+ overflow: auto;
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ }
+ .lal-resp {
+ height: 1026px;
+ margin: 10px;
+ }
+ .lal-conditions,
+ .lal-resp {
+ width: 100%;
+ padding: 10px;
+ border: 1px solid #ccc;
+ }
+ .lal-conditions {
+ margin: 10px 10px 20px;
+ }
+ .log-analysis {
+ align-self: center;
+ }
+ input,
+ textarea {
+ border: 1px solid #ccc;
+ width: 100%;
+ display: block;
+ margin-bottom: 6px;
+ outline: none;
+ }
+ .logDataBody {
+ margin-top: 5px;
+ textarea {
+ height: 200px;
+ }
+ }
+ .log-ana-btn {
+ color: #fff;
+ width: 150px;
+ height: 30px;
+ line-height: 30px;
+ text-align: center;
+ border-radius: 4px;
+ cursor: pointer;
+ &.bg-blue {
+ background-color: #448dfe;
+ }
+ }
+ .logRespContent {
+ height: 300px;
+ }
+ ul {
+ max-height: 200px;
+ min-height: 100px;
+ overflow: auto;
+ margin: 5px 0;
+ .tags {
+ width: 40%;
+ }
+ }
+ li {
+ span {
+ width: 20%;
+ line-height: 20px;
+ text-align: center;
+ display: inline-block;
+ border-bottom: 1px solid #ccc;
+ }
+ }
+ .no-data {
+ text-align: center;
+ }
+ #dsl {
+ height: 300px;
+ width: 100%;
+ border: 1px solid #ccc;
+ outline: none;
+ }
+ b {
+ font-weight: normal;
+ }
+ textarea {
+ padding: 5px;
+ }
+ .log-detail {
+ margin-bottom: 10px;
+ }
+ .require,
+ .error-tips {
+ color: red;
+ i {
+ display: block;
+ }
+ }
+ .error-tips {
+ margin-bottom: 20px;
+ }
+ label {
+ font-size: 14px;
+ font-weight: bold;
+ }
+</style>
diff --git a/src/views/components/debug/tool-bar.vue b/src/views/components/debug/tool-bar.vue
new file mode 100644
index 0000000..0417f17
--- /dev/null
+++ b/src/views/components/debug/tool-bar.vue
@@ -0,0 +1,79 @@
+<!-- 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="debug-tool-bar flex-v">
+ <span v-for="(i, index) in tabConstant" :key="index" class="mr-15">
+ <a
+ class="debug-tab mb-10"
+ @click="handleTab(i)"
+ :class="{
+ active: rocketLogLAL.tabType === i,
+ grey: rocketLogLAL.tabType !== i,
+ }"
+ >
+ {{ i }}
+ </a>
+ </span>
+ </div>
+</template>
+
+<script lang="ts">
+ import Vue from 'vue';
+ import { Mutation, State } from 'vuex-class';
+ import Component from 'vue-class-component';
+ import { State as rocketLogAnaState } from '@/store/modules/debug/log-lal';
+
+ @Component({
+ components: {},
+ })
+ export default class DebugToolBar extends Vue {
+ @Mutation('SET_TAB_TYPE') private SET_TAB_TYPE: any;
+ @State('rocketDebugLAL') private rocketLogLAL!: rocketLogAnaState;
+ private tabConstant = ['LAL'];
+ private handleTab(i: string) {
+ this.SET_TAB_TYPE(i);
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ .debug-tool-bar {
+ border-bottom: 1px solid #252a2f;
+ background-color: #333840;
+ padding: 10px 15px 0;
+ color: #eee;
+ }
+ .debug-tab {
+ display: inline-block;
+ padding: 4px 13px 4px 15px;
+ border-radius: 4px;
+ position: relative;
+ background-color: rgba(255, 255, 255, 0.07);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08);
+ will-change: border-color, color;
+ transition: border-color 0.3s, color 0.3s;
+ &.active::before {
+ content: '';
+ position: absolute;
+ display: inline-block;
+ width: 5px;
+ height: 10px;
+ border-radius: 4px;
+ background-color: #448dfe;
+ top: 9px;
+ left: 4px;
+ }
+ }
+</style>
diff --git a/src/views/components/log/log-bar.vue b/src/views/components/log/log-bar.vue
index fe369e5..7f4b58c 100644
--- a/src/views/components/log/log-bar.vue
+++ b/src/views/components/log/log-bar.vue
@@ -75,7 +75,7 @@
<RkPage :currentSize="pageSize" :currentPage="pageNum" @changePage="handleRefresh" :total="logState.total" />
</span>
</div>
- <div class="flex-h" v-show="showConditionsBox">
+ <div v-show="showConditionsBox">
<LogConditions />
</div>
</div>
@@ -219,7 +219,7 @@
}
private openConditionsBox() {
- this.showConditionsBox = !this.showConditionsBox;
+ this.showConditionsBox = true;
}
}
</script>
diff --git a/src/views/components/log/log-browser-detail.vue b/src/views/components/log/log-browser-detail.vue
index 5fc2aef..5c7a94d 100644
--- a/src/views/components/log/log-browser-detail.vue
+++ b/src/views/components/log/log-browser-detail.vue
@@ -40,7 +40,7 @@
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import LogTable from './log-table/log-table.vue';
- import { BrowserLogConstants } from './log-table/log-constant';
+ import { BrowserLogConstants } from './log-constant';
@Component({
components: { LogTable },
diff --git a/src/views/components/log/log-conditions.vue b/src/views/components/log/log-conditions.vue
index d2b561e..716e972 100644
--- a/src/views/components/log/log-conditions.vue
+++ b/src/views/components/log/log-conditions.vue
@@ -12,7 +12,7 @@
limitations under the License. -->
<template>
- <div class="rk-search-conditions flex-v">
+ <div class="rk-search-conditions">
<div class="flex-h">
<div class="mr-15" v-show="rocketLog.type.key === cateGoryService">
<span class="sm b grey mr-10">{{ $t('traceID') }}:</span>
diff --git a/src/views/components/log/log-table/log-constant.ts b/src/views/components/log/log-constant.ts
similarity index 99%
rename from src/views/components/log/log-table/log-constant.ts
rename to src/views/components/log/log-constant.ts
index 079d65a..96030d0 100644
--- a/src/views/components/log/log-table/log-constant.ts
+++ b/src/views/components/log/log-constant.ts
@@ -113,7 +113,6 @@
label: 'category',
value: 'category',
},
-
{
label: 'grade',
value: 'grade',
diff --git a/src/views/components/log/log-detail-content.vue b/src/views/components/log/log-detail-content.vue
new file mode 100644
index 0000000..c56c834
--- /dev/null
+++ b/src/views/components/log/log-detail-content.vue
@@ -0,0 +1,63 @@
+<!-- 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-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="currentLog[item.label]"
+ />
+ <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>
+</template>
+<script lang="ts">
+ import { Component, Prop, Vue } from 'vue-property-decorator';
+ import { ServiceLogDetail } from './log-constant';
+
+ @Component
+ export default class LogServiceDetailContent extends Vue {
+ @Prop() private currentLog: any;
+ private columns = ServiceLogDetail;
+ private logContent: string = '';
+
+ get logTags() {
+ if (!this.currentLog.tags) {
+ return [];
+ }
+ return this.currentLog.tags.map((d: { key: string; value: string }) => {
+ return `${d.key} = ${d.value}`;
+ });
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ .content {
+ max-width: 1000px;
+ min-height: 200px;
+ border: none;
+ outline: none;
+ color: #3d444f;
+ }
+</style>
diff --git a/src/views/components/log/log-service-detail.vue b/src/views/components/log/log-service-detail.vue
index 0c2e82e..972d44f 100644
--- a/src/views/components/log/log-service-detail.vue
+++ b/src/views/components/log/log-service-detail.vue
@@ -23,19 +23,7 @@
<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>
+ <LogServiceDetailContent :currentLog="currentLog" />
</rk-sidebox>
</div>
</template>
@@ -43,11 +31,12 @@
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import LogTable from './log-table/log-table.vue';
- import { ServiceLogDetail } from './log-table/log-constant';
+ import LogServiceDetailContent from './log-detail-content.vue';
+ import { ServiceLogDetail } from './log-constant';
import { formatJson } from '@/utils/formatJson';
@Component({
- components: { LogTable },
+ components: { LogTable, LogServiceDetailContent },
})
export default class LogServiceDetail extends Vue {
@Prop() private data: any;
@@ -59,13 +48,9 @@
private list = [];
private currentLog: any = {};
private logContent: string = '';
- private logTags: string = '';
private handleSelectLog(data: any[]) {
this.currentLog = data;
- this.logTags = this.currentLog.tags.map((d: { key: string; value: string }) => {
- return `${d.key} = ${d.value}`;
- });
if (this.currentLog.contentType === 'JSON') {
this.logContent = formatJson(JSON.parse(this.currentLog.content));
} else {
@@ -109,11 +94,4 @@
.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-browser-item.vue b/src/views/components/log/log-table/log-browser-item.vue
index 8394d03..b9349ed 100644
--- a/src/views/components/log/log-table/log-browser-item.vue
+++ b/src/views/components/log/log-table/log-browser-item.vue
@@ -32,7 +32,7 @@
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
- import { BrowserLogConstants } from './log-constant';
+ import { BrowserLogConstants } from '../log-constant';
@Component
export default class ServiceItem extends Vue {
diff --git a/src/views/components/log/log-table/log-service-item.vue b/src/views/components/log/log-table/log-service-item.vue
index a4601fa..2b051f4 100644
--- a/src/views/components/log/log-table/log-service-item.vue
+++ b/src/views/components/log/log-table/log-service-item.vue
@@ -34,7 +34,7 @@
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
- import { ServiceLogConstants } from './log-constant';
+ import { ServiceLogConstants } from '../log-constant';
@Component
export default class ServiceItem extends Vue {
diff --git a/src/views/components/log/log-table/log-table.vue b/src/views/components/log/log-table/log-table.vue
index 887d607..62d16f2 100644
--- a/src/views/components/log/log-table/log-table.vue
+++ b/src/views/components/log/log-table/log-table.vue
@@ -38,7 +38,7 @@
</div>
</template>
<script lang="js">
- import { ServiceLogConstants, BrowserLogConstants } from './log-constant';
+ import { ServiceLogConstants, BrowserLogConstants } from '../log-constant';
import BrowserItem from './log-browser-item';
import ServiceItem from './log-service-item';
diff --git a/src/views/containers/debug.vue b/src/views/containers/debug.vue
new file mode 100644
index 0000000..55bde5e
--- /dev/null
+++ b/src/views/containers/debug.vue
@@ -0,0 +1,40 @@
+<!-- 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-debug flex-v">
+ <DebugToolBar />
+ <LogLAL />
+ </div>
+</template>
+
+<script lang="ts">
+ import Vue from 'vue';
+ import Component from 'vue-class-component';
+ import DebugToolBar from '../components/debug/tool-bar.vue';
+ import LogLAL from '../components/debug/log-lal.vue';
+
+ @Component({
+ components: { DebugToolBar, LogLAL },
+ })
+ export default class Debug extends Vue {}
+</script>
+
+<style lang="scss" scoped>
+ .rk-debug {
+ flex-grow: 1;
+ height: 100%;
+ min-height: 0;
+ }
+</style>
diff --git a/vue.config.js b/vue.config.js
index ee2b28d..63e5c05 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
productionSourceMap: process.env.NODE_ENV !== 'production',
devServer: {
@@ -35,8 +35,9 @@
symbolId: '[name]',
});
},
- configureWebpack: (config) => {
- config.optimization = {
+ configureWebpack: {
+ plugins: [new MonacoWebpackPlugin()],
+ optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
@@ -45,8 +46,13 @@
test: /[\\/]node_modules[\\/]echarts[\\/]/,
priority: 2,
},
+ monacoEditor: {
+ name: 'monaco-editor',
+ test: /[\\/]node_modules[\\/]monaco-editor[\\/]/,
+ priority: 1,
+ },
},
},
- };
+ },
},
};