diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts index b3649192..ac45f3e6 100644 --- a/src/locales/lang/en.ts +++ b/src/locales/lang/en.ts @@ -324,11 +324,12 @@ const msg = { logContentEmpty: "The content of the log should not be empty.", debug: "Debug", addTraceID: "Please input a trace ID", + addTags: "Please input a tag", addKeywordsOfContent: "Please input a keyword of content", addExcludingKeywordsOfContent: "Please input a keyword of excluding content", noticeTag: "Please press Enter after inputting a tag(key=value).", conditionNotice: - "Notice: Please press enter after inputting a tag, key of content, exclude key of content.", + "Notice: Please press Enter after inputting a tag, key of content, exclude key of content(key=value).", cacheModalTitle: "Clear cache reminder", yes: "Yes", no: "No", diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts index d60322cf..0b605780 100644 --- a/src/locales/lang/zh.ts +++ b/src/locales/lang/zh.ts @@ -325,10 +325,12 @@ const msg = { logContentEmpty: "日志数据的内容不应该是空。", debug: "调试", addTraceID: "请输入一个Trace ID", + addTags: "请输入一个标签", addKeywordsOfContent: "请输入一个内容关键词", addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词", noticeTag: "请输入一个标签(key=value)之后回车", - conditionNotice: "请输入一个标签、内容关键词或者内容不包含的关键词之后回车", + conditionNotice: + "请输入一个标签、内容关键词或者内容不包含的关键词(key=value)之后回车", cacheModalTitle: "清除缓存提醒", yes: "是的", no: "不", diff --git a/src/router/alert.ts b/src/router/alert.ts deleted file mode 100644 index c0e27fb2..00000000 --- a/src/router/alert.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 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 { RouteRecordRaw } from "vue-router"; -import Layout from "@/layout/Index.vue"; - -export const routesAlert: Array = [ - { - path: "", - name: "Alerts", - meta: { - title: "alerts", - icon: "notification_important", - hasGroup: false, - exact: false, - }, - component: Layout, - children: [ - { - path: "/alerts", - name: "Alerts", - meta: { - title: "alerts", - icon: "notification_important", - hasGroup: false, - exact: false, - }, - component: () => import("@/views/Log.vue"), - }, - ], - }, -]; diff --git a/src/router/index.ts b/src/router/index.ts index 4ab9d190..aa6e470d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -21,9 +21,8 @@ import { routesMesh } from "./serviceMesh"; import { routesDatabase } from "./database"; import { routesInfra } from "./infrastructure"; import { routesDashboard } from "./dashboard"; -import { routesLog } from "./log"; +// import { routesLog } from "./log"; import { routesEvent } from "./event"; -import { routesAlert } from "./alert"; import { routesSetting } from "./setting"; import { routesAlarm } from "./alarm"; @@ -33,9 +32,7 @@ const routes: Array = [ ...routesDatabase, ...routesInfra, ...routesDashboard, - ...routesLog, ...routesEvent, - ...routesAlert, ...routesSetting, ...routesAlarm, ]; diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts index ad15f257..84af4f57 100644 --- a/src/store/modules/dashboard.ts +++ b/src/store/modules/dashboard.ts @@ -98,8 +98,8 @@ export const dashboardStore = defineStore({ showDepth: true, }; } - if (type === "Trace" || type === "Profile") { - newItem.h = 24; + if (type === "Trace" || type === "Profile" || type === "Log") { + newItem.h = 36; } this.activedGridItem = newItem.i; this.selectedGrid = newItem; @@ -150,7 +150,7 @@ export const dashboardStore = defineStore({ showDepth: true, }; } - if (type === "Trace" || type === "Profile") { + if (type === "Trace" || type === "Profile" || type === "Log") { newItem.h = 24; } if (this.layout[idx].children) { diff --git a/src/store/modules/log.ts b/src/store/modules/log.ts new file mode 100644 index 00000000..f7846d66 --- /dev/null +++ b/src/store/modules/log.ts @@ -0,0 +1,156 @@ +/** + * 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 { defineStore } from "pinia"; +import { Duration } from "@/types/app"; +import { Instance, Endpoint, Service } from "@/types/selector"; +import { store } from "@/store"; +import graphql from "@/graphql"; +import { AxiosResponse } from "axios"; +import { useAppStoreWithOut } from "@/store/modules/app"; +import { useSelectorStore } from "@/store/modules/selectors"; +import { useDashboardStore } from "@/store/modules/dashboard"; + +interface LogState { + services: Service[]; + instances: Instance[]; + endpoints: Endpoint[]; + conditions: any; + durationTime: Duration; + selectorStore: any; + supportQueryLogsByKeywords: boolean; + logs: any[]; + logsTotal: number; + loadLogs: boolean; +} + +export const logStore = defineStore({ + id: "trace", + state: (): LogState => ({ + services: [{ value: "0", label: "All" }], + instances: [{ value: "0", label: "All" }], + endpoints: [{ value: "0", label: "All" }], + conditions: { + queryDuration: useAppStoreWithOut().durationTime, + paging: { pageNum: 1, pageSize: 15, needTotal: true }, + }, + supportQueryLogsByKeywords: true, + durationTime: useAppStoreWithOut().durationTime, + selectorStore: useSelectorStore(), + logs: [], + logsTotal: 0, + loadLogs: false, + }), + actions: { + setLogCondition(data: any) { + this.conditions = { ...this.conditions, ...data }; + }, + async getServices(layer: string) { + const res: AxiosResponse = await graphql.query("queryServices").params({ + layer, + }); + if (res.data.errors) { + return res.data; + } + this.services = [ + { value: "0", label: "All" }, + ...res.data.data.services, + ] || [{ value: "0", label: "All" }]; + return res.data; + }, + async getInstances() { + const res: AxiosResponse = await graphql.query("queryInstances").params({ + serviceId: this.selectorStore.currentService.id, + duration: this.durationTime, + }); + + if (res.data.errors) { + return res.data; + } + this.instances = [ + { value: "0", label: "All" }, + ...res.data.data.pods, + ] || [{ value: " 0", label: "All" }]; + return res.data; + }, + async getEndpoints() { + const res: AxiosResponse = await graphql.query("queryEndpoints").params({ + serviceId: this.selectorStore.currentService.id, + duration: this.durationTime, + keyword: "", + }); + if (res.data.errors) { + return res.data; + } + this.endpoints = [ + { value: "0", label: "All" }, + ...res.data.data.pods, + ] || [{ value: "0", label: "All" }]; + return res.data; + }, + async queryLogsByKeywords() { + const res: AxiosResponse = await graphql + .query("queryLogsByKeywords") + .params({}); + + if (res.data.errors) { + return res.data; + } + + this.supportQueryLogsByKeywords = res.data.data.support; + return res.data; + }, + async getLogs() { + const dashboardStore = useDashboardStore(); + if (dashboardStore.layerId === "BROWSER") { + return this.getBrowserLogs(); + } + return this.getServiceLogs(); + }, + async getServiceLogs() { + this.loadLogs = true; + const res: AxiosResponse = await graphql + .query("queryServiceLogs") + .params({ condition: this.conditions }); + this.loadLogs = false; + if (res.data.errors) { + return res.data; + } + + this.logs = res.data.data.queryLogs.logs; + this.logsTotal = res.data.data.queryLogs.total; + return res.data; + }, + async getBrowserLogs() { + this.loadLogs = true; + const res: AxiosResponse = await graphql + .query("queryBrowserErrorLogs") + .params({ condition: this.conditions }); + + this.loadLogs = false; + if (res.data.errors) { + return res.data; + } + this.logs = res.data.data.queryBrowserErrorLogs.logs; + this.logsTotal = res.data.data.queryBrowserErrorLogs.total; + return res.data; + }, + }, +}); + +export function useLogStore(): any { + return logStore(store); +} diff --git a/src/styles/lib.scss b/src/styles/lib.scss index 3462512e..a589ae10 100644 --- a/src/styles/lib.scss +++ b/src/styles/lib.scss @@ -107,6 +107,10 @@ margin-bottom: 5px; } +.mt-5 { + margin-top: 5px; +} + .ml-5 { margin-left: 5px; } @@ -123,6 +127,10 @@ margin-left: 20px; } +.mb-10 { + margin-bottom: 10px; +} + .mr-5 { margin-right: 5px; } diff --git a/src/views/dashboard/controls/Log.vue b/src/views/dashboard/controls/Log.vue new file mode 100644 index 00000000..d0a22405 --- /dev/null +++ b/src/views/dashboard/controls/Log.vue @@ -0,0 +1,93 @@ + + + + diff --git a/src/views/dashboard/controls/Tab.vue b/src/views/dashboard/controls/Tab.vue index 20c106dd..78f45864 100644 --- a/src/views/dashboard/controls/Tab.vue +++ b/src/views/dashboard/controls/Tab.vue @@ -119,6 +119,7 @@ import Topology from "./Topology.vue"; import Widget from "./Widget.vue"; import Trace from "./Trace.vue"; import Profile from "./Profile.vue"; +import Log from "./Log.vue"; const props = { data: { @@ -129,7 +130,7 @@ const props = { }; export default defineComponent({ name: "Tab", - components: { Topology, Widget, Trace, Profile }, + components: { Topology, Widget, Trace, Profile, Log }, props, setup(props) { const { t } = useI18n(); diff --git a/src/views/dashboard/controls/index.ts b/src/views/dashboard/controls/index.ts index 4f2ee20e..7fdcd85a 100644 --- a/src/views/dashboard/controls/index.ts +++ b/src/views/dashboard/controls/index.ts @@ -19,5 +19,6 @@ import Tab from "./Tab.vue"; import Widget from "./Widget.vue"; import Trace from "./Trace.vue"; import Profile from "./Profile.vue"; +import Log from "./Log.vue"; -export default { Tab, Widget, Trace, Topology, Profile }; +export default { Tab, Widget, Trace, Topology, Profile, Log }; diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index 396de2cd..6917c976 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -168,6 +168,7 @@ export const ToolIcons = [ { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "merge", content: "Add Trace", id: "addTrace" }, { name: "timeline", content: "Add Profile", id: "addProfile" }, + { name: "assignment", content: "Add Log", id: "addLog" }, // { name: "save_alt", content: "Export", id: "export" }, // { name: "folder_open", content: "Import", id: "import" }, // { name: "settings", content: "Settings", id: "settings" }, diff --git a/src/views/dashboard/panel/Tool.vue b/src/views/dashboard/panel/Tool.vue index b052257e..ce05edd5 100644 --- a/src/views/dashboard/panel/Tool.vue +++ b/src/views/dashboard/panel/Tool.vue @@ -309,6 +309,9 @@ function setTabControls(id: string) { case "addTrace": dashboardStore.addTabControls("Trace"); break; + case "addLog": + dashboardStore.addTabControls("Log"); + break; case "addProfile": dashboardStore.addTabControls("Profile"); break; @@ -335,6 +338,9 @@ function setControls(id: string) { case "addProfile": dashboardStore.addControl("Profile"); break; + case "addLog": + dashboardStore.addControl("Log"); + break; case "addTopology": dashboardStore.addControl("Topology"); break; diff --git a/src/views/components/ConditionTags.vue b/src/views/dashboard/related/components/ConditionTags.vue similarity index 93% rename from src/views/components/ConditionTags.vue rename to src/views/dashboard/related/components/ConditionTags.vue index b73ae6a0..f755910d 100644 --- a/src/views/components/ConditionTags.vue +++ b/src/views/dashboard/related/components/ConditionTags.vue @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. --> diff --git a/src/views/components/LogTable/LogDetail.vue b/src/views/dashboard/related/components/LogTable/LogDetail.vue similarity index 71% rename from src/views/components/LogTable/LogDetail.vue rename to src/views/dashboard/related/components/LogTable/LogDetail.vue index 45881327..75104fb5 100644 --- a/src/views/components/LogTable/LogDetail.vue +++ b/src/views/dashboard/related/components/LogTable/LogDetail.vue @@ -19,22 +19,20 @@ limitations under the License. --> v-for="(item, index) in columns" :key="index" > -