diff --git a/commitlint.config.js b/commitlint.config.js index d5861f6b..6da72baa 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -44,6 +44,7 @@ module.exports = { "workflow", "types", "release", + "merge", ], ], }, diff --git a/src/components/Tags.vue b/src/components/Tags.vue new file mode 100644 index 00000000..90fb670c --- /dev/null +++ b/src/components/Tags.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/components/index.ts b/src/components/index.ts index 607c7ce7..2992ee49 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -21,6 +21,7 @@ import Selector from "./Selector.vue"; import Graph from "./Graph.vue"; import Radio from "./Radio.vue"; import SelectSingle from "./SelectSingle.vue"; +import Tags from "./Tags.vue"; import VueGridLayout from "vue-grid-layout"; const components: Indexable = { @@ -31,6 +32,7 @@ const components: Indexable = { Graph, Radio, SelectSingle, + Tags, }; const componentsName: string[] = Object.keys(components); diff --git a/src/hooks/useExpressionsProcessor.ts b/src/hooks/useExpressionsProcessor.ts index 6855696f..3ddf8662 100644 --- a/src/hooks/useExpressionsProcessor.ts +++ b/src/hooks/useExpressionsProcessor.ts @@ -15,13 +15,14 @@ * limitations under the License. */ import { RespFields } from "./data"; -import { ExpressionResultType } from "@/views/dashboard/data"; +import { EntityType, ExpressionResultType } from "@/views/dashboard/data"; import { ElMessage } from "element-plus"; import { useDashboardStore } from "@/store/modules/dashboard"; import { useSelectorStore } from "@/store/modules/selectors"; import { useAppStoreWithOut } from "@/store/modules/app"; import type { MetricConfigOpt } from "@/types/dashboard"; import type { Instance, Endpoint, Service } from "@/types/selector"; +import type { Node, Call } from "@/types/topology"; export async function useExpressionsQueryProcessor(config: Indexable) { function expressionsGraphqlPods() { @@ -312,3 +313,88 @@ export async function useExpressionsQueryPodsMetrics( return expressionParams; } + +export function useQueryTopologyExpressionsProcessor(metrics: string[], instances: (Call | Node)[]) { + const appStore = useAppStoreWithOut(); + const dashboardStore = useDashboardStore(); + + function getExpressionQuery() { + const conditions: { [key: string]: unknown } = { + duration: appStore.durationTime, + }; + const variables: string[] = [`$duration: Duration!`]; + const fragmentList = instances.map((d: any, index: number) => { + let serviceName; + let destServiceName; + let endpointName; + let serviceInstanceName; + let destServiceInstanceName; + let destEndpointName; + if (d.sourceObj && d.targetObj) { + // instances = Calls + serviceName = d.sourceObj.serviceName || d.sourceObj.name; + destServiceName = d.targetObj.serviceName || d.targetObj.name; + if (EntityType[4].value === dashboardStore.entity) { + serviceInstanceName = d.sourceObj.name; + destServiceInstanceName = d.targetObj.name; + } + if (EntityType[2].value === dashboardStore.entity) { + endpointName = d.sourceObj.name; + destEndpointName = d.targetObj.name; + } + } else { + // instances = Nodes + serviceName = d.serviceName || d.name; + if (EntityType[4].value === dashboardStore.entity) { + serviceInstanceName = d.name; + } + if (EntityType[2].value === dashboardStore.entity) { + endpointName = d.name; + } + } + const entity = { + serviceName, + normal: true, + serviceInstanceName, + endpointName, + destServiceName, + destNormal: destServiceName ? true : undefined, + destServiceInstanceName, + destEndpointName, + }; + variables.push(`$entity${index}: Entity!`); + conditions[`entity${index}`] = entity; + const f = metrics.map((name: string, idx: number) => { + if (index === 0) { + variables.push(`$expression${idx}: String!`); + conditions[`expression${idx}`] = name; + } + return `expression${index}${idx}: execExpression(expression: $expression${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`; + }); + return f; + }); + const fragment = fragmentList.flat(1).join(" "); + const queryStr = `query queryData(${variables}) {${fragment}}`; + + return { queryStr, conditions }; + } + function handleExpressionValues(resp: { [key: string]: any }) { + const obj: any = {}; + for (let idx = 0; idx < instances.length; idx++) { + for (let index = 0; index < metrics.length; index++) { + const k = "expression" + idx + index; + if (metrics[index]) { + if (!obj[metrics[index]]) { + obj[metrics[index]] = { + values: [], + }; + } + obj[metrics[index]].values.push({ value: resp[k].results[0].values[0].value, id: instances[idx].id }); + } + } + } + return obj; + } + + return { getExpressionQuery, handleExpressionValues }; +} diff --git a/src/layout/components/NavBar.vue b/src/layout/components/NavBar.vue index 26a0285e..43202ed5 100644 --- a/src/layout/components/NavBar.vue +++ b/src/layout/components/NavBar.vue @@ -14,7 +14,31 @@ See the License for the specific language governing permissions and limitations under the License. --> diff --git a/src/views/components/ConditionTags.vue b/src/views/components/ConditionTags.vue index f62629c2..9d33d104 100644 --- a/src/views/components/ConditionTags.vue +++ b/src/views/components/ConditionTags.vue @@ -71,7 +71,7 @@ limitations under the License. --> import { ElMessage } from "element-plus"; import { useAppStoreWithOut } from "@/store/modules/app"; - /*global defineEmits, defineProps */ + /*global defineEmits, defineProps, Recordable */ const emit = defineEmits(["update"]); const props = defineProps({ type: { type: String, default: "TRACE" }, @@ -118,7 +118,7 @@ limitations under the License. --> emit("update", { tagsMap, tagsList: tagsList.value }); } async function fetchTagKeys() { - let resp: any = {}; + let resp: Recordable = {}; if (props.type === "TRACE") { resp = await traceStore.getTagKeys(); } else { @@ -137,7 +137,7 @@ limitations under the License. --> async function fetchTagValues() { const param = tags.value.split("=")[0]; - let resp: any = {}; + let resp: Recordable = {}; if (props.type === "TRACE") { resp = await traceStore.getTagValues(param); } else { diff --git a/src/views/components/style.scss b/src/views/components/style.scss deleted file mode 100644 index 179e9fb1..00000000 --- a/src/views/components/style.scss +++ /dev/null @@ -1,115 +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. - */ - -.timeline-table { - padding: 30px 20px 20px 40px; - flex-grow: 1; - overflow: auto; - height: 100%; -} - -.time-line { - padding: 14px 30px; - min-height: 63px; - max-width: 132px; -} - -.timeline-table-i { - padding: 10px 15px; - border-left: 4px solid #eee; - position: relative; - - &::after { - content: ""; - display: inline-block; - position: absolute; - width: 7px; - height: 7px; - left: -23px; - top: 25px; - border-radius: 4px; - background-color: #448dfe; - } - - &::before { - content: ""; - display: inline-block; - position: absolute; - width: 1px; - height: calc(100% + 11px); - top: 0; - left: -20px; - border-radius: 5px; - background-color: #448dfe99; - } -} - -.timeline-table-i-scope { - display: inline-block; - padding: 0 8px; - border: 1px solid; - margin-top: -1px; - border-radius: 4px; -} - -.timeline-item { - cursor: pointer; - margin-bottom: 9px; -} - -.alarm-detail { - max-height: 600px; - overflow: auto; - - ul { - min-height: 100px; - overflow: auto; - margin-bottom: 20px; - } - - li { - cursor: pointer; - - > span { - width: 160px; - height: 20px; - line-height: 20px; - text-align: center; - display: inline-block; - border-bottom: 1px solid $disabled-color; - overflow: hidden; - } - } -} - -.keys { - font-weight: bold; - display: inline-block; - width: 120px; -} - -.source > span { - display: inline-block; -} - -.source > div { - padding-left: 120px; -} - -.uuid { - width: 280px; -} diff --git a/src/views/dashboard/Edit.vue b/src/views/dashboard/Edit.vue index 88cf5c8f..3d6d523a 100644 --- a/src/views/dashboard/Edit.vue +++ b/src/views/dashboard/Edit.vue @@ -41,13 +41,12 @@ limitations under the License. -->