From 9c0bb988e6f80d0c3492a1cd47547de7c1fa3150 Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Mon, 15 Aug 2022 16:49:00 +0800 Subject: [PATCH] feat: support the process dashboard and create the time range text widget (#138) --- src/assets/icons/control.svg | 2 +- src/assets/icons/library_add.svg | 17 + src/assets/icons/time_range.svg | 15 + src/graphql/fragments/ebpf.ts | 26 +- src/graphql/fragments/selector.ts | 44 +++ src/graphql/fragments/topology.ts | 23 ++ src/graphql/query/ebpf.ts | 6 + src/graphql/query/selector.ts | 4 + src/graphql/query/topology.ts | 2 + src/hooks/data.ts | 2 +- src/hooks/useProcessor.ts | 9 +- src/locales/lang/en.ts | 1 + src/locales/lang/es.ts | 1 + src/locales/lang/zh.ts | 1 + src/router/dashboard.ts | 33 +- src/store/data.ts | 8 + src/store/modules/dashboard.ts | 34 +- src/store/modules/ebpf.ts | 24 +- src/store/modules/selectors.ts | 62 +++- src/types/ebpf.d.ts | 24 +- src/types/selector.d.ts | 13 + .../dashboard/configuration/TimeRange.vue | 161 ++++++++ src/views/dashboard/configuration/index.ts | 2 + .../configuration/widget/metric/Index.vue | 14 +- src/views/dashboard/controls/Tab.vue | 20 +- src/views/dashboard/controls/TimeRange.vue | 187 ++++++++++ src/views/dashboard/controls/Widget.vue | 13 +- src/views/dashboard/controls/index.ts | 2 + src/views/dashboard/controls/tab.ts | 39 ++ src/views/dashboard/data.ts | 7 + src/views/dashboard/graphs/topology.ts | 32 ++ src/views/dashboard/panel/Tool.vue | 344 +++++++++++++----- .../D3Graph}/linkElement.ts | 0 .../D3Graph}/nodeElement.ts | 2 +- .../D3Graph}/simulation.ts | 0 .../utils => components/D3Graph}/zoom.ts | 0 .../related/components/TaskDetails.vue | 82 +++++ .../dashboard/related/demand-log/Header.vue | 1 - src/views/dashboard/related/ebpf/Header.vue | 5 +- .../related/ebpf/components/EBPFSchedules.vue | 7 +- .../related/ebpf/components/TaskList.vue | 56 +-- src/views/dashboard/related/event/Header.vue | 4 +- src/views/dashboard/related/log/Header.vue | 2 +- .../related/topology/components/Graph.vue | 15 +- 44 files changed, 1133 insertions(+), 213 deletions(-) create mode 100644 src/assets/icons/library_add.svg create mode 100644 src/assets/icons/time_range.svg create mode 100644 src/views/dashboard/configuration/TimeRange.vue create mode 100644 src/views/dashboard/controls/TimeRange.vue create mode 100644 src/views/dashboard/controls/tab.ts create mode 100644 src/views/dashboard/graphs/topology.ts rename src/views/dashboard/related/{topology/utils => components/D3Graph}/linkElement.ts (100%) rename src/views/dashboard/related/{topology/utils => components/D3Graph}/nodeElement.ts (99%) rename src/views/dashboard/related/{topology/utils => components/D3Graph}/simulation.ts (100%) rename src/views/dashboard/related/{topology/utils => components/D3Graph}/zoom.ts (100%) create mode 100644 src/views/dashboard/related/components/TaskDetails.vue diff --git a/src/assets/icons/control.svg b/src/assets/icons/control.svg index 250d63bf..8ecf7f50 100644 --- a/src/assets/icons/control.svg +++ b/src/assets/icons/control.svg @@ -12,4 +12,4 @@ 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. --> - \ No newline at end of file + \ No newline at end of file diff --git a/src/assets/icons/library_add.svg b/src/assets/icons/library_add.svg new file mode 100644 index 00000000..fb4b4f18 --- /dev/null +++ b/src/assets/icons/library_add.svg @@ -0,0 +1,17 @@ + + + + diff --git a/src/assets/icons/time_range.svg b/src/assets/icons/time_range.svg new file mode 100644 index 00000000..5b5238ba --- /dev/null +++ b/src/assets/icons/time_range.svg @@ -0,0 +1,15 @@ + + \ No newline at end of file diff --git a/src/graphql/fragments/ebpf.ts b/src/graphql/fragments/ebpf.ts index 920065d4..d5ec74e4 100644 --- a/src/graphql/fragments/ebpf.ts +++ b/src/graphql/fragments/ebpf.ts @@ -33,12 +33,15 @@ export const createEBPFTask = { }`, }; export const queryEBPFTasks = { - variable: "$serviceId: ID!", + variable: + "$serviceId: ID, $serviceInstanceId: ID, $targets: [EBPFProfilingTargetType!]", query: ` - queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId) { + queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId, serviceInstanceId: $serviceInstanceId, targets: $targets) { taskId serviceName serviceId + serviceInstanceId + serviceInstanceName processLabels taskStartTime triggerType @@ -90,3 +93,22 @@ export const analysisEBPFResult = { } }`, }; + +export const createNetworkProfiling = { + variable: "$request: EBPFProfilingNetworkTaskRequest!", + query: ` + createEBPFNetworkProfiling(request: $request) { + status + errorReason + id + }`, +}; + +export const keepNetworkProfiling = { + variable: "$taskId: ID!", + query: ` + keepEBPFNetworkProfiling(taskId: $taskId) { + status + errorReason + }`, +}; diff --git a/src/graphql/fragments/selector.ts b/src/graphql/fragments/selector.ts index a5c70392..285ab3d6 100644 --- a/src/graphql/fragments/selector.ts +++ b/src/graphql/fragments/selector.ts @@ -48,6 +48,29 @@ export const Instances = { } `, }; + +export const Processes = { + variable: "$instanceId: ID!, $duration: Duration!", + query: ` + processes: listProcesses(instanceId: $instanceId, duration: $duration) { + id + value: name + label: name + serviceId + serviceName + instanceId + instanceName + agentId + detectType + attributes { + name + value + } + labels + } +`, +}; + export const Endpoints = { variable: "$serviceId: ID!, $keyword: String!", query: ` @@ -102,3 +125,24 @@ export const getEndpoint = { } `, }; + +export const getProcess = { + variable: "$processId: ID!", + query: ` + process: getProcess(processId: $processId) { + id + value: name + label: name + serviceId + serviceName + instanceId + instanceName + agentId + detectType + attributes { + name + value + } + } + `, +}; diff --git a/src/graphql/fragments/topology.ts b/src/graphql/fragments/topology.ts index 7b84951c..edbd7380 100644 --- a/src/graphql/fragments/topology.ts +++ b/src/graphql/fragments/topology.ts @@ -75,3 +75,26 @@ export const InstanceTopology = { } `, }; +export const ProcessTopology = { + variable: "$serviceInstanceId: ID!, $duration: Duration!", + query: ` + topology: getProcessTopology(serviceInstanceId: $serviceInstanceId, + duration: $duration) { + nodes { + id + name + isReal + serviceName + serviceId + serviceInstanceId + serviceInstanceName + } + calls { + id + source + detectPoints + target + } + } +`, +}; diff --git a/src/graphql/query/ebpf.ts b/src/graphql/query/ebpf.ts index 131b57a3..052fc7af 100644 --- a/src/graphql/query/ebpf.ts +++ b/src/graphql/query/ebpf.ts @@ -21,6 +21,8 @@ import { queryEBPFTasks, queryEBPFSchedules, analysisEBPFResult, + createNetworkProfiling, + keepNetworkProfiling, } from "../fragments/ebpf"; export const getCreateTaskData = `query queryCreateTaskData(${queryCreateTaskData.variable}) {${queryCreateTaskData.query}}`; @@ -32,3 +34,7 @@ export const getEBPFTasks = `query queryEBPFTasks(${queryEBPFTasks.variable}) {$ export const getEBPFSchedules = `query queryEBPFSchedules(${queryEBPFSchedules.variable}) {${queryEBPFSchedules.query}}`; export const getEBPFResult = `query analysisEBPFResult(${analysisEBPFResult.variable}) {${analysisEBPFResult.query}}`; + +export const newNetworkProfiling = `mutation createNetworkProfiling(${createNetworkProfiling.variable}) {${createNetworkProfiling.query}}`; + +export const aliveNetworkProfiling = `mutation keepNetworkProfiling(${keepNetworkProfiling.variable}) {${keepNetworkProfiling.query}}`; diff --git a/src/graphql/query/selector.ts b/src/graphql/query/selector.ts index cbbccc30..dc8d446f 100644 --- a/src/graphql/query/selector.ts +++ b/src/graphql/query/selector.ts @@ -22,6 +22,8 @@ import { getService, getInstance, getEndpoint, + Processes, + getProcess, } from "../fragments/selector"; export const queryServices = `query queryServices(${Services.variable}) {${Services.query}}`; @@ -31,3 +33,5 @@ export const queryLayers = `query listLayer {${Layers.query}}`; export const queryService = `query queryService(${getService.variable}) {${getService.query}}`; export const queryInstance = `query queryInstance(${getInstance.variable}) {${getInstance.query}}`; export const queryEndpoint = `query queryInstance(${getEndpoint.variable}) {${getEndpoint.query}}`; +export const queryProcesses = `query queryProcesses(${Processes.variable}) {${Processes.query}}`; +export const queryProcess = `query queryProcess(${getProcess.variable}) {${getProcess.query}}`; diff --git a/src/graphql/query/topology.ts b/src/graphql/query/topology.ts index 705d94bc..bb5333b2 100644 --- a/src/graphql/query/topology.ts +++ b/src/graphql/query/topology.ts @@ -18,8 +18,10 @@ import { InstanceTopology, EndpointTopology, ServicesTopology, + ProcessTopology, } from "../fragments/topology"; export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`; export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`; export const getServicesTopology = `query queryData(${ServicesTopology.variable}) {${ServicesTopology.query}}`; +export const getProcessTopology = `query queryData(${ProcessTopology.variable}) {${ProcessTopology.query}}`; diff --git a/src/hooks/data.ts b/src/hooks/data.ts index f683cf8e..73eef8d1 100644 --- a/src/hooks/data.ts +++ b/src/hooks/data.ts @@ -32,7 +32,7 @@ export enum Calculations { Precision = "precision", ConvertSeconds = "convertSeconds", ConvertMilliseconds = "convertMilliseconds", - MsTos = "msTos", + MsToS = "msTos", Average = "average", PercentageAvg = "percentageAvg", ApdexAvg = "apdexAvg", diff --git a/src/hooks/useProcessor.ts b/src/hooks/useProcessor.ts index ae9d914b..c764d42e 100644 --- a/src/hooks/useProcessor.ts +++ b/src/hooks/useProcessor.ts @@ -383,19 +383,16 @@ export function aggregation( case Calculations.Apdex: data = val / 10000; break; - case Calculations.ApdexAvg: - data = val / 10000; - break; case Calculations.ConvertSeconds: - data = dayjs(val).format("YYYY-MM-DD HH:mm:ss"); + data = dayjs(val * 1000).format("YYYY-MM-DD HH:mm:ss"); break; case Calculations.ConvertMilliseconds: - data = dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss"); + data = dayjs(val).format("YYYY-MM-DD HH:mm:ss"); break; case Calculations.Precision: data = data.toFixed(2); break; - case Calculations.MsTos: + case Calculations.MsToS: data = (val / 1000).toFixed(2); break; case Calculations.SecondToDay: diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts index 51256016..cfc99215 100644 --- a/src/locales/lang/en.ts +++ b/src/locales/lang/en.ts @@ -149,6 +149,7 @@ const msg = { "The name only supports Chinese and English, horizontal lines and underscores. The length of the name is limited to 300 characters", duplicateName: "Duplicate name", enableAssociate: "Enable association", + text: "Text", seconds: "Seconds", hourTip: "Select Hour", minuteTip: "Select Minute", diff --git a/src/locales/lang/es.ts b/src/locales/lang/es.ts index 5f54bc3b..fc702987 100644 --- a/src/locales/lang/es.ts +++ b/src/locales/lang/es.ts @@ -145,6 +145,7 @@ const msg = { begin: "Inicio", associateOptions: "Opciones de asociación", widget: "Dispositivo pequeño", + text: "Texto", duplicateName: "Nombre duplicado", nameTip: "El nombre sólo admite chino e inglés, líneas horizontales y subrayado, y la longitud del nombre no excederá de 300 caracteres", diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts index dc776759..1713244e 100644 --- a/src/locales/lang/zh.ts +++ b/src/locales/lang/zh.ts @@ -146,6 +146,7 @@ const msg = { enableAssociate: "启用关联", nameTip: "该名称仅支持中文和英文、横线和下划线, 并且限制长度为300个字符", duplicateName: "重复的名称", + text: "文本", seconds: "秒", hourTip: "选择小时", minuteTip: "选择分钟", diff --git a/src/router/dashboard.ts b/src/router/dashboard.ts index c985e2fc..3fe651f2 100644 --- a/src/router/dashboard.ts +++ b/src/router/dashboard.ts @@ -182,7 +182,7 @@ export const routesDashboard: Array = [ import( /* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue" ), - name: "ViewPodRelation", + name: "PodRelation", meta: { notShow: true, }, @@ -205,6 +205,37 @@ export const routesDashboard: Array = [ }, ], }, + { + path: "", + redirect: + "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name", + component: () => + import( + /* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue" + ), + name: "ProcessRelation", + meta: { + notShow: true, + }, + children: [ + { + path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name", + component: () => + import( + /* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue" + ), + name: "ViewProcessRelation", + }, + { + path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/tab/:activeTabIndex", + component: () => + import( + /* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue" + ), + name: "ViewProcessRelationActiveTabIndex", + }, + ], + }, ], }, ]; diff --git a/src/store/data.ts b/src/store/data.ts index d6d3e01e..ce31dd2c 100644 --- a/src/store/data.ts +++ b/src/store/data.ts @@ -29,3 +29,11 @@ export const TextConfig = { fontSize: 14, textAlign: "left", }; + +export const TimeRangeConfig = { + fontColor: "black", + backgroundColor: "white", + fontSize: 14, + textAlign: "center", + text: "text", +}; diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts index 450c2373..bad5e8ef 100644 --- a/src/store/modules/dashboard.ts +++ b/src/store/modules/dashboard.ts @@ -21,7 +21,7 @@ import graphql from "@/graphql"; import query from "@/graphql/fetch"; import { DashboardItem } from "@/types/dashboard"; import { useSelectorStore } from "@/store/modules/selectors"; -import { NewControl, TextConfig } from "../data"; +import { NewControl, TextConfig, TimeRangeConfig } from "../data"; import { AxiosResponse } from "axios"; import { ElMessage } from "element-plus"; import { useI18n } from "vue-i18n"; @@ -113,13 +113,27 @@ export const dashboardStore = defineStore({ : 3, }; } - if (["Trace", "Profile", "Log", "DemandLog", "Ebpf"].includes(type)) { + if ( + [ + "Trace", + "Profile", + "Log", + "DemandLog", + "Ebpf", + "NetworkProfiling", + ].includes(type) + ) { newItem.h = 36; } if (type === "Text") { newItem.h = 6; newItem.graph = TextConfig; } + if (type === "TimeRange") { + newItem.w = 8; + newItem.h = 6; + newItem.graph = TimeRangeConfig; + } this.activedGridItem = newItem.i; this.selectedGrid = newItem; this.layout = this.layout.map((d: LayoutConfig) => { @@ -170,13 +184,27 @@ export const dashboardStore = defineStore({ showDepth: true, }; } - if (["Trace", "Profile", "Log", "DemandLog", "Ebpf"].includes(type)) { + if ( + [ + "Trace", + "Profile", + "Log", + "DemandLog", + "Ebpf", + "NetworkProfiling", + ].includes(type) + ) { newItem.h = 32; } if (type === "Text") { newItem.h = 6; newItem.graph = TextConfig; } + if (type === "TimeRange") { + newItem.w = 8; + newItem.h = 6; + newItem.graph = TextConfig; + } if (this.layout[idx].children) { const items = children.map((d: LayoutConfig) => { d.y = d.y + newItem.h; diff --git a/src/store/modules/ebpf.ts b/src/store/modules/ebpf.ts index 987422b8..e77e5706 100644 --- a/src/store/modules/ebpf.ts +++ b/src/store/modules/ebpf.ts @@ -25,8 +25,7 @@ import { import { store } from "@/store"; import graphql from "@/graphql"; import { AxiosResponse } from "axios"; - -interface EbpfStore { +interface EbpfState { taskList: EBPFTaskList[]; eBPFSchedules: EBPFProfilingSchedule[]; currentSchedule: EBPFProfilingSchedule | Record; @@ -40,7 +39,7 @@ interface EbpfStore { export const ebpfStore = defineStore({ id: "eBPF", - state: (): EbpfStore => ({ + state: (): EbpfState => ({ taskList: [], eBPFSchedules: [], currentSchedule: {}, @@ -53,7 +52,7 @@ export const ebpfStore = defineStore({ }), actions: { setSelectedTask(task: EBPFTaskList) { - this.selectedTask = task; + this.selectedTask = task || {}; }, setCurrentSchedule(s: EBPFProfilingSchedule) { this.currentSchedule = s; @@ -84,22 +83,31 @@ export const ebpfStore = defineStore({ if (res.data.errors) { return res.data; } - this.getTaskList(param.serviceId); + this.getTaskList({ + serviceId: param.serviceId, + targets: ["ON_CPU", "OFF_CPU"], + }); return res.data; }, - async getTaskList(serviceId: string) { - if (!serviceId) { + async getTaskList(params: { + serviceId: string; + serviceInstanceId: string; + targets: string[]; + }) { + if (!params.serviceId) { return new Promise((resolve) => resolve({})); } const res: AxiosResponse = await graphql .query("getEBPFTasks") - .params({ serviceId }); + .params(params); this.tip = ""; if (res.data.errors) { return res.data; } this.taskList = res.data.data.queryEBPFTasks || []; + this.selectedTask = this.taskList[0] || {}; + this.setSelectedTask(this.selectedTask); if (!this.taskList.length) { return res.data; } diff --git a/src/store/modules/selectors.ts b/src/store/modules/selectors.ts index f393052c..2e671d8e 100644 --- a/src/store/modules/selectors.ts +++ b/src/store/modules/selectors.ts @@ -15,7 +15,7 @@ * limitations under the License. */ import { defineStore } from "pinia"; -import { Service, Instance, Endpoint } from "@/types/selector"; +import { Service, Instance, Endpoint, Process } from "@/types/selector"; import { store } from "@/store"; import graphql from "@/graphql"; import { AxiosResponse } from "axios"; @@ -24,11 +24,15 @@ interface SelectorState { services: Service[]; destServices: Service[]; pods: Array; + processes: Process[]; + destProcesses: Process[]; currentService: Nullable; currentPod: Nullable; + currentProcess: Nullable; currentDestService: Nullable; currentDestPod: Nullable; destPods: Array; + currentDestProcess: Nullable; } export const selectorStore = defineStore({ @@ -38,10 +42,14 @@ export const selectorStore = defineStore({ destServices: [], pods: [], destPods: [], + processes: [], + destProcesses: [], currentService: null, currentPod: null, + currentProcess: null, currentDestService: null, currentDestPod: null, + currentDestProcess: null, }), actions: { setCurrentService(service: Nullable) { @@ -56,6 +64,18 @@ export const selectorStore = defineStore({ setCurrentDestPod(pod: Nullable) { this.currentDestPod = pod; }, + setCurrentProcess(process: Nullable) { + this.currentProcess = process; + }, + setCurrentDestProcess(process: Nullable) { + this.currentDestProcess = process; + }, + setDestPods(pods: Array) { + this.destPods = pods; + }, + setDestProcesses(processes: Array) { + this.destProcesses = processes; + }, async fetchLayers(): Promise { const res: AxiosResponse = await graphql.query("queryLayers").params({}); @@ -93,6 +113,27 @@ export const selectorStore = defineStore({ } return res.data; }, + async getProcesses(param?: { + instanceId: string; + isRelation: boolean; + }): Promise> { + const instanceId = param ? param.instanceId : this.currentPod?.id; + if (!instanceId) { + return null; + } + const res: AxiosResponse = await graphql.query("queryProcesses").params({ + instanceId, + duration: useAppStoreWithOut().durationTime, + }); + if (!res.data.errors) { + if (param && param.isRelation) { + this.destProcesses = res.data.data.processes || []; + return res.data; + } + this.processes = res.data.data.processes || []; + } + return res.data; + }, async getEndpoints(params: { keyword?: string; serviceId?: string; @@ -176,6 +217,25 @@ export const selectorStore = defineStore({ this.pods = [res.data.data.endpoint]; } + return res.data; + }, + async getProcess(instanceId: string, isRelation?: boolean) { + if (!instanceId) { + return; + } + const res: AxiosResponse = await graphql.query("queryProcess").params({ + instanceId, + }); + if (!res.data.errors) { + if (isRelation) { + this.currentDestProcess = res.data.data.process || null; + this.destProcesses = [res.data.data.process]; + return; + } + this.currentProcess = res.data.data.process || null; + this.processes = [res.data.data.process]; + } + return res.data; }, }, diff --git a/src/types/ebpf.d.ts b/src/types/ebpf.d.ts index 40852074..5dfca0ef 100644 --- a/src/types/ebpf.d.ts +++ b/src/types/ebpf.d.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { Process } from "./selector"; export interface EBPFTaskCreationRequest { serviceId: string; processLabels: string[]; @@ -43,18 +44,7 @@ export interface EBPFProfilingSchedule { startTime: number; } -export type Process = { - id: string; - name: string; - serviceId: string; - serviceName: string; - instanceId: string; - instanceName: string; - agentId: string; - detectType: string; - attributes: { name: string; value: string }[]; - labels: string[]; -}; +export type Process = Process; export type StackElement = { id: string; originId: string; @@ -75,3 +65,13 @@ export type AnalyzationTrees = { dumpCount: number; stackType: string; }; +export type ProcessNode = { + id: string; + name: string; + serviceId: string; + serviceName: string; + serviceInstanceId: string; + serviceInstanceName: string; + name: string; + isReal: boolean; +}; diff --git a/src/types/selector.d.ts b/src/types/selector.d.ts index 293ef469..fe4dd163 100644 --- a/src/types/selector.d.ts +++ b/src/types/selector.d.ts @@ -46,3 +46,16 @@ export type Service = { layers: string[]; shortName: string; }; + +export type Process = { + id: string; + name: string; + serviceId: string; + serviceName: string; + instanceId: string; + instanceName: string; + agentId: string; + detectType: string; + attributes: { name: string; value: string }[]; + labels: string[]; +}; diff --git a/src/views/dashboard/configuration/TimeRange.vue b/src/views/dashboard/configuration/TimeRange.vue new file mode 100644 index 00000000..13a493c1 --- /dev/null +++ b/src/views/dashboard/configuration/TimeRange.vue @@ -0,0 +1,161 @@ + + + + diff --git a/src/views/dashboard/configuration/index.ts b/src/views/dashboard/configuration/index.ts index 6d39f192..0055f828 100644 --- a/src/views/dashboard/configuration/index.ts +++ b/src/views/dashboard/configuration/index.ts @@ -19,10 +19,12 @@ import Text from "./Text.vue"; import Widget from "./Widget.vue"; import Topology from "./Topology.vue"; import Event from "./Event.vue"; +import TimeRange from "./TimeRange.vue"; export default { Text, Widget, Topology, Event, + TimeRange, }; diff --git a/src/views/dashboard/configuration/widget/metric/Index.vue b/src/views/dashboard/configuration/widget/metric/Index.vue index 3a63c062..233eb8a2 100644 --- a/src/views/dashboard/configuration/widget/metric/Index.vue +++ b/src/views/dashboard/configuration/widget/metric/Index.vue @@ -179,12 +179,16 @@ const setVisTypes = computed(() => { async function setMetricType(chart?: any) { const g = chart || dashboardStore.selectedGrid.graph || {}; - const json = await dashboardStore.fetchMetricList(); - if (json.errors) { - ElMessage.error(json.errors); - return; + let arr: any[] = states.metricList; + if (!chart) { + const json = await dashboardStore.fetchMetricList(); + if (json.errors) { + ElMessage.error(json.errors); + return; + } + arr = json.data.metrics; } - states.metricList = (json.data.metrics || []).filter( + states.metricList = (arr || []).filter( (d: { catalog: string; type: string }) => { if (states.isList) { if (d.type === MetricsType.REGULAR_VALUE) { diff --git a/src/views/dashboard/controls/Tab.vue b/src/views/dashboard/controls/Tab.vue index 370b28a5..2188862e 100644 --- a/src/views/dashboard/controls/Tab.vue +++ b/src/views/dashboard/controls/Tab.vue @@ -110,16 +110,8 @@ import { useRoute } from "vue-router"; import type { PropType } from "vue"; import { LayoutConfig } from "@/types/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard"; -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"; -import Text from "./Text.vue"; -import Ebpf from "./Ebpf.vue"; -import Event from "./Event.vue"; +import controls from "./tab"; import { dragIgnoreFrom } from "../data"; -import DemandLog from "./DemandLog.vue"; import copy from "@/utils/copy"; const props = { @@ -132,15 +124,7 @@ const props = { export default defineComponent({ name: "Tab", components: { - Topology, - Widget, - Trace, - Profile, - Log, - Text, - Ebpf, - DemandLog, - Event, + ...controls, }, props, setup(props) { diff --git a/src/views/dashboard/controls/TimeRange.vue b/src/views/dashboard/controls/TimeRange.vue new file mode 100644 index 00000000..8832f9c6 --- /dev/null +++ b/src/views/dashboard/controls/TimeRange.vue @@ -0,0 +1,187 @@ + + + + diff --git a/src/views/dashboard/controls/Widget.vue b/src/views/dashboard/controls/Widget.vue index c1653891..ec582664 100644 --- a/src/views/dashboard/controls/Widget.vue +++ b/src/views/dashboard/controls/Widget.vue @@ -213,7 +213,10 @@ export default defineComponent({ watch( () => [selectorStore.currentPod, selectorStore.currentDestPod], () => { - if (dashboardStore.entity === EntityType[0].value) { + if ( + dashboardStore.entity === EntityType[0].value || + dashboardStore.entity === EntityType[7].value + ) { return; } if (isList.value) { @@ -222,6 +225,14 @@ export default defineComponent({ queryMetrics(); } ); + watch( + () => [selectorStore.currentProcess, selectorStore.currentDestProcess], + () => { + if (dashboardStore.entity === EntityType[7].value) { + queryMetrics(); + } + } + ); watch( () => appStore.durationTime, () => { diff --git a/src/views/dashboard/controls/index.ts b/src/views/dashboard/controls/index.ts index 8130b98c..4c7754b1 100644 --- a/src/views/dashboard/controls/index.ts +++ b/src/views/dashboard/controls/index.ts @@ -24,6 +24,7 @@ import Text from "./Text.vue"; import Ebpf from "./Ebpf.vue"; import DemandLog from "./DemandLog.vue"; import Event from "./Event.vue"; +import TimeRange from "./TimeRange.vue"; export default { Tab, @@ -36,4 +37,5 @@ export default { Ebpf, DemandLog, Event, + TimeRange, }; diff --git a/src/views/dashboard/controls/tab.ts b/src/views/dashboard/controls/tab.ts new file mode 100644 index 00000000..07f07abf --- /dev/null +++ b/src/views/dashboard/controls/tab.ts @@ -0,0 +1,39 @@ +/** + * 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 Topology from "./Topology.vue"; +import Widget from "./Widget.vue"; +import Trace from "./Trace.vue"; +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"; +import Event from "./Event.vue"; +import TimeRange from "./TimeRange.vue"; + +export default { + Widget, + Trace, + Topology, + Profile, + Log, + Text, + Ebpf, + DemandLog, + Event, + TimeRange, +}; diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index de15ef0e..5e68d848 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -159,6 +159,7 @@ export const EntityType = [ key: 4, }, { value: "EndpointRelation", label: "Endpoint Relation", key: 4 }, + { value: "ProcessRelation", label: "Process Relation", key: 5 }, ]; export const ListEntity: any = { InstanceList: EntityType[3].value, @@ -207,6 +208,12 @@ export const EndpointTools = [ { name: "assignment", content: "Add Log", id: "addLog" }, { name: "event", content: "Add Event", id: "addEvent" }, ]; +export const ProcessTools = [ + { name: "playlist_add", content: "Add Widget", id: "addWidget" }, + { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, + { name: "time_range", content: "Add Time Range Text", id: "addTimeRange" }, +]; export const ServiceRelationTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, diff --git a/src/views/dashboard/graphs/topology.ts b/src/views/dashboard/graphs/topology.ts new file mode 100644 index 00000000..0b576ce2 --- /dev/null +++ b/src/views/dashboard/graphs/topology.ts @@ -0,0 +1,32 @@ +/** + * 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 Area from "./Area.vue"; +import Line from "./Line.vue"; +import Bar from "./Bar.vue"; +import TopList from "./TopList.vue"; +import Table from "./Table.vue"; +import Card from "./Card.vue"; + +export default { + Line, + Bar, + TopList, + Area, + Table, + Card, +}; diff --git a/src/views/dashboard/panel/Tool.vue b/src/views/dashboard/panel/Tool.vue index b240b93d..87b483d3 100644 --- a/src/views/dashboard/panel/Tool.vue +++ b/src/views/dashboard/panel/Tool.vue @@ -14,72 +14,98 @@ See the License for the specific language governing permissions and limitations under the License. -->