feat: enhance associating metrics with traces by refId (#192)

This commit is contained in:
Fine0830 2022-11-25 17:33:51 +08:00 committed by GitHub
parent 7a1c83b5fb
commit 23e9742946
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 42 deletions

View File

@ -124,7 +124,7 @@ export default defineComponent({
const title = computed(() => encodeURIComponent(widget.value.title || "")); const title = computed(() => encodeURIComponent(widget.value.title || ""));
const tips = computed(() => encodeURIComponent(widget.value.tips || "")); const tips = computed(() => encodeURIComponent(widget.value.tips || ""));
const hasAssociate = computed(() => const hasAssociate = computed(() =>
["Bar", "Line", "Area"].includes( ["Bar", "Line", "Area", "TopList"].includes(
dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph &&
dashboardStore.selectedGrid.graph.type dashboardStore.selectedGrid.graph.type
) )

View File

@ -13,7 +13,18 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div class="item"> <div v-if="type === 'TopList'" class="item">
<span class="label">RefId</span>
<Selector
size="small"
:value="refIdType"
:options="RefIdTypes"
placeholder="Select a refId"
@change="updateConfig({ refIdType: $event[0].value })"
class="selector"
/>
</div>
<div v-else class="item">
<span class="label">{{ t("enableRelatedTrace") }}</span> <span class="label">{{ t("enableRelatedTrace") }}</span>
<el-switch <el-switch
v-model="enableRelate" v-model="enableRelate"
@ -22,7 +33,7 @@ limitations under the License. -->
@change="updateConfig({ enableRelate })" @change="updateConfig({ enableRelate })"
/> />
</div> </div>
<div v-show="enableRelate"> <div v-if="enableRelate">
<div class="item"> <div class="item">
<span class="label">{{ t("status") }}</span> <span class="label">{{ t("status") }}</span>
<Selector <Selector
@ -60,15 +71,18 @@ limitations under the License. -->
import { ref } from "vue"; import { ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { Status, QueryOrders } from "../../data"; import { Status, QueryOrders, RefIdTypes } from "../../data";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const traceOpt = dashboardStore.selectedGrid.relatedTrace || {}; const { graph, relatedTrace } = dashboardStore.selectedGrid;
const traceOpt = (relatedTrace && relatedTrace.traceOpt) || {};
const status = ref<string>(traceOpt.status || Status[0].value); const status = ref<string>(traceOpt.status || Status[0].value);
const queryOrder = ref<string>(traceOpt.queryOrder || QueryOrders[0].value); const queryOrder = ref<string>(traceOpt.queryOrder || QueryOrders[0].value);
const latency = ref<boolean>(traceOpt.latency || false); const latency = ref<boolean>(traceOpt.latency || false);
const enableRelate = ref<boolean>(traceOpt.enableRelate || false); const enableRelate = ref<boolean>(traceOpt.enableRelate || false);
const type = ref<string>((graph && graph.type) || "");
const refIdType = ref<string>(traceOpt.refIdType || "traceId");
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const relatedTrace = { const relatedTrace = {

View File

@ -298,3 +298,7 @@ export const CalculationOpts = [
{ label: "Seconds to days", value: "secondToDay" }, { label: "Seconds to days", value: "secondToDay" },
{ label: "Nanoseconds to milliseconds", value: "nanosecondToMillisecond" }, { label: "Nanoseconds to milliseconds", value: "nanosecondToMillisecond" },
]; ];
export const RefIdTypes = [
{ label: "Trace ID", value: "traceId" },
{ label: "None", value: "none" },
];

View File

@ -32,7 +32,11 @@ limitations under the License. -->
<div class="operation" @click="handleClick(i.name)"> <div class="operation" @click="handleClick(i.name)">
<span>{{ t("copy") }}</span> <span>{{ t("copy") }}</span>
</div> </div>
<div class="operation" @click="viewTrace(i)"> <div
class="operation"
@click="viewTrace(i)"
v-show="refIdType === RefIdTypes[0].value"
>
<span>{{ t("viewTrace") }}</span> <span>{{ t("viewTrace") }}</span>
</div> </div>
</el-popover> </el-popover>
@ -63,7 +67,7 @@ import { computed, ref } from "vue";
import copy from "@/utils/copy"; import copy from "@/utils/copy";
import { TextColors } from "@/views/dashboard/data"; import { TextColors } from "@/views/dashboard/data";
import Trace from "@/views/dashboard/related/trace/Index.vue"; import Trace from "@/views/dashboard/related/trace/Index.vue";
import { QueryOrders, Status } from "../data"; import { QueryOrders, Status, RefIdTypes } from "../data";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
@ -73,7 +77,11 @@ const props = defineProps({
default: () => ({}), default: () => ({}),
}, },
config: { config: {
type: Object as PropType<{ color: string; metrics: string[] }>, type: Object as PropType<{
color: string;
metrics: string[];
relatedTrace: any;
}>,
default: () => ({ color: "purple" }), default: () => ({ color: "purple" }),
}, },
intervalTime: { type: Array as PropType<string[]>, default: () => [] }, intervalTime: { type: Array as PropType<string[]>, default: () => [] },
@ -83,6 +91,11 @@ const showTrace = ref<boolean>(false);
const traceOptions = ref<{ type: string; filters?: unknown }>({ const traceOptions = ref<{ type: string; filters?: unknown }>({
type: "Trace", type: "Trace",
}); });
const refIdType = computed(
() =>
(props.config.relatedTrace && props.config.relatedTrace.refIdType) ||
RefIdTypes[0].value
);
const key = computed(() => Object.keys(props.data)[0] || ""); const key = computed(() => Object.keys(props.data)[0] || "");
const available = computed( const available = computed(
() => () =>
@ -105,6 +118,7 @@ function viewTrace(item: { name: string; id: string; value: unknown }) {
...item, ...item,
queryOrder: QueryOrders[1].value, queryOrder: QueryOrders[1].value,
status: Status[2].value, status: Status[2].value,
id: item.id || item.name,
metricValue: [ metricValue: [
{ label: props.config.metrics[0], data: item.value, value: item.name }, { label: props.config.metrics[0], data: item.value, value: item.name },
], ],

View File

@ -13,7 +13,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div class="conditions flex-h"> <div v-if="filters.id" class="conditions flex-h">
<div class="label grey">TraceId:</div>
<el-input size="small" v-model="traceId" class="trace-id" />
</div>
<div class="conditions flex-h" v-else>
<el-radio-group v-model="conditions" @change="changeCondition"> <el-radio-group v-model="conditions" @change="changeCondition">
<el-radio-button <el-radio-button
v-for="(item, index) in items" v-for="(item, index) in items"
@ -40,12 +44,18 @@ limitations under the License. -->
</template> </template>
<div> <div>
<div class="title">{{ t("queryConditions") }}</div> <div class="title">{{ t("queryConditions") }}</div>
<div <div v-for="key in Object.keys(FiltersKeys)" :key="key">
v-for="key in Object.keys(FiltersKeys)" <span
:key="key" v-if="
v-show="traceStore.conditions[FiltersKeys[key]]" [
FiltersKeys.minTraceDuration,
FiltersKeys.maxTraceDuration,
].includes(key) && !isNaN(traceStore.conditions[FiltersKeys[key]])
"
> >
<span v-if="key !== 'duration'"> {{ t(key) }}: {{ traceStore.conditions[FiltersKeys[key]] }}
</span>
<span v-else-if="key !== 'duration'">
{{ t(key) }}: {{ traceStore.conditions[FiltersKeys[key]] }} {{ t(key) }}: {{ traceStore.conditions[FiltersKeys[key]] }}
</span> </span>
</div> </div>
@ -111,6 +121,7 @@ const dashboardStore = useDashboardStore();
const traceStore = useTraceStore(); const traceStore = useTraceStore();
const tagsList = ref<string[]>([]); const tagsList = ref<string[]>([]);
const tagsMap = ref<Option[]>([]); const tagsMap = ref<Option[]>([]);
const traceId = ref<string>(filters.refId || "");
const duration = ref<DurationTime>(filters.duration || appStore.durationTime); const duration = ref<DurationTime>(filters.duration || appStore.durationTime);
const state = reactive<Recordable>({ const state = reactive<Recordable>({
instance: "", instance: "",
@ -122,13 +133,13 @@ const items = ref<{ label: string; value: string }[]>([]);
const currentLatency = ref<number[]>( const currentLatency = ref<number[]>(
filters.latency ? filters.latency[0].data : [] filters.latency ? filters.latency[0].data : []
); );
init(); init();
async function init() { async function init() {
for (const d of Object.keys(filters)) { for (const d of Object.keys(filters)) {
if ( if (
["status", "queryOrder"].includes(d) || ["queryOrder"].includes(d) ||
(d === "status" && filters[d] && filters[d] !== "ALL") ||
(filters[d] && d === "latency") (filters[d] && d === "latency")
) { ) {
items.value.push({ label: d, value: FiltersKeys[d] }); items.value.push({ label: d, value: FiltersKeys[d] });
@ -199,20 +210,14 @@ function setCondition() {
traceState: Status[0].value, traceState: Status[0].value,
queryOrder: QueryOrders[0].value, queryOrder: QueryOrders[0].value,
queryDuration: duration.value, queryDuration: duration.value,
minTraceDuration: isNaN(currentLatency.value[0]) minTraceDuration: currentLatency.value[0],
? undefined maxTraceDuration: currentLatency.value[1],
: currentLatency.value[0] === currentLatency.value[1]
? currentLatency.value[0] - 10
: currentLatency.value[0],
maxTraceDuration:
isNaN(currentLatency.value[1]) || currentLatency.value[1] === Infinity
? undefined
: currentLatency.value[1],
tags: tagsMap.value.length ? tagsMap.value : undefined, tags: tagsMap.value.length ? tagsMap.value : undefined,
paging: { pageNum: 1, pageSize: 20 }, paging: { pageNum: 1, pageSize: 20 },
serviceId: state.service || undefined, serviceId: state.service || undefined,
endpointId: state.endpoint || undefined, endpointId: state.endpoint || undefined,
serviceInstanceId: state.instance || undefined, serviceInstanceId: state.instance || undefined,
traceId: traceId.value || undefined,
}; };
for (const k of items.value) { for (const k of items.value) {
if ( if (
@ -271,4 +276,13 @@ onUnmounted(() => {
margin-bottom: 10px; margin-bottom: 10px;
font-weight: bold; font-weight: bold;
} }
.trace-id {
width: 300px;
margin-left: 10px;
}
.label {
line-height: 22px;
}
</style> </style>

View File

@ -101,28 +101,41 @@ limitations under the License. -->
@closed="showEventDetail = false" @closed="showEventDetail = false"
> >
<div> <div>
<div>Name: {{ currentEvent.event || "" }}</div> <div class="mb-10">
<div> <span class="grey">Name:</span>
Start Time: {{ currentEvent.event || "" }}
</div>
<div class="mb-10">
<span class="grey">Start Time:</span>
{{ {{
currentEvent.startTime ? visDate(Number(currentEvent.startTime)) : "" currentEvent.startTime ? visDate(Number(currentEvent.startTime)) : ""
}} }}
</div> </div>
<div> <div class="mb-10">
End Time: <span class="grey">End Time:</span>
{{ currentEvent.endTime ? visDate(Number(currentEvent.endTime)) : "" }} {{ currentEvent.endTime ? visDate(Number(currentEvent.endTime)) : "" }}
</div> </div>
<div> <div class="mb-10">
Summary: <span class="grey">Summary:</span>
{{(currentEvent.summary || []) <div
.map((d: any) => d.key + "=" + d.value) class="mb-5"
.join("; ")}} v-for="(d, index) in currentEvent.summary || []"
:key="index"
style="white-space: pre-wrap"
>
{{ d.key + "=" + d.value }};
</div>
</div> </div>
<div> <div>
Tags: <span class="grey">Tags:</span>
{{(currentEvent.tags || []) <div
.map((d: any) => d.key + "=" + d.value) class="mb-5"
.join("; ")}} v-for="(tag, index) in currentEvent.tags || []"
:key="index"
style="white-space: pre-wrap"
>
{{ tag.key + "=" + tag.value }};
</div>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
@ -241,9 +254,7 @@ function visTimeline() {
width: "100%", width: "100%",
locale: "en", locale: "en",
groupHeightMode: "fitItems", groupHeightMode: "fitItems",
autoResize: false,
zoomMin: 80, zoomMin: 80,
zoomMax: 3600000,
}; };
visGraph.value = new Timeline(timeline.value, items, options); visGraph.value = new Timeline(timeline.value, items, options);