From eda44db0cd97f0035a9195b20f1907bcb26f3708 Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Tue, 25 Oct 2022 11:36:49 +0800 Subject: [PATCH] feat: associate metrics with trace widget on dashboards (#174) --- src/assets/icons/conditions.svg | 16 ++ src/assets/icons/copy.svg | 15 + src/assets/icons/info_outline.svg | 1 - src/assets/icons/operation.svg | 15 + src/components/Graph.vue | 155 ++++++---- src/graphql/query/selector.ts | 2 +- src/hooks/useAssociateProcessor.ts | 138 +++++++++ src/locales/lang/en.ts | 13 +- src/locales/lang/es.ts | 11 + src/locales/lang/zh.ts | 11 + src/router/data/general.ts | 2 +- src/store/modules/app.ts | 17 +- src/store/modules/trace.ts | 35 ++- src/styles/index.ts | 1 + src/styles/reset.scss | 8 + src/types/app.d.ts | 15 + src/types/components.d.ts | 1 + src/types/dashboard.d.ts | 38 ++- src/views/dashboard/configuration/Widget.vue | 8 + .../widget/RelatedTraceOptions.vue | 90 ++++++ .../dashboard/configuration/widget/index.ts | 2 + src/views/dashboard/controls/Tab.vue | 2 +- src/views/dashboard/controls/Widget.vue | 1 + src/views/dashboard/data.ts | 16 +- src/views/dashboard/graphs/Area.vue | 18 +- src/views/dashboard/graphs/Bar.vue | 36 +-- src/views/dashboard/graphs/Line.vue | 47 +-- src/views/dashboard/graphs/TopList.vue | 81 +++++- src/views/dashboard/related/trace/Detail.vue | 9 +- src/views/dashboard/related/trace/Filter.vue | 95 ++++--- src/views/dashboard/related/trace/Header.vue | 267 ++++++++++++++++++ src/views/dashboard/related/trace/Index.vue | 63 +++++ .../dashboard/related/trace/TraceList.vue | 4 +- 33 files changed, 1041 insertions(+), 192 deletions(-) create mode 100644 src/assets/icons/conditions.svg create mode 100644 src/assets/icons/copy.svg create mode 100644 src/assets/icons/operation.svg create mode 100644 src/hooks/useAssociateProcessor.ts create mode 100644 src/views/dashboard/configuration/widget/RelatedTraceOptions.vue create mode 100644 src/views/dashboard/related/trace/Header.vue create mode 100644 src/views/dashboard/related/trace/Index.vue diff --git a/src/assets/icons/conditions.svg b/src/assets/icons/conditions.svg new file mode 100644 index 00000000..25c14508 --- /dev/null +++ b/src/assets/icons/conditions.svg @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/src/assets/icons/copy.svg b/src/assets/icons/copy.svg new file mode 100644 index 00000000..bec007c6 --- /dev/null +++ b/src/assets/icons/copy.svg @@ -0,0 +1,15 @@ + + \ No newline at end of file diff --git a/src/assets/icons/info_outline.svg b/src/assets/icons/info_outline.svg index c9a2b468..3ba1c393 100644 --- a/src/assets/icons/info_outline.svg +++ b/src/assets/icons/info_outline.svg @@ -13,6 +13,5 @@ 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. --> -info_outline diff --git a/src/assets/icons/operation.svg b/src/assets/icons/operation.svg new file mode 100644 index 00000000..0fb8c0bd --- /dev/null +++ b/src/assets/icons/operation.svg @@ -0,0 +1,15 @@ + + \ No newline at end of file diff --git a/src/components/Graph.vue b/src/components/Graph.vue index 200cb1d8..5bc8974e 100644 --- a/src/components/Graph.vue +++ b/src/components/Graph.vue @@ -15,6 +15,27 @@ limitations under the License. --> + diff --git a/src/views/dashboard/configuration/widget/index.ts b/src/views/dashboard/configuration/widget/index.ts index 437b5fa1..e414dbc4 100644 --- a/src/views/dashboard/configuration/widget/index.ts +++ b/src/views/dashboard/configuration/widget/index.ts @@ -19,10 +19,12 @@ import StyleOptions from "./graph-styles"; import WidgetOptions from "./WidgetOptions.vue"; import MetricOptions from "./metric/Index.vue"; import AssociateOptions from "./AssociateOptions.vue"; +import RelatedTraceOptions from "./RelatedTraceOptions.vue"; export default { ...StyleOptions, WidgetOptions, MetricOptions, AssociateOptions, + RelatedTraceOptions, }; diff --git a/src/views/dashboard/controls/Tab.vue b/src/views/dashboard/controls/Tab.vue index a643ada9..58952e2f 100644 --- a/src/views/dashboard/controls/Tab.vue +++ b/src/views/dashboard/controls/Tab.vue @@ -40,7 +40,7 @@ limitations under the License. --> - + diff --git a/src/views/dashboard/controls/Widget.vue b/src/views/dashboard/controls/Widget.vue index 6d986f2e..f723984d 100644 --- a/src/views/dashboard/controls/Widget.vue +++ b/src/views/dashboard/controls/Widget.vue @@ -64,6 +64,7 @@ limitations under the License. --> id: data.id, metricConfig: data.metricConfig, filters: data.filters || {}, + relatedTrace: data.relatedTrace || {}, }" :needQuery="needQuery" @click="clickHandle" diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index 540c3171..534aeea6 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -174,7 +174,7 @@ export const SortOrder = [ ]; export const AllTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, - { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "merge", content: "Add Trace", id: "addTrace" }, @@ -182,7 +182,7 @@ export const AllTools = [ ]; export const ServiceTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, - { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "merge", content: "Add Trace", id: "addTrace" }, @@ -194,7 +194,7 @@ export const ServiceTools = [ ]; export const InstanceTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, - { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "library_books", content: "Add Text", id: "addText" }, { name: "merge", content: "Add Trace", id: "addTrace" }, { name: "assignment", content: "Add Log", id: "addLog" }, @@ -208,7 +208,7 @@ export const InstanceTools = [ ]; export const EndpointTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, - { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "merge", content: "Add Trace", id: "addTrace" }, @@ -217,25 +217,25 @@ export const EndpointTools = [ ]; export const ProcessTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, - { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "all_inbox", content: "Add Tabs", 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" }, + { name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, ]; export const EndpointRelationTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, - { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "library_books", content: "Add Text", id: "addText" }, ]; export const InstanceRelationTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, - { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "all_inbox", content: "Add Tabs", id: "addTab" }, { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, ]; diff --git a/src/views/dashboard/graphs/Area.vue b/src/views/dashboard/graphs/Area.vue index 66c1fb46..46927f91 100644 --- a/src/views/dashboard/graphs/Area.vue +++ b/src/views/dashboard/graphs/Area.vue @@ -24,7 +24,12 @@ limitations under the License. --> diff --git a/src/views/dashboard/related/trace/Detail.vue b/src/views/dashboard/related/trace/Detail.vue index d00574e1..d195a055 100644 --- a/src/views/dashboard/related/trace/Detail.vue +++ b/src/views/dashboard/related/trace/Detail.vue @@ -34,7 +34,7 @@ limitations under the License. --> -
+
- +
diff --git a/src/views/dashboard/related/trace/Filter.vue b/src/views/dashboard/related/trace/Filter.vue index d10e896d..fd9c369c 100644 --- a/src/views/dashboard/related/trace/Filter.vue +++ b/src/views/dashboard/related/trace/Filter.vue @@ -95,17 +95,15 @@ limitations under the License. --> import { ref, reactive, watch, onUnmounted } from "vue"; import type { PropType } from "vue"; import { useI18n } from "vue-i18n"; -import { Option } from "@/types/app"; -import { Status } from "../../data"; +import { Option, DurationTime } from "@/types/app"; import { useTraceStore } from "@/store/modules/trace"; import { useDashboardStore } from "@/store/modules/dashboard"; import { useAppStoreWithOut } from "@/store/modules/app"; import { useSelectorStore } from "@/store/modules/selectors"; import ConditionTags from "@/views/components/ConditionTags.vue"; import { ElMessage } from "element-plus"; -import { EntityType } from "../../data"; +import { EntityType, QueryOrders, Status } from "../../data"; import { LayoutConfig } from "@/types/dashboard"; -import { DurationTime } from "@/types/app"; /*global defineProps, Recordable */ const props = defineProps({ @@ -115,28 +113,29 @@ const props = defineProps({ default: () => ({ graph: {} }), }, }); -const traceId = ref( - (props.data.filters && props.data.filters.traceId) || "" -); +const filters = reactive(props.data.filters || {}); +const traceId = ref(filters.traceId || ""); const { t } = useI18n(); const appStore = useAppStoreWithOut(); const selectorStore = useSelectorStore(); const dashboardStore = useDashboardStore(); const traceStore = useTraceStore(); -const duration = ref( - (props.data.filters && props.data.filters.duration) || appStore.durationTime -); +const duration = ref(filters.duration || appStore.durationTime); const minTraceDuration = ref(); const maxTraceDuration = ref(); const tagsList = ref([]); const tagsMap = ref([]); const state = reactive({ - status: { label: "All", value: "ALL" }, + status: filters.status === "ERROR" ? Status[2] : Status[0], instance: { value: "0", label: "All" }, endpoint: { value: "0", label: "All" }, service: { value: "", label: "" }, }); - +if (filters.queryOrder) { + traceStore.setTraceCondition({ + queryOrder: filters.queryOrder, + }); +} if (props.needQuery) { init(); } @@ -164,7 +163,7 @@ async function getServices() { ElMessage.error(resp.errors); return; } - state.service = traceStore.services[0]; + state.service = getCurrentNode(traceStore.services) || traceStore.services[0]; getEndpoints(state.service.id); getInstances(state.service.id); } @@ -175,7 +174,8 @@ async function getEndpoints(id?: string, keyword?: string) { ElMessage.error(resp.errors); return; } - state.endpoint = traceStore.endpoints[0]; + state.endpoint = + getCurrentNode(traceStore.endpoints) || traceStore.endpoints[0]; } async function getInstances(id?: string) { const resp = await traceStore.getInstances(id); @@ -183,9 +183,39 @@ async function getInstances(id?: string) { ElMessage.error(resp.errors); return; } - state.instance = traceStore.instances[0]; + state.instance = + getCurrentNode(traceStore.instances) || traceStore.instances[0]; } -function searchTraces() { +function getCurrentNode(arr: { id: string }[]) { + let item; + if (!props.data.filters) { + return item; + } + if (props.data.filters.id) { + item = arr.find((d: { id: string }) => d.id === props.data.filters?.id); + } + return item; +} +function setCondition() { + let param: any = { + traceState: state.status.value || "ALL", + tags: tagsMap.value.length ? tagsMap.value : undefined, + queryOrder: traceStore.conditions.queryOrder || QueryOrders[1].value, + queryDuration: duration.value, + minTraceDuration: Number(minTraceDuration.value), + maxTraceDuration: Number(maxTraceDuration.value), + traceId: traceId.value || undefined, + paging: { pageNum: 1, pageSize: 20 }, + }; + if (props.data.filters && props.data.filters.id) { + param = { + ...param, + serviceId: selectorStore.currentService.id, + endpointId: state.endpoint.id || undefined, + serviceInstanceId: state.instance.id || undefined, + }; + return param; + } let endpoint = "", instance = ""; if (dashboardStore.entity === EntityType[2].value) { @@ -194,21 +224,18 @@ function searchTraces() { if (dashboardStore.entity === EntityType[3].value) { instance = selectorStore.currentPod.id; } - traceStore.setTraceCondition({ + param = { + ...param, serviceId: selectorStore.currentService ? selectorStore.currentService.id : state.service.id, - traceId: traceId.value || undefined, endpointId: endpoint || state.endpoint.id || undefined, serviceInstanceId: instance || state.instance.id || undefined, - traceState: state.status.value || "ALL", - queryDuration: duration.value, - minTraceDuration: Number(minTraceDuration.value), - maxTraceDuration: Number(maxTraceDuration.value), - queryOrder: traceStore.conditions.queryOrder || "BY_DURATION", - tags: tagsMap.value.length ? tagsMap.value : undefined, - paging: { pageNum: 1, pageSize: 20 }, - }); + }; + return param; +} +function searchTraces() { + traceStore.setTraceCondition(setCondition()); queryTraces(); } async function queryTraces() { @@ -263,17 +290,19 @@ watch( } } ); +// Event widget associate with trace widget watch( () => props.data.filters, (newJson, oldJson) => { - if (props.data.filters) { - if (JSON.stringify(newJson) === JSON.stringify(oldJson)) { - return; - } - traceId.value = props.data.filters.traceId || ""; - duration.value = props.data.filters.duration || appStore.durationTime; - init(); + if (!props.data.filters) { + return; } + if (JSON.stringify(newJson) === JSON.stringify(oldJson)) { + return; + } + traceId.value = props.data.filters.traceId || ""; + duration.value = props.data.filters.duration || appStore.durationTime; + init(); } ); diff --git a/src/views/dashboard/related/trace/Header.vue b/src/views/dashboard/related/trace/Header.vue new file mode 100644 index 00000000..ac735b2d --- /dev/null +++ b/src/views/dashboard/related/trace/Header.vue @@ -0,0 +1,267 @@ + + + + diff --git a/src/views/dashboard/related/trace/Index.vue b/src/views/dashboard/related/trace/Index.vue new file mode 100644 index 00000000..72b1bedc --- /dev/null +++ b/src/views/dashboard/related/trace/Index.vue @@ -0,0 +1,63 @@ + + + + diff --git a/src/views/dashboard/related/trace/TraceList.vue b/src/views/dashboard/related/trace/TraceList.vue index aa36e106..8b964777 100644 --- a/src/views/dashboard/related/trace/TraceList.vue +++ b/src/views/dashboard/related/trace/TraceList.vue @@ -58,8 +58,8 @@ limitations under the License. --> {{ i.endpointNames[0] }}
- {{ i.duration }} ms{{ dateFormat(parseInt(i.start, 10)) }} + {{ i.duration }} ms + {{ dateFormat(parseInt(i.start, 10)) }}