mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-10-15 04:09:14 +00:00
refactor: optimize data types for widgets and dashboards (#490)
This commit is contained in:
@@ -24,6 +24,7 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Dashboard from "./dashboard/Edit.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { DashboardItem } from "@/types/dashboard";
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
@@ -38,7 +39,7 @@ limitations under the License. -->
|
||||
dashboardStore.setMode(false);
|
||||
await dashboardStore.setDashboards();
|
||||
const item = dashboardStore.dashboards.find(
|
||||
(d: { name: string; isRoot: boolean; layer: string; entity: string }) =>
|
||||
(d: DashboardItem) =>
|
||||
d.layer === dashboardStore.layerId && [EntityType[0].value, EntityType[1].value].includes(d.entity) && d.isRoot,
|
||||
);
|
||||
if (!item) {
|
||||
|
@@ -87,7 +87,7 @@ limitations under the License. -->
|
||||
alarmStore.alarms.length === pageSize ? pageSize * pageNum.value + 1 : pageSize * pageNum.value,
|
||||
);
|
||||
const maxRange = computed(() =>
|
||||
getMaxRange(appStore.coldStageMode ? appStore.recordsTTL.coldNormal : appStore.recordsTTL.normal),
|
||||
getMaxRange(appStore.coldStageMode ? appStore.recordsTTL?.coldNormal || 0 : appStore.recordsTTL?.normal || 0),
|
||||
);
|
||||
|
||||
refreshAlarms({ pageNum: 1 });
|
||||
|
@@ -28,7 +28,7 @@ limitations under the License. -->
|
||||
:destroy-on-close="true"
|
||||
@closed="dashboardStore.setConfigPanel(false)"
|
||||
>
|
||||
<component :is="dashboardStore.selectedGrid.type" />
|
||||
<component :is="dashboardStore.selectedGrid?.type" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="dashboardStore.showLinkConfig"
|
||||
@@ -77,9 +77,9 @@ limitations under the License. -->
|
||||
dashboardStore.setLayout(setWidgetsID(layout.children || []));
|
||||
if (p.entity) {
|
||||
dashboardStore.setCurrentDashboard({
|
||||
layer: p.layerId,
|
||||
entity: p.entity,
|
||||
name: p.name,
|
||||
layer: p.layerId as string,
|
||||
entity: p.entity as string,
|
||||
name: p.name as string,
|
||||
id: c.id,
|
||||
isRoot: layout.isRoot,
|
||||
});
|
||||
@@ -112,7 +112,7 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
dashboardStore.setCurrentDashboard({});
|
||||
dashboardStore.setCurrentDashboard(null);
|
||||
});
|
||||
|
||||
return {
|
||||
|
@@ -578,14 +578,17 @@ limitations under the License. -->
|
||||
name: value,
|
||||
});
|
||||
dashboards.value = dashboardStore.dashboards.map((item: DashboardItem) => {
|
||||
if (dashboardStore.currentDashboard.id === item.id) {
|
||||
item = dashboardStore.currentDashboard;
|
||||
if (dashboardStore.currentDashboard?.id === item.id) {
|
||||
item = dashboardStore.currentDashboard as DashboardItem;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
dashboardStore.resetDashboards(dashboards.value);
|
||||
sessionStorage.setItem("dashboards", JSON.stringify(dashboards.value));
|
||||
sessionStorage.removeItem(key);
|
||||
if (!dashboardStore.currentDashboard) {
|
||||
return;
|
||||
}
|
||||
const str = [
|
||||
dashboardStore.currentDashboard.layer,
|
||||
dashboardStore.currentDashboard.entity,
|
||||
|
@@ -81,8 +81,8 @@ limitations under the License. -->
|
||||
|
||||
init();
|
||||
async function init() {
|
||||
dashboardStore.setLayer(route.params.layer);
|
||||
dashboardStore.setEntity(route.params.entity);
|
||||
dashboardStore.setLayer(route.params.layer as string);
|
||||
dashboardStore.setEntity(route.params.entity as string);
|
||||
const { auto, autoPeriod } = config.value;
|
||||
if (auto) {
|
||||
await setDuration();
|
||||
@@ -102,30 +102,30 @@ limitations under the License. -->
|
||||
async function setSelector() {
|
||||
const { serviceId, podId, processId, destServiceId, destPodId, destProcessId, entity } = route.params;
|
||||
if (serviceId) {
|
||||
await selectorStore.getService(serviceId);
|
||||
await selectorStore.getService(serviceId as string);
|
||||
}
|
||||
if (
|
||||
[EntityType[4].value, EntityType[5].value, EntityType[6].value, EntityType[7].value].includes(
|
||||
entity as string,
|
||||
)
|
||||
) {
|
||||
await selectorStore.getService(destServiceId, true);
|
||||
await selectorStore.getService(destServiceId as string, true);
|
||||
}
|
||||
if ([EntityType[3].value, EntityType[5].value, EntityType[7].value].includes(entity as string)) {
|
||||
await selectorStore.getInstance(podId);
|
||||
await selectorStore.getInstance(podId as string);
|
||||
}
|
||||
if ([EntityType[2].value, EntityType[6].value].includes(entity as string)) {
|
||||
await selectorStore.getEndpoint(podId);
|
||||
await selectorStore.getEndpoint(podId as string);
|
||||
}
|
||||
if (EntityType[6].value === entity) {
|
||||
await selectorStore.getEndpoint(destPodId, true);
|
||||
await selectorStore.getEndpoint(destPodId as string, true);
|
||||
}
|
||||
if ([EntityType[5].value, EntityType[7].value].includes(entity as string)) {
|
||||
await selectorStore.getInstance(destPodId, true);
|
||||
await selectorStore.getInstance(destPodId as string, true);
|
||||
}
|
||||
if (EntityType[7].value === entity) {
|
||||
selectorStore.getProcess(processId);
|
||||
selectorStore.getProcess(destProcessId, true);
|
||||
selectorStore.getProcess(processId as string);
|
||||
selectorStore.getProcess(destProcessId as string, true);
|
||||
}
|
||||
}
|
||||
async function queryMetrics() {
|
||||
|
@@ -25,15 +25,15 @@ limitations under the License. -->
|
||||
<div v-else>
|
||||
<label>{{ t("auto") }}</label>
|
||||
<el-switch class="mr-5" v-model="auto" style="height: 25px" />
|
||||
<Selector v-model="freshOpt" :options="RefreshOptions" size="small" />
|
||||
<Selector style="width: 200px" v-model="freshOpt" :options="RefreshOptions" />
|
||||
<div class="mt-5">
|
||||
<label>{{ t("period") }}</label>
|
||||
<el-input class="auto-period" size="small" type="number" v-model="period" min="1" />
|
||||
<el-input class="auto-period" type="number" v-model="period" min="1" />
|
||||
<span class="ml-5">{{ t("second") }}</span>
|
||||
<i class="ml-10">{{ t("timeReload") }}</i>
|
||||
</div>
|
||||
</div>
|
||||
<el-button size="small" type="primary" class="mt-20" @click="getLink">{{ t("generateLink") }}</el-button>
|
||||
<el-button type="primary" class="mt-20" @click="getLink">{{ t("generateLink") }}</el-button>
|
||||
<div v-show="widgetLink" class="mt-10">
|
||||
<span @click="viewPage" class="link">
|
||||
{{ host + widgetLink }}
|
||||
|
@@ -49,12 +49,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { EntityType } from "../data";
|
||||
import type { DashboardItem } from "@/types/dashboard";
|
||||
import type { DashboardItem, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const instanceDashboardName = ref<boolean>(dashboardStore.selectedGrid.instanceDashboardName);
|
||||
const processDashboardName = ref<number>(dashboardStore.selectedGrid.processDashboardName);
|
||||
const instanceDashboardName = ref<string>(dashboardStore.selectedGrid?.instanceDashboardName || "");
|
||||
const processDashboardName = ref<string>(dashboardStore.selectedGrid?.processDashboardName || "");
|
||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||
const instanceDashboards: Array<DashboardItem & { label: string; value: string }> = [];
|
||||
const processDashboards: Array<DashboardItem & { label: string; value: string }> = [];
|
||||
@@ -76,14 +76,14 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
function applyConfig() {
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
dashboardStore.setConfigPanel(false);
|
||||
}
|
||||
function changeDashboard(param: { [key: string]: unknown }) {
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
...param,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -28,23 +28,22 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ref } from "vue";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const originConfig = dashboardStore.selectedGrid;
|
||||
const eventAssociate = ref(dashboardStore.selectedGrid.eventAssociate || false);
|
||||
const eventAssociate = ref(dashboardStore.selectedGrid?.eventAssociate || false);
|
||||
|
||||
function updateConfig() {
|
||||
dashboardStore.selectedGrid = {
|
||||
...dashboardStore.selectedGrid,
|
||||
eventAssociate,
|
||||
};
|
||||
dashboardStore.selectWidget(dashboardStore.selectedGrid);
|
||||
const { selectedGrid } = dashboardStore;
|
||||
|
||||
dashboardStore.selectWidget({ ...selectedGrid, eventAssociate: eventAssociate.value } as LayoutConfig);
|
||||
}
|
||||
|
||||
function applyConfig() {
|
||||
dashboardStore.setConfigPanel(false);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
}
|
||||
|
||||
function cancelConfig() {
|
||||
|
@@ -33,13 +33,14 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { WidgetType, ListEntity } from "@/views/dashboard/data";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const originConfig = dashboardStore.selectedGrid;
|
||||
const expressions = reactive<{ [key: string]: string }>({});
|
||||
const widgetTabs = computed(() =>
|
||||
(dashboardStore.selectedGrid.children || []).filter((child: any) =>
|
||||
(dashboardStore.selectedGrid?.children || []).filter((child: any) =>
|
||||
child.children.find(
|
||||
(item: any) =>
|
||||
item.type === WidgetType.Widget &&
|
||||
@@ -48,7 +49,7 @@ limitations under the License. -->
|
||||
),
|
||||
);
|
||||
|
||||
for (const child of originConfig.children || []) {
|
||||
for (const child of originConfig?.children || []) {
|
||||
expressions[child.name] = child.expression || "";
|
||||
}
|
||||
function changeExpression(name: string) {
|
||||
@@ -56,7 +57,7 @@ limitations under the License. -->
|
||||
ElMessage.error("Only support the is_present function");
|
||||
return;
|
||||
}
|
||||
const children = JSON.parse(JSON.stringify(dashboardStore.selectedGrid.children || []));
|
||||
const children = JSON.parse(JSON.stringify(dashboardStore.selectedGrid?.children || []));
|
||||
|
||||
for (const item of children) {
|
||||
if (item.name === name) {
|
||||
@@ -64,11 +65,11 @@ limitations under the License. -->
|
||||
}
|
||||
}
|
||||
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, children });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, children } as LayoutConfig);
|
||||
}
|
||||
function applyConfig() {
|
||||
dashboardStore.setConfigPanel(false);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
}
|
||||
|
||||
function cancelConfig() {
|
||||
|
@@ -78,10 +78,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ref } from "vue";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { LayoutConfig, TextConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const originConfig = dashboardStore.selectedGrid;
|
||||
const graph = originConfig.graph || {};
|
||||
const graph = (originConfig?.graph as TextConfig) || {};
|
||||
const url = ref(graph.url || "");
|
||||
const backgroundColor = ref(graph.backgroundColor || "green");
|
||||
const fontColor = ref(graph.fontColor || "white");
|
||||
@@ -112,14 +114,14 @@ limitations under the License. -->
|
||||
function changeConfig(param: { [key: string]: unknown }) {
|
||||
const { selectedGrid } = dashboardStore;
|
||||
const graph = {
|
||||
...selectedGrid.graph,
|
||||
...selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
function applyConfig() {
|
||||
dashboardStore.setConfigPanel(false);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
}
|
||||
|
||||
function cancelConfig() {
|
||||
|
@@ -30,11 +30,12 @@ limitations under the License. -->
|
||||
import { ref } from "vue";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { validateAndSanitizeUrl } from "@/utils/validateAndSanitizeUrl";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const originConfig = dashboardStore.selectedGrid;
|
||||
const widget = originConfig.widget || {};
|
||||
const widget = originConfig?.widget || {};
|
||||
const url = ref(widget.url || "");
|
||||
const urlError = ref("");
|
||||
|
||||
@@ -55,10 +56,10 @@ limitations under the License. -->
|
||||
|
||||
const { selectedGrid } = dashboardStore;
|
||||
const widget = {
|
||||
...dashboardStore.selectedGrid.widget,
|
||||
...dashboardStore.selectedGrid?.widget,
|
||||
[key]: param[key], // Use the sanitized URL directly, no need for decodeURIComponent
|
||||
};
|
||||
dashboardStore.selectWidget({ ...selectedGrid, widget });
|
||||
dashboardStore.selectWidget({ ...selectedGrid, widget } as LayoutConfig);
|
||||
}
|
||||
|
||||
function applyConfig() {
|
||||
@@ -66,7 +67,7 @@ limitations under the License. -->
|
||||
return; // Don't apply if there's a validation error
|
||||
}
|
||||
dashboardStore.setConfigPanel(false);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
}
|
||||
|
||||
function cancelConfig() {
|
||||
|
@@ -74,11 +74,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ref } from "vue";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { TimeRangeConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const originConfig = dashboardStore.selectedGrid;
|
||||
const graph = originConfig.graph || {};
|
||||
const graph = (originConfig?.graph as TimeRangeConfig) || {};
|
||||
const backgroundColor = ref(graph.backgroundColor || "green");
|
||||
const fontColor = ref(graph.fontColor || "white");
|
||||
const fontSize = ref<number>(graph.fontSize || 12);
|
||||
@@ -107,14 +108,14 @@ limitations under the License. -->
|
||||
function changeConfig(param: { [key: string]: unknown }) {
|
||||
const { selectedGrid } = dashboardStore;
|
||||
const graph = {
|
||||
...selectedGrid.graph,
|
||||
...selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
function applyConfig() {
|
||||
dashboardStore.setConfigPanel(false);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
}
|
||||
|
||||
function cancelConfig() {
|
||||
|
@@ -34,24 +34,25 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { DepthList } from "../data";
|
||||
import type { Option } from "@/types/app";
|
||||
import type { TopologyConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
const showDepth = ref<boolean>(graph.showDepth);
|
||||
const depth = ref<number>(graph.depth || 2);
|
||||
const graph = (dashboardStore.selectedGrid?.graph as TopologyConfig) || {};
|
||||
const showDepth = ref<boolean>(graph?.showDepth || false);
|
||||
const depth = ref<number>(graph?.depth || 2);
|
||||
|
||||
function applyConfig() {
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
dashboardStore.setConfigPanel(false);
|
||||
}
|
||||
function changeConfig(param: { [key: string]: unknown }) {
|
||||
const { selectedGrid } = dashboardStore;
|
||||
const graph = {
|
||||
...selectedGrid.graph,
|
||||
...selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
function changeDepth(opt: Option[] | any) {
|
||||
const val = opt[0].value;
|
||||
|
@@ -32,16 +32,16 @@ limitations under the License. -->
|
||||
:data="states.source"
|
||||
:config="{
|
||||
...graph,
|
||||
decorations: dashboardStore.selectedGrid.graph?.decorations,
|
||||
legend: dashboardStore.selectedGrid.graph?.legend,
|
||||
i: dashboardStore.selectedGrid.i,
|
||||
metricConfig: dashboardStore.selectedGrid.metricConfig,
|
||||
relatedTrace: dashboardStore.selectedGrid.relatedTrace,
|
||||
expressions: dashboardStore.selectedGrid.expressions || [],
|
||||
typesOfMQE: dashboardStore.selectedGrid.typesOfMQE || [],
|
||||
subExpressions: dashboardStore.selectedGrid.subExpressions || [],
|
||||
subTypesOfMQE: dashboardStore.selectedGrid.subTypesOfMQE || [],
|
||||
valueRelatedDashboard: dashboardStore.selectedGrid.valueRelatedDashboard,
|
||||
valueMappings: dashboardStore.selectedGrid?.graph?.valueMappings,
|
||||
legend: dashboardStore.selectedGrid?.graph?.legend,
|
||||
i: dashboardStore.selectedGrid?.i,
|
||||
metricConfig: dashboardStore.selectedGrid?.metricConfig,
|
||||
relatedTrace: dashboardStore.selectedGrid?.relatedTrace,
|
||||
expressions: dashboardStore.selectedGrid?.expressions || [],
|
||||
typesOfMQE: dashboardStore.selectedGrid?.typesOfMQE || [],
|
||||
subExpressions: dashboardStore.selectedGrid?.subExpressions || [],
|
||||
subTypesOfMQE: dashboardStore.selectedGrid?.subTypesOfMQE || [],
|
||||
valueRelatedDashboard: dashboardStore.selectedGrid?.valueRelatedDashboard,
|
||||
}"
|
||||
:needQuery="true"
|
||||
@expressionTips="getErrors"
|
||||
@@ -88,6 +88,7 @@ limitations under the License. -->
|
||||
import type { Option } from "@/types/app";
|
||||
import graphs from "../graphs";
|
||||
import CustomOptions from "./widget/index";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
export default defineComponent({
|
||||
name: "WidgetEdit",
|
||||
@@ -106,23 +107,21 @@ limitations under the License. -->
|
||||
const states = reactive<{
|
||||
activeNames: string;
|
||||
source: unknown;
|
||||
index: string;
|
||||
index: string | undefined;
|
||||
visType: Option[];
|
||||
}>({
|
||||
activeNames: "1",
|
||||
source: {},
|
||||
index: dashboardStore.selectedGrid.i,
|
||||
index: dashboardStore.selectedGrid?.i,
|
||||
visType: [],
|
||||
});
|
||||
const originConfig = dashboardStore.selectedGrid;
|
||||
const widget = computed(() => dashboardStore.selectedGrid.widget || {});
|
||||
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||
const widget = computed(() => dashboardStore.selectedGrid?.widget || {});
|
||||
const graph = computed(() => dashboardStore.selectedGrid?.graph || {});
|
||||
const title = computed(() => encodeURIComponent(widget.value.title || ""));
|
||||
const tips = computed(() => encodeURIComponent(widget.value.tips || ""));
|
||||
const hasAssociate = computed(() =>
|
||||
["Bar", "Line", "Area", "TopList"].includes(
|
||||
dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph.type,
|
||||
),
|
||||
["Bar", "Line", "Area", "TopList"].includes(dashboardStore.selectedGrid?.graph?.type || ""),
|
||||
);
|
||||
|
||||
function getSource(source: unknown) {
|
||||
@@ -140,7 +139,7 @@ limitations under the License. -->
|
||||
|
||||
function applyConfig() {
|
||||
dashboardStore.setConfigPanel(false);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||
dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
|
||||
}
|
||||
|
||||
function cancelConfig() {
|
||||
|
@@ -33,24 +33,25 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import type { Option } from "@/types/app";
|
||||
import type { DashboardItem, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const associate = dashboardStore.selectedGrid.associate || [];
|
||||
const associate = dashboardStore.selectedGrid?.associate || [];
|
||||
const widgetIds = ref<string[]>(associate.map((d: { widgetId: string }) => d.widgetId));
|
||||
const widgets: any = computed(() => {
|
||||
const widgetList = getDashboard(dashboardStore.currentDashboard).widgets;
|
||||
const widgetList = getDashboard(dashboardStore.currentDashboard as DashboardItem).widgets;
|
||||
const items = [];
|
||||
for (const d of widgetList) {
|
||||
const isLinear = ["Bar", "Line", "Area"].includes((d.graph && d.graph.type) || "");
|
||||
if (isLinear && d.id && dashboardStore.selectedGrid.id !== d.id) {
|
||||
if (isLinear && d.id && dashboardStore.selectedGrid?.id !== d.id) {
|
||||
items.push({ value: d.id, label: (d.widget && d.widget.name) || d.id });
|
||||
}
|
||||
}
|
||||
return items;
|
||||
});
|
||||
function updateWidgetConfig(options: Option[]) {
|
||||
const arr: any = getDashboard(dashboardStore.currentDashboard).widgets;
|
||||
const arr: any = getDashboard(dashboardStore.currentDashboard as DashboardItem).widgets;
|
||||
const opt = options.map((d: Option) => {
|
||||
return { widgetId: d.value };
|
||||
});
|
||||
@@ -60,7 +61,7 @@ limitations under the License. -->
|
||||
...dashboardStore.selectedGrid,
|
||||
associate: opt,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...widget });
|
||||
dashboardStore.selectWidget({ ...widget } as LayoutConfig);
|
||||
|
||||
// remove unuse association widget option
|
||||
for (const id of widgetIds.value) {
|
||||
@@ -76,7 +77,7 @@ limitations under the License. -->
|
||||
// add association options in target widgets
|
||||
for (let i = 0; i < opt.length; i++) {
|
||||
const item = JSON.parse(JSON.stringify(opt));
|
||||
item[i] = { widgetId: dashboardStore.selectedGrid.id };
|
||||
item[i] = { widgetId: dashboardStore.selectedGrid?.id };
|
||||
const w = arr.find((d: { id: string }) => d.id === opt[i].widgetId);
|
||||
const config = {
|
||||
...w,
|
||||
|
@@ -62,6 +62,7 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { RefIdTypes } from "../../data";
|
||||
import type { LayoutConfig, RelatedTrace } from "@/types/dashboard";
|
||||
|
||||
const QueryOrders = [
|
||||
{ label: "None", value: "BY_START_TIME" },
|
||||
@@ -74,21 +75,20 @@ limitations under the License. -->
|
||||
];
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const { graph, relatedTrace } = dashboardStore.selectedGrid;
|
||||
const traceOpt = relatedTrace || {};
|
||||
const status = ref<string>(traceOpt.status || Status[0].value);
|
||||
const queryOrder = ref<string>(traceOpt.queryOrder || QueryOrders[0].value);
|
||||
const latency = ref<boolean>(traceOpt.latency || false);
|
||||
const enableRelate = ref<boolean>(traceOpt.enableRelate || false);
|
||||
const type = ref<string>((graph && graph.type) || "");
|
||||
const refIdType = ref<string>(traceOpt.refIdType || "");
|
||||
const traceOpt = dashboardStore.selectedGrid?.relatedTrace as RelatedTrace;
|
||||
const status = ref<string>(traceOpt?.status || Status[0].value);
|
||||
const queryOrder = ref<string>(traceOpt?.queryOrder || QueryOrders[0].value);
|
||||
const latency = ref<boolean>(traceOpt?.latency || false);
|
||||
const enableRelate = ref<boolean>(traceOpt?.enableRelate || false);
|
||||
const type = ref<string>(dashboardStore.selectedGrid?.graph?.type || "");
|
||||
const refIdType = ref<string>(traceOpt?.refIdType || "");
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const relatedTrace = {
|
||||
...dashboardStore.selectedGrid.relatedTrace,
|
||||
...dashboardStore.selectedGrid?.relatedTrace,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, relatedTrace });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, relatedTrace } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -50,11 +50,11 @@ limitations under the License. -->
|
||||
import { ElMessage } from "element-plus";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
import type { LayoutConfig, DashboardItem } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const widget = dashboardStore.selectedGrid.widget || {};
|
||||
const widget = dashboardStore.selectedGrid?.widget || {};
|
||||
const title = ref<string>(widget.title || "");
|
||||
const tips = ref<string>(widget.tips || "");
|
||||
const name = ref<string>(widget.name || "");
|
||||
@@ -66,10 +66,10 @@ limitations under the License. -->
|
||||
}
|
||||
const { selectedGrid } = dashboardStore;
|
||||
const widget = {
|
||||
...dashboardStore.selectedGrid.widget,
|
||||
...dashboardStore.selectedGrid?.widget,
|
||||
[key]: decodeURIComponent(param[key]),
|
||||
};
|
||||
dashboardStore.selectWidget({ ...selectedGrid, widget });
|
||||
dashboardStore.selectWidget({ ...selectedGrid, widget } as LayoutConfig);
|
||||
}
|
||||
function updateWidgetName(param: { [key: string]: string }) {
|
||||
const key = Object.keys(param)[0];
|
||||
@@ -79,7 +79,7 @@ limitations under the License. -->
|
||||
ElMessage.error(t("nameTip"));
|
||||
return;
|
||||
}
|
||||
const { widgets } = getDashboard(dashboardStore.currentDashboard);
|
||||
const { widgets } = getDashboard(dashboardStore.currentDashboard as DashboardItem);
|
||||
const item = widgets.find((d: LayoutConfig) => d.widget && d.widget.name === n);
|
||||
if (item) {
|
||||
ElMessage.error(t("duplicateName"));
|
||||
|
@@ -33,19 +33,20 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Legend from "./components/Legend.vue";
|
||||
import type { AreaConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
const graph = (dashboardStore.selectedGrid?.graph as AreaConfig) || {};
|
||||
|
||||
const opacity = ref(graph.opacity);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -29,18 +29,19 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import Legend from "./components/Legend.vue";
|
||||
import type { BarConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph;
|
||||
const graph = (dashboardStore.selectedGrid?.graph as BarConfig) || {};
|
||||
const showBackground = ref(graph.showBackground || false);
|
||||
|
||||
function changeConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -39,19 +39,20 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import ValueMappings from "./components/ValueMappings.vue";
|
||||
import type { CardConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
const graph = (dashboardStore.selectedGrid?.graph as CardConfig) || {};
|
||||
const fontSize = ref(graph.fontSize);
|
||||
const showUnit = ref<boolean>(graph.showUnit);
|
||||
const showUnit = ref<boolean>(graph.showUnit || false);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -31,19 +31,20 @@ limitations under the License. -->
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { EndpointListConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph;
|
||||
const graph = (dashboardStore.selectedGrid?.graph as EndpointListConfig) || {};
|
||||
const { t } = useI18n();
|
||||
|
||||
const fontSize = ref(graph.fontSize);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -31,18 +31,19 @@ limitations under the License. -->
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { CardConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
const graph = (dashboardStore.selectedGrid?.graph as CardConfig) || {};
|
||||
const fontSize = ref(graph.fontSize);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -31,18 +31,19 @@ limitations under the License. -->
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { InstanceListConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph;
|
||||
const graph = (dashboardStore.selectedGrid?.graph as InstanceListConfig) || {};
|
||||
const fontSize = ref(graph.fontSize);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -51,20 +51,21 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Legend from "./components/Legend.vue";
|
||||
import { isDef } from "@/utils/is";
|
||||
import type { LineConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||
const graph = computed(() => (dashboardStore.selectedGrid?.graph as LineConfig) || {});
|
||||
const smooth = ref(graph.value.smooth);
|
||||
const showSymbol = ref(isDef(graph.value.showSymbol) ? graph.value.showSymbol : true);
|
||||
const step = ref(graph.value.step);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -40,19 +40,20 @@ limitations under the License. -->
|
||||
import { ref, computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { ServiceListConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||
const graph = computed(() => (dashboardStore.selectedGrid?.graph as ServiceListConfig) || {});
|
||||
const fontSize = ref(graph.value.fontSize);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const { selectedGrid } = dashboardStore;
|
||||
const graph = {
|
||||
...selectedGrid.graph,
|
||||
...selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -41,19 +41,20 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import ValueMappings from "./components/ValueMappings.vue";
|
||||
import type { TableConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
const graph = (dashboardStore.selectedGrid?.graph as TableConfig) || {};
|
||||
const showTableValues = ref(graph.showTableValues);
|
||||
const tableHeaderCol2 = ref(graph.tableHeaderCol2);
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -29,10 +29,11 @@ limitations under the License. -->
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { TopListConfig, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
const graph = (dashboardStore.selectedGrid?.graph as TopListConfig) || {};
|
||||
const color = ref(graph.color || "purple");
|
||||
const Colors = [
|
||||
{ label: "Purple", value: "purple" },
|
||||
@@ -47,10 +48,10 @@ limitations under the License. -->
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
...param,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -94,11 +94,11 @@ limitations under the License. -->
|
||||
import { computed, reactive } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { LegendOptions } from "@/types/dashboard";
|
||||
import type { LegendOptions, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||
const graph = computed(() => dashboardStore.selectedGrid?.graph || {});
|
||||
const legend = reactive<LegendOptions>({
|
||||
show: true,
|
||||
total: false,
|
||||
@@ -113,17 +113,17 @@ limitations under the License. -->
|
||||
});
|
||||
|
||||
function updateLegendConfig(param: { [key: string]: unknown }) {
|
||||
const g = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
legend: {
|
||||
...dashboardStore.selectedGrid.graph.legend,
|
||||
...dashboardStore.selectedGrid?.graph?.legend,
|
||||
...param,
|
||||
},
|
||||
};
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
graph: g,
|
||||
});
|
||||
graph,
|
||||
} as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -39,14 +39,15 @@ limitations under the License. -->
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const graph = dashboardStore.selectedGrid.graph;
|
||||
const graph = dashboardStore.selectedGrid?.graph || {};
|
||||
const valueMappings = ref<{ [key: string]: string }>(graph?.valueMappings || {});
|
||||
const keys = ref<string[]>(graph.valueMappings ? Object.keys(valueMappings.value) : [""]);
|
||||
const keys = ref<string[]>(graph?.valueMappings ? Object.keys(valueMappings.value) : [""]);
|
||||
|
||||
function changeKeys(event: any, index: number) {
|
||||
const params = event.target.textContent || "";
|
||||
@@ -82,10 +83,10 @@ limitations under the License. -->
|
||||
|
||||
function updateConfig() {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
valueMappings: valueMappings.value,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -126,7 +126,7 @@ limitations under the License. -->
|
||||
import Icon from "@/components/Icon.vue";
|
||||
import { useDashboardQueryProcessor } from "@/hooks/useExpressionsProcessor";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import type { DashboardItem, MetricConfigOpt } from "@/types/dashboard";
|
||||
import type { DashboardItem, MetricConfigOpt, LayoutConfig } from "@/types/dashboard";
|
||||
import Standard from "./Standard.vue";
|
||||
|
||||
/*global defineEmits, Indexable */
|
||||
@@ -142,11 +142,11 @@ limitations under the License. -->
|
||||
},
|
||||
});
|
||||
const dashboardStore = useDashboardStore();
|
||||
const metrics = computed(() => dashboardStore.selectedGrid.expressions || []);
|
||||
const subMetrics = computed(() => dashboardStore.selectedGrid.subExpressions || []);
|
||||
const subMetricTypes = computed(() => dashboardStore.selectedGrid.subTypesOfMQE || []);
|
||||
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||
const typesOfMQE = computed(() => dashboardStore.selectedGrid.typesOfMQE || []);
|
||||
const metrics = computed(() => dashboardStore.selectedGrid?.expressions || []);
|
||||
const subMetrics = computed(() => dashboardStore.selectedGrid?.subExpressions || []);
|
||||
const subMetricTypes = computed(() => dashboardStore.selectedGrid?.subTypesOfMQE || []);
|
||||
const graph = computed(() => dashboardStore.selectedGrid?.graph || {});
|
||||
const typesOfMQE = computed(() => dashboardStore.selectedGrid?.typesOfMQE || []);
|
||||
const states = reactive<{
|
||||
metrics: string[];
|
||||
subMetrics: string[];
|
||||
@@ -166,13 +166,13 @@ limitations under the License. -->
|
||||
metricTypeList: [],
|
||||
isList: false,
|
||||
isTopList: false,
|
||||
dashboardName: graph.value.dashboardName,
|
||||
dashboardName: graph.value.dashboardName || "",
|
||||
dashboardList: [{ label: "", value: "" }],
|
||||
tips: [],
|
||||
subTips: [],
|
||||
subMetrics: subMetrics.value.length ? subMetrics.value : [""],
|
||||
subMetricTypes: subMetricTypes.value.length ? subMetricTypes.value : [""],
|
||||
valueRelatedDashboard: dashboardStore.selectedGrid.valueRelatedDashboard,
|
||||
valueRelatedDashboard: dashboardStore.selectedGrid?.valueRelatedDashboard || "",
|
||||
});
|
||||
const currentMetricConfig = ref<MetricConfigOpt>({
|
||||
unit: "",
|
||||
@@ -182,7 +182,7 @@ limitations under the License. -->
|
||||
});
|
||||
|
||||
states.isTopList = graph.value.type === ChartTypes[4].value;
|
||||
states.isList = ListChartTypes.includes(graph.value.type);
|
||||
states.isList = ListChartTypes.includes(graph.value.type || "");
|
||||
const defaultLen = ref<number>(states.isList ? 5 : 20);
|
||||
|
||||
setDashboards();
|
||||
@@ -201,7 +201,7 @@ limitations under the License. -->
|
||||
});
|
||||
|
||||
function setDashboards(type?: string) {
|
||||
const chart = type || (dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph.type);
|
||||
const chart = type || dashboardStore.selectedGrid?.graph?.type || "";
|
||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||
const arr = list.reduce((prev: (DashboardItem & { label: string; value: string })[], d: DashboardItem) => {
|
||||
if (d.layer === dashboardStore.layerId) {
|
||||
@@ -237,7 +237,7 @@ limitations under the License. -->
|
||||
...dashboardStore.selectedGrid,
|
||||
expressions: [""],
|
||||
typesOfMQE: [""],
|
||||
});
|
||||
} as LayoutConfig);
|
||||
states.metrics = [""];
|
||||
states.metricTypes = [""];
|
||||
defaultLen.value = 5;
|
||||
@@ -246,7 +246,7 @@ limitations under the License. -->
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
graph: chart,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
setDashboards(chart.type);
|
||||
states.dashboardName = "";
|
||||
defaultLen.value = 10;
|
||||
@@ -260,7 +260,7 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
async function queryMetricsWithExpressions() {
|
||||
const { expressions, metricConfig, i } = dashboardStore.selectedGrid;
|
||||
const { expressions, metricConfig, i } = dashboardStore.selectedGrid as LayoutConfig;
|
||||
if (!(expressions && expressions[0])) {
|
||||
return emit("update", {});
|
||||
}
|
||||
@@ -272,7 +272,7 @@ limitations under the License. -->
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
typesOfMQE: states.metricTypes,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
emit("update", params.source || {});
|
||||
if (states.isTopList) {
|
||||
const values: any = Object.values(params.source)[0];
|
||||
@@ -292,7 +292,7 @@ limitations under the License. -->
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
valueRelatedDashboard: states.valueRelatedDashboard,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
}
|
||||
|
||||
function changeDashboard(opt: { value: string }[]) {
|
||||
@@ -302,13 +302,13 @@ limitations under the License. -->
|
||||
states.dashboardName = opt[0].value;
|
||||
}
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...dashboardStore.selectedGrid?.graph,
|
||||
dashboardName: states.dashboardName,
|
||||
};
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
graph,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
}
|
||||
function addMetric() {
|
||||
states.metrics.push("");
|
||||
@@ -350,7 +350,7 @@ limitations under the License. -->
|
||||
states.metrics.splice(index, 1);
|
||||
states.metricTypes.splice(index, 1);
|
||||
states.tips.splice(index, 1);
|
||||
const config = dashboardStore.selectedGrid.metricConfig || [];
|
||||
const config = dashboardStore.selectedGrid?.metricConfig || [];
|
||||
const metricConfig = config[index] ? config.splice(index, 1) : config;
|
||||
let p = {};
|
||||
if (states.isList) {
|
||||
@@ -369,7 +369,7 @@ limitations under the License. -->
|
||||
...dashboardStore.selectedGrid,
|
||||
...p,
|
||||
metricConfig,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
queryMetrics();
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ limitations under the License. -->
|
||||
labelsIndex: "",
|
||||
sortOrder: "DES",
|
||||
};
|
||||
if (!dashboardStore.selectedGrid.metricConfig || !dashboardStore.selectedGrid.metricConfig[index]) {
|
||||
if (!dashboardStore.selectedGrid?.metricConfig || !dashboardStore.selectedGrid?.metricConfig[index]) {
|
||||
currentMetricConfig.value = n;
|
||||
return;
|
||||
}
|
||||
@@ -397,7 +397,7 @@ limitations under the License. -->
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
expressions: states.metrics,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
if (params) {
|
||||
await queryMetrics();
|
||||
}
|
||||
@@ -410,7 +410,7 @@ limitations under the License. -->
|
||||
...dashboardStore.selectedGrid,
|
||||
subExpressions: states.subMetrics,
|
||||
subTypesOfMQE: states.subMetricTypes,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
if (params) {
|
||||
await queryMetrics();
|
||||
}
|
||||
|
@@ -86,7 +86,7 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { SortOrder, ExpressionResultType, ListChartTypes } from "@/views/dashboard/data";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { MetricConfigOpt } from "@/types/dashboard";
|
||||
import type { MetricConfigOpt, LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineEmits, defineProps */
|
||||
const props = defineProps({
|
||||
@@ -103,13 +103,15 @@ limitations under the License. -->
|
||||
...props.currentMetricConfig,
|
||||
topN: props.currentMetricConfig.topN || 10,
|
||||
});
|
||||
const metricTypes = computed(() => dashboardStore.selectedGrid.typesOfMQE || []);
|
||||
const metricTypes = computed(() => dashboardStore.selectedGrid?.typesOfMQE || []);
|
||||
const isList = computed(() => {
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
return ListChartTypes.includes(graph.type);
|
||||
const graph = dashboardStore.selectedGrid?.graph || {};
|
||||
return ListChartTypes.includes(graph.type || "");
|
||||
});
|
||||
const isTopn = computed(() =>
|
||||
[ExpressionResultType.RECORD_LIST, ExpressionResultType.SORTED_LIST].includes(metricTypes.value[props.index]),
|
||||
[ExpressionResultType.RECORD_LIST, ExpressionResultType.SORTED_LIST].includes(
|
||||
metricTypes.value[props.index] as ExpressionResultType,
|
||||
),
|
||||
);
|
||||
|
||||
function updateConfig(index: number, param: { [key: string]: string }) {
|
||||
@@ -120,13 +122,13 @@ limitations under the License. -->
|
||||
changeConfigs(index, { [key]: decodeURIComponent(param[key]) });
|
||||
}
|
||||
function changeConfigs(index: number, param: { [key: string]: string | number }) {
|
||||
const metricConfig = dashboardStore.selectedGrid.metricConfig || [];
|
||||
const metricConfig = dashboardStore.selectedGrid?.metricConfig || [];
|
||||
|
||||
metricConfig[index] = { ...metricConfig[index], ...param };
|
||||
dashboardStore.selectWidget({
|
||||
...dashboardStore.selectedGrid,
|
||||
metricConfig,
|
||||
});
|
||||
} as LayoutConfig);
|
||||
emit("update");
|
||||
}
|
||||
watch(
|
||||
|
@@ -34,11 +34,12 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Content from "../related/async-profiling/Content.vue";
|
||||
import Header from "../related/async-profiling/Header.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps*/
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -36,11 +36,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Content from "../related/continuous-profiling/Content.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -31,15 +31,17 @@ limitations under the License. -->
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Header from "../related/demand-log/Header.vue";
|
||||
import Content from "../related/demand-log/Content.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({}),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -34,11 +34,12 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Header from "../related/ebpf/Header.vue";
|
||||
import Content from "../related/ebpf/Content.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -36,15 +36,17 @@ limitations under the License. -->
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Header from "../related/event/Header.vue";
|
||||
import Content from "../related/event/Content.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({}),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -33,11 +33,11 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Content from "../related/network-profiling/Content.vue";
|
||||
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -34,11 +34,12 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Header from "../related/profile/Header.vue";
|
||||
import Content from "../related/profile/Content.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -161,12 +161,12 @@ limitations under the License. -->
|
||||
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i);
|
||||
|
||||
dashboardStore.setActiveTabIndex(activeTabIndex.value);
|
||||
if (dashboardStore.layout[l].children.length) {
|
||||
if (dashboardStore.layout[l]?.children?.length) {
|
||||
const tab = dashboardStore.layout[l].children[activeTabIndex.value];
|
||||
dashboardStore.setCurrentTabItems(
|
||||
tab.enable === false ? [] : dashboardStore.layout[l].children[activeTabIndex.value].children,
|
||||
);
|
||||
dashboardStore.setActiveTabIndex(activeTabIndex.value, props.data.i);
|
||||
dashboardStore.setActiveTabIndex(activeTabIndex.value, Number(props.data.i));
|
||||
}
|
||||
queryExpressions();
|
||||
|
||||
@@ -177,7 +177,7 @@ limitations under the License. -->
|
||||
dashboardStore.selectWidget(props.data);
|
||||
dashboardStore.setActiveTabIndex(idx);
|
||||
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i);
|
||||
dashboardStore.setCurrentTabItems(dashboardStore.layout[l].children[activeTabIndex.value].children);
|
||||
dashboardStore.setCurrentTabItems(dashboardStore.layout[l]?.children?.[activeTabIndex.value]?.children || []);
|
||||
needQuery.value = true;
|
||||
if (route.params.activeTabIndex) {
|
||||
let p = location.href.split("/tab/")[0];
|
||||
@@ -192,10 +192,10 @@ limitations under the License. -->
|
||||
function deleteTabItem(e: Event, idx: number) {
|
||||
e.stopPropagation();
|
||||
dashboardStore.removeTabItem(props.data, idx);
|
||||
const kids = dashboardStore.layout[l].children[0];
|
||||
const kids = dashboardStore.layout[l]?.children?.[0];
|
||||
const arr = (kids && kids.children) || [];
|
||||
dashboardStore.setCurrentTabItems(arr);
|
||||
dashboardStore.activeGridItem(0);
|
||||
dashboardStore.activeGridItem("0");
|
||||
activeTabIndex.value = 0;
|
||||
needQuery.value = true;
|
||||
}
|
||||
@@ -226,7 +226,7 @@ limitations under the License. -->
|
||||
}
|
||||
function layoutUpdatedEvent() {
|
||||
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i);
|
||||
dashboardStore.setCurrentTabItems(dashboardStore.layout[l].children[activeTabIndex.value].children);
|
||||
dashboardStore.setCurrentTabItems(dashboardStore.layout[l]?.children?.[activeTabIndex.value]?.children || []);
|
||||
}
|
||||
function getStringWidth(s: string) {
|
||||
const dom = document.createElement("span");
|
||||
@@ -282,7 +282,7 @@ limitations under the License. -->
|
||||
const index = (props.data.children || []).findIndex((tab: any) => tab.enable !== false) || 0;
|
||||
const items = ((props.data.children || [])[index] || {}).children;
|
||||
dashboardStore.setCurrentTabItems(items || []);
|
||||
dashboardStore.activeGridItem(0);
|
||||
dashboardStore.activeGridItem("0");
|
||||
activeTabIndex.value = index;
|
||||
dashboardStore.setActiveTabIndex(activeTabIndex.value);
|
||||
needQuery.value = true;
|
||||
@@ -324,7 +324,7 @@ limitations under the License. -->
|
||||
dashboardStore.activeGridItem(props.data.i);
|
||||
dashboardStore.selectWidget(props.data);
|
||||
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i);
|
||||
dashboardStore.setCurrentTabItems(dashboardStore.layout[l].children[activeTabIndex.value].children);
|
||||
dashboardStore.setCurrentTabItems(dashboardStore.layout[l]?.children?.[activeTabIndex.value]?.children || []);
|
||||
needQuery.value = true;
|
||||
if (route.params.activeTabIndex) {
|
||||
let p = location.href.split("/tab/")[0];
|
||||
|
@@ -33,11 +33,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Content from "../related/task-timeline/Content.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -58,18 +58,19 @@ limitations under the License. -->
|
||||
import { TextColors } from "@/views/dashboard/data";
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
import { Themes } from "@/constants/data";
|
||||
import type { LayoutConfig, TextConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStoreWithOut();
|
||||
const graph = computed(() => props.data.graph || {});
|
||||
const graph = computed(() => (props.data.graph as TextConfig) || {});
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
||||
const backgroundColor = computed(
|
||||
|
@@ -50,11 +50,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { validateAndSanitizeUrl } from "@/utils/validateAndSanitizeUrl";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -63,17 +63,18 @@ limitations under the License. -->
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
import { TextColors } from "@/views/dashboard/data";
|
||||
import type { LayoutConfig, TimeRangeConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const graph = computed(() => props.data.graph || {});
|
||||
const graph = computed(() => (props.data.graph as TimeRangeConfig) || {});
|
||||
const dashboardStore = useDashboardStore();
|
||||
const appStore = useAppStoreWithOut();
|
||||
const content = computed(() => {
|
||||
|
@@ -37,11 +37,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import Topology from "../related/topology/Index.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -53,11 +53,12 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { mutationObserver } from "@/utils/mutation";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
/* global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
activeIndex: { type: String, default: "" },
|
||||
|
@@ -80,7 +80,7 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useDashboardQueryProcessor } from "@/hooks/useExpressionsProcessor";
|
||||
import { ListChartTypes } from "../data";
|
||||
import type { EventParams } from "@/types/dashboard";
|
||||
import type { EventParams, DashboardItem } from "@/types/dashboard";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
|
||||
const props = {
|
||||
@@ -141,7 +141,7 @@ limitations under the License. -->
|
||||
}
|
||||
}
|
||||
function clickHandle(params: EventParams | any) {
|
||||
const { widgets } = getDashboard(dashboardStore.currentDashboard);
|
||||
const { widgets } = getDashboard(dashboardStore.currentDashboard as DashboardItem);
|
||||
const associate = (props.data.associate && props.data.associate) || [];
|
||||
|
||||
for (const item of associate) {
|
||||
@@ -170,7 +170,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
const chart = dashboardStore.selectedGrid.graph || {};
|
||||
if (ListChartTypes.includes(chart.type)) {
|
||||
if (ListChartTypes.includes(chart.type || "")) {
|
||||
return;
|
||||
}
|
||||
queryMetrics();
|
||||
|
@@ -192,7 +192,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
router.push(
|
||||
`/dashboard/${dashboard.layer}/${dashboard.entity}/${selectorStore.currentService.id}/${scope.row.id}/${dashboard.name}`,
|
||||
`/dashboard/${dashboard.layer}/${dashboard.entity}/${selectorStore.currentService?.id}/${scope.row.id}/${dashboard.name}`,
|
||||
);
|
||||
}
|
||||
async function searchList() {
|
||||
|
@@ -208,7 +208,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
router.push(
|
||||
`/dashboard/${dashboard.layer}/${dashboard.entity}/${selectorStore.currentService.id}/${
|
||||
`/dashboard/${dashboard.layer}/${dashboard.entity}/${selectorStore.currentService?.id}/${
|
||||
scope.row.id
|
||||
}/${dashboard.name.split(" ").join("-")}`,
|
||||
);
|
||||
|
@@ -85,6 +85,10 @@ limitations under the License. -->
|
||||
import type { MetricConfigOpt } from "@/types/dashboard";
|
||||
import ColumnGraph from "./components/ColumnGraph.vue";
|
||||
|
||||
interface ServiceWithGroup extends Service {
|
||||
merge: boolean;
|
||||
group: string;
|
||||
}
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
@@ -115,12 +119,12 @@ limitations under the License. -->
|
||||
const chartLoading = ref<boolean>(false);
|
||||
const currentPage = ref<number>(1);
|
||||
const pageSize = 10;
|
||||
const services = ref<Service[]>([]);
|
||||
const services = ref<ServiceWithGroup[]>([]);
|
||||
const colMetrics = ref<string[]>([]);
|
||||
const colSubMetrics = ref<string[]>([]);
|
||||
const searchText = ref<string>("");
|
||||
const groups = ref<any>({});
|
||||
const sortServices = ref<(Service & { merge: boolean })[]>([]);
|
||||
const sortServices = ref<ServiceWithGroup[]>([]);
|
||||
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
|
||||
const typesOfMQE = ref<string[]>(props.config.typesOfMQE || []);
|
||||
|
||||
@@ -144,12 +148,12 @@ limitations under the License. -->
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
const s = sortServices.value.filter((d: Service, index: number) => index < pageSize);
|
||||
}) as ServiceWithGroup[];
|
||||
const s = sortServices.value.filter((d: ServiceWithGroup, index: number) => index < pageSize);
|
||||
setServices(s);
|
||||
}
|
||||
|
||||
function setServices(arr: (Service & { merge: boolean })[]) {
|
||||
function setServices(arr: ServiceWithGroup[]) {
|
||||
groups.value = {};
|
||||
const map: { [key: string]: any[] } = arr.reduce((result: { [key: string]: any[] }, item: any) => {
|
||||
item.group = item.group || "";
|
||||
@@ -191,11 +195,11 @@ limitations under the License. -->
|
||||
|
||||
router.push(path);
|
||||
}
|
||||
async function queryServiceMetrics(arr: Service[]) {
|
||||
async function queryServiceMetrics(arr: ServiceWithGroup[]) {
|
||||
if (!arr.length) {
|
||||
return;
|
||||
}
|
||||
const currentServices = arr.map((d: Service) => {
|
||||
const currentServices = arr.map((d: ServiceWithGroup) => {
|
||||
return {
|
||||
id: d.id,
|
||||
value: d.value,
|
||||
@@ -203,13 +207,13 @@ limitations under the License. -->
|
||||
layers: d.layers,
|
||||
group: d.group,
|
||||
normal: d.normal,
|
||||
merge: d.merge,
|
||||
merge: d.merge || false,
|
||||
shortName: d.shortName,
|
||||
};
|
||||
});
|
||||
queryServiceExpressions(currentServices);
|
||||
}
|
||||
async function queryServiceExpressions(currentServices: Service[]) {
|
||||
async function queryServiceExpressions(currentServices: ServiceWithGroup[]) {
|
||||
const expressions = props.config.expressions || [];
|
||||
const subExpressions = props.config.subExpressions || [];
|
||||
|
||||
@@ -254,7 +258,7 @@ limitations under the License. -->
|
||||
if (searchText.value) {
|
||||
services = sortServices.value.filter((d: { label: string }) => d.label.includes(searchText.value));
|
||||
}
|
||||
const arr = services.filter((d: Service, index: number) => {
|
||||
const arr = services.filter((d: ServiceWithGroup, index: number) => {
|
||||
if (index >= (currentPage.value - 1) * pageSize && index < pageSize * currentPage.value) {
|
||||
return d;
|
||||
}
|
||||
|
@@ -70,13 +70,12 @@ limitations under the License. -->
|
||||
import { TextColors, MetricCatalog } from "@/views/dashboard/data";
|
||||
import Trace from "@/views/dashboard/related/trace/Index.vue";
|
||||
import { WidgetType, QueryOrders, Status, RefIdTypes, ExpressionResultType } from "@/views/dashboard/data";
|
||||
import type { Filters, RelatedTrace, TopListData, TopListItem } from "@/types/dashboard";
|
||||
|
||||
/*global defineProps, Recordable*/
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<{
|
||||
[key: string]: { name: string; value: number; refId: string; owner: object }[];
|
||||
}>,
|
||||
type: Object as PropType<TopListData>,
|
||||
default: () => ({}),
|
||||
},
|
||||
config: {
|
||||
@@ -84,7 +83,7 @@ limitations under the License. -->
|
||||
color: string;
|
||||
expressions: string[];
|
||||
typesOfMQE: string[];
|
||||
relatedTrace: any;
|
||||
relatedTrace: RelatedTrace;
|
||||
valueRelatedDashboard: string;
|
||||
}>,
|
||||
default: () => ({ color: "purple" }),
|
||||
@@ -94,28 +93,29 @@ limitations under the License. -->
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const showTrace = ref<boolean>(false);
|
||||
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
||||
const traceOptions = ref<{ type: string; filters?: Filters } | any>({
|
||||
...props.data,
|
||||
type: WidgetType.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<string>(() => Object.keys(props.data)[0] || "");
|
||||
const available = computed(
|
||||
() => Array.isArray(props.data[key.value]) && props.data[key.value][0] && props.data[key.value][0].value,
|
||||
);
|
||||
const maxValue = computed(() => {
|
||||
if (!(props.data[key.value] && props.data[key.value].length)) {
|
||||
if (!props.data[key.value].length) {
|
||||
return 0;
|
||||
}
|
||||
const temp: number[] = props.data[key.value].map((i: any) => i.value);
|
||||
const temp: number[] = props.data?.[key.value].map((i: any) => i.value);
|
||||
return Math.max.apply(null, temp);
|
||||
});
|
||||
function handleClick(i: string) {
|
||||
copy(i);
|
||||
}
|
||||
function viewTrace(item: { name: string; refId: string; value: unknown; owner: object }) {
|
||||
const filters = {
|
||||
function viewTrace(item: TopListItem) {
|
||||
const filters: Filters = {
|
||||
...item,
|
||||
queryOrder: QueryOrders[1].value,
|
||||
status: Status[2].value,
|
||||
@@ -130,7 +130,7 @@ limitations under the License. -->
|
||||
};
|
||||
showTrace.value = true;
|
||||
}
|
||||
function viewDashboard(item: Recordable) {
|
||||
function viewDashboard(item: TopListItem) {
|
||||
const { owner } = item;
|
||||
let path;
|
||||
if (owner.scope === MetricCatalog.SERVICE) {
|
||||
|
@@ -85,12 +85,13 @@ limitations under the License. -->
|
||||
}
|
||||
}
|
||||
if (item.type === WidgetType.Tab) {
|
||||
const index = isNaN(item.activedTabIndex) ? 0 : item.activedTabIndex;
|
||||
widgets.push(
|
||||
...item.children[index].children.filter(
|
||||
const index = isNaN(item.activedTabIndex as number) ? 0 : (item.activedTabIndex as number);
|
||||
if (item.children && item.children[index]) {
|
||||
const list = item.children[index]?.children.filter(
|
||||
(d: LayoutConfig) => d.type === WidgetType.Widget && !ListChartTypes.includes(d.graph?.type || ""),
|
||||
),
|
||||
);
|
||||
);
|
||||
widgets.push(...list);
|
||||
}
|
||||
}
|
||||
}
|
||||
const configList = widgets.map((d: LayoutConfig) => ({
|
||||
|
@@ -168,6 +168,7 @@ limitations under the License. -->
|
||||
import type { Option } from "@/types/app";
|
||||
import InstanceMap from "@/views/dashboard/related/topology/pod/InstanceMap.vue";
|
||||
import HierarchyMap from "@/views/dashboard/related/topology/service/HierarchyMap.vue";
|
||||
import { Process, Instance, Endpoint } from "@/types/selector";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
@@ -175,7 +176,7 @@ limitations under the License. -->
|
||||
const topologyStore = useTopologyStore();
|
||||
const appStore = useAppStoreWithOut();
|
||||
const route = useRoute();
|
||||
const params = route?.params || {};
|
||||
const params: any = route?.params || {};
|
||||
const toolIcons = ref<{ name: string; content: string; id: WidgetType }[]>(AllTools);
|
||||
const loading = ref<boolean>(false);
|
||||
const showHierarchy = ref<boolean>(false);
|
||||
@@ -252,7 +253,8 @@ limitations under the License. -->
|
||||
ElMessage.error(json.errors);
|
||||
return;
|
||||
}
|
||||
let currentService, currentDestService;
|
||||
let currentService = null,
|
||||
currentDestService = null;
|
||||
if (states.currentService) {
|
||||
for (const d of selectorStore.services) {
|
||||
if (d.value === states.currentService) {
|
||||
@@ -274,22 +276,22 @@ limitations under the License. -->
|
||||
}
|
||||
selectorStore.setCurrentService(currentService);
|
||||
selectorStore.setCurrentDestService(currentDestService);
|
||||
states.currentService = selectorStore.currentService && selectorStore.currentService.value;
|
||||
states.currentDestService = selectorStore.currentDestService && selectorStore.currentDestService.value;
|
||||
states.currentService = selectorStore.currentService?.value || "";
|
||||
states.currentDestService = selectorStore.currentDestService?.value || "";
|
||||
}
|
||||
|
||||
async function setSourceSelector() {
|
||||
await selectorStore.getService(String(params.serviceId));
|
||||
states.currentService = selectorStore.currentService.value;
|
||||
states.currentService = selectorStore.currentService?.value || "";
|
||||
const e = String(params.entity).split("Relation")[0];
|
||||
|
||||
await fetchPods(e, selectorStore.currentService.id, true);
|
||||
await fetchPods(e, selectorStore.currentService?.id, true);
|
||||
}
|
||||
|
||||
async function setDestSelector() {
|
||||
await selectorStore.getService(String(params.destServiceId), true);
|
||||
states.currentDestService = selectorStore.currentDestService.value;
|
||||
await fetchPods(String(params.entity), selectorStore.currentDestService.id, true);
|
||||
states.currentDestService = selectorStore.currentDestService?.value || "";
|
||||
await fetchPods(String(params.entity), selectorStore.currentDestService?.id || "", true);
|
||||
}
|
||||
|
||||
async function getServices() {
|
||||
@@ -341,14 +343,14 @@ limitations under the License. -->
|
||||
EntityType[8].value,
|
||||
].includes(dashboardStore.entity)
|
||||
) {
|
||||
await fetchPods(e, selectorStore.currentService.id, true);
|
||||
await fetchPods(e, selectorStore.currentService?.id || "", true);
|
||||
}
|
||||
if (!selectorStore.currentDestService) {
|
||||
return;
|
||||
}
|
||||
states.currentDestService = selectorStore.currentDestService.value;
|
||||
if ([EntityType[5].value, EntityType[6].value, EntityType[7].value].includes(dashboardStore.entity)) {
|
||||
await fetchPods(dashboardStore.entity, selectorStore.currentDestService.id, true);
|
||||
await fetchPods(dashboardStore.entity, selectorStore.currentDestService?.id || "", true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +362,7 @@ limitations under the License. -->
|
||||
states.currentPod = "";
|
||||
states.currentProcess = "";
|
||||
const e = dashboardStore.entity.split("Relation")[0];
|
||||
fetchPods(e, selectorStore.currentService.id, true);
|
||||
fetchPods(e, selectorStore.currentService?.id, true);
|
||||
} else {
|
||||
selectorStore.setCurrentService(null);
|
||||
}
|
||||
@@ -373,7 +375,7 @@ limitations under the License. -->
|
||||
selectorStore.setCurrentDestPod(null);
|
||||
states.currentDestPod = "";
|
||||
states.currentDestProcess = "";
|
||||
fetchPods(dashboardStore.entity, selectorStore.currentDestService.id, true);
|
||||
fetchPods(dashboardStore.entity, selectorStore.currentDestService?.id || "", true);
|
||||
} else {
|
||||
selectorStore.setCurrentDestService(null);
|
||||
}
|
||||
@@ -395,12 +397,12 @@ limitations under the License. -->
|
||||
}
|
||||
}
|
||||
|
||||
function changeDestProcess(pod: Option[]) {
|
||||
selectorStore.setCurrentDestProcess(pod[0] || null);
|
||||
function changeDestProcess(pod: Process[]) {
|
||||
selectorStore.setCurrentDestProcess(pod[0]);
|
||||
states.currentDestProcess = pod[0].label || "";
|
||||
}
|
||||
|
||||
function changeProcess(pod: Option[]) {
|
||||
function changeProcess(pod: Process[]) {
|
||||
selectorStore.setCurrentProcess(pod[0] || null);
|
||||
states.currentProcess = pod[0].label || "";
|
||||
}
|
||||
@@ -447,7 +449,10 @@ limitations under the License. -->
|
||||
dashboardStore.addControl(id);
|
||||
}
|
||||
|
||||
async function fetchPods(type: string, serviceId: string, setPod: boolean, param?: { keyword?: string }) {
|
||||
async function fetchPods(type: string, serviceId: string | undefined, setPod: boolean, param?: { keyword?: string }) {
|
||||
if (!serviceId) {
|
||||
return;
|
||||
}
|
||||
let resp;
|
||||
switch (type) {
|
||||
case EntityType[2].value:
|
||||
@@ -517,11 +522,11 @@ limitations under the License. -->
|
||||
|
||||
async function fetchProcess(setPod: boolean) {
|
||||
const resp = await selectorStore.getProcesses({
|
||||
instanceId: selectorStore.currentPod.id,
|
||||
instanceId: selectorStore.currentPod?.id || "",
|
||||
});
|
||||
if (setPod) {
|
||||
const process = selectorStore.currentProcess?.id || params.processId || selectorStore.processes[0].id;
|
||||
const currentProcess = selectorStore.processes.find((d: { id: string }) => d.id === process);
|
||||
const currentProcess = selectorStore.processes.find((d: Process) => d.id === process);
|
||||
if (currentProcess) {
|
||||
selectorStore.setCurrentProcess(currentProcess);
|
||||
states.currentProcess = currentProcess.label;
|
||||
@@ -534,7 +539,7 @@ limitations under the License. -->
|
||||
}
|
||||
async function fetchDestProcess(setPod: boolean) {
|
||||
const resp = await selectorStore.getProcesses({
|
||||
instanceId: selectorStore.currentDestPod.id,
|
||||
instanceId: selectorStore.currentDestPod?.id,
|
||||
isRelation: true,
|
||||
});
|
||||
if (setPod) {
|
||||
@@ -572,7 +577,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
const destPod = selectorStore.currentDestPod?.id || params.destPodId || selectorStore.destPods[0].id;
|
||||
const currentDestPod = selectorStore.destPods.find((d: { id: string }) => d.id === destPod);
|
||||
const currentDestPod = selectorStore.destPods.find((d: Instance | Endpoint) => d.id === destPod);
|
||||
if (!currentDestPod) {
|
||||
states.currentDestPod = "";
|
||||
selectorStore.setCurrentDestPod(null);
|
||||
@@ -604,7 +609,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
const pod = selectorStore.currentPod?.id || params.podId || selectorStore.pods[0].id;
|
||||
const currentPod = selectorStore.pods.find((d: { id: string }) => d.id === pod);
|
||||
const currentPod = selectorStore.pods.find((d: Endpoint | Instance) => d.id === pod);
|
||||
if (!currentPod) {
|
||||
selectorStore.setCurrentPod(null);
|
||||
states.currentPod = "";
|
||||
@@ -651,13 +656,13 @@ limitations under the License. -->
|
||||
const param = {
|
||||
keyword: query,
|
||||
};
|
||||
fetchPods(EntityType[2].value, selectorStore.currentService.id, false, param);
|
||||
fetchPods(EntityType[2].value, selectorStore.currentService?.id, false, param);
|
||||
}
|
||||
function searchDestPods(query: string) {
|
||||
const param = {
|
||||
keyword: query,
|
||||
};
|
||||
fetchPods(EntityType[6].value, selectorStore.currentDestService.id, false, param);
|
||||
fetchPods(EntityType[6].value, selectorStore.currentDestService?.id, false, param);
|
||||
}
|
||||
function viewTopology() {
|
||||
showHierarchy.value = true;
|
||||
|
@@ -35,12 +35,12 @@ limitations under the License. -->
|
||||
import EBPFStack from "@/views/dashboard/related/ebpf/components/EBPFStack.vue";
|
||||
import { ComponentType } from "./components/data";
|
||||
|
||||
const asyncProfilingStore = useAsyncProfilingStore();
|
||||
const asyncProfilingStore: ReturnType<typeof useAsyncProfilingStore> = useAsyncProfilingStore();
|
||||
const selectorStore = useSelectorStore();
|
||||
|
||||
onMounted(async () => {
|
||||
const resp = await asyncProfilingStore.getServiceInstances({ serviceId: selectorStore.currentService.id });
|
||||
if (resp && resp.errors) {
|
||||
const resp = await asyncProfilingStore.getServiceInstances({ serviceId: selectorStore.currentService?.id || "" });
|
||||
if (resp?.errors) {
|
||||
ElMessage.error(resp.errors);
|
||||
}
|
||||
});
|
||||
|
@@ -50,7 +50,7 @@ limitations under the License. -->
|
||||
const serviceInstanceIds = ref<string[]>([]);
|
||||
const selectedEventType = ref<string>("");
|
||||
const eventTypes = computed(() =>
|
||||
(asyncProfilingStore.selectedTask.events ?? [])
|
||||
(asyncProfilingStore.selectedTask?.events || [])
|
||||
.map((d: string) => {
|
||||
if (d === ProfilingEvents[1]) {
|
||||
return [
|
||||
@@ -65,7 +65,7 @@ limitations under the License. -->
|
||||
);
|
||||
const instances = computed(() =>
|
||||
asyncProfilingStore.instances.filter((d: Instance) =>
|
||||
(asyncProfilingStore.selectedTask.successInstanceIds ?? []).includes(d.id),
|
||||
(asyncProfilingStore.selectedTask?.successInstanceIds || []).includes(d.id || ""),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -80,12 +80,12 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
async function analyzeProfiling() {
|
||||
const instanceIds = asyncProfilingStore.instances
|
||||
const instanceIds = (asyncProfilingStore.instances || [])
|
||||
.filter((d: Instance) => (serviceInstanceIds.value ?? []).includes(d.value))
|
||||
.map((d: Instance) => d.id);
|
||||
.map((d: Instance) => d.id || "") as string[];
|
||||
const res = await asyncProfilingStore.getAsyncProfilingAnalyze({
|
||||
instanceIds,
|
||||
taskId: asyncProfilingStore.selectedTask.id,
|
||||
taskId: asyncProfilingStore.selectedTask?.id || "",
|
||||
eventType: (EventsMap as any)[selectedEventType.value],
|
||||
});
|
||||
if (res.data && res.data.errors) {
|
||||
@@ -95,7 +95,7 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
watch(
|
||||
() => asyncProfilingStore.selectedTask.successInstanceIds,
|
||||
() => asyncProfilingStore.selectedTask?.successInstanceIds,
|
||||
() => {
|
||||
serviceInstanceIds.value = [];
|
||||
selectedEventType.value = "";
|
||||
|
@@ -114,6 +114,7 @@ limitations under the License. -->
|
||||
import { useSelectorStore } from "@/store/modules/selectors";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { DurationOptions, ProfilingEvents } from "./data";
|
||||
import type { AsyncProfileTaskCreationRequest } from "@/types/async-profiling";
|
||||
|
||||
/* global defineEmits */
|
||||
const emits = defineEmits(["close"]);
|
||||
@@ -165,12 +166,12 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
const params = {
|
||||
serviceId: selectorStore.currentService.id,
|
||||
serviceId: selectorStore.currentService?.id,
|
||||
serviceInstanceIds: serviceInstanceIds.value,
|
||||
duration: finalDuration,
|
||||
events: asyncEvents.value,
|
||||
execArgs: execArgs.value,
|
||||
};
|
||||
} as AsyncProfileTaskCreationRequest;
|
||||
loading.value = true;
|
||||
const res = await asyncProfilingStore.createTask(params);
|
||||
loading.value = false;
|
||||
|
@@ -26,7 +26,7 @@ limitations under the License. -->
|
||||
@click="changeTask(i)"
|
||||
:key="index"
|
||||
:class="{
|
||||
selected: asyncProfilingStore.selectedTask.id === i.id,
|
||||
selected: asyncProfilingStore.selectedTask?.id === i.id,
|
||||
}"
|
||||
>
|
||||
<td class="profile-td">
|
||||
@@ -50,7 +50,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="showDetail" :destroy-on-close="true" fullscreen @closed="showDetail = false">
|
||||
<div class="profile-detail flex-v" v-if="asyncProfilingStore.selectedTask.id">
|
||||
<div class="profile-detail flex-v" v-if="asyncProfilingStore.selectedTask?.id">
|
||||
<div>
|
||||
<h5 class="mb-10">{{ t("task") }}.</h5>
|
||||
<div class="mb-10 clear item">
|
||||
@@ -67,20 +67,15 @@ limitations under the License. -->
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("duration") }}:</span>
|
||||
<span class="g-sm-8 wba">{{ asyncProfilingStore.selectedTask.duration / 60 }}min</span>
|
||||
<span class="g-sm-8 wba">{{ asyncProfilingStore.selectedTask?.duration / 60 }}min</span>
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("events") }}:</span>
|
||||
<span class="g-sm-8 wba"> {{ asyncProfilingStore.selectedTask.events.join(", ") }} </span>
|
||||
<span class="g-sm-8 wba"> {{ (asyncProfilingStore.selectedTask?.events || []).join(", ") }} </span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h5
|
||||
class="mb-5 mt-10"
|
||||
v-show="asyncProfilingStore.selectedTask.logs && asyncProfilingStore.selectedTask.logs.length"
|
||||
>
|
||||
{{ t("logs") }}.
|
||||
</h5>
|
||||
<h5 class="mb-5 mt-10" v-show="asyncProfilingStore.selectedTask?.logs?.length"> {{ t("logs") }}. </h5>
|
||||
<div v-for="(i, index) in Object.keys(instanceLogs)" :key="index">
|
||||
<div class="sm">
|
||||
<span class="mr-10 grey">{{ t("instance") }}:</span>
|
||||
@@ -128,7 +123,8 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useSelectorStore } from "@/store/modules/selectors";
|
||||
import { useAsyncProfilingStore } from "@/store/modules/async-profiling";
|
||||
import type { TaskLog, TaskListItem } from "@/types/profile";
|
||||
import type { TaskLog } from "@/types/profile";
|
||||
import type { AsyncProfilingTask } from "@/types/async-profiling";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { dateFormat } from "@/utils/dateFormat";
|
||||
import type { Instance, Service } from "@/types/selector";
|
||||
@@ -156,13 +152,13 @@ limitations under the License. -->
|
||||
}
|
||||
}
|
||||
|
||||
async function changeTask(item: TaskListItem) {
|
||||
if (item.id !== asyncProfilingStore.selectedTask.id) {
|
||||
async function changeTask(item: AsyncProfilingTask) {
|
||||
if (item.id !== asyncProfilingStore.selectedTask?.id) {
|
||||
asyncProfilingStore.setAnalyzeTrees([]);
|
||||
asyncProfilingStore.setSelectedTask(item);
|
||||
}
|
||||
service.value = (selectorStore.services.filter((s: Service) => s.id === item.serviceId)[0] ?? {}).label;
|
||||
const res = await asyncProfilingStore.getTaskLogs({ taskId: item.id });
|
||||
const res = await asyncProfilingStore.getTaskLogs({ taskID: item.id });
|
||||
|
||||
if (res.errors) {
|
||||
ElMessage.error(res.errors);
|
||||
|
@@ -19,38 +19,38 @@ limitations under the License. -->
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("taskId") }}:</span>
|
||||
<span class="g-sm-8 wba">
|
||||
{{ details.taskId }}
|
||||
{{ details?.taskId || "" }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("service") }}:</span>
|
||||
<span class="g-sm-8 wba">
|
||||
{{ details.serviceName }}
|
||||
{{ details?.serviceName || "" }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("labels") }}:</span>
|
||||
<span class="g-sm-8 wba">
|
||||
{{ details.processLabels.join(";") }}
|
||||
{{ details?.processLabels?.join(";") }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("monitorTime") }}:</span>
|
||||
<span class="g-sm-8 wba">
|
||||
{{ dateFormat(details.taskStartTime) }}
|
||||
{{ dateFormat(details?.taskStartTime || NaN) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("monitorDuration") }}:</span>
|
||||
<span class="g-sm-8 wba"> {{ details.fixedTriggerDuration / 60 }} min </span>
|
||||
<span class="g-sm-8 wba"> {{ (details?.fixedTriggerDuration || 0) / 60 }} min </span>
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("triggerType") }}:</span>
|
||||
<span class="g-sm-8 wba">{{ details.triggerType }}</span>
|
||||
<span class="g-sm-8 wba">{{ details?.triggerType }}</span>
|
||||
</div>
|
||||
<div class="mb-10 clear item">
|
||||
<span class="g-sm-4 grey">{{ t("targetType") }}:</span>
|
||||
<span class="g-sm-8 wba">{{ details.targetType }}</span>
|
||||
<span class="g-sm-8 wba">{{ details?.targetType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -61,10 +61,10 @@ limitations under the License. -->
|
||||
import { useI18n } from "vue-i18n";
|
||||
import type { EBPFTaskList } from "@/types/ebpf";
|
||||
|
||||
/*global defineProps */
|
||||
/*global defineProps, Nullable */
|
||||
defineProps({
|
||||
details: {
|
||||
type: Object as PropType<EBPFTaskList>,
|
||||
type: Object as PropType<Nullable<EBPFTaskList>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
@@ -84,6 +84,7 @@ limitations under the License. -->
|
||||
import router from "@/router";
|
||||
import { HeaderLabels, HeaderChildLabels } from "../data";
|
||||
import { EntityType } from "../../../data";
|
||||
import type { Instance } from "@/types/selector";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
@@ -97,14 +98,14 @@ limitations under the License. -->
|
||||
const selectorStore = useSelectorStore();
|
||||
const continousProfilingStore = useContinousProfilingStore();
|
||||
const pageSize = 10;
|
||||
const currentInstances = ref<MonitorInstance[]>([]);
|
||||
const currentInstances = ref<Instance[]>([]);
|
||||
|
||||
function viewProcessDashboard(process: MonitorProcess, instance: MonitorInstance) {
|
||||
if (!props.config.processDashboardName) {
|
||||
return;
|
||||
}
|
||||
router.push(
|
||||
`/dashboard/${dashboardStore.layerId}/${EntityType[8].value}/${selectorStore.currentService.id}/${instance.id}/${process.id}/${props.config.processDashboardName}`,
|
||||
`/dashboard/${dashboardStore.layerId}/${EntityType[8].value}/${selectorStore.currentService?.id}/${instance.id}/${process.id}/${props.config.processDashboardName}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,12 +114,12 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
router.push(
|
||||
`/dashboard/${dashboardStore.layerId}/${EntityType[3].value}/${selectorStore.currentService.id}/${instance.id}/${props.config.instanceDashboardName}`,
|
||||
`/dashboard/${dashboardStore.layerId}/${EntityType[3].value}/${selectorStore.currentService?.id}/${instance.id}/${props.config.instanceDashboardName}`,
|
||||
);
|
||||
}
|
||||
|
||||
async function changePage(pageIndex: number) {
|
||||
currentInstances.value = continousProfilingStore.instances.filter((d: unknown, index: number) => {
|
||||
currentInstances.value = continousProfilingStore.instances.filter((d: Instance, index: number) => {
|
||||
if (index >= (pageIndex - 1) * pageSize && index < pageIndex * pageSize) {
|
||||
return d;
|
||||
}
|
||||
@@ -129,7 +130,7 @@ limitations under the License. -->
|
||||
() => continousProfilingStore.instances,
|
||||
() => {
|
||||
currentInstances.value = continousProfilingStore.instances.filter(
|
||||
(_: unknown, index: number) => index < pageSize,
|
||||
(_: Instance, index: number) => index < pageSize,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@@ -35,7 +35,7 @@ limitations under the License. -->
|
||||
<td
|
||||
class="profile-td"
|
||||
:class="{
|
||||
selected: continousProfilingStore.selectedStrategy.id === i.id,
|
||||
selected: continousProfilingStore.selectedStrategy?.id === i.id,
|
||||
}"
|
||||
v-if="i.type"
|
||||
>
|
||||
@@ -81,7 +81,7 @@ limitations under the License. -->
|
||||
|
||||
const { t } = useI18n();
|
||||
const selectorStore = useSelectorStore();
|
||||
const continousProfilingStore = useContinousProfilingStore();
|
||||
const continousProfilingStore: ReturnType<typeof useContinousProfilingStore> = useContinousProfilingStore();
|
||||
const updateStrategies = ref<boolean>(false);
|
||||
const inProcess = ref<boolean>(false);
|
||||
|
||||
|
@@ -77,7 +77,7 @@ limitations under the License. -->
|
||||
}
|
||||
toRaw(monacoInstance.value).dispose();
|
||||
monacoInstance.value = null;
|
||||
demandLogStore.setLogs("");
|
||||
demandLogStore.setLogs([]);
|
||||
});
|
||||
watch(
|
||||
() => appStore.theme,
|
||||
|
@@ -152,7 +152,7 @@ limitations under the License. -->
|
||||
if (!(state.instance.id || (selectorStore.currentPod && selectorStore.currentPod.id))) {
|
||||
return;
|
||||
}
|
||||
const resp = await demandLogStore.getContainers(state.instance.id || selectorStore.currentPod.id);
|
||||
const resp = await demandLogStore.getContainers(state.instance.id || selectorStore.currentPod?.id || "");
|
||||
if (resp.errors) {
|
||||
disabled.value = true;
|
||||
ElMessage.error(resp.errors);
|
||||
@@ -193,7 +193,7 @@ limitations under the License. -->
|
||||
function searchLogs() {
|
||||
let instance = "";
|
||||
if (dashboardStore.entity === EntityType[3].value) {
|
||||
instance = selectorStore.currentPod.id;
|
||||
instance = selectorStore.currentPod?.id || "";
|
||||
}
|
||||
const serviceInstanceId = instance || (state.instance && state.instance.id) || "";
|
||||
demandLogStore.setLogCondition({
|
||||
@@ -247,6 +247,7 @@ limitations under the License. -->
|
||||
const keywordsOfContentList = keywordsOfContent.value || [];
|
||||
keywordsOfContentList.splice(index, 1);
|
||||
demandLogStore.setLogCondition({
|
||||
...demandLogStore.conditions,
|
||||
keywordsOfContent: keywordsOfContentList,
|
||||
});
|
||||
contentStr.value = "";
|
||||
@@ -262,12 +263,14 @@ limitations under the License. -->
|
||||
if (type === "keywordsOfContent") {
|
||||
keywordsOfContent.value.push(contentStr.value);
|
||||
demandLogStore.setLogCondition({
|
||||
...demandLogStore.conditions,
|
||||
[type]: keywordsOfContent.value,
|
||||
});
|
||||
contentStr.value = "";
|
||||
} else if (type === "excludingKeywordsOfContent") {
|
||||
excludingKeywordsOfContent.value.push(excludingContentStr.value);
|
||||
demandLogStore.setLogCondition({
|
||||
...demandLogStore.conditions,
|
||||
[type]: excludingKeywordsOfContent.value,
|
||||
});
|
||||
excludingContentStr.value = "";
|
||||
@@ -277,6 +280,7 @@ limitations under the License. -->
|
||||
function removeExcludeContent(index: number) {
|
||||
excludingKeywordsOfContent.value.splice(index, 1);
|
||||
demandLogStore.setLogCondition({
|
||||
...demandLogStore.conditions,
|
||||
excludingKeywordsOfContent: excludingKeywordsOfContent.value,
|
||||
});
|
||||
excludingContentStr.value = "";
|
||||
@@ -297,7 +301,7 @@ limitations under the License. -->
|
||||
() => {
|
||||
if (dashboardStore.entity === EntityType[0].value) {
|
||||
fetchSelectors();
|
||||
demandLogStore.setLogs("");
|
||||
demandLogStore.setLogs([]);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -306,7 +310,7 @@ limitations under the License. -->
|
||||
() => {
|
||||
if (dashboardStore.entity === EntityType[3].value) {
|
||||
fetchSelectors();
|
||||
demandLogStore.setLogs("");
|
||||
demandLogStore.setLogs([]);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@@ -68,7 +68,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
newTask.value = true;
|
||||
ebpfStore.getCreateTaskData(selectorStore.currentService.id);
|
||||
ebpfStore.getCreateTaskData(selectorStore.currentService.id || "");
|
||||
}
|
||||
|
||||
watch(
|
||||
|
@@ -32,7 +32,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
<div class="flex-h">
|
||||
<Selector
|
||||
v-if="ebpfStore.selectedTask.targetType === 'OFF_CPU'"
|
||||
v-if="ebpfStore.selectedTask?.targetType === 'OFF_CPU'"
|
||||
:value="aggregateType"
|
||||
:options="AggregateTypes"
|
||||
size="small"
|
||||
@@ -102,7 +102,7 @@ limitations under the License. -->
|
||||
import { dateFormat } from "@/utils/dateFormat";
|
||||
|
||||
const { t } = useI18n();
|
||||
const ebpfStore = useEbpfStore();
|
||||
const ebpfStore: ReturnType<typeof useEbpfStore> = useEbpfStore();
|
||||
const pageSize = 5;
|
||||
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
||||
const selectedProcesses = ref<string[]>([]);
|
||||
@@ -163,7 +163,7 @@ limitations under the License. -->
|
||||
}
|
||||
}
|
||||
const res = await ebpfStore.getEBPFAnalyze({
|
||||
scheduleIdList,
|
||||
scheduleIdList: scheduleIdList as string[],
|
||||
timeRanges,
|
||||
aggregateType: aggregateType.value,
|
||||
});
|
||||
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License. -->
|
||||
<template>
|
||||
<div id="graph-stack" ref="graph">
|
||||
<span class="tip" v-show="ebpfStore.ebpfTips">{{ ebpfStore.ebpfTips }}</span>
|
||||
<span class="tip" v-show="(ebpfStore as any).ebpfTips">{{ (ebpfStore as any).ebpfTips }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@@ -25,6 +25,7 @@ limitations under the License. -->
|
||||
import { useEbpfStore } from "@/store/modules/ebpf";
|
||||
import { useAsyncProfilingStore } from "@/store/modules/async-profiling";
|
||||
import type { StackElement } from "@/types/ebpf";
|
||||
import type { StackElement as AsyncProfilingStackElement } from "@/types/async-profiling";
|
||||
import { AggregateTypes } from "./data";
|
||||
import { JFREventType, ComponentType } from "@/views/dashboard/related/async-profiling/components/data";
|
||||
import "d3-flame-graph/dist/d3-flamegraph.css";
|
||||
@@ -37,7 +38,8 @@ limitations under the License. -->
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
const ebpfStore = props.type === ComponentType ? useAsyncProfilingStore() : useEbpfStore();
|
||||
const ebpfStore: ReturnType<typeof useAsyncProfilingStore | typeof useEbpfStore> =
|
||||
props.type === ComponentType ? useAsyncProfilingStore() : useEbpfStore();
|
||||
const stackTree = ref<Nullable<StackElement>>(null);
|
||||
const selectStack = ref<Nullable<StackElement>>(null);
|
||||
const graph = ref<Nullable<HTMLDivElement>>(null);
|
||||
@@ -67,12 +69,15 @@ limitations under the License. -->
|
||||
};
|
||||
countRange();
|
||||
if (props.type === ComponentType) {
|
||||
const elements = processTree(ebpfStore.analyzeTrees[0].elements);
|
||||
const elements = processTree(
|
||||
((ebpfStore as ReturnType<typeof useAsyncProfilingStore>).analyzeTrees[0].elements ||
|
||||
[]) as AsyncProfilingStackElement[],
|
||||
);
|
||||
stackTree.value = elements;
|
||||
root = { ...root, ...elements };
|
||||
} else {
|
||||
for (const tree of ebpfStore.analyzeTrees) {
|
||||
const ele = processTree(tree.elements);
|
||||
for (const tree of (ebpfStore as ReturnType<typeof useEbpfStore>).analyzeTrees) {
|
||||
const ele = processTree(tree.elements as StackElement[]);
|
||||
root.children && root.children.push(ele);
|
||||
}
|
||||
const param = (root.children || []).reduce(
|
||||
@@ -134,7 +139,7 @@ limitations under the License. -->
|
||||
if (!ebpfStore.analyzeTrees.length) {
|
||||
return;
|
||||
}
|
||||
const { type } = ebpfStore.analyzeTrees[0];
|
||||
const { type } = ebpfStore.analyzeTrees[0] as any;
|
||||
if ([JFREventType.LOCK].includes(type)) {
|
||||
return `<div class="mb-5">Duration: ${item.dumpCount} ns</div>`;
|
||||
}
|
||||
@@ -144,15 +149,15 @@ limitations under the License. -->
|
||||
return `<div class="mb-5">Memory: ${item.dumpCount} byte</div>`;
|
||||
}
|
||||
|
||||
ebpfStore.aggregateType === AggregateTypes[0].value
|
||||
(ebpfStore as ReturnType<typeof useEbpfStore>).aggregateType === AggregateTypes[0].value
|
||||
? `<div class="mb-5">Dump Count: ${item.dumpCount}</div>`
|
||||
: `<div class="mb-5">Duration: ${item.dumpCount} ns</div>`;
|
||||
}
|
||||
|
||||
function countRange() {
|
||||
const list = [];
|
||||
for (const tree of ebpfStore.analyzeTrees) {
|
||||
for (const ele of tree.elements) {
|
||||
for (const tree of (ebpfStore as ReturnType<typeof useEbpfStore>).analyzeTrees) {
|
||||
for (const ele of tree.elements || []) {
|
||||
list.push(ele.dumpCount);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +165,7 @@ limitations under the License. -->
|
||||
min.value = Math.min(...list);
|
||||
}
|
||||
|
||||
function processTree(arr: StackElement[]) {
|
||||
function processTree(arr: StackElement[] | AsyncProfilingStackElement[]) {
|
||||
const copyArr = JSON.parse(JSON.stringify(arr));
|
||||
const obj: any = {};
|
||||
let res = null;
|
||||
|
@@ -77,6 +77,7 @@ limitations under the License. -->
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { InitTaskField, TargetTypes } from "./data";
|
||||
import type { EBPFTaskCreationRequest } from "@/types/ebpf";
|
||||
|
||||
/* global defineEmits */
|
||||
const emits = defineEmits(["close"]);
|
||||
@@ -109,13 +110,16 @@ limitations under the License. -->
|
||||
}
|
||||
disabled.value = true;
|
||||
const date = monitorTime.value === "0" ? new Date() : time.value;
|
||||
if (!selectorStore.currentService?.id) {
|
||||
return;
|
||||
}
|
||||
const params = {
|
||||
serviceId: selectorStore.currentService.id,
|
||||
serviceId: selectorStore.currentService?.id,
|
||||
processLabels: labels.value,
|
||||
startTime: date.getTime(),
|
||||
duration: monitorDuration.value * 60,
|
||||
targetType: type.value,
|
||||
};
|
||||
} as EBPFTaskCreationRequest;
|
||||
const res = await eBPFStore.createTask(params);
|
||||
if (res.errors) {
|
||||
ElMessage.error(res.errors);
|
||||
|
@@ -25,7 +25,7 @@ limitations under the License. -->
|
||||
<td
|
||||
class="profile-td"
|
||||
:class="{
|
||||
selected: ebpfStore.selectedTask.taskId === i.taskId,
|
||||
selected: ebpfStore.selectedTask?.taskId === i.taskId,
|
||||
}"
|
||||
>
|
||||
<div class="ell">
|
||||
@@ -37,9 +37,9 @@ limitations under the License. -->
|
||||
</a>
|
||||
</div>
|
||||
<div class="grey ell sm">
|
||||
<span class="mr-10 sm">{{ dateFormat(i.taskStartTime) }}</span>
|
||||
<span class="mr-10 sm">{{ dateFormat(i.taskStartTime || NaN) }}</span>
|
||||
<span class="mr-10 sm">
|
||||
{{ dateFormat(i.taskStartTime + i.fixedTriggerDuration * 1000) }}
|
||||
{{ dateFormat(i.taskStartTime + (i.fixedTriggerDuration || 0) * 1000) }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
@@ -61,14 +61,15 @@ limitations under the License. -->
|
||||
import TaskDetails from "../../components/TaskDetails.vue";
|
||||
import { dateFormat } from "@/utils/dateFormat";
|
||||
|
||||
/* global Nullable */
|
||||
const { t } = useI18n();
|
||||
const ebpfStore = useEbpfStore();
|
||||
const viewDetail = ref<boolean>(false);
|
||||
|
||||
async function changeTask(item: EBPFTaskList) {
|
||||
async function changeTask(item: Nullable<EBPFTaskList>) {
|
||||
ebpfStore.setSelectedTask(item);
|
||||
const res = await ebpfStore.getEBPFSchedules({
|
||||
taskId: item.taskId,
|
||||
taskId: item?.taskId || "",
|
||||
});
|
||||
if (res.errors) {
|
||||
ElMessage.error(res.errors);
|
||||
|
@@ -16,11 +16,11 @@ limitations under the License. -->
|
||||
<div ref="timeline" class="events"></div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted } from "vue";
|
||||
import { ref, watch, onMounted, PropType } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
import { useThrottleFn } from "@vueuse/core";
|
||||
import type { Event } from "@/types/events";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
import type { LayoutConfig, DashboardItem } from "@/types/dashboard";
|
||||
import { useEventStore } from "@/store/modules/event";
|
||||
import { DataSet, Timeline } from "vis-timeline/standalone";
|
||||
import "vis-timeline/styles/vis-timeline-graph2d.css";
|
||||
@@ -32,10 +32,10 @@ limitations under the License. -->
|
||||
import { WidgetType } from "@/views/dashboard/data";
|
||||
|
||||
const eventStore = useEventStore();
|
||||
/*global defineProps, Nullable */
|
||||
/*global Nullable */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
@@ -106,7 +106,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
dashboardStore.selectWidget(props.data);
|
||||
const dashboard = getDashboard(dashboardStore.currentDashboard).widgets;
|
||||
const dashboard = getDashboard(dashboardStore.currentDashboard as DashboardItem).widgets;
|
||||
associateMetrics(properties.items, events, dashboard);
|
||||
associateTraceLog(properties.items, events, dashboard);
|
||||
});
|
||||
@@ -130,11 +130,10 @@ limitations under the License. -->
|
||||
const i = events[index - 1 || 0];
|
||||
for (const widget of widgets) {
|
||||
if (isNaN(index)) {
|
||||
const item = {
|
||||
const item: LayoutConfig = {
|
||||
...widget,
|
||||
filters: {
|
||||
sourceId: props.data.id || "",
|
||||
duration: null,
|
||||
},
|
||||
};
|
||||
dashboardStore.setWidget(item);
|
||||
@@ -154,8 +153,8 @@ limitations under the License. -->
|
||||
filters: {
|
||||
sourceId: props.data.id || "",
|
||||
duration: {
|
||||
start: dateFormatStep(getLocalTime(appStore.utc, start), step, true),
|
||||
end: dateFormatStep(getLocalTime(appStore.utc, end), step, true),
|
||||
startTime: dateFormatStep(getLocalTime(appStore.utc, start), step, true),
|
||||
endTime: dateFormatStep(getLocalTime(appStore.utc, end), step, true),
|
||||
step,
|
||||
},
|
||||
},
|
||||
@@ -187,14 +186,14 @@ limitations under the License. -->
|
||||
|
||||
for (const widget of widgets) {
|
||||
if (isNaN(index)) {
|
||||
const item = {
|
||||
const item: LayoutConfig = {
|
||||
...widget,
|
||||
filters: {
|
||||
sourceId: dashboardStore.selectedGrid.id || "",
|
||||
sourceId: dashboardStore.selectedGrid?.id || "",
|
||||
isRange: true,
|
||||
duration: {
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -203,10 +202,10 @@ limitations under the License. -->
|
||||
const { start, end } = setEndTime(i.start, i.end);
|
||||
const startTime = dateFormatTime(start, appStore.duration.step);
|
||||
const endTime = dateFormatTime(end, appStore.duration.step);
|
||||
const item = {
|
||||
const item: LayoutConfig = {
|
||||
...widget,
|
||||
filters: {
|
||||
sourceId: dashboardStore.selectedGrid.id || "",
|
||||
sourceId: dashboardStore.selectedGrid?.id || "",
|
||||
isRange: true,
|
||||
duration: {
|
||||
startTime,
|
||||
|
@@ -150,7 +150,6 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
eventStore.setEventCondition({
|
||||
// layer: dashboardStore.layerId,
|
||||
paging: {
|
||||
pageNum: pageNum.value,
|
||||
pageSize: pageSize,
|
||||
|
@@ -150,17 +150,22 @@ limitations under the License. -->
|
||||
needQuery: { type: Boolean, default: true },
|
||||
data: {
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStoreWithOut();
|
||||
const appStore: ReturnType<typeof useAppStoreWithOut> = useAppStoreWithOut();
|
||||
const selectorStore = useSelectorStore();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const logStore = useLogStore();
|
||||
const { setDurationRow, getDurationTime, getMaxRange } = useDuration();
|
||||
const traceId = ref<string>((props.data.filters && props.data.filters.traceId) || "");
|
||||
const duration = ref<DurationTime>((props.data.filters && props.data.filters.duration) || getDurationTime());
|
||||
const traceId = ref<string>(props.data.filters?.traceId || "");
|
||||
const { duration: filtersDuration } = props.data.filters || {};
|
||||
const duration = ref<DurationTime>(
|
||||
filtersDuration
|
||||
? { start: filtersDuration.startTime || "", end: filtersDuration.endTime || "", step: filtersDuration.step || "" }
|
||||
: getDurationTime(),
|
||||
);
|
||||
const keywordsOfContent = ref<string[]>([]);
|
||||
const excludingKeywordsOfContent = ref<string[]>([]);
|
||||
const tagsList = ref<string[]>([]);
|
||||
@@ -175,17 +180,17 @@ limitations under the License. -->
|
||||
service: { value: "", label: "" },
|
||||
category: { value: "ALL", label: "All" },
|
||||
});
|
||||
const maxRange = computed(() =>
|
||||
getMaxRange(
|
||||
appStore.coldStageMode
|
||||
? isBrowser.value
|
||||
? appStore.recordsTTL.coldBrowserErrorLog
|
||||
: appStore.recordsTTL.coldLog
|
||||
: isBrowser.value
|
||||
? appStore.recordsTTL.browserErrorLog
|
||||
: appStore.recordsTTL.log,
|
||||
),
|
||||
);
|
||||
const maxRange = computed(() => {
|
||||
const ttl = appStore.coldStageMode
|
||||
? isBrowser.value
|
||||
? appStore.recordsTTL?.coldBrowserErrorLog
|
||||
: appStore.recordsTTL?.coldLog
|
||||
: isBrowser.value
|
||||
? appStore.recordsTTL?.browserErrorLog
|
||||
: appStore.recordsTTL?.log;
|
||||
|
||||
return getMaxRange(ttl as number);
|
||||
});
|
||||
if (props.needQuery) {
|
||||
init();
|
||||
}
|
||||
@@ -259,10 +264,10 @@ limitations under the License. -->
|
||||
let endpoint = "",
|
||||
instance = "";
|
||||
if (dashboardStore.entity === EntityType[2].value) {
|
||||
endpoint = selectorStore.currentPod.id;
|
||||
endpoint = selectorStore.currentPod?.id || "";
|
||||
}
|
||||
if (dashboardStore.entity === EntityType[3].value) {
|
||||
instance = selectorStore.currentPod.id;
|
||||
instance = selectorStore.currentPod?.id || "";
|
||||
}
|
||||
if (dashboardStore.layerId === "BROWSER") {
|
||||
logStore.setLogCondition({
|
||||
@@ -396,8 +401,15 @@ limitations under the License. -->
|
||||
if (JSON.stringify(newJson) === JSON.stringify(oldJson)) {
|
||||
return;
|
||||
}
|
||||
traceId.value = props.data.filters.traceId || "";
|
||||
duration.value = props.data.filters.duration || getDurationTime();
|
||||
const { traceId: filtersTraceId, duration: filtersDuration } = props.data.filters || {};
|
||||
traceId.value = filtersTraceId || "";
|
||||
duration.value = filtersDuration
|
||||
? {
|
||||
start: filtersDuration.startTime || "",
|
||||
end: filtersDuration.endTime || "",
|
||||
step: filtersDuration.step || "",
|
||||
}
|
||||
: getDurationTime();
|
||||
init();
|
||||
}
|
||||
},
|
||||
|
@@ -39,19 +39,19 @@ limitations under the License. -->
|
||||
import { ServiceLogConstants } from "./data";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
import type { LayoutConfig, DashboardItem } from "@/types/dashboard";
|
||||
import { dateFormat } from "@/utils/dateFormat";
|
||||
import { WidgetType } from "@/views/dashboard/data";
|
||||
import { useLogStore } from "@/store/modules/log";
|
||||
const logStore = useLogStore();
|
||||
|
||||
/*global defineProps, defineEmits, Recordable */
|
||||
/*global defineProps, defineEmits */
|
||||
const props = defineProps({
|
||||
data: { type: Object as any, default: () => ({}) },
|
||||
noLink: { type: Boolean, default: true },
|
||||
});
|
||||
const dashboardStore = useDashboardStore();
|
||||
const options: Recordable<LayoutConfig> = inject("options") || {};
|
||||
const options: LayoutConfig | null = inject("options") || null;
|
||||
const emit = defineEmits(["select"]);
|
||||
const columns = ServiceLogConstants;
|
||||
const level = computed(() => {
|
||||
@@ -78,11 +78,11 @@ limitations under the License. -->
|
||||
emit("select", props.data);
|
||||
}
|
||||
function linkTrace(id: string) {
|
||||
const { associationWidget } = getDashboard(dashboardStore.currentDashboard);
|
||||
const { associationWidget } = getDashboard(dashboardStore.currentDashboard as DashboardItem);
|
||||
associationWidget(
|
||||
(options.id as any) || "",
|
||||
(options?.id || "") as string,
|
||||
{
|
||||
sourceId: options.id || "",
|
||||
sourceId: (options?.id || "") as string,
|
||||
traceId: id,
|
||||
id: props.data.serviceId || "",
|
||||
},
|
||||
|
@@ -128,6 +128,7 @@ limitations under the License. -->
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
import icons from "@/assets/img/icons";
|
||||
import { Themes } from "@/constants/data";
|
||||
import type { EBPFTaskList } from "@/types/ebpf";
|
||||
|
||||
/*global Nullable, defineProps */
|
||||
const props = defineProps({
|
||||
@@ -361,7 +362,7 @@ limitations under the License. -->
|
||||
if (dates.value) {
|
||||
times = dates.value;
|
||||
} else {
|
||||
const { taskStartTime, fixedTriggerDuration } = networkProfilingStore.selectedNetworkTask;
|
||||
const { taskStartTime, fixedTriggerDuration } = (networkProfilingStore.selectedNetworkTask as EBPFTaskList) || {};
|
||||
const startTime =
|
||||
fixedTriggerDuration > 1800 ? taskStartTime + fixedTriggerDuration * 1000 - 30 * 60 * 1000 : taskStartTime;
|
||||
times = {
|
||||
|
@@ -15,7 +15,7 @@ limitations under the License. -->
|
||||
<template>
|
||||
<div class="label">{{ t("linkDashboard") }}</div>
|
||||
<Selector
|
||||
:value="(dashboardStore.selectedGrid && dashboardStore.selectedGrid.linkDashboard) || ''"
|
||||
:value="dashboardStore.selectedGrid?.linkDashboard || ''"
|
||||
:options="linkDashboards"
|
||||
size="small"
|
||||
placeholder="Please input a dashboard name for calls"
|
||||
@@ -30,6 +30,7 @@ limitations under the License. -->
|
||||
import type { DashboardItem } from "@/types/dashboard";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { EntityType } from "@/views/dashboard/data";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
/*global defineEmits */
|
||||
const emits = defineEmits(["update"]);
|
||||
const { t } = useI18n();
|
||||
@@ -55,13 +56,19 @@ limitations under the License. -->
|
||||
|
||||
function changeLinkDashboard(opt: { value: string }[]) {
|
||||
const linkDashboard = opt.length ? opt[0].value : "";
|
||||
const p = {
|
||||
const item = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 0,
|
||||
h: 0,
|
||||
i: "",
|
||||
type: "",
|
||||
...dashboardStore.selectedGrid,
|
||||
linkDashboard,
|
||||
};
|
||||
dashboardStore.selectWidget(p);
|
||||
dashboardStore.setConfigs(p);
|
||||
emits("update", p);
|
||||
dashboardStore.selectWidget(item as LayoutConfig);
|
||||
dashboardStore.setConfigs(item as LayoutConfig);
|
||||
emits("update", item);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -39,7 +39,7 @@ limitations under the License. -->
|
||||
<td
|
||||
class="profile-td"
|
||||
:class="{
|
||||
selected: networkProfilingStore.selectedNetworkTask.taskId === i.taskId,
|
||||
selected: networkProfilingStore.selectedNetworkTask?.taskId === i.taskId,
|
||||
}"
|
||||
>
|
||||
<div class="ell">
|
||||
@@ -103,7 +103,8 @@ limitations under the License. -->
|
||||
getTopology();
|
||||
}
|
||||
async function getTopology() {
|
||||
const { taskStartTime, fixedTriggerDuration, taskId } = networkProfilingStore.selectedNetworkTask;
|
||||
const { taskStartTime, fixedTriggerDuration, taskId } =
|
||||
(networkProfilingStore.selectedNetworkTask as EBPFTaskList) || {};
|
||||
const serviceInstanceId = (selectorStore.currentPod && selectorStore.currentPod.id) || "";
|
||||
const startTime =
|
||||
fixedTriggerDuration > 1800 ? taskStartTime + fixedTriggerDuration * 1000 - 30 * 60 * 1000 : taskStartTime;
|
||||
@@ -171,7 +172,9 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
async function keepAliveNetwork() {
|
||||
const res = await networkProfilingStore.keepNetworkProfiling(networkProfilingStore.selectedNetworkTask.taskId);
|
||||
const res = await networkProfilingStore.keepNetworkProfiling(
|
||||
networkProfilingStore.selectedNetworkTask?.taskId || "",
|
||||
);
|
||||
if (res.errors) {
|
||||
intervalKeepAlive.value && clearInterval(intervalKeepAlive.value);
|
||||
return ElMessage.error(res.errors);
|
||||
|
@@ -36,6 +36,7 @@ limitations under the License. -->
|
||||
import dateFormatStep from "@/utils/dateFormat";
|
||||
import getLocalTime from "@/utils/localtime";
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
import type { EBPFTaskList } from "@/types/ebpf";
|
||||
|
||||
/*global Nullable, defineEmits */
|
||||
const emits = defineEmits(["get"]);
|
||||
@@ -55,10 +56,11 @@ limitations under the License. -->
|
||||
if (!timeRange.value) {
|
||||
return;
|
||||
}
|
||||
if (!networkProfilingStore.selectedNetworkTask.taskId) {
|
||||
if (!networkProfilingStore.selectedNetworkTask?.taskId) {
|
||||
return;
|
||||
}
|
||||
const { taskStartTime, fixedTriggerDuration, targetType, taskId } = networkProfilingStore.selectedNetworkTask;
|
||||
const { taskStartTime, fixedTriggerDuration, targetType, taskId } =
|
||||
(networkProfilingStore.selectedNetworkTask as EBPFTaskList) || {};
|
||||
if (task.value[0] && task.value[0].data.taskId === taskId) {
|
||||
if (isUpdate.value) {
|
||||
return;
|
||||
|
@@ -89,7 +89,7 @@ limitations under the License. -->
|
||||
};
|
||||
countRange();
|
||||
for (const tree of profileStore.analyzeTrees) {
|
||||
const ele = processTree(tree.elements);
|
||||
const ele = processTree(tree.elements as TraceProfilingElement[]);
|
||||
root.children && root.children.push(ele);
|
||||
}
|
||||
const param = (root.children || []).reduce(
|
||||
|
@@ -70,7 +70,7 @@ limitations under the License. -->
|
||||
if (!selectorStore.currentService) {
|
||||
return;
|
||||
}
|
||||
const service = selectorStore.currentService.id;
|
||||
const service = selectorStore.currentService.id || "";
|
||||
const res = await profileStore.getEndpoints(service, keyword);
|
||||
|
||||
if (res.errors) {
|
||||
|
@@ -98,7 +98,7 @@ limitations under the License. -->
|
||||
if (!selectorStore.currentService) {
|
||||
return;
|
||||
}
|
||||
const service = selectorStore.currentService.id;
|
||||
const service = selectorStore.currentService.id || "";
|
||||
const res = await profileStore.getEndpoints(service, keyword);
|
||||
|
||||
if (res.errors) {
|
||||
@@ -129,10 +129,14 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
async function createTask() {
|
||||
if (!selectorStore.currentService?.id) {
|
||||
ElMessage.error("Please select a service");
|
||||
return;
|
||||
}
|
||||
emits("close");
|
||||
const date = monitorTime.value === "0" ? new Date() : time.value;
|
||||
const params = {
|
||||
serviceId: selectorStore.currentService.id,
|
||||
serviceId: selectorStore.currentService?.id || "",
|
||||
endpointName: endpointName.value,
|
||||
startTime: date.getTime(),
|
||||
duration: Number(monitorDuration.value),
|
||||
|
@@ -56,7 +56,7 @@ limitations under the License. -->
|
||||
const { t } = useI18n();
|
||||
const profileStore = useProfileStore();
|
||||
const key = computed(
|
||||
() => (profileStore.currentSegment.spans?.length && profileStore.currentSegment.spans[0].segmentId) || "",
|
||||
() => (profileStore.currentSegment?.spans?.length && profileStore.currentSegment?.spans[0]?.segmentId) || "",
|
||||
);
|
||||
|
||||
async function selectSegment(item: Trace) {
|
||||
|
@@ -35,14 +35,14 @@ limitations under the License. -->
|
||||
@change="selectDisplayMode"
|
||||
class="mr-10 fliter"
|
||||
/>
|
||||
<el-button type="primary" size="small" :disabled="!profileStore.currentSpan.profiled" @click="analyzeProfile()">
|
||||
<el-button type="primary" size="small" :disabled="!profileStore.currentSpan?.profiled" @click="analyzeProfile()">
|
||||
{{ t("analyze") }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="profile-table">
|
||||
<Table
|
||||
:data="profileStore.segmentSpans"
|
||||
:traceId="profileStore.currentSegment.traceId"
|
||||
:data="(profileStore.segmentSpans as SegmentSpan[])"
|
||||
:traceId="profileStore.currentSegment?.traceId"
|
||||
:headerType="WidgetType.Profile"
|
||||
@select="selectSpan"
|
||||
/>
|
||||
@@ -55,7 +55,7 @@ limitations under the License. -->
|
||||
import Table from "../../trace/components/Table.vue";
|
||||
import { useProfileStore } from "@/store/modules/profile";
|
||||
import Selector from "@/components/Selector.vue";
|
||||
import type { Span } from "@/types/trace";
|
||||
import type { SegmentSpan, ProfileTimeRange, ProfileAnalyzeParams } from "@/types/profile";
|
||||
import type { Option } from "@/types/app";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { ProfileDataMode, ProfileDisplayMode } from "./data";
|
||||
@@ -68,9 +68,9 @@ limitations under the License. -->
|
||||
const dataMode = ref<string>("include");
|
||||
const displayMode = ref<string>("tree");
|
||||
const message = ref<string>("");
|
||||
const timeRange = ref<Array<{ start: number; end: number }>>([]);
|
||||
const timeRange = ref<ProfileTimeRange[]>([]);
|
||||
|
||||
function selectSpan(span: Span) {
|
||||
function selectSpan(span: SegmentSpan) {
|
||||
profileStore.setCurrentSpan(span);
|
||||
}
|
||||
|
||||
@@ -85,15 +85,15 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
async function analyzeProfile() {
|
||||
if (!profileStore.currentSpan.profiled) {
|
||||
if (!profileStore.currentSpan?.profiled) {
|
||||
ElMessage.info("It's a un-profiled span");
|
||||
return;
|
||||
}
|
||||
emits("loading", true);
|
||||
updateTimeRange();
|
||||
const params = timeRange.value.map((t: { start: number; end: number }) => {
|
||||
const params: ProfileAnalyzeParams[] = timeRange.value.map((t: ProfileTimeRange) => {
|
||||
return {
|
||||
segmentId: profileStore.currentSpan.segmentId,
|
||||
segmentId: profileStore.currentSpan?.segmentId || "",
|
||||
timeRange: t,
|
||||
};
|
||||
});
|
||||
@@ -111,19 +111,19 @@ limitations under the License. -->
|
||||
if (dataMode.value === "include") {
|
||||
timeRange.value = [
|
||||
{
|
||||
start: profileStore.currentSpan.startTime,
|
||||
end: profileStore.currentSpan.endTime,
|
||||
start: profileStore.currentSpan?.startTime || 0,
|
||||
end: profileStore.currentSpan?.endTime || 0,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
const { children, startTime, endTime } = profileStore.currentSpan;
|
||||
let dateRange = [];
|
||||
const { children, startTime, endTime } = profileStore.currentSpan || {};
|
||||
let dateRange: ProfileTimeRange[] = [];
|
||||
|
||||
if (!children || !children.length) {
|
||||
if (!children?.length) {
|
||||
timeRange.value = [
|
||||
{
|
||||
start: startTime,
|
||||
end: endTime,
|
||||
start: startTime || 0,
|
||||
end: endTime || 0,
|
||||
},
|
||||
];
|
||||
return;
|
||||
@@ -131,16 +131,16 @@ limitations under the License. -->
|
||||
for (const item of children) {
|
||||
dateRange.push(
|
||||
{
|
||||
start: startTime,
|
||||
end: item.startTime,
|
||||
start: startTime || 0,
|
||||
end: item.startTime || 0,
|
||||
},
|
||||
{
|
||||
start: item.endTime,
|
||||
end: endTime,
|
||||
start: item.endTime || 0,
|
||||
end: endTime || 0,
|
||||
},
|
||||
);
|
||||
}
|
||||
dateRange = dateRange.reduce((prev: any[], cur) => {
|
||||
dateRange = dateRange.reduce((prev: ProfileTimeRange[], cur: ProfileTimeRange) => {
|
||||
let isUpdate = false;
|
||||
for (const item of prev) {
|
||||
if (cur.start <= item.end && item.start <= cur.start) {
|
||||
|
@@ -118,7 +118,7 @@ limitations under the License. -->
|
||||
const instanceLogs = ref<TaskLog | any>({});
|
||||
|
||||
async function changeTask(item: TaskListItem) {
|
||||
profileStore.setCurrentSegment({});
|
||||
profileStore.setCurrentSegment(null);
|
||||
profileStore.setCurrentTask(item);
|
||||
const res = await profileStore.getSegmentList({ taskID: item.id });
|
||||
if (res.errors) {
|
||||
|
@@ -13,12 +13,12 @@ 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. -->
|
||||
<template>
|
||||
<div class="content" v-if="taskTimelineStore.selectedTask.targetType === TargetTypes[2].value">
|
||||
<div class="content" v-if="taskTimelineStore.selectedTask?.targetType === TargetTypes[2].value">
|
||||
<process-topology v-if="networkProfilingStore.nodes.length" :config="config" />
|
||||
</div>
|
||||
<div
|
||||
class="content"
|
||||
v-if="[TargetTypes[1].value, TargetTypes[0].value].includes(taskTimelineStore.selectedTask.targetType)"
|
||||
v-if="[TargetTypes[1].value, TargetTypes[0].value].includes(taskTimelineStore.selectedTask?.targetType as string)"
|
||||
>
|
||||
<div class="schedules">
|
||||
<EBPFSchedules />
|
||||
@@ -27,7 +27,7 @@ limitations under the License. -->
|
||||
<EBPFStack />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text" v-if="!taskTimelineStore.selectedTask.targetType">
|
||||
<div class="text" v-if="!taskTimelineStore.selectedTask?.targetType">
|
||||
{{ t("noData") }}
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -16,7 +16,7 @@ limitations under the License. -->
|
||||
<div ref="timeline" class="task-timeline"></div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted, onUnmounted } from "vue";
|
||||
import { ref, watch, onMounted, onUnmounted, PropType } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
import { useThrottleFn } from "@vueuse/core";
|
||||
import { ElMessage } from "element-plus";
|
||||
@@ -28,6 +28,7 @@ limitations under the License. -->
|
||||
import { DataSet, Timeline } from "vis-timeline/standalone";
|
||||
import "vis-timeline/styles/vis-timeline-graph2d.css";
|
||||
import { EBPFProfilingTriggerType } from "@/store/data";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const taskTimelineStore = useTaskTimelineStore();
|
||||
const selectorStore = useSelectorStore();
|
||||
@@ -36,7 +37,7 @@ limitations under the License. -->
|
||||
/* global defineProps, Nullable */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
@@ -57,11 +58,11 @@ limitations under the License. -->
|
||||
async function init() {
|
||||
const serviceId = (selectorStore.currentService && selectorStore.currentService.id) || "";
|
||||
const serviceInstanceId = (selectorStore.currentPod && selectorStore.currentPod.id) || "";
|
||||
const type = continousProfilingStore.selectedStrategy.type;
|
||||
const type = continousProfilingStore.selectedStrategy?.type || "";
|
||||
const res = await taskTimelineStore.getContinousTaskList({
|
||||
serviceId,
|
||||
serviceInstanceId,
|
||||
targets: type ? [type] : null,
|
||||
targets: type ? [type] : [],
|
||||
triggerType: EBPFProfilingTriggerType.CONTINUOUS_PROFILING,
|
||||
});
|
||||
if (res.errors) {
|
||||
@@ -121,7 +122,7 @@ limitations under the License. -->
|
||||
visGraph.value.on("select", async (properties: { items: number[] }) => {
|
||||
dashboardStore.selectWidget(props.data);
|
||||
const index = properties.items[0];
|
||||
const task = taskTimelineStore.taskList[index];
|
||||
const task = taskTimelineStore.taskList[index] as EBPFTaskList;
|
||||
|
||||
await taskTimelineStore.setSelectedTask(task);
|
||||
await taskTimelineStore.getGraphData();
|
||||
|
@@ -75,7 +75,7 @@ limitations under the License. -->
|
||||
import type { PropType } from "vue";
|
||||
import { ref, computed, watch } from "vue";
|
||||
import * as d3 from "d3";
|
||||
import type { Node, Call } from "@/types/topology";
|
||||
import type { Node, Call, HierarchyNode } from "@/types/topology";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import icons from "@/assets/img/icons";
|
||||
import { changeNode, computeHierarchyLevels, hierarchy } from "./utils/layout";
|
||||
@@ -92,7 +92,7 @@ limitations under the License. -->
|
||||
default: "",
|
||||
},
|
||||
nodes: {
|
||||
type: Array as PropType<Node[]>,
|
||||
type: Array as PropType<(Node | HierarchyNode)[]>,
|
||||
default: () => [],
|
||||
},
|
||||
calls: {
|
||||
@@ -136,7 +136,7 @@ limitations under the License. -->
|
||||
|
||||
function draw() {
|
||||
const levels = computeHierarchyLevels(props.nodes);
|
||||
topologyLayout.value = hierarchy(levels, props.calls, radius);
|
||||
topologyLayout.value = hierarchy(levels as Node[][], props.calls, radius);
|
||||
graphWidth.value = topologyLayout.value.layout.width;
|
||||
graphHeight.value = topologyLayout.value.layout.height;
|
||||
const drag: any = d3.drag().on("drag", (d: { x: number; y: number }) => {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as d3 from "d3";
|
||||
import type { Node, Call } from "@/types/topology";
|
||||
import type { Node, Call, HierarchyNode } from "@/types/topology";
|
||||
|
||||
export function layout(levels: Node[][], calls: Call[], radius: number) {
|
||||
// precompute level depth
|
||||
@@ -279,14 +279,14 @@ export function hierarchy(levels: Node[][], calls: Call[], radius: number) {
|
||||
|
||||
return { nodes, layout, calls: computeCallPos(calls, radius) };
|
||||
}
|
||||
export function computeHierarchyLevels(nodes: Node[]) {
|
||||
const levelsNum: number[] = nodes.map((d: Node) => d.l || 0);
|
||||
export function computeHierarchyLevels(nodes: (Node | HierarchyNode)[]) {
|
||||
const levelsNum: number[] = nodes.map((d: Node | HierarchyNode) => (d as Node).l || 0);
|
||||
const list = [...new Set(levelsNum)];
|
||||
const sortedArr = list.sort((a, b) => b - a);
|
||||
const nodesList = [];
|
||||
|
||||
for (const min of sortedArr) {
|
||||
const arr = nodes.filter((d) => d.l === min);
|
||||
const arr = nodes.filter((d) => (d as Node).l === min);
|
||||
nodesList.push(arr);
|
||||
}
|
||||
|
||||
|
@@ -52,6 +52,7 @@ limitations under the License. -->
|
||||
import { EntityType, ConfigFieldTypes } from "@/views/dashboard/data";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import type { MetricConfigOpt } from "@/types/dashboard";
|
||||
|
||||
/*global defineEmits, defineProps */
|
||||
const props = defineProps({
|
||||
@@ -68,16 +69,16 @@ limitations under the License. -->
|
||||
return props.expressions || [];
|
||||
}
|
||||
let metrics: string[] = [];
|
||||
const { linkServerExpressions, linkClientExpressions, nodeExpressions } = dashboardStore.selectedGrid;
|
||||
const { linkServerExpressions, linkClientExpressions, nodeExpressions } = dashboardStore.selectedGrid || {};
|
||||
switch (props.type) {
|
||||
case "linkServerMetricConfig":
|
||||
metrics = linkServerExpressions;
|
||||
metrics = linkServerExpressions || [];
|
||||
break;
|
||||
case "linkClientMetricConfig":
|
||||
metrics = linkClientExpressions;
|
||||
metrics = linkClientExpressions || [];
|
||||
break;
|
||||
case "nodeMetricConfig":
|
||||
metrics = nodeExpressions;
|
||||
metrics = nodeExpressions || [];
|
||||
break;
|
||||
}
|
||||
return metrics || [];
|
||||
@@ -106,17 +107,17 @@ limitations under the License. -->
|
||||
|
||||
return config || [];
|
||||
}
|
||||
let config = [];
|
||||
let config: MetricConfigOpt[] = [];
|
||||
|
||||
switch (props.type) {
|
||||
case "linkServerMetricConfig":
|
||||
config = dashboardStore.selectedGrid.linkServerMetricConfig;
|
||||
config = dashboardStore.selectedGrid?.linkServerMetricConfig || [];
|
||||
break;
|
||||
case "linkClientMetricConfig":
|
||||
config = dashboardStore.selectedGrid.linkClientMetricConfig;
|
||||
config = dashboardStore.selectedGrid?.linkClientMetricConfig || [];
|
||||
break;
|
||||
case "nodeMetricConfig":
|
||||
config = dashboardStore.selectedGrid.nodeMetricConfig;
|
||||
config = dashboardStore.selectedGrid?.nodeMetricConfig || [];
|
||||
break;
|
||||
}
|
||||
return config || [];
|
||||
|
@@ -161,7 +161,7 @@ limitations under the License. -->
|
||||
import { ScopeType, EntityType, CallTypes } from "@/views/dashboard/data";
|
||||
import type { Option } from "@/types/app";
|
||||
import { useQueryTopologyExpressionsProcessor } from "@/hooks/useExpressionsProcessor";
|
||||
import type { DashboardItem, MetricConfigOpt } from "@/types/dashboard";
|
||||
import type { DashboardItem, MetricConfigOpt, LayoutConfig, NodeDashboard } from "@/types/dashboard";
|
||||
import type { Node } from "@/types/topology";
|
||||
import Metrics from "./Metrics.vue";
|
||||
|
||||
@@ -171,38 +171,28 @@ limitations under the License. -->
|
||||
const dashboardStore = useDashboardStore();
|
||||
const topologyStore = useTopologyStore();
|
||||
const { selectedGrid } = dashboardStore;
|
||||
const nodeDashboard =
|
||||
selectedGrid.nodeDashboard && selectedGrid.nodeDashboard.length ? selectedGrid.nodeDashboard : "";
|
||||
const isService = [EntityType[0].value, EntityType[1].value].includes(dashboardStore.entity);
|
||||
const items = reactive<
|
||||
{
|
||||
scope: string;
|
||||
dashboard: string;
|
||||
}[]
|
||||
>(isService && nodeDashboard ? nodeDashboard : [{ scope: "", dashboard: "" }]);
|
||||
const isService: boolean = [EntityType[0].value, EntityType[1].value].includes(dashboardStore.entity);
|
||||
const items = reactive<NodeDashboard[]>((isService && selectedGrid?.nodeDashboard) || [{ scope: "", dashboard: "" }]);
|
||||
const states = reactive<{
|
||||
linkDashboard: string;
|
||||
nodeDashboard: {
|
||||
scope: string;
|
||||
dashboard: string;
|
||||
}[];
|
||||
nodeDashboard: NodeDashboard[];
|
||||
linkDashboards: (DashboardItem & { label: string; value: string })[];
|
||||
nodeDashboards: (DashboardItem & { label: string; value: string })[];
|
||||
linkServerExpressions: string[];
|
||||
linkClientExpressions: string[];
|
||||
nodeExpressions: string[];
|
||||
}>({
|
||||
linkDashboard: selectedGrid.linkDashboard || "",
|
||||
nodeDashboard: selectedGrid.nodeDashboard || [],
|
||||
linkDashboard: selectedGrid?.linkDashboard || "",
|
||||
nodeDashboard: selectedGrid?.nodeDashboard || [],
|
||||
linkDashboards: [],
|
||||
nodeDashboards: [],
|
||||
linkServerExpressions: selectedGrid.linkServerExpressions || [],
|
||||
linkClientExpressions: selectedGrid.linkClientExpressions || [],
|
||||
nodeExpressions: selectedGrid.nodeExpressions || [],
|
||||
linkServerExpressions: selectedGrid?.linkServerExpressions || [],
|
||||
linkClientExpressions: selectedGrid?.linkClientExpressions || [],
|
||||
nodeExpressions: selectedGrid?.nodeExpressions || [],
|
||||
});
|
||||
const legendMQE = ref<{ expression: string }>(selectedGrid.legendMQE || { expression: "" });
|
||||
const legendMQE = ref<{ expression: string }>(selectedGrid?.legendMQE || { expression: "" });
|
||||
const configType = ref<string>("");
|
||||
const description = reactive<any>(selectedGrid.description || {});
|
||||
const description = reactive<any>(selectedGrid?.description || {});
|
||||
|
||||
getDashboardList();
|
||||
async function getDashboardList() {
|
||||
@@ -237,7 +227,7 @@ limitations under the License. -->
|
||||
}
|
||||
async function setLegend() {
|
||||
updateSettings();
|
||||
const expression = dashboardStore.selectedGrid.legendMQE && dashboardStore.selectedGrid.legendMQE.expression;
|
||||
const expression: string = dashboardStore.selectedGrid?.legendMQE?.expression || "";
|
||||
const { getMetrics } = useQueryTopologyExpressionsProcessor(
|
||||
[expression],
|
||||
topologyStore.nodes.filter((d: Node) => d.isReal),
|
||||
@@ -295,7 +285,7 @@ limitations under the License. -->
|
||||
legendMQE: legendMQE.value,
|
||||
...metricConfig,
|
||||
description,
|
||||
};
|
||||
} as LayoutConfig;
|
||||
dashboardStore.selectWidget(param);
|
||||
dashboardStore.setConfigs(param);
|
||||
emit("update", param);
|
||||
@@ -314,7 +304,7 @@ limitations under the License. -->
|
||||
states.linkClientExpressions = param;
|
||||
updateSettings();
|
||||
if (!states.linkClientExpressions.length) {
|
||||
topologyStore.changeLinkClientMetrics({});
|
||||
topologyStore.setLinkClientMetrics({});
|
||||
return;
|
||||
}
|
||||
topologyStore.getLinkExpressions(states.linkClientExpressions, CallTypes.Client);
|
||||
|
@@ -125,11 +125,11 @@ limitations under the License. -->
|
||||
const html = exprssions.map((m: string, index: number) => {
|
||||
const metric =
|
||||
topologyStore.hierarchyInstanceNodeMetrics[data.layer || ""][m].values.find(
|
||||
(val: { id: string; value: string }) => val.id === data.id,
|
||||
) || {};
|
||||
(val: { id: string; value: unknown }) => val.id === data.id,
|
||||
) || null;
|
||||
const opt: MetricConfigOpt = nodeMetricConfig[index] || {};
|
||||
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric.value || NaN} ${
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric?.value || NaN} ${
|
||||
opt.unit || ""
|
||||
}</div>`;
|
||||
});
|
||||
|
@@ -102,7 +102,7 @@ limitations under the License. -->
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
loadTopology(selectorStore.currentPod && selectorStore.currentPod.id);
|
||||
loadTopology(selectorStore.currentPod?.id);
|
||||
window.addEventListener("resize", resize);
|
||||
});
|
||||
|
||||
@@ -134,7 +134,7 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
function inspect() {
|
||||
const id = topologyStore.node.id;
|
||||
const id = topologyStore.node?.id;
|
||||
topologyStore.setNode(null);
|
||||
topologyStore.setLink(null);
|
||||
loadTopology(id);
|
||||
@@ -158,7 +158,7 @@ limitations under the License. -->
|
||||
ElMessage.error(`The dashboard named ${settings.value.nodeDashboard} doesn't exist`);
|
||||
return;
|
||||
}
|
||||
const path = `/dashboard/${dashboard.layer}/${entity}/${topologyStore.node.serviceId}/${topologyStore.node.id}/${dashboard.name}`;
|
||||
const path = `/dashboard/${dashboard.layer}/${entity}/${topologyStore.node?.serviceId}/${topologyStore.node?.id}/${dashboard.name}`;
|
||||
const routeUrl = router.resolve({ path });
|
||||
window.open(routeUrl.href, "_blank");
|
||||
topologyStore.setNode(null);
|
||||
@@ -175,7 +175,7 @@ limitations under the License. -->
|
||||
}
|
||||
|
||||
function backToTopology() {
|
||||
loadTopology(selectorStore.currentPod.id);
|
||||
loadTopology(selectorStore.currentPod?.id);
|
||||
topologyStore.setNode(null);
|
||||
}
|
||||
|
||||
@@ -210,14 +210,14 @@ limitations under the License. -->
|
||||
|
||||
async function changeDepth(opt: Option[] | any) {
|
||||
depth.value = opt[0].value;
|
||||
loadTopology(selectorStore.currentPod.id);
|
||||
loadTopology(selectorStore.currentPod?.id);
|
||||
}
|
||||
|
||||
async function getTopology(id?: string) {
|
||||
let resp;
|
||||
switch (dashboardStore.entity) {
|
||||
case EntityType[2].value:
|
||||
resp = await topologyStore.updateEndpointTopology([id], Number(depth.value));
|
||||
resp = await topologyStore.updateEndpointTopology([id as string], Number(depth.value));
|
||||
break;
|
||||
case EntityType[5].value:
|
||||
resp = await topologyStore.getInstanceTopology();
|
||||
@@ -238,7 +238,7 @@ limitations under the License. -->
|
||||
watch(
|
||||
() => [selectorStore.currentPod],
|
||||
() => {
|
||||
loadTopology(selectorStore.currentPod.id);
|
||||
loadTopology(selectorStore.currentPod?.id);
|
||||
topologyStore.setNode(null);
|
||||
topologyStore.setLink(null);
|
||||
},
|
||||
@@ -257,7 +257,7 @@ limitations under the License. -->
|
||||
watch(
|
||||
() => appStore.durationTime,
|
||||
() => {
|
||||
loadTopology(selectorStore.currentPod.id);
|
||||
loadTopology(selectorStore.currentPod?.id);
|
||||
topologyStore.setNode(null);
|
||||
topologyStore.setLink(null);
|
||||
},
|
||||
|
@@ -91,11 +91,11 @@ limitations under the License. -->
|
||||
const htmlServer = serverMetrics.map((m, index) => {
|
||||
const metric =
|
||||
topologyStore.linkServerMetrics[m]?.values?.find((val: { id: string; value: unknown }) => val.id === data.id) ||
|
||||
{};
|
||||
null;
|
||||
if (metric) {
|
||||
const opt: MetricConfigOpt = linkServerMetricConfig[index] || {};
|
||||
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric.value} ${
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric?.value} ${
|
||||
opt.unit || ""
|
||||
}</div>`;
|
||||
}
|
||||
@@ -104,9 +104,9 @@ limitations under the License. -->
|
||||
const opt: MetricConfigOpt = linkClientMetricConfig[index] || {};
|
||||
const metric =
|
||||
topologyStore.linkClientMetrics[m]?.values?.find((val: { id: string; value: unknown }) => val.id === data.id) ||
|
||||
{};
|
||||
null;
|
||||
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric.value} ${opt.unit || ""}</div>`;
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric?.value} ${opt.unit || ""}</div>`;
|
||||
});
|
||||
const html = [
|
||||
`<div>${data.sourceObj.serviceName} -> ${data.targetObj.serviceName}</div>`,
|
||||
@@ -123,10 +123,10 @@ limitations under the License. -->
|
||||
const html = nodeMetrics.map((m, index) => {
|
||||
const metric =
|
||||
topologyStore.nodeMetricValue[m]?.values?.find((val: { id: string; value: unknown }) => val.id === data.id) ||
|
||||
{};
|
||||
null;
|
||||
const opt: MetricConfigOpt = nodeMetricConfig[index] || {};
|
||||
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric.value} ${opt.unit || ""}</div>`;
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric?.value} ${opt.unit || ""}</div>`;
|
||||
});
|
||||
return [` <div><span>name: </span>${data.serviceName}</div>`, ...html].join(" ");
|
||||
}
|
||||
|
@@ -133,10 +133,10 @@ limitations under the License. -->
|
||||
const html = exprssions.map((m: string, index: number) => {
|
||||
const metric =
|
||||
topologyStore.hierarchyNodeMetrics[data.layer || ""][m].values.find(
|
||||
(val: { id: string; value: string }) => val.id === data.id,
|
||||
) || {};
|
||||
(val: { id: string; value: unknown }) => val.id === data.id,
|
||||
) || null;
|
||||
const opt: MetricConfigOpt = nodeMetricConfig[index] || {};
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric.value || NaN} ${
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric?.value || NaN} ${
|
||||
opt.unit || ""
|
||||
}</div>`;
|
||||
});
|
||||
|
@@ -219,10 +219,10 @@ limitations under the License. -->
|
||||
loading.value = true;
|
||||
topologyStore.setNode(null);
|
||||
topologyStore.setLink(null);
|
||||
const resp = await getTopology();
|
||||
const resp: any = await getTopology();
|
||||
loading.value = false;
|
||||
|
||||
if (resp && resp.errors) {
|
||||
if (resp?.errors) {
|
||||
ElMessage.error(resp.errors);
|
||||
}
|
||||
await update();
|
||||
@@ -309,10 +309,10 @@ limitations under the License. -->
|
||||
const nodeMetricConfig = settings.value.nodeMetricConfig || [];
|
||||
const html = nodeMetrics.map((m, index) => {
|
||||
const metric =
|
||||
topologyStore.nodeMetricValue[m]?.values?.find((val: { id: string; value: string }) => val.id === data.id) ||
|
||||
{};
|
||||
topologyStore.nodeMetricValue[m]?.values?.find((val: { id: string; value: unknown }) => val.id === data.id) ||
|
||||
null;
|
||||
const opt: MetricConfigOpt = nodeMetricConfig[index] || {};
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric.value || NaN} ${
|
||||
return ` <div class="mb-5"><span class="grey">${opt.label || m}: </span>${metric?.value || NaN} ${
|
||||
opt.unit || "unknown"
|
||||
}</div>`;
|
||||
});
|
||||
@@ -415,11 +415,11 @@ limitations under the License. -->
|
||||
hierarchyRelated.value = true;
|
||||
}
|
||||
async function handleInspect() {
|
||||
const id = topologyStore.node.id;
|
||||
const id = topologyStore.node?.id || "";
|
||||
loading.value = true;
|
||||
const resp = await topologyStore.getDepthServiceTopology([id], Number(depth.value));
|
||||
const resp: any = await topologyStore.getDepthServiceTopology([id], Number(depth.value));
|
||||
loading.value = false;
|
||||
if (resp && resp.errors) {
|
||||
if (resp?.errors) {
|
||||
ElMessage.error(resp.errors);
|
||||
}
|
||||
await update();
|
||||
@@ -431,7 +431,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
const origin = dashboardStore.entity;
|
||||
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[2].value}/${topologyStore.node.id}/${params.dashboard}`;
|
||||
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[2].value}/${topologyStore.node?.id}/${params.dashboard}`;
|
||||
const routeUrl = router.resolve({ path });
|
||||
|
||||
window.open(routeUrl.href, "_blank");
|
||||
@@ -442,7 +442,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
const origin = dashboardStore.entity;
|
||||
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[3].value}/${topologyStore.node.id}/${params.dashboard}`;
|
||||
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[3].value}/${topologyStore.node?.id}/${params.dashboard}`;
|
||||
const routeUrl = router.resolve({ path });
|
||||
|
||||
window.open(routeUrl.href, "_blank");
|
||||
@@ -453,7 +453,7 @@ limitations under the License. -->
|
||||
return;
|
||||
}
|
||||
const origin = dashboardStore.entity;
|
||||
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[0].value}/${topologyStore.node.id}/${params.dashboard}`;
|
||||
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[0].value}/${topologyStore.node?.id}/${params.dashboard}`;
|
||||
const routeUrl = router.resolve({ path });
|
||||
|
||||
window.open(routeUrl.href, "_blank");
|
||||
@@ -495,8 +495,8 @@ limitations under the License. -->
|
||||
}
|
||||
async function getTopology() {
|
||||
const ids = selectorStore.services.map((d: Service) => d.id);
|
||||
const serviceIds = dashboardStore.entity === EntityType[0].value ? [selectorStore.currentService.id] : ids;
|
||||
const resp = await topologyStore.getDepthServiceTopology(serviceIds, Number(depth.value));
|
||||
const serviceIds = dashboardStore.entity === EntityType[0].value ? [selectorStore.currentService?.id] : ids;
|
||||
const resp = await topologyStore.getDepthServiceTopology(serviceIds as string[], Number(depth.value));
|
||||
return resp;
|
||||
}
|
||||
function setConfig() {
|
||||
|
@@ -12,9 +12,9 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License. -->
|
||||
<template>
|
||||
<div class="trace-detail" v-loading="loading">
|
||||
<div class="trace-detail-wrapper clear" v-if="traceStore.currentTrace.endpointNames">
|
||||
<div class="trace-detail-wrapper clear" v-if="traceStore.currentTrace?.endpointNames">
|
||||
<h5 class="mb-5 mt-0">
|
||||
<span class="vm">{{ traceStore.currentTrace.endpointNames[0] }}</span>
|
||||
<span class="vm">{{ traceStore.currentTrace?.endpointNames?.[0] }}</span>
|
||||
<div class="trace-log-btn">
|
||||
<el-button size="small" class="mr-10" type="primary" @click="searchTraceLogs">
|
||||
{{ t("viewLogs") }}
|
||||
@@ -79,10 +79,10 @@ limitations under the License. -->
|
||||
<div class="no-data" v-else>{{ t("noData") }}</div>
|
||||
<div class="trace-chart">
|
||||
<component
|
||||
v-if="traceStore.currentTrace.endpointNames"
|
||||
v-if="traceStore.currentTrace?.endpointNames"
|
||||
:is="displayMode"
|
||||
:data="traceStore.traceSpans"
|
||||
:traceId="traceStore.currentTrace.traceIds[0].value"
|
||||
:traceId="traceStore.currentTrace?.traceIds?.[0]?.value"
|
||||
:showBtnDetail="false"
|
||||
:headerType="WidgetType.Trace"
|
||||
/>
|
||||
@@ -115,8 +115,7 @@ limitations under the License. -->
|
||||
props,
|
||||
setup(props) {
|
||||
const appStore = useAppStoreWithOut();
|
||||
/*global Recordable */
|
||||
const options: Recordable<LayoutConfig> = inject("options") || {};
|
||||
const options: LayoutConfig | null = inject("options") || null;
|
||||
const { t } = useI18n();
|
||||
const traceStore = useTraceStore();
|
||||
const loading = ref<boolean>(false);
|
||||
@@ -124,7 +123,7 @@ limitations under the License. -->
|
||||
const displayMode = ref<string>("List");
|
||||
|
||||
function handleClick() {
|
||||
copy(traceId.value || traceStore.currentTrace.traceIds[0].value);
|
||||
copy(traceId.value || traceStore.currentTrace?.traceIds?.[0]?.value);
|
||||
}
|
||||
|
||||
async function changeTraceId(opt: Option[]) {
|
||||
@@ -140,10 +139,10 @@ limitations under the License. -->
|
||||
async function searchTraceLogs() {
|
||||
const { associationWidget } = getDashboard();
|
||||
associationWidget(
|
||||
(options.id as any) || "",
|
||||
options?.id || "",
|
||||
{
|
||||
sourceId: options?.id || "",
|
||||
traceId: traceId.value || traceStore.currentTrace.traceIds[0].value,
|
||||
traceId: traceId.value || traceStore.currentTrace?.traceIds?.[0]?.value,
|
||||
id: props.serviceId || undefined,
|
||||
},
|
||||
WidgetType.Log,
|
||||
|
@@ -115,11 +115,16 @@ limitations under the License. -->
|
||||
const appStore = useAppStoreWithOut();
|
||||
const selectorStore = useSelectorStore();
|
||||
const dashboardStore = useDashboardStore();
|
||||
const traceStore = useTraceStore();
|
||||
const traceStore: ReturnType<typeof useTraceStore> = useTraceStore();
|
||||
const { setDurationRow, getDurationTime, getMaxRange } = useDuration();
|
||||
const filters = reactive<Recordable>(props.data.filters || {});
|
||||
const traceId = ref<string>(filters.traceId || "");
|
||||
const duration = ref<DurationTime>(filters.duration || getDurationTime());
|
||||
const { duration: filtersDuration } = filters;
|
||||
const duration = ref<DurationTime>(
|
||||
filtersDuration
|
||||
? { start: filtersDuration.startTime || "", end: filtersDuration.endTime || "", step: filtersDuration.step || "" }
|
||||
: getDurationTime(),
|
||||
);
|
||||
const minTraceDuration = ref<number>();
|
||||
const maxTraceDuration = ref<number>();
|
||||
const tagsList = ref<string[]>([]);
|
||||
@@ -132,7 +137,7 @@ limitations under the License. -->
|
||||
});
|
||||
const durationRow = ref<Duration>(InitializationDurationRow);
|
||||
const maxRange = computed(() =>
|
||||
getMaxRange(appStore.coldStageMode ? appStore.recordsTTL.coldTrace : appStore.recordsTTL.trace),
|
||||
getMaxRange(appStore.coldStageMode ? appStore.recordsTTL?.coldTrace || 0 : appStore.recordsTTL?.trace || 0),
|
||||
);
|
||||
if (filters.queryOrder) {
|
||||
traceStore.setTraceCondition({
|
||||
@@ -171,7 +176,7 @@ limitations under the License. -->
|
||||
state.service = { value: "", label: "" };
|
||||
return;
|
||||
} else {
|
||||
state.service = getCurrentNode(traceStore.services) || traceStore.services[0];
|
||||
state.service = getCurrentNode(traceStore.services as { id: string }[]) || traceStore.services[0];
|
||||
}
|
||||
|
||||
emits("get", state.service.id);
|
||||
@@ -186,7 +191,7 @@ limitations under the License. -->
|
||||
ElMessage.error(resp.errors);
|
||||
return;
|
||||
}
|
||||
state.endpoint = getCurrentNode(traceStore.endpoints) || traceStore.endpoints[0];
|
||||
state.endpoint = getCurrentNode(traceStore.endpoints as { id: string }[]) || traceStore.endpoints[0];
|
||||
}
|
||||
async function getInstances(id?: string) {
|
||||
const resp = await traceStore.getInstances(id);
|
||||
@@ -194,7 +199,7 @@ limitations under the License. -->
|
||||
ElMessage.error(resp.errors);
|
||||
return;
|
||||
}
|
||||
state.instance = getCurrentNode(traceStore.instances) || traceStore.instances[0];
|
||||
state.instance = getCurrentNode(traceStore.instances as { id: string }[]) || traceStore.instances[0];
|
||||
}
|
||||
function getCurrentNode(arr: { id: string }[]) {
|
||||
let item;
|
||||
@@ -230,10 +235,10 @@ limitations under the License. -->
|
||||
let endpoint = "",
|
||||
instance = "";
|
||||
if (dashboardStore.entity === EntityType[2].value) {
|
||||
endpoint = selectorStore.currentPod.id;
|
||||
endpoint = selectorStore.currentPod?.id || "";
|
||||
}
|
||||
if (dashboardStore.entity === EntityType[3].value) {
|
||||
instance = selectorStore.currentPod.id;
|
||||
instance = selectorStore.currentPod?.id || "";
|
||||
}
|
||||
param = {
|
||||
...param,
|
||||
@@ -320,8 +325,15 @@ limitations under the License. -->
|
||||
if (JSON.stringify(newJson) === JSON.stringify(oldJson)) {
|
||||
return;
|
||||
}
|
||||
traceId.value = props.data.filters.traceId || "";
|
||||
duration.value = props.data.filters.duration || getDurationTime();
|
||||
const { traceId: filtersTraceId, duration: filtersDuration } = props.data.filters || {};
|
||||
traceId.value = filtersTraceId || "";
|
||||
duration.value = filtersDuration
|
||||
? {
|
||||
start: filtersDuration.startTime || "",
|
||||
end: filtersDuration.endTime || "",
|
||||
step: filtersDuration.step || "",
|
||||
}
|
||||
: getDurationTime();
|
||||
init();
|
||||
},
|
||||
);
|
||||
|
@@ -19,7 +19,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
<div class="conditions flex-h" v-else>
|
||||
<el-radio-group v-model="conditions" @change="changeCondition" size="small">
|
||||
<el-radio-button v-for="(item, index) in items" :label="item.label" :key="item.label + index" border>
|
||||
<el-radio-button v-for="(item, index) in items" :value="item.label" :key="item.label + index" border>
|
||||
{{ t(item.label) }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
@@ -92,6 +92,7 @@ limitations under the License. -->
|
||||
import ConditionTags from "@/views/components/ConditionTags.vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { EntityType, QueryOrders, Status } from "../../data";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
const FiltersKeys: { [key: string]: string } = {
|
||||
status: "traceState",
|
||||
@@ -104,8 +105,8 @@ limitations under the License. -->
|
||||
const props = defineProps({
|
||||
needQuery: { type: Boolean, default: true },
|
||||
data: {
|
||||
type: Object as PropType<Recordable>,
|
||||
default: () => ({ graph: {} }),
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const { t } = useI18n();
|
||||
@@ -118,7 +119,12 @@ limitations under the License. -->
|
||||
const tagsList = ref<string[]>([]);
|
||||
const tagsMap = ref<Option[]>([]);
|
||||
const traceId = ref<string>(filters.refId || "");
|
||||
const duration = ref<DurationTime>(filters.duration || appStore.durationTime);
|
||||
const { duration: filtersDuration } = props.data.filters || {};
|
||||
const duration = ref<DurationTime>(
|
||||
filtersDuration
|
||||
? { start: filtersDuration.startTime || "", end: filtersDuration.endTime || "", step: filtersDuration.step || "" }
|
||||
: appStore.durationTime,
|
||||
);
|
||||
const state = reactive<Recordable>({
|
||||
instance: "",
|
||||
endpoint: "",
|
||||
@@ -150,12 +156,12 @@ limitations under the License. -->
|
||||
state.instance = filters.owner.serviceInstanceID;
|
||||
}
|
||||
} else {
|
||||
state.service = selectorStore.currentService.id;
|
||||
state.service = selectorStore.currentService?.id || "";
|
||||
if (dashboardStore.entity === EntityType[2].value) {
|
||||
state.endpoint = selectorStore.currentPod.id;
|
||||
state.endpoint = selectorStore.currentPod?.id || "";
|
||||
}
|
||||
if (dashboardStore.entity === EntityType[3].value) {
|
||||
state.instance = selectorStore.currentPod.id;
|
||||
state.instance = selectorStore.currentPod?.id || "";
|
||||
}
|
||||
}
|
||||
await queryTraces();
|
||||
@@ -169,7 +175,7 @@ limitations under the License. -->
|
||||
await getService();
|
||||
}
|
||||
if (dashboardStore.entity === EntityType[0].value) {
|
||||
state.service = selectorStore.currentService.id;
|
||||
state.service = selectorStore.currentService?.id || "";
|
||||
await getInstance();
|
||||
if (!state.instance) {
|
||||
await getEndpoint();
|
||||
|
@@ -30,10 +30,10 @@ limitations under the License. -->
|
||||
import TraceList from "./TraceList.vue";
|
||||
import TraceDetail from "./Detail.vue";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
/*global defineProps, Recordable */
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<LayoutConfig | Recordable>,
|
||||
type: Object as PropType<LayoutConfig>,
|
||||
default: () => ({ graph: {} }),
|
||||
},
|
||||
});
|
||||
|
@@ -56,7 +56,7 @@ limitations under the License. -->
|
||||
red: i.isError,
|
||||
}"
|
||||
>
|
||||
<span class="b">{{ i.endpointNames[0] }}</span>
|
||||
<span class="b">{{ i.endpointNames?.[0] }}</span>
|
||||
</div>
|
||||
<div class="grey ell sm">
|
||||
<span class="tag mr-10 sm"> {{ i.duration }} ms </span>
|
||||
|
@@ -61,10 +61,11 @@ limitations under the License. -->
|
||||
import { mutationObserver } from "@/utils/mutation";
|
||||
import { TraceGraphType } from "../constant";
|
||||
import { Themes } from "@/constants/data";
|
||||
import type { SegmentSpan } from "@/types/profile";
|
||||
|
||||
/* global Recordable, Nullable */
|
||||
const props = defineProps({
|
||||
data: { type: Array as PropType<Span[]>, default: () => [] },
|
||||
data: { type: Array as PropType<(Span | SegmentSpan)[]>, default: () => [] },
|
||||
traceId: { type: String, default: "" },
|
||||
type: { type: String, default: TraceGraphType.LIST },
|
||||
headerType: { type: String, default: "" },
|
||||
@@ -79,8 +80,8 @@ limitations under the License. -->
|
||||
const refSpans = ref<Array<Ref>>([]);
|
||||
const tree = ref<Nullable<any>>(null);
|
||||
const traceGraph = ref<Nullable<HTMLDivElement>>(null);
|
||||
const parentSpans = ref<Array<Span>>([]);
|
||||
const refParentSpans = ref<Array<Span>>([]);
|
||||
const parentSpans = ref<Array<Span | SegmentSpan>>([]);
|
||||
const refParentSpans = ref<Array<Span | SegmentSpan>>([]);
|
||||
const debounceFunc = debounce(draw, 500);
|
||||
const visDate = (date: number, pattern = "YYYY-MM-DD HH:mm:ss:SSS") => dayjs(date).format(pattern);
|
||||
|
||||
|
@@ -157,18 +157,17 @@ limitations under the License. -->
|
||||
import { dateFormat } from "@/utils/dateFormat";
|
||||
import { useTraceStore } from "@/store/modules/trace";
|
||||
import LogTable from "@/views/dashboard/related/log/LogTable/Index.vue";
|
||||
import type { SpanAttachedEvent } from "@/types/trace";
|
||||
import type { SpanAttachedEvent, Ref, Span } from "@/types/trace";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { WidgetType } from "@/views/dashboard/data";
|
||||
import type { LayoutConfig } from "@/types/dashboard";
|
||||
|
||||
import type { LayoutConfig, DashboardItem } from "@/types/dashboard";
|
||||
/*global defineProps, Nullable, Recordable */
|
||||
const props = defineProps({
|
||||
currentSpan: { type: Object as PropType<Recordable>, default: () => ({}) },
|
||||
currentSpan: { type: Object as PropType<Span>, default: () => ({}) },
|
||||
traceId: { type: String, default: "" },
|
||||
});
|
||||
const options: Recordable<LayoutConfig> = inject("options") || {};
|
||||
const options: LayoutConfig | null = inject("options") || null;
|
||||
const { t } = useI18n();
|
||||
const traceStore = useTraceStore();
|
||||
const dashboardStore = useDashboardStore();
|
||||
@@ -246,12 +245,12 @@ limitations under the License. -->
|
||||
tree.value.draw();
|
||||
}
|
||||
|
||||
function viewRelateTrace(item: Recordable) {
|
||||
const { associationWidget } = getDashboard(dashboardStore.currentDashboard);
|
||||
function viewRelateTrace(item: Ref) {
|
||||
const { associationWidget } = getDashboard(dashboardStore.currentDashboard as DashboardItem);
|
||||
associationWidget(
|
||||
(options.id as any) || "",
|
||||
(options?.id as string) || "",
|
||||
{
|
||||
sourceId: options.id || "",
|
||||
sourceId: (options?.id as string) || "",
|
||||
traceId: item.traceId || "",
|
||||
id: "0",
|
||||
},
|
||||
|
@@ -24,11 +24,12 @@ limitations under the License. -->
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from "vue";
|
||||
import type { Span } from "@/types/trace";
|
||||
import type { SegmentSpan } from "@/types/profile";
|
||||
import Graph from "./D3Graph/Index.vue";
|
||||
import { TraceGraphType } from "./constant";
|
||||
|
||||
defineProps({
|
||||
data: { type: Array as PropType<Span[]>, default: () => [] },
|
||||
data: { type: Array as PropType<(Span | SegmentSpan)[]>, default: () => [] },
|
||||
traceId: { type: String, default: "" },
|
||||
headerType: { type: String, default: "" },
|
||||
});
|
||||
|
@@ -17,16 +17,16 @@ limitations under the License. -->
|
||||
<div v-if="type === TraceGraphType.STATISTICS">
|
||||
<div class="trace-item">
|
||||
<div :class="['method']">
|
||||
<el-tooltip :content="data.groupRef.endpointName" placement="top" :show-after="300">
|
||||
<el-tooltip :content="data.groupRef?.endpointName" placement="top" :show-after="300">
|
||||
<span>
|
||||
{{ data.groupRef.endpointName }}
|
||||
{{ data.groupRef?.endpointName }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div :class="['type']">
|
||||
<el-tooltip :content="data.groupRef.type" placement="top" :show-after="300">
|
||||
<el-tooltip :content="data.groupRef?.type" placement="top" :show-after="300">
|
||||
<span>
|
||||
{{ data.groupRef.type }}
|
||||
{{ data.groupRef?.type }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
@@ -40,7 +40,7 @@ limitations under the License. -->
|
||||
{{ data.sumTime }}
|
||||
</div>
|
||||
<div class="avg-time">
|
||||
{{ parseInt(data.avgTime) }}
|
||||
{{ parseInt(data.avgTime || "0") }}
|
||||
</div>
|
||||
<div class="count">
|
||||
{{ data.count }}
|
||||
@@ -52,7 +52,7 @@ limitations under the License. -->
|
||||
@click="selectSpan"
|
||||
:class="[
|
||||
'trace-item',
|
||||
'level' + (data.level - 1),
|
||||
'level' + ((data.level || 0) - 1),
|
||||
{ 'trace-item-error': data.isError },
|
||||
{ profiled: data.profiled === false },
|
||||
`trace-item-${data.key}`,
|
||||
@@ -60,9 +60,9 @@ limitations under the License. -->
|
||||
:data-text="data.profiled === false ? 'No Thread Dump' : ''"
|
||||
>
|
||||
<div
|
||||
:class="['method', 'level' + (data.level - 1)]"
|
||||
:class="['method', 'level' + ((data.level || 0) - 1)]"
|
||||
:style="{
|
||||
'text-indent': (data.level - 1) * 10 + 'px',
|
||||
'text-indent': ((data.level || 0) - 1) * 10 + 'px',
|
||||
width: `${method}px`,
|
||||
}"
|
||||
>
|
||||
@@ -152,10 +152,11 @@ limitations under the License. -->
|
||||
import { Themes } from "@/constants/data";
|
||||
import { TraceGraphType } from "../constant";
|
||||
import { WidgetType } from "@/views/dashboard/data";
|
||||
import type { Span, Ref } from "@/types/trace";
|
||||
|
||||
/*global Recordable*/
|
||||
const props = {
|
||||
data: { type: Object as PropType<Recordable>, default: () => ({}) },
|
||||
data: { type: Object as PropType<Span>, default: () => ({}) },
|
||||
method: { type: Number, default: 0 },
|
||||
type: { type: String, default: "" },
|
||||
headerType: { type: String, default: "" },
|
||||
@@ -181,7 +182,7 @@ limitations under the License. -->
|
||||
} else {
|
||||
const data = props.data;
|
||||
const exec = data.endTime - data.startTime ? data.endTime - data.startTime : 0;
|
||||
let result = (exec / data.totalExec) * 100;
|
||||
let result = (exec / (data.totalExec || 0)) * 100;
|
||||
result = result > 100 ? 100 : result;
|
||||
const resultStr = result.toFixed(4) + "%";
|
||||
return resultStr === "0.0000%" ? "0.9%" : resultStr;
|
||||
@@ -193,7 +194,7 @@ limitations under the License. -->
|
||||
return resultStr === "0.0000%" ? "0.9%" : resultStr;
|
||||
});
|
||||
const isCrossThread = computed(() => {
|
||||
const key = props.data.refs.findIndex((d: { type: string }) => d.type === "CROSS_THREAD");
|
||||
const key = props.data.refs?.findIndex((d: Ref) => d.type === "CROSS_THREAD") ?? -1;
|
||||
return key > -1 ? true : false;
|
||||
});
|
||||
function toggle() {
|
||||
@@ -228,7 +229,7 @@ limitations under the License. -->
|
||||
selectedItem(props.data);
|
||||
viewSpanDetail(dom);
|
||||
}
|
||||
function selectedItem(span: Recordable) {
|
||||
function selectedItem(span: Span) {
|
||||
traceStore.setSelectedSpan(span);
|
||||
}
|
||||
function viewSpanDetail(dom: HTMLSpanElement) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user