refactor: optimize data types for widgets and dashboards (#490)

This commit is contained in:
Fine0830
2025-08-14 18:25:40 +08:00
committed by GitHub
parent e885b61353
commit 54a700bf19
141 changed files with 972 additions and 743 deletions

View File

@@ -166,8 +166,8 @@ describe("Main Application", () => {
const mockStore = useAppStoreWithOut();
// Mock async operations to take time
mockStore.getActivateMenus.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
mockStore.queryOAPTimeInfo.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
vi.mocked(mockStore.getActivateMenus).mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
vi.mocked(mockStore.queryOAPTimeInfo).mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
// Test async operations
const promises = [mockStore.getActivateMenus(), mockStore.queryOAPTimeInfo()];

View File

@@ -55,11 +55,11 @@ limitations under the License. -->
import type { PropType, Ref } from "vue";
import { useI18n } from "vue-i18n";
import type { EventParams } from "@/types/app";
import type { Filters, RelatedTrace } from "@/types/dashboard";
import type { Filters, RelatedTrace, AssociateProcessorProps } from "@/types/dashboard";
import { useECharts } from "@/hooks/useEcharts";
import { addResizeListener, removeResizeListener } from "@/utils/event";
import Trace from "@/views/dashboard/related/trace/Index.vue";
import associateProcessor from "@/hooks/useAssociateProcessor";
import useAssociateProcessor from "@/hooks/useAssociateProcessor";
import { WidgetType } from "@/views/dashboard/data";
import SelectorLegend from "./Legend.vue";
@@ -71,7 +71,7 @@ limitations under the License. -->
const { setOptions, resize, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>);
const currentParams = ref<Nullable<EventParams>>(null);
const showTrace = ref<boolean>(false);
const traceOptions = ref<{ type: string; filters?: unknown }>({
const traceOptions = ref<{ type: string; filters?: unknown } | any>({
type: WidgetType.Trace,
});
const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN });
@@ -187,7 +187,11 @@ limitations under the License. -->
return;
}
if (props.filters.isRange) {
const { eventAssociate } = associateProcessor(props);
const { eventAssociate } = useAssociateProcessor({
filters: props.filters,
option: props.option,
relatedTrace: props.relatedTrace,
} as AssociateProcessorProps);
const options = eventAssociate();
setOptions(options || props.option);
} else {
@@ -200,7 +204,12 @@ limitations under the License. -->
}
function viewTrace() {
const item = associateProcessor(props).traceFilters(currentParams.value);
const item = useAssociateProcessor({
filters: props.filters,
option: props.option,
relatedTrace: props.relatedTrace,
} as AssociateProcessorProps).traceFilters(currentParams.value);
traceOptions.value = {
...traceOptions.value,
filters: item,
@@ -243,8 +252,12 @@ limitations under the License. -->
return;
}
let options;
if (props.filters && props.filters.isRange) {
const { eventAssociate } = associateProcessor(props);
if (props.filters?.isRange) {
const { eventAssociate } = useAssociateProcessor({
filters: props.filters,
option: props.option,
relatedTrace: props.relatedTrace,
} as AssociateProcessorProps);
options = eventAssociate();
}
setOptions(options || props.option);

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<el-radio-group v-model="selected" @change="checked">
<el-radio v-for="item in options" :key="item.value" :label="item.value">
<el-radio v-for="item in options" :key="item.value" :value="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>

View File

@@ -71,5 +71,8 @@ export async function httpQuery({
return response.json();
} else {
console.error(new HTTPError(response));
return {
errors: [new HTTPError(response)],
};
}
}

View File

@@ -23,8 +23,8 @@ import { useAppStoreWithOut } from "@/store/modules/app";
vi.mock("@/store/modules/app", () => ({
useAppStoreWithOut: vi.fn(),
InitializationDurationRow: {
start: "2023-01-01 00:00:00",
end: "2023-01-02 00:00:00",
start: new Date("2023-01-01 00:00:00"),
end: new Date("2023-01-02 00:00:00"),
step: "HOUR",
},
}));
@@ -46,11 +46,11 @@ vi.mock("@/utils/dateFormat", () => ({
describe("useDuration hook", () => {
const mockAppStore = {
utc: false,
};
} as unknown as ReturnType<typeof useAppStoreWithOut>;
beforeEach(() => {
vi.clearAllMocks();
(useAppStoreWithOut as any).mockReturnValue(mockAppStore);
vi.mocked(useAppStoreWithOut).mockReturnValue(mockAppStore);
});
describe("setDurationRow", () => {
@@ -93,12 +93,12 @@ describe("useDuration hook", () => {
});
describe("getMaxRange", () => {
it("should return empty array for day -1", () => {
it("should return date range for negative days", () => {
const { getMaxRange } = useDuration();
const result = getMaxRange(-1);
expect(result).toEqual([]);
expect(result).toHaveLength(0);
});
it("should return date range for positive days", () => {

View File

@@ -18,8 +18,9 @@ import { useAppStoreWithOut } from "@/store/modules/app";
import dateFormatStep from "@/utils/dateFormat";
import getLocalTime from "@/utils/localtime";
import type { EventParams } from "@/types/app";
import type { AssociateProcessorProps, Series } from "@/types/dashboard";
export default function associateProcessor(props: Indexable) {
export default function useAssociateProcessor(props: AssociateProcessorProps) {
function eventAssociate() {
if (!props.filters) {
return;
@@ -75,8 +76,8 @@ export default function associateProcessor(props: Indexable) {
if (start) {
const end = start;
duration = {
start: dateFormatStep(getLocalTime(appStore.utc, new Date(start)), step, true),
end: dateFormatStep(getLocalTime(appStore.utc, new Date(end)), step, true),
startTime: dateFormatStep(getLocalTime(appStore.utc, new Date(start)), step, true),
endTime: dateFormatStep(getLocalTime(appStore.utc, new Date(end)), step, true),
step,
};
}
@@ -84,14 +85,14 @@ export default function associateProcessor(props: Indexable) {
const status = relatedTrace.status;
const queryOrder = relatedTrace.queryOrder;
const latency = relatedTrace.latency;
const series = props.option.series || [];
const series = (props.option.series || []) as Series[];
const item: Indexable = {
duration,
queryOrder,
status,
};
if (latency) {
const latencyList = series.map((d: { name: string; data: number[][] }, index: number) => {
const latencyList = series.map((d: Series, index: number) => {
const data = [
d.data[currentParams.dataIndex][1],
series[index + 1] ? series[index + 1].data[currentParams.dataIndex][1] : Infinity,
@@ -104,7 +105,7 @@ export default function associateProcessor(props: Indexable) {
});
item.latency = latencyList;
}
const value = series.map((d: { name: string; data: number[][] }, index: number) => {
const value = series.map((d: Series, index: number) => {
return {
label: d.name,
value: String(index),

View File

@@ -16,7 +16,7 @@
*/
import { ElMessage } from "element-plus";
import { useDashboardStore } from "@/store/modules/dashboard";
import type { LayoutConfig } from "@/types/dashboard";
import type { LayoutConfig, Filters } from "@/types/dashboard";
import { ConfigFieldTypes } from "@/views/dashboard/data";
export default function getDashboard(param?: { name?: string; layer: string; entity: string }, t?: string) {
@@ -28,12 +28,12 @@ export default function getDashboard(param?: { name?: string; layer: string; ent
if (type === ConfigFieldTypes.NAME) {
dashboard = list.find(
(d: { name: string; layer: string; entity: string }) =>
d.name === opt.name && d.entity === opt.entity && d.layer === opt.layer,
d.name === opt?.name && d.entity === opt?.entity && d.layer === opt?.layer,
);
} else {
dashboard = list.find(
(d: { name: string; layer: string; entity: string; isDefault: boolean }) =>
d.isDefault && d.entity === opt.entity && d.layer === opt.layer,
d.isDefault && d.entity === opt?.entity && d.layer === opt?.layer,
);
}
const all = dashboardStore.layout;
@@ -52,7 +52,7 @@ export default function getDashboard(param?: { name?: string; layer: string; ent
widgets.push(item);
}
}
function associationWidget(sourceId: string, filters: unknown, type: string) {
function associationWidget(sourceId: string, filters: Filters, type: string) {
const widget = widgets.find((d: { type: string }) => d.type === type);
if (!widget) {
return ElMessage.info(`There has no a ${type} widget in the dashboard`);

View File

@@ -42,9 +42,13 @@ export function useDuration() {
durationRow = data;
}
function getMaxRange(day: number) {
if (day === -1) {
if (day === undefined || day === null) {
return [];
}
if (isNaN(day) || day < 0) {
return [];
}
const gap = (day + 1) * 24 * 60 * 60 * 1000;
const dates: Date[] = [new Date(new Date().getTime() - gap), new Date()];

View File

@@ -68,8 +68,8 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
if (idx === 0) {
variables.push(`$entity: Entity!`);
const entity = {
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService?.value,
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService?.normal,
serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation", "Process"].includes(
dashboardStore.entity,
)
@@ -81,8 +81,8 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
processName: dashboardStore.entity.includes("Process")
? selectorStore.currentProcess && selectorStore.currentProcess.value
: undefined,
destNormal: isRelation ? selectorStore.currentDestService.normal : undefined,
destServiceName: isRelation ? selectorStore.currentDestService.value : undefined,
destNormal: isRelation ? selectorStore.currentDestService?.normal : undefined,
destServiceName: isRelation ? selectorStore.currentDestService?.value : undefined,
destServiceInstanceName: ["ServiceInstanceRelation", "ProcessRelation"].includes(dashboardStore.entity)
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
: undefined,
@@ -247,7 +247,7 @@ export async function useExpressionsQueryPodsMetrics(
duration: appStore.durationTime,
};
const variables: string[] = [`$duration: Duration!`];
const currentService = selectorStore.currentService || {};
const currentService = selectorStore.currentService || ({} as Service);
const fragmentList = pods.map((d: (Instance | Endpoint | Service) & Indexable, index: number) => {
const entity = {
serviceName: scope === "Service" ? d.label : currentService.label,
@@ -373,7 +373,9 @@ export async function useExpressionsQueryPodsMetrics(
const dashboardStore = useDashboardStore();
const params = await expressionsGraphqlPods(pods);
const json = await dashboardStore.fetchMetricValue(params);
const json = await dashboardStore.fetchMetricValue(
params as { queryStr: string; conditions: { [key: string]: unknown } },
);
if (json.errors) {
ElMessage.error(json.errors);

View File

@@ -143,15 +143,15 @@ limitations under the License. -->
appStore.setColdStageMode(coldStage.value);
if (coldStage.value) {
handleMetricsTTL({
minute: appStore.metricsTTL.coldMinute,
hour: appStore.metricsTTL.coldHour,
day: appStore.metricsTTL.coldDay,
minute: appStore.metricsTTL?.coldMinute || NaN,
hour: appStore.metricsTTL?.coldHour || NaN,
day: appStore.metricsTTL?.coldDay || NaN,
});
} else {
handleMetricsTTL({
minute: appStore.metricsTTL.minute,
hour: appStore.metricsTTL.hour,
day: appStore.metricsTTL.day,
minute: appStore.metricsTTL?.minute || NaN,
hour: appStore.metricsTTL?.hour || NaN,
day: appStore.metricsTTL?.day || NaN,
});
}
appStore.setDuration(InitializationDurationRow);
@@ -303,7 +303,7 @@ limitations under the License. -->
}
const serviceId = route.params.serviceId;
const list = serviceDashboards.map((d: { path: string } & DashboardItem, index: number) => {
const list = serviceDashboards.map((d: DashboardItem, index: number) => {
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
if (serviceId) {
path = `/dashboard/${d.layer}/${d.entity}/${serviceId}/${d.name}`;
@@ -321,7 +321,7 @@ limitations under the License. -->
const endpointDashboards = dashboardStore.dashboards.filter(
(d: DashboardItem) => MetricCatalog.ENDPOINT === d.entity && dashboard.layer === d.layer,
);
const list = endpointDashboards.map((d: { path: string } & DashboardItem, index: number) => {
const list = endpointDashboards.map((d: DashboardItem, index: number) => {
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
if (podId) {
path = `/dashboard/${d.layer}/${d.entity}/${serviceId}/${podId}/${d.name}`;
@@ -341,7 +341,7 @@ limitations under the License. -->
const serviceRelationDashboards = dashboardStore.dashboards.filter(
(d: DashboardItem) => MetricCatalog.SERVICE_RELATION === d.entity && dashboard.layer === d.layer,
);
const list = serviceRelationDashboards.map((d: { path: string } & DashboardItem, index: number) => {
const list = serviceRelationDashboards.map((d: DashboardItem, index: number) => {
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
if (destServiceId) {
path = `/dashboard/related/${d.layer}/${d.entity}/${serviceId}/${destServiceId}/${d.name}`;
@@ -355,11 +355,11 @@ limitations under the License. -->
});
pathNames.value.push(list);
}
if ([MetricCatalog.Process, MetricCatalog.PROCESS_RELATION].includes(dashboard.entity)) {
if ([MetricCatalog.Process, MetricCatalog.PROCESS_RELATION].includes(dashboard.entity as MetricCatalog)) {
const InstanceDashboards = dashboardStore.dashboards.filter(
(d: DashboardItem) => MetricCatalog.SERVICE_INSTANCE === d.entity && dashboard.layer === d.layer,
);
const list = InstanceDashboards.map((d: { path: string } & DashboardItem, index: number) => {
const list = InstanceDashboards.map((d: DashboardItem, index: number) => {
let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
if (podId) {
path = `/dashboard/${d.layer}/${d.entity}/${serviceId}/${podId}/${d.name}`;

View File

@@ -24,6 +24,8 @@ export const NewControl = {
h: 12,
i: "0",
type: WidgetType.Widget,
widget: {},
graph: {},
};
export const TextConfig = {
fontColor: "white",

View File

@@ -72,8 +72,8 @@ describe("App Store", () => {
expect(store.theme).toBe(Themes.Dark);
expect(store.coldStageMode).toBe(false);
expect(store.maxRange).toEqual([]);
expect(store.metricsTTL).toEqual({});
expect(store.recordsTTL).toEqual({});
expect(store.metricsTTL).toEqual(null);
expect(store.recordsTTL).toEqual(null);
});
it("should have correct duration row initialization", () => {

View File

@@ -56,6 +56,6 @@ export const alarmStore = defineStore({
},
});
export function useAlarmStore(): Recordable {
export function useAlarmStore() {
return alarmStore(store);
}

View File

@@ -38,8 +38,8 @@ interface AppState {
theme: string;
coldStageMode: boolean;
maxRange: Date[];
metricsTTL: Recordable<MetricsTTL>;
recordsTTL: Recordable<RecordsTTL>;
metricsTTL: Nullable<MetricsTTL>;
recordsTTL: Nullable<RecordsTTL>;
}
export const InitializationDurationRow = {
@@ -64,8 +64,8 @@ export const appStore = defineStore({
theme: Themes.Dark,
coldStageMode: false,
maxRange: [],
metricsTTL: {},
recordsTTL: {},
metricsTTL: null,
recordsTTL: null,
}),
getters: {
duration(): Duration {
@@ -224,6 +224,6 @@ export const appStore = defineStore({
},
},
});
export function useAppStoreWithOut(): Recordable {
export function useAppStoreWithOut() {
return appStore(store);
}

View File

@@ -28,9 +28,9 @@ import { useSelectorStore } from "@/store/modules/selectors";
import type { Instance } from "@/types/selector";
interface AsyncProfilingState {
taskList: Array<Recordable<AsyncProfilingTask>>;
selectedTask: Recordable<AsyncProfilingTask>;
taskProgress: Recordable<AsyncProfilerTaskProgress>;
taskList: Array<AsyncProfilingTask>;
selectedTask: Nullable<AsyncProfilingTask>;
taskProgress: Nullable<AsyncProfilerTaskProgress>;
instances: Instance[];
analyzeTrees: AsyncProfilerStackElement[];
loadingTree: boolean;
@@ -41,15 +41,15 @@ export const asyncProfilingStore = defineStore({
id: "asyncProfiling",
state: (): AsyncProfilingState => ({
taskList: [],
selectedTask: {},
taskProgress: {},
selectedTask: null,
taskProgress: null,
instances: [],
analyzeTrees: [],
loadingTree: false,
loadingTasks: false,
}),
actions: {
setSelectedTask(task: Recordable<AsyncProfilingTask>) {
setSelectedTask(task: Nullable<AsyncProfilingTask>) {
this.selectedTask = task || {};
},
setAnalyzeTrees(tree: AsyncProfilerStackElement[]) {
@@ -57,10 +57,13 @@ export const asyncProfilingStore = defineStore({
},
async getTaskList() {
const selectorStore = useSelectorStore();
if (!selectorStore.currentService?.id) {
return;
}
this.loadingTasks = true;
const response = await graphql.query("getAsyncTaskList").params({
request: {
serviceId: selectorStore.currentService.id,
serviceId: selectorStore.currentService?.id,
limit: 10000,
},
});
@@ -86,7 +89,7 @@ export const asyncProfilingStore = defineStore({
this.taskProgress = response.data.taskProgress;
return response;
},
async getServiceInstances(param: { serviceId: string; isRelation: boolean }) {
async getServiceInstances(param: { serviceId: string; isRelation?: boolean }) {
if (!param.serviceId) {
return null;
}
@@ -103,6 +106,9 @@ export const asyncProfilingStore = defineStore({
return response;
},
async createTask(param: AsyncProfileTaskCreationRequest) {
if (!param.serviceId) {
return;
}
const response = await graphql.query("saveAsyncProfileTask").params({ asyncProfilerTaskCreationRequest: param });
if (response.errors) {
@@ -133,6 +139,6 @@ export const asyncProfilingStore = defineStore({
},
});
export function useAsyncProfilingStore(): Recordable {
export function useAsyncProfilingStore() {
return asyncProfilingStore(store);
}

View File

@@ -24,16 +24,16 @@ import type { MonitorInstance, MonitorProcess } from "@/types/continous-profilin
import { dateFormat } from "@/utils/dateFormat";
interface ContinousProfilingState {
strategyList: Array<Recordable<StrategyItem>>;
selectedStrategy: Recordable<StrategyItem>;
taskList: Array<Recordable<EBPFTaskList>>;
selectedTask: Recordable<EBPFTaskList>;
strategyList: Array<StrategyItem>;
selectedStrategy: Nullable<StrategyItem>;
taskList: Array<EBPFTaskList>;
selectedTask: Nullable<EBPFTaskList>;
errorTip: string;
errorReason: string;
instances: Instance[];
instance: Nullable<Instance>;
eBPFSchedules: EBPFProfilingSchedule[];
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
currentSchedule: Nullable<EBPFProfilingSchedule>;
analyzeTrees: AnalyzationTrees[];
ebpfTips: string;
aggregateType: string;
@@ -45,15 +45,15 @@ export const continousProfilingStore = defineStore({
id: "continousProfiling",
state: (): ContinousProfilingState => ({
strategyList: [],
selectedStrategy: {},
selectedStrategy: null,
taskList: [],
selectedTask: {},
selectedTask: null,
errorReason: "",
errorTip: "",
ebpfTips: "",
instances: [],
eBPFSchedules: [],
currentSchedule: {},
currentSchedule: null,
analyzeTrees: [],
aggregateType: "COUNT",
instance: null,
@@ -61,7 +61,7 @@ export const continousProfilingStore = defineStore({
policyLoading: false,
}),
actions: {
setSelectedStrategy(task: Recordable<StrategyItem>) {
setSelectedStrategy(task: Nullable<StrategyItem>) {
this.selectedStrategy = task || {};
},
setselectedTask(task: Recordable<EBPFTaskList>) {
@@ -165,6 +165,6 @@ export const continousProfilingStore = defineStore({
},
});
export function useContinousProfilingStore(): Recordable {
export function useContinousProfilingStore() {
return continousProfilingStore(store);
}

View File

@@ -31,11 +31,11 @@ interface DashboardState {
entity: string;
layerId: string;
activedGridItem: string;
selectorStore: Recordable;
selectorStore: ReturnType<typeof useSelectorStore>;
showTopology: boolean;
currentTabItems: LayoutConfig[];
dashboards: DashboardItem[];
currentDashboard: Nullable<DashboardItem>;
currentDashboard: DashboardItem;
editMode: boolean;
currentTabIndex: number;
showLinkConfig: boolean;
@@ -54,7 +54,7 @@ export const dashboardStore = defineStore({
showTopology: false,
currentTabItems: [],
dashboards: [],
currentDashboard: null,
currentDashboard: {} as DashboardItem,
editMode: false,
currentTabIndex: 0,
showLinkConfig: false,
@@ -73,8 +73,8 @@ export const dashboardStore = defineStore({
this.dashboards = list;
sessionStorage.setItem("dashboards", JSON.stringify(list));
},
setCurrentDashboard(item: DashboardItem) {
this.currentDashboard = item;
setCurrentDashboard(item: Nullable<DashboardItem>) {
this.currentDashboard = item || {};
},
addControl(type: WidgetType) {
const arr = this.layout.map((d: Recordable) => Number(d.i));
@@ -253,7 +253,7 @@ export const dashboardStore = defineStore({
setTopology(show: boolean) {
this.showTopology = show;
},
setConfigs(param: { [key: string]: unknown }) {
setConfigs(param: LayoutConfig) {
const actived = this.activedGridItem.split("-");
const index = this.layout.findIndex((d: LayoutConfig) => actived[0] === d.i);
if (actived.length === 3) {
@@ -353,7 +353,7 @@ export const dashboardStore = defineStore({
}
this.dashboards = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
},
async updateDashboard(setting: { id: string; configuration: string }) {
async updateDashboard(setting: { id?: string; configuration: string }) {
const resp = await graphql.query("updateTemplate").params({
setting,
});
@@ -448,6 +448,6 @@ export const dashboardStore = defineStore({
},
});
export function useDashboardStore(): Recordable {
export function useDashboardStore() {
return dashboardStore(store);
}

View File

@@ -57,7 +57,7 @@ export const demandLogStore = defineStore({
this.logs = logs;
this.message = message || "";
},
async getInstances(id: string) {
async getInstances(id?: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "Service ID is required" }));
@@ -113,6 +113,6 @@ export const demandLogStore = defineStore({
},
});
export function useDemandLogStore(): Recordable {
export function useDemandLogStore() {
return demandLogStore(store);
}

View File

@@ -21,14 +21,14 @@ import { store } from "@/store";
import graphql from "@/graphql";
import { EBPFProfilingTriggerType } from "../data";
interface EbpfState {
taskList: Array<Recordable<EBPFTaskList>>;
taskList: Array<EBPFTaskList>;
eBPFSchedules: EBPFProfilingSchedule[];
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
currentSchedule: Nullable<EBPFProfilingSchedule>;
analyzeTrees: AnalyzationTrees[];
labels: Option[];
couldProfiling: boolean;
ebpfTips: string;
selectedTask: Recordable<EBPFTaskList>;
selectedTask: Nullable<EBPFTaskList>;
aggregateType: string;
}
@@ -37,16 +37,16 @@ export const ebpfStore = defineStore({
state: (): EbpfState => ({
taskList: [],
eBPFSchedules: [],
currentSchedule: {},
currentSchedule: null,
analyzeTrees: [],
labels: [{ value: "", label: "" }],
couldProfiling: false,
ebpfTips: "",
selectedTask: {},
selectedTask: null,
aggregateType: "COUNT",
}),
actions: {
setSelectedTask(task: Recordable<EBPFTaskList>) {
setSelectedTask(task: Nullable<EBPFTaskList>) {
this.selectedTask = task || {};
},
setCurrentSchedule(s: EBPFProfilingSchedule) {
@@ -81,7 +81,7 @@ export const ebpfStore = defineStore({
});
return response;
},
async getTaskList(params: { serviceId: string; targets: string[] }) {
async getTaskList(params: { serviceId: string; targets: string[]; triggerType: string }) {
if (!params.serviceId) {
return new Promise((resolve) => resolve({}));
}
@@ -155,6 +155,6 @@ export const ebpfStore = defineStore({
},
});
export function useEbpfStore(): Recordable {
export function useEbpfStore() {
return ebpfStore(store);
}

View File

@@ -45,7 +45,7 @@ export const eventStore = defineStore({
this.condition = data;
},
async getInstances() {
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
const serviceId = useSelectorStore().currentService?.id || "";
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "" }));
@@ -62,7 +62,7 @@ export const eventStore = defineStore({
return response;
},
async getEndpoints(keyword?: string) {
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
const serviceId = useSelectorStore().currentService?.id || "";
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "" }));
}
@@ -111,6 +111,6 @@ export const eventStore = defineStore({
},
});
export function useEventStore(): Recordable {
export function useEventStore() {
return eventStore(store);
}

View File

@@ -73,7 +73,7 @@ export const logStore = defineStore({
return response;
},
async getInstances(id: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
const serviceId = this.selectorStore.currentService?.id || id;
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "Service ID is required" }));
}
@@ -89,7 +89,10 @@ export const logStore = defineStore({
return response;
},
async getEndpoints(id: string, keyword?: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
const serviceId = this.selectorStore.currentService?.id || id;
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "Service ID is required" }));
}
const response = await graphql.query("queryEndpoints").params({
serviceId,
duration: useAppStoreWithOut().durationTime,

View File

@@ -24,9 +24,9 @@ import { ElMessage } from "element-plus";
import type { DurationTime } from "@/types/app";
interface NetworkProfilingState {
networkTasks: Array<Recordable<EBPFTaskList>>;
networkTasks: EBPFTaskList[];
networkTip: string;
selectedNetworkTask: Recordable<EBPFTaskList>;
selectedNetworkTask: Nullable<EBPFTaskList>;
nodes: ProcessNode[];
calls: Call[];
node: Nullable<ProcessNode>;
@@ -43,7 +43,7 @@ export const networkProfilingStore = defineStore({
state: (): NetworkProfilingState => ({
networkTasks: [],
networkTip: "",
selectedNetworkTask: {},
selectedNetworkTask: null,
nodes: [],
calls: [],
node: null,
@@ -55,13 +55,13 @@ export const networkProfilingStore = defineStore({
loadNodes: false,
}),
actions: {
setSelectedNetworkTask(task: Recordable<EBPFTaskList>) {
setSelectedNetworkTask(task: Nullable<EBPFTaskList>) {
this.selectedNetworkTask = task || {};
},
setNode(node: Nullable<ProcessNode>) {
this.node = node;
},
setLink(link: Call) {
setLink(link: Nullable<Call>) {
this.call = link;
},
seNodes(nodes: Node[]) {
@@ -137,7 +137,12 @@ export const networkProfilingStore = defineStore({
}
return response;
},
async getTaskList(params: { serviceId: string; serviceInstanceId: string; targets: string[] }) {
async getTaskList(params: {
serviceId: string;
serviceInstanceId: string;
targets: string[];
triggerType: string;
}) {
if (!params.serviceId) {
return new Promise((resolve) => resolve({}));
}
@@ -188,6 +193,6 @@ export const networkProfilingStore = defineStore({
},
});
export function useNetworkProfilingStore(): Recordable {
export function useNetworkProfilingStore() {
return networkProfilingStore(store);
}

View File

@@ -22,6 +22,7 @@ import type {
ProfileAnalyzationTrees,
TaskLog,
ProfileTaskCreationRequest,
ProfileAnalyzeParams,
} from "@/types/profile";
import type { Trace } from "@/types/trace";
import { store } from "@/store";
@@ -34,11 +35,11 @@ interface ProfileState {
taskEndpoints: Endpoint[];
condition: { serviceId: string; endpointName: string };
taskList: TaskListItem[];
currentTask: Recordable<TaskListItem>;
currentTask: Nullable<TaskListItem>;
segmentList: Trace[];
currentSegment: Recordable<Trace>;
segmentSpans: Array<Recordable<SegmentSpan>>;
currentSpan: Recordable<SegmentSpan>;
currentSegment: Nullable<Trace>;
segmentSpans: SegmentSpan[];
currentSpan: Nullable<SegmentSpan>;
analyzeTrees: ProfileAnalyzationTrees;
taskLogs: TaskLog[];
highlightTop: boolean;
@@ -52,10 +53,10 @@ export const profileStore = defineStore({
condition: { serviceId: "", endpointName: "" },
taskList: [],
segmentList: [],
currentTask: {},
currentSegment: {},
currentTask: null,
currentSegment: null,
segmentSpans: [],
currentSpan: {},
currentSpan: null,
analyzeTrees: [],
taskLogs: [],
highlightTop: true,
@@ -71,19 +72,19 @@ export const profileStore = defineStore({
this.currentTask = task || {};
this.analyzeTrees = [];
},
setSegmentSpans(spans: Recordable<SegmentSpan>[]) {
setSegmentSpans(spans: Nullable<SegmentSpan>[]) {
this.currentSpan = spans[0] || {};
this.segmentSpans = spans;
},
setCurrentSpan(span: Recordable<SegmentSpan>) {
this.currentSpan = span;
setCurrentSpan(span: Nullable<SegmentSpan>) {
this.currentSpan = span || {};
this.analyzeTrees = [];
},
setCurrentSegment(segment: Trace) {
setCurrentSegment(segment: Nullable<Trace>) {
this.currentSegment = segment || {};
this.segmentSpans = segment.spans || [];
if (segment.spans) {
this.currentSpan = segment.spans[0] || {};
this.segmentSpans = segment?.spans || [];
if (segment?.spans) {
this.currentSpan = segment?.spans[0] || {};
} else {
this.currentSpan = {};
}
@@ -160,7 +161,7 @@ export const profileStore = defineStore({
this.setCurrentSegment(segmentList[0]);
this.getSegmentSpans(segmentList[0].segmentId);
} else {
this.setCurrentSegment({});
this.setCurrentSegment(null);
}
return response;
},
@@ -194,7 +195,7 @@ export const profileStore = defineStore({
this.currentSpan = segment.spans[index];
return response;
},
async getProfileAnalyze(params: Array<{ segmentId: string; timeRange: { start: number; end: number } }>) {
async getProfileAnalyze(params: ProfileAnalyzeParams[]) {
if (!params.length) {
return new Promise((resolve) => resolve({}));
}
@@ -238,6 +239,6 @@ export const profileStore = defineStore({
},
});
export function useProfileStore(): Recordable {
export function useProfileStore() {
return profileStore(store);
}

View File

@@ -88,7 +88,7 @@ export const selectorStore = defineStore({
}
return res.data;
},
async getServiceInstances(param?: { serviceId: string; isRelation: boolean }) {
async getServiceInstances(param?: { serviceId: string; isRelation?: boolean }) {
const serviceId = param ? param.serviceId : this.currentService?.id;
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "Service ID is required" }));
@@ -106,7 +106,7 @@ export const selectorStore = defineStore({
}
return resp;
},
async getProcesses(param?: { instanceId: string; isRelation: boolean }) {
async getProcesses(param?: { instanceId: string | undefined; isRelation?: boolean }) {
const instanceId = param ? param.instanceId : this.currentPod?.id;
if (!instanceId) {
return null;
@@ -147,7 +147,7 @@ export const selectorStore = defineStore({
}
return res;
},
async getService(serviceId: string, isRelation: boolean) {
async getService(serviceId: string, isRelation?: boolean) {
if (!serviceId) {
return;
}
@@ -185,7 +185,7 @@ export const selectorStore = defineStore({
return res;
},
async getEndpoint(endpointId: string, isRelation?: string) {
async getEndpoint(endpointId: string, isRelation?: boolean) {
if (!endpointId) {
return;
}
@@ -226,6 +226,6 @@ export const selectorStore = defineStore({
},
});
export function useSelectorStore(): Recordable {
export function useSelectorStore() {
return selectorStore(store);
}

View File

@@ -24,7 +24,7 @@ import { TTLTypes, TTLColdMap } from "../data";
interface SettingsState {
clusterNodes: ClusterNode[];
debuggingConfig: Indexable<string>;
configTTL: Recordable<ConfigTTL>;
configTTL: Nullable<ConfigTTL>;
}
export const settingsStore = defineStore({
@@ -32,7 +32,7 @@ export const settingsStore = defineStore({
state: (): SettingsState => ({
clusterNodes: [],
debuggingConfig: {},
configTTL: {},
configTTL: null,
}),
actions: {
async getClusterNodes() {
@@ -48,11 +48,14 @@ export const settingsStore = defineStore({
method: "get",
path: "ConfigTTL",
});
for (const item of Object.keys(response)) {
this.configTTL = {};
const keys = Object.keys(response).filter((k: string) => k);
for (const item of keys) {
const rows = [];
const row: Indexable<string> = { type: TTLTypes.HotAndWarm };
const rowCold: Indexable<string> = { type: TTLTypes.Cold };
for (const key of Object.keys(response[item])) {
const itemKeys = Object.keys(response[item]).filter((k: string) => k);
for (const key of itemKeys) {
if (HotAndWarmOpt.includes(key)) {
row[key] = response[item][key];
} else {
@@ -75,6 +78,6 @@ export const settingsStore = defineStore({
},
});
export function useSettingsStore(): Recordable {
export function useSettingsStore() {
return settingsStore(store);
}

View File

@@ -29,7 +29,7 @@ import { TargetTypes } from "@/views/dashboard/related/continuous-profiling/data
interface taskTimelineState {
loading: boolean;
taskList: EBPFTaskList[];
selectedTask: Recordable<EBPFTaskList>;
selectedTask: Nullable<EBPFTaskList>;
}
export const taskTimelineStore = defineStore({
@@ -37,11 +37,11 @@ export const taskTimelineStore = defineStore({
state: (): taskTimelineState => ({
loading: false,
taskList: [],
selectedTask: {},
selectedTask: null,
}),
actions: {
setSelectedTask(task: Recordable<EBPFTaskList>) {
this.selectedTask = task || {};
setSelectedTask(task: Nullable<EBPFTaskList>) {
this.selectedTask = task;
},
setTaskList(list: EBPFTaskList[]) {
this.taskList = list;
@@ -126,6 +126,6 @@ export const taskTimelineStore = defineStore({
},
});
export function useTaskTimelineStore(): Recordable {
export function useTaskTimelineStore() {
return taskTimelineStore(store);
}

View File

@@ -61,10 +61,10 @@ export const topologyStore = defineStore({
hierarchyInstanceNodeMetrics: {},
}),
actions: {
setNode(node: Node) {
setNode(node: Nullable<Node>) {
this.node = node;
},
setLink(link: Call) {
setLink(link: Nullable<Call>) {
this.call = link;
},
setInstanceTopology(data: { nodes: Node[]; calls: Call[] }) {
@@ -572,6 +572,6 @@ export const topologyStore = defineStore({
},
});
export function useTopologyStore(): Recordable {
export function useTopologyStore() {
return topologyStore(store);
}

View File

@@ -30,7 +30,7 @@ interface TraceState {
endpoints: Endpoint[];
traceList: Trace[];
traceSpans: Span[];
currentTrace: Recordable<Trace>;
currentTrace: Nullable<Trace>;
conditions: Recordable;
traceSpanLogs: Recordable[];
selectorStore: Recordable;
@@ -42,12 +42,12 @@ const { getDurationTime } = useDuration();
export const traceStore = defineStore({
id: "trace",
state: (): TraceState => ({
services: [{ value: "0", label: "All" }],
instances: [{ value: "0", label: "All" }],
endpoints: [{ value: "0", label: "All" }],
services: [{ value: "0", label: "All", id: "" }],
instances: [{ value: "0", label: "All", id: "" }],
endpoints: [{ value: "0", label: "All", id: "" }],
traceList: [],
traceSpans: [],
currentTrace: {},
currentTrace: null,
selectedSpan: {},
conditions: {
queryDuration: getDurationTime(),
@@ -63,7 +63,7 @@ export const traceStore = defineStore({
setTraceCondition(data: Recordable) {
this.conditions = { ...this.conditions, ...data };
},
setCurrentTrace(trace: Recordable<Trace>) {
setCurrentTrace(trace: Trace) {
this.currentTrace = trace;
},
setTraceSpans(spans: Span[]) {
@@ -121,7 +121,7 @@ export const traceStore = defineStore({
endpointId,
});
},
async getInstances(id: string) {
async getInstances(id?: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "Service ID is required" }));
@@ -137,7 +137,7 @@ export const traceStore = defineStore({
this.instances = [{ value: "0", label: "All" }, ...response.data.pods];
return response;
},
async getEndpoints(id: string, keyword?: string) {
async getEndpoints(id?: string, keyword?: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
if (!serviceId) {
return new Promise((resolve) => resolve({ errors: "Service ID is required" }));
@@ -211,6 +211,6 @@ export const traceStore = defineStore({
},
});
export function useTraceStore(): Recordable {
export function useTraceStore() {
return traceStore(store);
}

View File

@@ -20,9 +20,12 @@ export type AsyncProfilingTask = {
serviceId: string;
serviceInstanceIds: string[];
createTime: number;
events: string;
events: string[];
duration: number;
execArgs: string;
errorInstanceIds: string[];
successInstanceIds: string[];
logs: AsyncProfilerTaskLog[];
};
export type AsyncProfileTaskCreationRequest = {
@@ -39,6 +42,7 @@ export type AsyncProfilerStackElement = {
codeSignature: string;
total: number;
self: number;
elements?: StackElement[];
};
export type AsyncProfilerTaskProgress = {

View File

@@ -18,6 +18,7 @@
export interface StrategyItem {
type: string;
checkItems: CheckItems[];
id?: string;
}
export type CheckItems = {
type: string;

View File

@@ -19,11 +19,17 @@ export type DashboardItem = {
id?: string;
entity: string;
layer: string;
isRoot: boolean;
isRoot?: boolean;
name: string;
isDefault: boolean;
isDefault?: boolean;
expressions?: string[];
expressionsConfig?: MetricConfigOpt[];
path?: string;
};
export type NodeDashboard = {
scope: string;
dashboard: string;
};
export interface LayoutConfig {
x: number;
@@ -47,26 +53,86 @@ export interface LayoutConfig {
subExpressions?: string[];
subTypesOfMQE?: string[];
valueRelatedDashboard?: string;
legendMQE?: LegendMQE;
linkDashboard?: string;
nodeDashboard?: NodeDashboard[];
linkServerExpressions?: string[];
linkClientExpressions?: string[];
nodeExpressions?: string[];
description?: any;
linkServerMetricConfig?: MetricConfigOpt[];
linkClientMetricConfig?: MetricConfigOpt[];
nodeMetricConfig?: MetricConfigOpt[];
instanceDashboardName?: string;
processDashboardName?: string;
}
type LegendMQE = {
expression: string;
};
export type RelatedTrace = {
duration: DurationTime;
status: string;
queryOrder: string;
latency: boolean;
enableRelate: boolean;
refIdType: string;
};
export type FilterDuration = {
startTime: string;
endTime: string;
step?: string;
};
export type Owner = {
scope: string;
serviceID: string;
serviceInstanceID: string;
endpointID: string;
};
export type TopListItem = {
name: string;
value: string;
refId: string;
owner: Owner;
};
export type TopListData = {
[key: string]: TopListItem[];
};
export type Filters = {
dataIndex: number;
sourceId: string;
dataIndex?: number;
sourceId?: string;
isRange?: boolean;
duration?: DurationTime;
duration?: FilterDuration;
traceId?: string;
spanId?: string;
segmentId?: string;
id?: string;
queryOrder?: string;
status?: string;
metricValue?: { label: string; data: string; value: string }[];
owner?: Nullable<Owner>;
isReadRecords?: boolean | undefined;
};
export type Series = {
data: (number | string)[][];
name: string;
};
export type FilterOption = {
series: Series[];
type: string;
legend: LegendOptions;
};
export type AssociateProcessorProps = {
filters: Filters;
option: FilterOption;
relatedTrace: RelatedTrace;
};
export type MetricConfigOpt = {
@@ -83,6 +149,8 @@ export interface WidgetConfig {
name?: string;
title?: string;
tips?: string;
url?: string;
type?: string;
}
export type GraphConfig =
@@ -93,14 +161,29 @@ export type GraphConfig =
| EndpointListConfig
| ServiceListConfig
| InstanceListConfig
| TopologyConfig;
export interface BarConfig {
| TopologyConfig
| TextConfig
| TimeRangeConfig
| TopListConfig;
export interface BaseConfig {
type?: string;
valueMappings?: { [key: string]: string };
legend?: LegendOptions;
dashboardName?: string;
}
export interface TimeRangeConfig extends BaseConfig {
fontSize: number;
backgroundColor: string;
textAlign: string;
fontColor: string;
text: string;
}
export interface BarConfig extends BaseConfig {
showBackground?: boolean;
legend?: LegendOptions;
}
export interface LineConfig extends AreaConfig {
type?: string;
smooth?: boolean;
showSymbol?: boolean;
step?: boolean;
@@ -111,60 +194,54 @@ export interface LineConfig extends AreaConfig {
noTooltips?: boolean;
}
export interface AreaConfig {
type?: string;
export interface AreaConfig extends BaseConfig {
opacity?: number;
legend?: LegendOptions;
}
export interface CardConfig {
type?: string;
export interface CardConfig extends BaseConfig {
fontSize?: number;
showUnit?: boolean;
textAlign?: "center" | "right" | "left";
valueMappings?: { [key: string]: string };
}
export interface TextConfig {
export interface TextConfig extends BaseConfig {
fontSize: number;
backgroundColor: string;
textAlign: string;
fontColor: string;
content: string;
url: string;
}
export interface TableConfig {
type?: string;
export interface TableConfig extends BaseConfig {
showTableValues: boolean;
tableHeaderCol2: string;
}
export interface TopListConfig {
type?: string;
export interface TopListConfig extends BaseConfig {
topN: number;
color: string;
}
export interface ServiceListConfig {
type?: string;
export interface ServiceListConfig extends BaseConfig {
dashboardName: string;
fontSize: number;
showGroup: boolean;
}
export interface InstanceListConfig {
type?: string;
export interface InstanceListConfig extends BaseConfig {
dashboardName: string;
fontSize: number;
}
export interface EndpointListConfig {
type?: string;
export interface EndpointListConfig extends BaseConfig {
dashboardName: string;
fontSize: number;
}
export interface TopologyConfig {
type?: string;
export interface TopologyConfig extends BaseConfig {
backgroundColor?: string;
fontColor?: string;
iconTheme?: boolean;
@@ -172,6 +249,7 @@ export interface TopologyConfig {
fontSize?: number;
depth?: number;
showDepth?: boolean;
showBackground?: boolean;
}
export type EventParams = {
componentType: string;
@@ -207,6 +285,6 @@ type MetricLabel = {
type MetricValue = {
name: string;
value: string;
owner: null | string;
owner: Nullable<Owner>;
refId: null | string;
};

View File

@@ -21,7 +21,7 @@ export interface Conditions {
serviceInstanceId: string;
duration: DurationTime;
keywordsOfContent?: string[];
excludingKeywordsOfContent?: string;
excludingKeywordsOfContent?: string[];
}
export interface Log {

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import type { Process as selectorProcess } from "./selector";
import type { Process as SelectorProcess } from "./selector";
export interface EBPFTaskCreationRequest {
serviceId: string;
@@ -55,16 +55,17 @@ interface ProfilingCause {
current: number;
};
}
export interface Process extends SelectorProcess {
labels: string[];
}
export interface EBPFProfilingSchedule {
scheduleId: string;
taskId: string;
process: selectorProcess;
process: Process;
endTime: number;
startTime: number;
}
export type Process = selectorProcess;
export type StackElement = {
id: string;
originId: string;
@@ -99,6 +100,8 @@ export type AnalyzationTrees = {
symbol: string;
dumpCount: number;
stackType: string;
aggregateType: string;
elements?: StackElement[];
};
export type ProcessNode = {
id: string;

View File

@@ -37,13 +37,13 @@ export type Event = {
};
export interface QueryEventCondition {
uuid: string;
uuid?: string;
source: SourceInput;
name: string;
name?: string;
type: EventType;
time: Duration;
order: string;
paging: { pageNum: number; pageSize: number; needTotal: boolean };
time?: Duration;
order?: string;
paging: { pageNum: number; pageSize: number; needTotal?: boolean };
}
type SourceInput = {

View File

@@ -14,6 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { Span } from "./trace";
type ProfileStackElement = {
id: string;
parentId: string;
@@ -45,22 +47,7 @@ export interface TaskListItem {
successInstanceIds: string[];
serviceInstanceIds: string[];
}
export interface SegmentSpan {
spanId: string;
parentSpanId: string;
serviceCode: string;
serviceInstanceName: string;
startTime: number;
endTime: number;
endpointName: string;
type: string;
peer: string;
component: string;
isError: boolean;
layer: string;
tags: Recordable[];
logs: Recordable[];
}
export type SegmentSpan = Span;
export interface ProfileTaskCreationRequest {
serviceId: string;
@@ -71,3 +58,6 @@ export interface ProfileTaskCreationRequest {
dumpPeriod: number;
maxSamplingCount: number;
}
export type ProfileTimeRange = { start: number; end: number };
export type ProfileAnalyzeParams = { segmentId: string; timeRange: ProfileTimeRange };

View File

@@ -14,16 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type Service = {
export interface Service {
id?: string;
label: string;
value: string;
layers?: string[];
normal?: boolean;
group?: string;
merge?: string;
shortName?: string;
};
}
export type Instance = {
value: string;
@@ -42,7 +41,7 @@ export type Endpoint = {
merge?: string;
};
export type Process = {
export interface Process {
id: string;
name: string;
serviceId: string;
@@ -52,5 +51,6 @@ export type Process = {
agentId: string;
detectType: string;
attributes: { name: string; value: string }[];
labels: string[];
};
value: string;
label: string;
}

View File

@@ -24,6 +24,6 @@ export type ClusterNode = {
};
export type ConfigTTL = {
metrics: MetricsTTL;
records: RecordsTTL;
metrics: MetricsTTL[];
records: RecordsTTL[];
};

View File

@@ -52,6 +52,7 @@ export interface Node {
y?: number;
level?: number;
l?: number;
serviceId?: string;
}
export interface ServiceHierarchy {

View File

@@ -23,6 +23,8 @@ export interface Trace {
traceIds: Array<string | any>;
segmentId: string;
spans: Span[];
endpointNames: string[];
traceId: string;
}
export interface Span {
@@ -44,10 +46,21 @@ export interface Span {
endTime: number;
dur?: number;
children?: Span[];
tags?: Array<Map<string, string>>;
logs?: log[];
tags?: { value: string; key: string }[];
logs?: LogRef[];
parentSegmentId?: string;
key?: string;
serviceInstanceName?: string;
attachedEvents?: SpanAttachedEvent[];
level?: number;
totalExec?: number;
groupRef?: StatisticsGroupRef;
maxTime?: number;
minTime?: number;
sumTime?: number;
avgTime?: number;
count?: number;
profiled?: boolean;
}
export type Ref = {
type?: string;
@@ -55,9 +68,9 @@ export type Ref = {
parentSpanId: number;
traceId: string;
};
export interface log {
export interface LogRef {
time: number;
data: Map<string, string>;
data: { key: string; value: string }[];
}
export interface StatisticsSpan {

View File

@@ -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) {

View File

@@ -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 });

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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() {

View File

@@ -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 }}

View File

@@ -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>

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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,

View File

@@ -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>

View File

@@ -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"));

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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(

View File

@@ -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: "" },

View File

@@ -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: "" },

View File

@@ -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: "" },

View File

@@ -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: "" },

View File

@@ -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: "" },

View File

@@ -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: "" },

View File

@@ -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: "" },

View File

@@ -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];

View File

@@ -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: "" },

View File

@@ -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(

View File

@@ -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: "" },

View File

@@ -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(() => {

View File

@@ -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: "" },

View File

@@ -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: "" },

View File

@@ -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();

View File

@@ -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() {

View File

@@ -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("-")}`,
);

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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) => ({

View File

@@ -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;

View File

@@ -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);
}
});

View File

@@ -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 = "";

View File

@@ -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;

View File

@@ -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);

View File

@@ -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: () => ({}),
},
});

View File

@@ -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,
);
},
);

View File

@@ -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);

View File

@@ -77,7 +77,7 @@ limitations under the License. -->
}
toRaw(monacoInstance.value).dispose();
monacoInstance.value = null;
demandLogStore.setLogs("");
demandLogStore.setLogs([]);
});
watch(
() => appStore.theme,

View File

@@ -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([]);
}
},
);

Some files were not shown because too many files have changed in this diff Show More