From 30069ce82505c973b624531209611cea32d6db10 Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Thu, 2 Jun 2022 20:09:38 +0800 Subject: [PATCH] feat: visualize a on-demand log widget (#99) --- package-lock.json | 61 +++ package.json | 2 + src/assets/icons/demand.svg | 16 + src/graphql/fragments/demand-log.ts | 38 ++ src/graphql/index.ts | 2 + src/graphql/query/demand-log.ts | 22 + src/hooks/useEcharts.ts | 4 + src/locales/lang/en.ts | 6 + src/locales/lang/es.ts | 19 +- src/locales/lang/zh.ts | 6 + src/store/modules/dashboard.ts | 11 +- src/store/modules/demand-log.ts | 124 ++++++ src/types/app.d.ts | 4 + src/types/demand-log.ts | 31 ++ src/types/monaco-editor.ts | 17 + src/views/dashboard/controls/DemandLog.vue | 93 ++++ src/views/dashboard/controls/Tab.vue | 11 +- src/views/dashboard/controls/index.ts | 13 +- src/views/dashboard/data.ts | 2 + src/views/dashboard/panel/Tool.vue | 6 + .../dashboard/related/demand-log/Content.vue | 78 ++++ .../dashboard/related/demand-log/Header.vue | 412 ++++++++++++++++++ .../dashboard/related/demand-log/data.ts | 37 ++ .../related/ebpf/components/EBPFSchedules.vue | 2 +- vue.config.js | 9 +- 25 files changed, 1012 insertions(+), 14 deletions(-) create mode 100644 src/assets/icons/demand.svg create mode 100644 src/graphql/fragments/demand-log.ts create mode 100644 src/graphql/query/demand-log.ts create mode 100644 src/store/modules/demand-log.ts create mode 100644 src/types/demand-log.ts create mode 100644 src/types/monaco-editor.ts create mode 100644 src/views/dashboard/controls/DemandLog.vue create mode 100644 src/views/dashboard/related/demand-log/Content.vue create mode 100644 src/views/dashboard/related/demand-log/Header.vue create mode 100644 src/views/dashboard/related/demand-log/data.ts diff --git a/package-lock.json b/package-lock.json index fe87d6cc..c908f59a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "echarts": "^5.2.2", "element-plus": "^2.0.2", "lodash": "^4.17.21", + "monaco-editor": "^0.27.0", "pinia": "^2.0.5", "vue": "^3.0.0", "vue-grid-layout": "^3.0.0-beta1", @@ -50,6 +51,7 @@ "eslint-plugin-vue": "^7.0.0", "husky": "^7.0.4", "lint-staged": "^12.1.3", + "monaco-editor-webpack-plugin": "^4.1.2", "node-sass": "^6.0.1", "postcss-html": "^1.3.0", "postcss-scss": "^4.0.2", @@ -18234,6 +18236,38 @@ "node": "*" } }, + "node_modules/monaco-editor": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.27.0.tgz", + "integrity": "sha512-UhwP78Wb8w0ZSYoKXQNTV/0CHObp6NS3nCt51QfKE6sKyBo5PBsvuDOHoI2ooBakc6uIwByRLHVeT7+yXQe2fQ==" + }, + "node_modules/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, + "dependencies": { + "loader-utils": "^2.0.0" + }, + "peerDependencies": { + "monaco-editor": "0.25.x || 0.26.x || 0.27.x", + "webpack": "^4.5.0 || 5.x" + } + }, + "node_modules/monaco-editor-webpack-plugin/node_modules/loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -43271,6 +43305,33 @@ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", "dev": true }, + "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": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", diff --git a/package.json b/package.json index ece16b3a..e1f48cc3 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "echarts": "^5.2.2", "element-plus": "^2.0.2", "lodash": "^4.17.21", + "monaco-editor": "^0.27.0", "pinia": "^2.0.5", "vue": "^3.0.0", "vue-grid-layout": "^3.0.0-beta1", @@ -52,6 +53,7 @@ "eslint-plugin-vue": "^7.0.0", "husky": "^7.0.4", "lint-staged": "^12.1.3", + "monaco-editor-webpack-plugin": "^4.1.2", "node-sass": "^6.0.1", "postcss-html": "^1.3.0", "postcss-scss": "^4.0.2", diff --git a/src/assets/icons/demand.svg b/src/assets/icons/demand.svg new file mode 100644 index 00000000..4b1b60db --- /dev/null +++ b/src/assets/icons/demand.svg @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/src/graphql/fragments/demand-log.ts b/src/graphql/fragments/demand-log.ts new file mode 100644 index 00000000..40df4977 --- /dev/null +++ b/src/graphql/fragments/demand-log.ts @@ -0,0 +1,38 @@ +/** + * 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 queryContainers = { + variable: "$condition: OndemandContainergQueryCondition!", + query: ` + containers: listContainers(condition: $condition) { + errorReason + containers + }`, +}; + +export const queryStreamingLogs = { + variable: "$condition: OndemandLogQueryCondition", + query: ` + logs: ondemandPodLogs(condition: $condition) { + errorReason + logs { + timestamp + contentType + content + } + }`, +}; diff --git a/src/graphql/index.ts b/src/graphql/index.ts index 3b76c9fb..19271544 100644 --- a/src/graphql/index.ts +++ b/src/graphql/index.ts @@ -26,6 +26,7 @@ import * as profile from "./query/profile"; import * as alarm from "./query/alarm"; import * as event from "./query/event"; import * as ebpf from "./query/ebpf"; +import * as demandLog from "./query/demand-log"; const query: { [key: string]: string } = { ...app, @@ -38,6 +39,7 @@ const query: { [key: string]: string } = { ...alarm, ...event, ...ebpf, + ...demandLog, }; class Graphql { private queryData = ""; diff --git a/src/graphql/query/demand-log.ts b/src/graphql/query/demand-log.ts new file mode 100644 index 00000000..94fd1432 --- /dev/null +++ b/src/graphql/query/demand-log.ts @@ -0,0 +1,22 @@ +/** + * 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 { queryContainers, queryStreamingLogs } from "../fragments/demand-log"; + +export const fetchContainers = `query listContainers(${queryContainers.variable}) {${queryContainers.query}}`; + +export const fetchDemandPodLogs = `query ondemandPodLogs(${queryStreamingLogs.variable}) {${queryStreamingLogs.query}}`; diff --git a/src/hooks/useEcharts.ts b/src/hooks/useEcharts.ts index 16b505b2..01f7d7ed 100644 --- a/src/hooks/useEcharts.ts +++ b/src/hooks/useEcharts.ts @@ -79,7 +79,11 @@ export function useECharts( if (!el || !unref(el)) { return; } + const { width, height } = el.getBoundingClientRect(); + if (!width || !height) { + return; + } chartInstance = echarts.init(el, t); const { removeEvent } = useEventListener({ el: window, diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts index 7f55d4a0..7749d634 100644 --- a/src/locales/lang/en.ts +++ b/src/locales/lang/en.ts @@ -136,7 +136,13 @@ const msg = { targetType: "Target Type", ebpfTip: "Don't have a process for profiling", processSelect: "Click to select processes", + container: "Container", + limit: "Limit", page: "Page", + interval: "Refresh Interval", + pause: "Pause", + begin: "Start", + seconds: "Seconds", hourTip: "Select Hour", minuteTip: "Select Minute", secondTip: "Select Second", diff --git a/src/locales/lang/es.ts b/src/locales/lang/es.ts index 40ef1fda..c5c8a58e 100644 --- a/src/locales/lang/es.ts +++ b/src/locales/lang/es.ts @@ -74,8 +74,10 @@ const msg = { editGraph: "Editar Opciones", dashboardName: "Selecciona Nombre del Panel", linkDashboard: "Nombre del panel relacionado con llamadas de la topología", - linkServerMetrics: "Métricas de servidor relacionadas con llamadas de la topología", - linkClientMetrics: "Métricas de cliente relacionadas con llamadas de la topología", + linkServerMetrics: + "Métricas de servidor relacionadas con llamadas de la topología", + linkClientMetrics: + "Métricas de cliente relacionadas con llamadas de la topología", nodeDashboard: "Nombre del panel relacionado con nodos de la topología", nodeMetrics: "Mêtricas relacionas con nodos de la topología", instanceDashboard: "Nombre del panel relacionado con instancias de servicio", @@ -137,6 +139,10 @@ const msg = { ebpfTip: "Le falta el proceso para perfilar", processSelect: "Click para seleccionar proceso", page: "Página", + interval: "Intervalo de actualización", + pause: "Pausa", + begin: "Inicio", + seconds: "Segundos", hourTip: "Seleccione Hora", minuteTip: "Seleccione Minuto", secondTip: "Seleccione Segundo", @@ -303,7 +309,8 @@ const msg = { destEndpoint: "Endpoint Destinación", eventSource: "Fuente Envento", modalTitle: "Inspección", - selectRedirectPage: "Quiere inspeccionar las Trazas or Registros de datos del servicio %s?", + selectRedirectPage: + "Quiere inspeccionar las Trazas or Registros de datos del servicio %s?", logAnalysis: "Lenguaje de Análisis de Registro de Datos", logDataBody: "Contenido del Registro de Datos", addType: "Por favor introduzca un tipo", @@ -324,8 +331,10 @@ const msg = { addTraceID: "Por favor introduzca el ID de la traza", addTags: "Por favor introduzaca una etiqueta", addKeywordsOfContent: "Por favor introduzca una clave de contenido", - addExcludingKeywordsOfContent: "Por favor introduzca una clave excluyente de contenido", - noticeTag: "Por favor presione Intro después de introducir una etiqueta(clave=valor).", + addExcludingKeywordsOfContent: + "Por favor introduzca una clave excluyente de contenido", + noticeTag: + "Por favor presione Intro después de introducir una etiqueta(clave=valor).", conditionNotice: "Aviso: Por favor presione Intro después de introducir una clave de contenido, excluir clave de contenido(clave=valor).", language: "Lenguaje", diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts index 88af9d13..10d8837a 100644 --- a/src/locales/lang/zh.ts +++ b/src/locales/lang/zh.ts @@ -134,7 +134,13 @@ const msg = { targetType: "目标类型", processSelect: "点击选择进程", ebpfTip: "没有进程可以分析", + container: "容器", + limit: "范围", page: "页面", + interval: "刷新间隔时间", + pause: "暂停", + begin: "开始", + seconds: "秒", hourTip: "选择小时", minuteTip: "选择分钟", secondTip: "选择秒数", diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts index 2ed20f17..596ac8b6 100644 --- a/src/store/modules/dashboard.ts +++ b/src/store/modules/dashboard.ts @@ -114,7 +114,8 @@ export const dashboardStore = defineStore({ type === "Trace" || type === "Profile" || type === "Log" || - type === "Ebpf" + type === "Ebpf" || + type === "DemandLog" ) { newItem.h = 36; } @@ -170,7 +171,13 @@ export const dashboardStore = defineStore({ showDepth: true, }; } - if (type === "Trace" || type === "Profile" || type === "Log") { + if ( + type === "Trace" || + type === "Profile" || + type === "Log" || + type === "DemandLog" || + type === "Ebpf" + ) { newItem.h = 32; } if (type === "Text") { diff --git a/src/store/modules/demand-log.ts b/src/store/modules/demand-log.ts new file mode 100644 index 00000000..0eaf7d1e --- /dev/null +++ b/src/store/modules/demand-log.ts @@ -0,0 +1,124 @@ +import { ElMessage } from "element-plus"; +/** + * 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 { Instance } 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 { Conditions, Log } from "@/types/demand-log"; + +interface DemandLogState { + containers: Instance[]; + instances: Instance[]; + conditions: Conditions; + selectorStore: any; + logs: Log[]; + loadLogs: boolean; + message: string; +} + +export const demandLogStore = defineStore({ + id: "demandLog", + state: (): DemandLogState => ({ + containers: [{ label: "", value: "" }], + instances: [{ value: "", label: "" }], + conditions: { + container: "", + serviceInstanceId: "", + duration: useAppStoreWithOut().durationTime, + }, + selectorStore: useSelectorStore(), + logs: [], + loadLogs: false, + message: "", + }), + actions: { + setLogCondition(data: Conditions) { + this.conditions = { ...this.conditions, ...data }; + }, + setLogs(logs: Log[], message?: string) { + this.logs = logs; + this.message = message || ""; + }, + async getInstances(id: string) { + const serviceId = this.selectorStore.currentService + ? this.selectorStore.currentService.id + : id; + const res: AxiosResponse = await graphql.query("queryInstances").params({ + serviceId, + duration: useAppStoreWithOut().durationTime, + }); + + if (res.data.errors) { + return res.data; + } + this.instances = res.data.data.pods || []; + return res.data; + }, + async getContainers(serviceInstanceId: string) { + if (!serviceInstanceId) { + return new Promise((resolve) => + resolve({ errors: "No service instance" }) + ); + } + const condition = { + serviceInstanceId, + }; + const res: AxiosResponse = await graphql + .query("fetchContainers") + .params({ condition }); + + if (res.data.errors) { + return res.data; + } + if (res.data.data.containers.errorReason) { + this.containers = [{ label: "", value: "" }]; + return res.data; + } + this.containers = res.data.data.containers.containers.map((d: string) => { + return { label: d, value: d }; + }); + return res.data; + }, + async getDemandLogs() { + this.loadLogs = true; + const res: AxiosResponse = await graphql + .query("fetchDemandPodLogs") + .params({ condition: this.conditions }); + this.loadLogs = false; + if (res.data.errors) { + return res.data; + } + if (res.data.data.logs.errorReason) { + this.setLogs("", res.data.data.logs.errorReason); + return res.data; + } + const logs = res.data.data.logs.logs + .map((d: Log) => d.content) + .join("\n"); + this.setLogs(logs); + return res.data; + }, + }, +}); + +export function useDemandLogStore(): any { + return demandLogStore(store); +} diff --git a/src/types/app.d.ts b/src/types/app.d.ts index 74e69c32..ee35299a 100644 --- a/src/types/app.d.ts +++ b/src/types/app.d.ts @@ -28,3 +28,7 @@ export interface DurationTime { end: string; step: string; } +export type Paging = { + pageNum: number; + pageSize: number; +}; diff --git a/src/types/demand-log.ts b/src/types/demand-log.ts new file mode 100644 index 00000000..44a24ab7 --- /dev/null +++ b/src/types/demand-log.ts @@ -0,0 +1,31 @@ +/** + * 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 { DurationTime } from "./app"; + +export interface Conditions { + container: string; + serviceInstanceId: string; + duration: DurationTime; + keywordsOfContent?: string[]; + excludingKeywordsOfContent?: string; +} + +export interface Log { + content: string; + timestamp: number; + contentType: string; +} diff --git a/src/types/monaco-editor.ts b/src/types/monaco-editor.ts new file mode 100644 index 00000000..0e7645a5 --- /dev/null +++ b/src/types/monaco-editor.ts @@ -0,0 +1,17 @@ +/** + * 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. + */ +declare module "monaco-editor"; diff --git a/src/views/dashboard/controls/DemandLog.vue b/src/views/dashboard/controls/DemandLog.vue new file mode 100644 index 00000000..543bad00 --- /dev/null +++ b/src/views/dashboard/controls/DemandLog.vue @@ -0,0 +1,93 @@ + + + + diff --git a/src/views/dashboard/controls/Tab.vue b/src/views/dashboard/controls/Tab.vue index 524e9f7e..50642870 100644 --- a/src/views/dashboard/controls/Tab.vue +++ b/src/views/dashboard/controls/Tab.vue @@ -110,6 +110,7 @@ import Log from "./Log.vue"; import Text from "./Text.vue"; import Ebpf from "./Ebpf.vue"; import { dragIgnoreFrom } from "../data"; +import DemandLog from "./DemandLog.vue"; const props = { data: { @@ -120,7 +121,7 @@ const props = { }; export default defineComponent({ name: "Tab", - components: { Topology, Widget, Trace, Profile, Log, Text, Ebpf }, + components: { Topology, Widget, Trace, Profile, Log, Text, Ebpf, DemandLog }, props, setup(props) { const { t } = useI18n(); @@ -250,21 +251,23 @@ export default defineComponent({ span { display: inline-block; - padding: 0 10px; - margin: 0 10px; height: 40px; line-height: 40px; cursor: pointer; + text-align: center; } .tab-name { - max-width: 130px; + max-width: 110px; height: 20px; line-height: 20px; outline: none; color: #333; font-style: normal; margin-right: 5px; + overflow: hidden; + text-overflow: ellipsis; + text-align: center; } .tab-icons { diff --git a/src/views/dashboard/controls/index.ts b/src/views/dashboard/controls/index.ts index 01fc5dc5..858bc5c5 100644 --- a/src/views/dashboard/controls/index.ts +++ b/src/views/dashboard/controls/index.ts @@ -22,5 +22,16 @@ import Profile from "./Profile.vue"; import Log from "./Log.vue"; import Text from "./Text.vue"; import Ebpf from "./Ebpf.vue"; +import DemandLog from "./DemandLog.vue"; -export default { Tab, Widget, Trace, Topology, Profile, Log, Text, Ebpf }; +export default { + Tab, + Widget, + Trace, + Topology, + Profile, + Log, + Text, + Ebpf, + DemandLog, +}; diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index c6e4bc32..b19f65e7 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -186,6 +186,7 @@ export const ServiceTools = [ { name: "timeline", content: "Trace Profiling", id: "addProfile" }, { name: "insert_chart", content: "eBPF Profiling", id: "addEbpf" }, { name: "assignment", content: "Log", id: "addLog" }, + { name: "demand", content: "Add On Demand Log", id: "addDemandLog" }, ]; export const InstanceTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, @@ -193,6 +194,7 @@ export const InstanceTools = [ { name: "library_books", content: "Add Text", id: "addText" }, { name: "merge", content: "Add Trace", id: "addTrace" }, { name: "assignment", content: "Add Log", id: "addLog" }, + { name: "demand", content: "Add On Demand Log", id: "addDemandLog" }, ]; export const EndpointTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, diff --git a/src/views/dashboard/panel/Tool.vue b/src/views/dashboard/panel/Tool.vue index bc96d8c3..8d8ed374 100644 --- a/src/views/dashboard/panel/Tool.vue +++ b/src/views/dashboard/panel/Tool.vue @@ -455,6 +455,9 @@ function setTabControls(id: string) { case "addText": dashboardStore.addTabControls("Text"); break; + case "addDemandLog": + dashboardStore.addTabControls("DemandLog"); + break; default: ElMessage.info("Don't support this control"); break; @@ -487,6 +490,9 @@ function setControls(id: string) { case "addText": dashboardStore.addControl("Text"); break; + case "addDemandLog": + dashboardStore.addControl("DemandLog"); + break; default: dashboardStore.addControl("Widget"); } diff --git a/src/views/dashboard/related/demand-log/Content.vue b/src/views/dashboard/related/demand-log/Content.vue new file mode 100644 index 00000000..a3577f97 --- /dev/null +++ b/src/views/dashboard/related/demand-log/Content.vue @@ -0,0 +1,78 @@ + + + + diff --git a/src/views/dashboard/related/demand-log/Header.vue b/src/views/dashboard/related/demand-log/Header.vue new file mode 100644 index 00000000..3164bc9c --- /dev/null +++ b/src/views/dashboard/related/demand-log/Header.vue @@ -0,0 +1,412 @@ + + + + diff --git a/src/views/dashboard/related/demand-log/data.ts b/src/views/dashboard/related/demand-log/data.ts new file mode 100644 index 00000000..0ef8c235 --- /dev/null +++ b/src/views/dashboard/related/demand-log/data.ts @@ -0,0 +1,37 @@ +/** + * 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 TimeRanges = [ + { label: "From 5 seconds ago -- Now", value: 5 }, + { label: "From 10 seconds ago -- Now", value: 10 }, + { label: "From 15 seconds ago -- Now", value: 15 }, + { label: "From 30 seconds ago -- Now", value: 30 }, + { label: "From 45 seconds ago -- Now", value: 45 }, + { label: "From 1 minute ago -- Now", value: 60 }, + { label: "From 5 minutes ago -- Now", value: 300 }, + { label: "From 15 minutes ago -- Now", value: 900 }, + { label: "From 30 minutes ago -- Now", value: 1800 }, +]; +export const IntervalOpts = [ + { label: "None", value: 0 }, + { label: "5 seconds", value: 5 }, + { label: "10 seconds", value: 10 }, + { label: "15 seconds", value: 15 }, + { label: "30 seconds", value: 30 }, + { label: "45 seconds", value: 45 }, + { label: "1 minute", value: 60 }, +]; diff --git a/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue b/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue index d58dfe91..21539fd1 100644 --- a/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue +++ b/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue @@ -253,7 +253,7 @@ watch( } .inputs { - width: 350px; + width: 400px; } .input-with-search { diff --git a/vue.config.js b/vue.config.js index dd9d016c..d26454e6 100644 --- a/vue.config.js +++ b/vue.config.js @@ -15,6 +15,7 @@ * limitations under the License. */ +const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin"); const AutoImport = require("unplugin-auto-import/webpack"); const Components = require("unplugin-vue-components/webpack"); const { ElementPlusResolver } = require("unplugin-vue-components/resolvers"); @@ -64,6 +65,11 @@ module.exports = { test: /[\\/]node_modules[\\/]echarts|zrender[\\/]/, priority: 30, }, + monacoEditor: { + name: "monaco-editor", + test: /[\\/]node_modules[\\/]monaco-editor[\\/]/, + priority: 40, + }, elementPlus: { name: "element-plus", test: /[\\/]node_modules[\\/]element-plus|@element-plus[\\/]/, @@ -98,7 +104,8 @@ module.exports = { Components({ resolvers: [ElementPlusResolver({ importStyle: "css" })], dts: "./src/types/components.d.ts", - }) + }), + new MonacoWebpackPlugin() ); }, };