mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-02 18:04:54 +00:00
feat: enhance associating metrics with traces by refId
(#192)
This commit is contained in:
parent
7a1c83b5fb
commit
23e9742946
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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 = {
|
||||||
|
@ -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" },
|
||||||
|
];
|
||||||
|
@ -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 },
|
||||||
],
|
],
|
||||||
|
@ -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,
|
||||||
<span v-if="key !== 'duration'">
|
FiltersKeys.maxTraceDuration,
|
||||||
|
].includes(key) && !isNaN(traceStore.conditions[FiltersKeys[key]])
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ 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>
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user