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(); const mockStore = useAppStoreWithOut();
// Mock async operations to take time // Mock async operations to take time
mockStore.getActivateMenus.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100))); vi.mocked(mockStore.getActivateMenus).mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
mockStore.queryOAPTimeInfo.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100))); vi.mocked(mockStore.queryOAPTimeInfo).mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
// Test async operations // Test async operations
const promises = [mockStore.getActivateMenus(), mockStore.queryOAPTimeInfo()]; const promises = [mockStore.getActivateMenus(), mockStore.queryOAPTimeInfo()];

View File

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

View File

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

View File

@@ -71,5 +71,8 @@ export async function httpQuery({
return response.json(); return response.json();
} else { } else {
console.error(new HTTPError(response)); 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", () => ({ vi.mock("@/store/modules/app", () => ({
useAppStoreWithOut: vi.fn(), useAppStoreWithOut: vi.fn(),
InitializationDurationRow: { InitializationDurationRow: {
start: "2023-01-01 00:00:00", start: new Date("2023-01-01 00:00:00"),
end: "2023-01-02 00:00:00", end: new Date("2023-01-02 00:00:00"),
step: "HOUR", step: "HOUR",
}, },
})); }));
@@ -46,11 +46,11 @@ vi.mock("@/utils/dateFormat", () => ({
describe("useDuration hook", () => { describe("useDuration hook", () => {
const mockAppStore = { const mockAppStore = {
utc: false, utc: false,
}; } as unknown as ReturnType<typeof useAppStoreWithOut>;
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();
(useAppStoreWithOut as any).mockReturnValue(mockAppStore); vi.mocked(useAppStoreWithOut).mockReturnValue(mockAppStore);
}); });
describe("setDurationRow", () => { describe("setDurationRow", () => {
@@ -93,12 +93,12 @@ describe("useDuration hook", () => {
}); });
describe("getMaxRange", () => { describe("getMaxRange", () => {
it("should return empty array for day -1", () => { it("should return date range for negative days", () => {
const { getMaxRange } = useDuration(); const { getMaxRange } = useDuration();
const result = getMaxRange(-1); const result = getMaxRange(-1);
expect(result).toEqual([]); expect(result).toHaveLength(0);
}); });
it("should return date range for positive days", () => { 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 dateFormatStep from "@/utils/dateFormat";
import getLocalTime from "@/utils/localtime"; import getLocalTime from "@/utils/localtime";
import type { EventParams } from "@/types/app"; 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() { function eventAssociate() {
if (!props.filters) { if (!props.filters) {
return; return;
@@ -75,8 +76,8 @@ export default function associateProcessor(props: Indexable) {
if (start) { if (start) {
const end = start; const end = start;
duration = { duration = {
start: dateFormatStep(getLocalTime(appStore.utc, new Date(start)), step, true), startTime: dateFormatStep(getLocalTime(appStore.utc, new Date(start)), step, true),
end: dateFormatStep(getLocalTime(appStore.utc, new Date(end)), step, true), endTime: dateFormatStep(getLocalTime(appStore.utc, new Date(end)), step, true),
step, step,
}; };
} }
@@ -84,14 +85,14 @@ export default function associateProcessor(props: Indexable) {
const status = relatedTrace.status; const status = relatedTrace.status;
const queryOrder = relatedTrace.queryOrder; const queryOrder = relatedTrace.queryOrder;
const latency = relatedTrace.latency; const latency = relatedTrace.latency;
const series = props.option.series || []; const series = (props.option.series || []) as Series[];
const item: Indexable = { const item: Indexable = {
duration, duration,
queryOrder, queryOrder,
status, status,
}; };
if (latency) { if (latency) {
const latencyList = series.map((d: { name: string; data: number[][] }, index: number) => { const latencyList = series.map((d: Series, index: number) => {
const data = [ const data = [
d.data[currentParams.dataIndex][1], d.data[currentParams.dataIndex][1],
series[index + 1] ? series[index + 1].data[currentParams.dataIndex][1] : Infinity, series[index + 1] ? series[index + 1].data[currentParams.dataIndex][1] : Infinity,
@@ -104,7 +105,7 @@ export default function associateProcessor(props: Indexable) {
}); });
item.latency = latencyList; item.latency = latencyList;
} }
const value = series.map((d: { name: string; data: number[][] }, index: number) => { const value = series.map((d: Series, index: number) => {
return { return {
label: d.name, label: d.name,
value: String(index), value: String(index),

View File

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

View File

@@ -42,9 +42,13 @@ export function useDuration() {
durationRow = data; durationRow = data;
} }
function getMaxRange(day: number) { function getMaxRange(day: number) {
if (day === -1) { if (day === undefined || day === null) {
return []; return [];
} }
if (isNaN(day) || day < 0) {
return [];
}
const gap = (day + 1) * 24 * 60 * 60 * 1000; const gap = (day + 1) * 24 * 60 * 60 * 1000;
const dates: Date[] = [new Date(new Date().getTime() - gap), new Date()]; 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) { if (idx === 0) {
variables.push(`$entity: Entity!`); variables.push(`$entity: Entity!`);
const entity = { const entity = {
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value, serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService?.value,
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal, normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService?.normal,
serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation", "Process"].includes( serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation", "Process"].includes(
dashboardStore.entity, dashboardStore.entity,
) )
@@ -81,8 +81,8 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
processName: dashboardStore.entity.includes("Process") processName: dashboardStore.entity.includes("Process")
? selectorStore.currentProcess && selectorStore.currentProcess.value ? selectorStore.currentProcess && selectorStore.currentProcess.value
: undefined, : undefined,
destNormal: isRelation ? selectorStore.currentDestService.normal : undefined, destNormal: isRelation ? selectorStore.currentDestService?.normal : undefined,
destServiceName: isRelation ? selectorStore.currentDestService.value : undefined, destServiceName: isRelation ? selectorStore.currentDestService?.value : undefined,
destServiceInstanceName: ["ServiceInstanceRelation", "ProcessRelation"].includes(dashboardStore.entity) destServiceInstanceName: ["ServiceInstanceRelation", "ProcessRelation"].includes(dashboardStore.entity)
? selectorStore.currentDestPod && selectorStore.currentDestPod.value ? selectorStore.currentDestPod && selectorStore.currentDestPod.value
: undefined, : undefined,
@@ -247,7 +247,7 @@ export async function useExpressionsQueryPodsMetrics(
duration: appStore.durationTime, duration: appStore.durationTime,
}; };
const variables: string[] = [`$duration: Duration!`]; 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 fragmentList = pods.map((d: (Instance | Endpoint | Service) & Indexable, index: number) => {
const entity = { const entity = {
serviceName: scope === "Service" ? d.label : currentService.label, serviceName: scope === "Service" ? d.label : currentService.label,
@@ -373,7 +373,9 @@ export async function useExpressionsQueryPodsMetrics(
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const params = await expressionsGraphqlPods(pods); 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) { if (json.errors) {
ElMessage.error(json.errors); ElMessage.error(json.errors);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -19,11 +19,17 @@ export type DashboardItem = {
id?: string; id?: string;
entity: string; entity: string;
layer: string; layer: string;
isRoot: boolean; isRoot?: boolean;
name: string; name: string;
isDefault: boolean; isDefault?: boolean;
expressions?: string[]; expressions?: string[];
expressionsConfig?: MetricConfigOpt[]; expressionsConfig?: MetricConfigOpt[];
path?: string;
};
export type NodeDashboard = {
scope: string;
dashboard: string;
}; };
export interface LayoutConfig { export interface LayoutConfig {
x: number; x: number;
@@ -47,26 +53,86 @@ export interface LayoutConfig {
subExpressions?: string[]; subExpressions?: string[];
subTypesOfMQE?: string[]; subTypesOfMQE?: string[];
valueRelatedDashboard?: 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 = { export type RelatedTrace = {
duration: DurationTime; duration: DurationTime;
status: string; status: string;
queryOrder: string; queryOrder: string;
latency: boolean; latency: boolean;
enableRelate: 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 = { export type Filters = {
dataIndex: number; dataIndex?: number;
sourceId: string; sourceId?: string;
isRange?: boolean; isRange?: boolean;
duration?: DurationTime; duration?: FilterDuration;
traceId?: string; traceId?: string;
spanId?: string; spanId?: string;
segmentId?: string; segmentId?: string;
id?: string; id?: string;
queryOrder?: string; queryOrder?: string;
status?: 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 = { export type MetricConfigOpt = {
@@ -83,6 +149,8 @@ export interface WidgetConfig {
name?: string; name?: string;
title?: string; title?: string;
tips?: string; tips?: string;
url?: string;
type?: string;
} }
export type GraphConfig = export type GraphConfig =
@@ -93,14 +161,29 @@ export type GraphConfig =
| EndpointListConfig | EndpointListConfig
| ServiceListConfig | ServiceListConfig
| InstanceListConfig | InstanceListConfig
| TopologyConfig; | TopologyConfig
export interface BarConfig { | TextConfig
| TimeRangeConfig
| TopListConfig;
export interface BaseConfig {
type?: string; 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; showBackground?: boolean;
legend?: LegendOptions; legend?: LegendOptions;
} }
export interface LineConfig extends AreaConfig { export interface LineConfig extends AreaConfig {
type?: string;
smooth?: boolean; smooth?: boolean;
showSymbol?: boolean; showSymbol?: boolean;
step?: boolean; step?: boolean;
@@ -111,60 +194,54 @@ export interface LineConfig extends AreaConfig {
noTooltips?: boolean; noTooltips?: boolean;
} }
export interface AreaConfig { export interface AreaConfig extends BaseConfig {
type?: string;
opacity?: number; opacity?: number;
legend?: LegendOptions; legend?: LegendOptions;
} }
export interface CardConfig { export interface CardConfig extends BaseConfig {
type?: string;
fontSize?: number; fontSize?: number;
showUnit?: boolean; showUnit?: boolean;
textAlign?: "center" | "right" | "left"; textAlign?: "center" | "right" | "left";
valueMappings?: { [key: string]: string }; valueMappings?: { [key: string]: string };
} }
export interface TextConfig { export interface TextConfig extends BaseConfig {
fontSize: number; fontSize: number;
backgroundColor: string; backgroundColor: string;
textAlign: string; textAlign: string;
fontColor: string; fontColor: string;
content: string; content: string;
url: string;
} }
export interface TableConfig { export interface TableConfig extends BaseConfig {
type?: string;
showTableValues: boolean; showTableValues: boolean;
tableHeaderCol2: string; tableHeaderCol2: string;
} }
export interface TopListConfig { export interface TopListConfig extends BaseConfig {
type?: string;
topN: number; topN: number;
color: string;
} }
export interface ServiceListConfig { export interface ServiceListConfig extends BaseConfig {
type?: string;
dashboardName: string; dashboardName: string;
fontSize: number; fontSize: number;
showGroup: boolean; showGroup: boolean;
} }
export interface InstanceListConfig { export interface InstanceListConfig extends BaseConfig {
type?: string;
dashboardName: string; dashboardName: string;
fontSize: number; fontSize: number;
} }
export interface EndpointListConfig { export interface EndpointListConfig extends BaseConfig {
type?: string;
dashboardName: string; dashboardName: string;
fontSize: number; fontSize: number;
} }
export interface TopologyConfig { export interface TopologyConfig extends BaseConfig {
type?: string;
backgroundColor?: string; backgroundColor?: string;
fontColor?: string; fontColor?: string;
iconTheme?: boolean; iconTheme?: boolean;
@@ -172,6 +249,7 @@ export interface TopologyConfig {
fontSize?: number; fontSize?: number;
depth?: number; depth?: number;
showDepth?: boolean; showDepth?: boolean;
showBackground?: boolean;
} }
export type EventParams = { export type EventParams = {
componentType: string; componentType: string;
@@ -207,6 +285,6 @@ type MetricLabel = {
type MetricValue = { type MetricValue = {
name: string; name: string;
value: string; value: string;
owner: null | string; owner: Nullable<Owner>;
refId: null | string; refId: null | string;
}; };

View File

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

View File

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

View File

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

View File

@@ -14,6 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import type { Span } from "./trace";
type ProfileStackElement = { type ProfileStackElement = {
id: string; id: string;
parentId: string; parentId: string;
@@ -45,22 +47,7 @@ export interface TaskListItem {
successInstanceIds: string[]; successInstanceIds: string[];
serviceInstanceIds: string[]; serviceInstanceIds: string[];
} }
export interface SegmentSpan { export type SegmentSpan = Span;
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 interface ProfileTaskCreationRequest { export interface ProfileTaskCreationRequest {
serviceId: string; serviceId: string;
@@ -71,3 +58,6 @@ export interface ProfileTaskCreationRequest {
dumpPeriod: number; dumpPeriod: number;
maxSamplingCount: 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 * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
export type Service = { export interface Service {
id?: string; id?: string;
label: string; label: string;
value: string; value: string;
layers?: string[]; layers?: string[];
normal?: boolean; normal?: boolean;
group?: string; group?: string;
merge?: string;
shortName?: string; shortName?: string;
}; }
export type Instance = { export type Instance = {
value: string; value: string;
@@ -42,7 +41,7 @@ export type Endpoint = {
merge?: string; merge?: string;
}; };
export type Process = { export interface Process {
id: string; id: string;
name: string; name: string;
serviceId: string; serviceId: string;
@@ -52,5 +51,6 @@ export type Process = {
agentId: string; agentId: string;
detectType: string; detectType: string;
attributes: { name: string; value: string }[]; attributes: { name: string; value: string }[];
labels: string[]; value: string;
}; label: string;
}

View File

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

View File

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

View File

@@ -23,6 +23,8 @@ export interface Trace {
traceIds: Array<string | any>; traceIds: Array<string | any>;
segmentId: string; segmentId: string;
spans: Span[]; spans: Span[];
endpointNames: string[];
traceId: string;
} }
export interface Span { export interface Span {
@@ -44,10 +46,21 @@ export interface Span {
endTime: number; endTime: number;
dur?: number; dur?: number;
children?: Span[]; children?: Span[];
tags?: Array<Map<string, string>>; tags?: { value: string; key: string }[];
logs?: log[]; logs?: LogRef[];
parentSegmentId?: string; parentSegmentId?: string;
key?: 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 = { export type Ref = {
type?: string; type?: string;
@@ -55,9 +68,9 @@ export type Ref = {
parentSpanId: number; parentSpanId: number;
traceId: string; traceId: string;
}; };
export interface log { export interface LogRef {
time: number; time: number;
data: Map<string, string>; data: { key: string; value: string }[];
} }
export interface StatisticsSpan { export interface StatisticsSpan {

View File

@@ -24,6 +24,7 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Dashboard from "./dashboard/Edit.vue"; import Dashboard from "./dashboard/Edit.vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { DashboardItem } from "@/types/dashboard";
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@@ -38,7 +39,7 @@ limitations under the License. -->
dashboardStore.setMode(false); dashboardStore.setMode(false);
await dashboardStore.setDashboards(); await dashboardStore.setDashboards();
const item = dashboardStore.dashboards.find( 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, d.layer === dashboardStore.layerId && [EntityType[0].value, EntityType[1].value].includes(d.entity) && d.isRoot,
); );
if (!item) { if (!item) {

View File

@@ -87,7 +87,7 @@ limitations under the License. -->
alarmStore.alarms.length === pageSize ? pageSize * pageNum.value + 1 : pageSize * pageNum.value, alarmStore.alarms.length === pageSize ? pageSize * pageNum.value + 1 : pageSize * pageNum.value,
); );
const maxRange = computed(() => 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 }); refreshAlarms({ pageNum: 1 });

View File

@@ -28,7 +28,7 @@ limitations under the License. -->
:destroy-on-close="true" :destroy-on-close="true"
@closed="dashboardStore.setConfigPanel(false)" @closed="dashboardStore.setConfigPanel(false)"
> >
<component :is="dashboardStore.selectedGrid.type" /> <component :is="dashboardStore.selectedGrid?.type" />
</el-dialog> </el-dialog>
<el-dialog <el-dialog
v-model="dashboardStore.showLinkConfig" v-model="dashboardStore.showLinkConfig"
@@ -77,9 +77,9 @@ limitations under the License. -->
dashboardStore.setLayout(setWidgetsID(layout.children || [])); dashboardStore.setLayout(setWidgetsID(layout.children || []));
if (p.entity) { if (p.entity) {
dashboardStore.setCurrentDashboard({ dashboardStore.setCurrentDashboard({
layer: p.layerId, layer: p.layerId as string,
entity: p.entity, entity: p.entity as string,
name: p.name, name: p.name as string,
id: c.id, id: c.id,
isRoot: layout.isRoot, isRoot: layout.isRoot,
}); });
@@ -112,7 +112,7 @@ limitations under the License. -->
} }
onUnmounted(() => { onUnmounted(() => {
dashboardStore.setCurrentDashboard({}); dashboardStore.setCurrentDashboard(null);
}); });
return { return {

View File

@@ -578,14 +578,17 @@ limitations under the License. -->
name: value, name: value,
}); });
dashboards.value = dashboardStore.dashboards.map((item: DashboardItem) => { dashboards.value = dashboardStore.dashboards.map((item: DashboardItem) => {
if (dashboardStore.currentDashboard.id === item.id) { if (dashboardStore.currentDashboard?.id === item.id) {
item = dashboardStore.currentDashboard; item = dashboardStore.currentDashboard as DashboardItem;
} }
return item; return item;
}); });
dashboardStore.resetDashboards(dashboards.value); dashboardStore.resetDashboards(dashboards.value);
sessionStorage.setItem("dashboards", JSON.stringify(dashboards.value)); sessionStorage.setItem("dashboards", JSON.stringify(dashboards.value));
sessionStorage.removeItem(key); sessionStorage.removeItem(key);
if (!dashboardStore.currentDashboard) {
return;
}
const str = [ const str = [
dashboardStore.currentDashboard.layer, dashboardStore.currentDashboard.layer,
dashboardStore.currentDashboard.entity, dashboardStore.currentDashboard.entity,

View File

@@ -81,8 +81,8 @@ limitations under the License. -->
init(); init();
async function init() { async function init() {
dashboardStore.setLayer(route.params.layer); dashboardStore.setLayer(route.params.layer as string);
dashboardStore.setEntity(route.params.entity); dashboardStore.setEntity(route.params.entity as string);
const { auto, autoPeriod } = config.value; const { auto, autoPeriod } = config.value;
if (auto) { if (auto) {
await setDuration(); await setDuration();
@@ -102,30 +102,30 @@ limitations under the License. -->
async function setSelector() { async function setSelector() {
const { serviceId, podId, processId, destServiceId, destPodId, destProcessId, entity } = route.params; const { serviceId, podId, processId, destServiceId, destPodId, destProcessId, entity } = route.params;
if (serviceId) { if (serviceId) {
await selectorStore.getService(serviceId); await selectorStore.getService(serviceId as string);
} }
if ( if (
[EntityType[4].value, EntityType[5].value, EntityType[6].value, EntityType[7].value].includes( [EntityType[4].value, EntityType[5].value, EntityType[6].value, EntityType[7].value].includes(
entity as string, 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)) { 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)) { 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) { 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)) { 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) { if (EntityType[7].value === entity) {
selectorStore.getProcess(processId); selectorStore.getProcess(processId as string);
selectorStore.getProcess(destProcessId, true); selectorStore.getProcess(destProcessId as string, true);
} }
} }
async function queryMetrics() { async function queryMetrics() {

View File

@@ -25,15 +25,15 @@ limitations under the License. -->
<div v-else> <div v-else>
<label>{{ t("auto") }}</label> <label>{{ t("auto") }}</label>
<el-switch class="mr-5" v-model="auto" style="height: 25px" /> <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"> <div class="mt-5">
<label>{{ t("period") }}</label> <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> <span class="ml-5">{{ t("second") }}</span>
<i class="ml-10">{{ t("timeReload") }}</i> <i class="ml-10">{{ t("timeReload") }}</i>
</div> </div>
</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"> <div v-show="widgetLink" class="mt-10">
<span @click="viewPage" class="link"> <span @click="viewPage" class="link">
{{ host + widgetLink }} {{ host + widgetLink }}

View File

@@ -49,12 +49,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { EntityType } from "../data"; import { EntityType } from "../data";
import type { DashboardItem } from "@/types/dashboard"; import type { DashboardItem, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const instanceDashboardName = ref<boolean>(dashboardStore.selectedGrid.instanceDashboardName); const instanceDashboardName = ref<string>(dashboardStore.selectedGrid?.instanceDashboardName || "");
const processDashboardName = ref<number>(dashboardStore.selectedGrid.processDashboardName); const processDashboardName = ref<string>(dashboardStore.selectedGrid?.processDashboardName || "");
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]"); const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
const instanceDashboards: Array<DashboardItem & { label: string; value: string }> = []; const instanceDashboards: Array<DashboardItem & { label: string; value: string }> = [];
const processDashboards: Array<DashboardItem & { label: string; value: string }> = []; const processDashboards: Array<DashboardItem & { label: string; value: string }> = [];
@@ -76,14 +76,14 @@ limitations under the License. -->
} }
function applyConfig() { function applyConfig() {
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
} }
function changeDashboard(param: { [key: string]: unknown }) { function changeDashboard(param: { [key: string]: unknown }) {
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
...param, ...param,
}); } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -28,23 +28,22 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { ref } from "vue"; import { ref } from "vue";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const originConfig = dashboardStore.selectedGrid; const originConfig = dashboardStore.selectedGrid;
const eventAssociate = ref(dashboardStore.selectedGrid.eventAssociate || false); const eventAssociate = ref(dashboardStore.selectedGrid?.eventAssociate || false);
function updateConfig() { function updateConfig() {
dashboardStore.selectedGrid = { const { selectedGrid } = dashboardStore;
...dashboardStore.selectedGrid,
eventAssociate, dashboardStore.selectWidget({ ...selectedGrid, eventAssociate: eventAssociate.value } as LayoutConfig);
};
dashboardStore.selectWidget(dashboardStore.selectedGrid);
} }
function applyConfig() { function applyConfig() {
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
} }
function cancelConfig() { function cancelConfig() {

View File

@@ -33,13 +33,14 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { WidgetType, ListEntity } from "@/views/dashboard/data"; import { WidgetType, ListEntity } from "@/views/dashboard/data";
import type { LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const originConfig = dashboardStore.selectedGrid; const originConfig = dashboardStore.selectedGrid;
const expressions = reactive<{ [key: string]: string }>({}); const expressions = reactive<{ [key: string]: string }>({});
const widgetTabs = computed(() => const widgetTabs = computed(() =>
(dashboardStore.selectedGrid.children || []).filter((child: any) => (dashboardStore.selectedGrid?.children || []).filter((child: any) =>
child.children.find( child.children.find(
(item: any) => (item: any) =>
item.type === WidgetType.Widget && 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 || ""; expressions[child.name] = child.expression || "";
} }
function changeExpression(name: string) { function changeExpression(name: string) {
@@ -56,7 +57,7 @@ limitations under the License. -->
ElMessage.error("Only support the is_present function"); ElMessage.error("Only support the is_present function");
return; return;
} }
const children = JSON.parse(JSON.stringify(dashboardStore.selectedGrid.children || [])); const children = JSON.parse(JSON.stringify(dashboardStore.selectedGrid?.children || []));
for (const item of children) { for (const item of children) {
if (item.name === name) { 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() { function applyConfig() {
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
} }
function cancelConfig() { function cancelConfig() {

View File

@@ -78,10 +78,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { ref } from "vue"; import { ref } from "vue";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { LayoutConfig, TextConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const originConfig = dashboardStore.selectedGrid; const originConfig = dashboardStore.selectedGrid;
const graph = originConfig.graph || {}; const graph = (originConfig?.graph as TextConfig) || {};
const url = ref(graph.url || ""); const url = ref(graph.url || "");
const backgroundColor = ref(graph.backgroundColor || "green"); const backgroundColor = ref(graph.backgroundColor || "green");
const fontColor = ref(graph.fontColor || "white"); const fontColor = ref(graph.fontColor || "white");
@@ -112,14 +114,14 @@ limitations under the License. -->
function changeConfig(param: { [key: string]: unknown }) { function changeConfig(param: { [key: string]: unknown }) {
const { selectedGrid } = dashboardStore; const { selectedGrid } = dashboardStore;
const graph = { const graph = {
...selectedGrid.graph, ...selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...selectedGrid, graph }); dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
} }
function applyConfig() { function applyConfig() {
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
} }
function cancelConfig() { function cancelConfig() {

View File

@@ -30,11 +30,12 @@ limitations under the License. -->
import { ref } from "vue"; import { ref } from "vue";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { validateAndSanitizeUrl } from "@/utils/validateAndSanitizeUrl"; import { validateAndSanitizeUrl } from "@/utils/validateAndSanitizeUrl";
import type { LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const originConfig = dashboardStore.selectedGrid; const originConfig = dashboardStore.selectedGrid;
const widget = originConfig.widget || {}; const widget = originConfig?.widget || {};
const url = ref(widget.url || ""); const url = ref(widget.url || "");
const urlError = ref(""); const urlError = ref("");
@@ -55,10 +56,10 @@ limitations under the License. -->
const { selectedGrid } = dashboardStore; const { selectedGrid } = dashboardStore;
const widget = { const widget = {
...dashboardStore.selectedGrid.widget, ...dashboardStore.selectedGrid?.widget,
[key]: param[key], // Use the sanitized URL directly, no need for decodeURIComponent [key]: param[key], // Use the sanitized URL directly, no need for decodeURIComponent
}; };
dashboardStore.selectWidget({ ...selectedGrid, widget }); dashboardStore.selectWidget({ ...selectedGrid, widget } as LayoutConfig);
} }
function applyConfig() { function applyConfig() {
@@ -66,7 +67,7 @@ limitations under the License. -->
return; // Don't apply if there's a validation error return; // Don't apply if there's a validation error
} }
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
} }
function cancelConfig() { function cancelConfig() {

View File

@@ -74,11 +74,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { ref } from "vue"; import { ref } from "vue";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { TimeRangeConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const originConfig = dashboardStore.selectedGrid; const originConfig = dashboardStore.selectedGrid;
const graph = originConfig.graph || {}; const graph = (originConfig?.graph as TimeRangeConfig) || {};
const backgroundColor = ref(graph.backgroundColor || "green"); const backgroundColor = ref(graph.backgroundColor || "green");
const fontColor = ref(graph.fontColor || "white"); const fontColor = ref(graph.fontColor || "white");
const fontSize = ref<number>(graph.fontSize || 12); const fontSize = ref<number>(graph.fontSize || 12);
@@ -107,14 +108,14 @@ limitations under the License. -->
function changeConfig(param: { [key: string]: unknown }) { function changeConfig(param: { [key: string]: unknown }) {
const { selectedGrid } = dashboardStore; const { selectedGrid } = dashboardStore;
const graph = { const graph = {
...selectedGrid.graph, ...selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...selectedGrid, graph }); dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
} }
function applyConfig() { function applyConfig() {
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
} }
function cancelConfig() { function cancelConfig() {

View File

@@ -34,24 +34,25 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { DepthList } from "../data"; import { DepthList } from "../data";
import type { Option } from "@/types/app"; import type { Option } from "@/types/app";
import type { TopologyConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph || {}; const graph = (dashboardStore.selectedGrid?.graph as TopologyConfig) || {};
const showDepth = ref<boolean>(graph.showDepth); const showDepth = ref<boolean>(graph?.showDepth || false);
const depth = ref<number>(graph.depth || 2); const depth = ref<number>(graph?.depth || 2);
function applyConfig() { function applyConfig() {
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
} }
function changeConfig(param: { [key: string]: unknown }) { function changeConfig(param: { [key: string]: unknown }) {
const { selectedGrid } = dashboardStore; const { selectedGrid } = dashboardStore;
const graph = { const graph = {
...selectedGrid.graph, ...selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...selectedGrid, graph }); dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
} }
function changeDepth(opt: Option[] | any) { function changeDepth(opt: Option[] | any) {
const val = opt[0].value; const val = opt[0].value;

View File

@@ -32,16 +32,16 @@ limitations under the License. -->
:data="states.source" :data="states.source"
:config="{ :config="{
...graph, ...graph,
decorations: dashboardStore.selectedGrid.graph?.decorations, valueMappings: dashboardStore.selectedGrid?.graph?.valueMappings,
legend: dashboardStore.selectedGrid.graph?.legend, legend: dashboardStore.selectedGrid?.graph?.legend,
i: dashboardStore.selectedGrid.i, i: dashboardStore.selectedGrid?.i,
metricConfig: dashboardStore.selectedGrid.metricConfig, metricConfig: dashboardStore.selectedGrid?.metricConfig,
relatedTrace: dashboardStore.selectedGrid.relatedTrace, relatedTrace: dashboardStore.selectedGrid?.relatedTrace,
expressions: dashboardStore.selectedGrid.expressions || [], expressions: dashboardStore.selectedGrid?.expressions || [],
typesOfMQE: dashboardStore.selectedGrid.typesOfMQE || [], typesOfMQE: dashboardStore.selectedGrid?.typesOfMQE || [],
subExpressions: dashboardStore.selectedGrid.subExpressions || [], subExpressions: dashboardStore.selectedGrid?.subExpressions || [],
subTypesOfMQE: dashboardStore.selectedGrid.subTypesOfMQE || [], subTypesOfMQE: dashboardStore.selectedGrid?.subTypesOfMQE || [],
valueRelatedDashboard: dashboardStore.selectedGrid.valueRelatedDashboard, valueRelatedDashboard: dashboardStore.selectedGrid?.valueRelatedDashboard,
}" }"
:needQuery="true" :needQuery="true"
@expressionTips="getErrors" @expressionTips="getErrors"
@@ -88,6 +88,7 @@ limitations under the License. -->
import type { Option } from "@/types/app"; import type { Option } from "@/types/app";
import graphs from "../graphs"; import graphs from "../graphs";
import CustomOptions from "./widget/index"; import CustomOptions from "./widget/index";
import type { LayoutConfig } from "@/types/dashboard";
export default defineComponent({ export default defineComponent({
name: "WidgetEdit", name: "WidgetEdit",
@@ -106,23 +107,21 @@ limitations under the License. -->
const states = reactive<{ const states = reactive<{
activeNames: string; activeNames: string;
source: unknown; source: unknown;
index: string; index: string | undefined;
visType: Option[]; visType: Option[];
}>({ }>({
activeNames: "1", activeNames: "1",
source: {}, source: {},
index: dashboardStore.selectedGrid.i, index: dashboardStore.selectedGrid?.i,
visType: [], visType: [],
}); });
const originConfig = dashboardStore.selectedGrid; const originConfig = dashboardStore.selectedGrid;
const widget = computed(() => dashboardStore.selectedGrid.widget || {}); const widget = computed(() => dashboardStore.selectedGrid?.widget || {});
const graph = computed(() => dashboardStore.selectedGrid.graph || {}); const graph = computed(() => dashboardStore.selectedGrid?.graph || {});
const title = computed(() => encodeURIComponent(widget.value.title || "")); const title = computed(() => encodeURIComponent(widget.value.title || ""));
const tips = computed(() => encodeURIComponent(widget.value.tips || "")); const tips = computed(() => encodeURIComponent(widget.value.tips || ""));
const hasAssociate = computed(() => const hasAssociate = computed(() =>
["Bar", "Line", "Area", "TopList"].includes( ["Bar", "Line", "Area", "TopList"].includes(dashboardStore.selectedGrid?.graph?.type || ""),
dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph.type,
),
); );
function getSource(source: unknown) { function getSource(source: unknown) {
@@ -140,7 +139,7 @@ limitations under the License. -->
function applyConfig() { function applyConfig() {
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid as LayoutConfig);
} }
function cancelConfig() { function cancelConfig() {

View File

@@ -33,24 +33,25 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import getDashboard from "@/hooks/useDashboardsSession"; import getDashboard from "@/hooks/useDashboardsSession";
import type { Option } from "@/types/app"; import type { Option } from "@/types/app";
import type { DashboardItem, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); 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 widgetIds = ref<string[]>(associate.map((d: { widgetId: string }) => d.widgetId));
const widgets: any = computed(() => { const widgets: any = computed(() => {
const widgetList = getDashboard(dashboardStore.currentDashboard).widgets; const widgetList = getDashboard(dashboardStore.currentDashboard as DashboardItem).widgets;
const items = []; const items = [];
for (const d of widgetList) { for (const d of widgetList) {
const isLinear = ["Bar", "Line", "Area"].includes((d.graph && d.graph.type) || ""); 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 }); items.push({ value: d.id, label: (d.widget && d.widget.name) || d.id });
} }
} }
return items; return items;
}); });
function updateWidgetConfig(options: Option[]) { 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) => { const opt = options.map((d: Option) => {
return { widgetId: d.value }; return { widgetId: d.value };
}); });
@@ -60,7 +61,7 @@ limitations under the License. -->
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
associate: opt, associate: opt,
}; };
dashboardStore.selectWidget({ ...widget }); dashboardStore.selectWidget({ ...widget } as LayoutConfig);
// remove unuse association widget option // remove unuse association widget option
for (const id of widgetIds.value) { for (const id of widgetIds.value) {
@@ -76,7 +77,7 @@ limitations under the License. -->
// add association options in target widgets // add association options in target widgets
for (let i = 0; i < opt.length; i++) { for (let i = 0; i < opt.length; i++) {
const item = JSON.parse(JSON.stringify(opt)); 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 w = arr.find((d: { id: string }) => d.id === opt[i].widgetId);
const config = { const config = {
...w, ...w,

View File

@@ -62,6 +62,7 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { RefIdTypes } from "../../data"; import { RefIdTypes } from "../../data";
import type { LayoutConfig, RelatedTrace } from "@/types/dashboard";
const QueryOrders = [ const QueryOrders = [
{ label: "None", value: "BY_START_TIME" }, { label: "None", value: "BY_START_TIME" },
@@ -74,21 +75,20 @@ limitations under the License. -->
]; ];
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const { graph, relatedTrace } = dashboardStore.selectedGrid; const traceOpt = dashboardStore.selectedGrid?.relatedTrace as RelatedTrace;
const traceOpt = relatedTrace || {}; const status = ref<string>(traceOpt?.status || Status[0].value);
const status = ref<string>(traceOpt.status || Status[0].value); const queryOrder = ref<string>(traceOpt?.queryOrder || QueryOrders[0].value);
const queryOrder = ref<string>(traceOpt.queryOrder || QueryOrders[0].value); const latency = ref<boolean>(traceOpt?.latency || false);
const latency = ref<boolean>(traceOpt.latency || false); const enableRelate = ref<boolean>(traceOpt?.enableRelate || false);
const enableRelate = ref<boolean>(traceOpt.enableRelate || false); const type = ref<string>(dashboardStore.selectedGrid?.graph?.type || "");
const type = ref<string>((graph && graph.type) || ""); const refIdType = ref<string>(traceOpt?.refIdType || "");
const refIdType = ref<string>(traceOpt.refIdType || "");
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const relatedTrace = { const relatedTrace = {
...dashboardStore.selectedGrid.relatedTrace, ...dashboardStore.selectedGrid?.relatedTrace,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, relatedTrace }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, relatedTrace } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -50,11 +50,11 @@ limitations under the License. -->
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import getDashboard from "@/hooks/useDashboardsSession"; import getDashboard from "@/hooks/useDashboardsSession";
import type { LayoutConfig } from "@/types/dashboard"; import type { LayoutConfig, DashboardItem } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const widget = dashboardStore.selectedGrid.widget || {}; const widget = dashboardStore.selectedGrid?.widget || {};
const title = ref<string>(widget.title || ""); const title = ref<string>(widget.title || "");
const tips = ref<string>(widget.tips || ""); const tips = ref<string>(widget.tips || "");
const name = ref<string>(widget.name || ""); const name = ref<string>(widget.name || "");
@@ -66,10 +66,10 @@ limitations under the License. -->
} }
const { selectedGrid } = dashboardStore; const { selectedGrid } = dashboardStore;
const widget = { const widget = {
...dashboardStore.selectedGrid.widget, ...dashboardStore.selectedGrid?.widget,
[key]: decodeURIComponent(param[key]), [key]: decodeURIComponent(param[key]),
}; };
dashboardStore.selectWidget({ ...selectedGrid, widget }); dashboardStore.selectWidget({ ...selectedGrid, widget } as LayoutConfig);
} }
function updateWidgetName(param: { [key: string]: string }) { function updateWidgetName(param: { [key: string]: string }) {
const key = Object.keys(param)[0]; const key = Object.keys(param)[0];
@@ -79,7 +79,7 @@ limitations under the License. -->
ElMessage.error(t("nameTip")); ElMessage.error(t("nameTip"));
return; 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); const item = widgets.find((d: LayoutConfig) => d.widget && d.widget.name === n);
if (item) { if (item) {
ElMessage.error(t("duplicateName")); ElMessage.error(t("duplicateName"));

View File

@@ -33,19 +33,20 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Legend from "./components/Legend.vue"; import Legend from "./components/Legend.vue";
import type { AreaConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph || {}; const graph = (dashboardStore.selectedGrid?.graph as AreaConfig) || {};
const opacity = ref(graph.opacity); const opacity = ref(graph.opacity);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -29,18 +29,19 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import Legend from "./components/Legend.vue"; import Legend from "./components/Legend.vue";
import type { BarConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph; const graph = (dashboardStore.selectedGrid?.graph as BarConfig) || {};
const showBackground = ref(graph.showBackground || false); const showBackground = ref(graph.showBackground || false);
function changeConfig(param: { [key: string]: unknown }) { function changeConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -39,19 +39,20 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import ValueMappings from "./components/ValueMappings.vue"; import ValueMappings from "./components/ValueMappings.vue";
import type { CardConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph || {}; const graph = (dashboardStore.selectedGrid?.graph as CardConfig) || {};
const fontSize = ref(graph.fontSize); const fontSize = ref(graph.fontSize);
const showUnit = ref<boolean>(graph.showUnit); const showUnit = ref<boolean>(graph.showUnit || false);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -31,19 +31,20 @@ limitations under the License. -->
import { ref } from "vue"; import { ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { EndpointListConfig, LayoutConfig } from "@/types/dashboard";
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph; const graph = (dashboardStore.selectedGrid?.graph as EndpointListConfig) || {};
const { t } = useI18n(); const { t } = useI18n();
const fontSize = ref(graph.fontSize); const fontSize = ref(graph.fontSize);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -31,18 +31,19 @@ limitations under the License. -->
import { ref } from "vue"; import { ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { CardConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph || {}; const graph = (dashboardStore.selectedGrid?.graph as CardConfig) || {};
const fontSize = ref(graph.fontSize); const fontSize = ref(graph.fontSize);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -31,18 +31,19 @@ limitations under the License. -->
import { ref } from "vue"; import { ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { InstanceListConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph; const graph = (dashboardStore.selectedGrid?.graph as InstanceListConfig) || {};
const fontSize = ref(graph.fontSize); const fontSize = ref(graph.fontSize);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -51,20 +51,21 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Legend from "./components/Legend.vue"; import Legend from "./components/Legend.vue";
import { isDef } from "@/utils/is"; import { isDef } from "@/utils/is";
import type { LineConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = computed(() => dashboardStore.selectedGrid.graph || {}); const graph = computed(() => (dashboardStore.selectedGrid?.graph as LineConfig) || {});
const smooth = ref(graph.value.smooth); const smooth = ref(graph.value.smooth);
const showSymbol = ref(isDef(graph.value.showSymbol) ? graph.value.showSymbol : true); const showSymbol = ref(isDef(graph.value.showSymbol) ? graph.value.showSymbol : true);
const step = ref(graph.value.step); const step = ref(graph.value.step);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -40,19 +40,20 @@ limitations under the License. -->
import { ref, computed } from "vue"; import { ref, computed } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { ServiceListConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = computed(() => dashboardStore.selectedGrid.graph || {}); const graph = computed(() => (dashboardStore.selectedGrid?.graph as ServiceListConfig) || {});
const fontSize = ref(graph.value.fontSize); const fontSize = ref(graph.value.fontSize);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const { selectedGrid } = dashboardStore; const { selectedGrid } = dashboardStore;
const graph = { const graph = {
...selectedGrid.graph, ...selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...selectedGrid, graph }); dashboardStore.selectWidget({ ...selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -41,19 +41,20 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import ValueMappings from "./components/ValueMappings.vue"; import ValueMappings from "./components/ValueMappings.vue";
import type { TableConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph || {}; const graph = (dashboardStore.selectedGrid?.graph as TableConfig) || {};
const showTableValues = ref(graph.showTableValues); const showTableValues = ref(graph.showTableValues);
const tableHeaderCol2 = ref(graph.tableHeaderCol2); const tableHeaderCol2 = ref(graph.tableHeaderCol2);
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -29,10 +29,11 @@ limitations under the License. -->
import { ref } from "vue"; import { ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { TopListConfig, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph || {}; const graph = (dashboardStore.selectedGrid?.graph as TopListConfig) || {};
const color = ref(graph.color || "purple"); const color = ref(graph.color || "purple");
const Colors = [ const Colors = [
{ label: "Purple", value: "purple" }, { label: "Purple", value: "purple" },
@@ -47,10 +48,10 @@ limitations under the License. -->
function updateConfig(param: { [key: string]: unknown }) { function updateConfig(param: { [key: string]: unknown }) {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
...param, ...param,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -94,11 +94,11 @@ limitations under the License. -->
import { computed, reactive } from "vue"; import { computed, reactive } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { LegendOptions } from "@/types/dashboard"; import type { LegendOptions, LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = computed(() => dashboardStore.selectedGrid.graph || {}); const graph = computed(() => dashboardStore.selectedGrid?.graph || {});
const legend = reactive<LegendOptions>({ const legend = reactive<LegendOptions>({
show: true, show: true,
total: false, total: false,
@@ -113,17 +113,17 @@ limitations under the License. -->
}); });
function updateLegendConfig(param: { [key: string]: unknown }) { function updateLegendConfig(param: { [key: string]: unknown }) {
const g = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
legend: { legend: {
...dashboardStore.selectedGrid.graph.legend, ...dashboardStore.selectedGrid?.graph?.legend,
...param, ...param,
}, },
}; };
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
graph: g, graph,
}); } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -39,14 +39,15 @@ limitations under the License. -->
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from "vue"; import { ref } from "vue";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard";
import type { LayoutConfig } from "@/types/dashboard";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph; const graph = dashboardStore.selectedGrid?.graph || {};
const valueMappings = ref<{ [key: string]: string }>(graph?.valueMappings || {}); 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) { function changeKeys(event: any, index: number) {
const params = event.target.textContent || ""; const params = event.target.textContent || "";
@@ -82,10 +83,10 @@ limitations under the License. -->
function updateConfig() { function updateConfig() {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
valueMappings: valueMappings.value, valueMappings: valueMappings.value,
}; };
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph }); dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph } as LayoutConfig);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -126,7 +126,7 @@ limitations under the License. -->
import Icon from "@/components/Icon.vue"; import Icon from "@/components/Icon.vue";
import { useDashboardQueryProcessor } from "@/hooks/useExpressionsProcessor"; import { useDashboardQueryProcessor } from "@/hooks/useExpressionsProcessor";
import { useI18n } from "vue-i18n"; 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"; import Standard from "./Standard.vue";
/*global defineEmits, Indexable */ /*global defineEmits, Indexable */
@@ -142,11 +142,11 @@ limitations under the License. -->
}, },
}); });
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const metrics = computed(() => dashboardStore.selectedGrid.expressions || []); const metrics = computed(() => dashboardStore.selectedGrid?.expressions || []);
const subMetrics = computed(() => dashboardStore.selectedGrid.subExpressions || []); const subMetrics = computed(() => dashboardStore.selectedGrid?.subExpressions || []);
const subMetricTypes = computed(() => dashboardStore.selectedGrid.subTypesOfMQE || []); const subMetricTypes = computed(() => dashboardStore.selectedGrid?.subTypesOfMQE || []);
const graph = computed(() => dashboardStore.selectedGrid.graph || {}); const graph = computed(() => dashboardStore.selectedGrid?.graph || {});
const typesOfMQE = computed(() => dashboardStore.selectedGrid.typesOfMQE || []); const typesOfMQE = computed(() => dashboardStore.selectedGrid?.typesOfMQE || []);
const states = reactive<{ const states = reactive<{
metrics: string[]; metrics: string[];
subMetrics: string[]; subMetrics: string[];
@@ -166,13 +166,13 @@ limitations under the License. -->
metricTypeList: [], metricTypeList: [],
isList: false, isList: false,
isTopList: false, isTopList: false,
dashboardName: graph.value.dashboardName, dashboardName: graph.value.dashboardName || "",
dashboardList: [{ label: "", value: "" }], dashboardList: [{ label: "", value: "" }],
tips: [], tips: [],
subTips: [], subTips: [],
subMetrics: subMetrics.value.length ? subMetrics.value : [""], subMetrics: subMetrics.value.length ? subMetrics.value : [""],
subMetricTypes: subMetricTypes.value.length ? subMetricTypes.value : [""], subMetricTypes: subMetricTypes.value.length ? subMetricTypes.value : [""],
valueRelatedDashboard: dashboardStore.selectedGrid.valueRelatedDashboard, valueRelatedDashboard: dashboardStore.selectedGrid?.valueRelatedDashboard || "",
}); });
const currentMetricConfig = ref<MetricConfigOpt>({ const currentMetricConfig = ref<MetricConfigOpt>({
unit: "", unit: "",
@@ -182,7 +182,7 @@ limitations under the License. -->
}); });
states.isTopList = graph.value.type === ChartTypes[4].value; 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); const defaultLen = ref<number>(states.isList ? 5 : 20);
setDashboards(); setDashboards();
@@ -201,7 +201,7 @@ limitations under the License. -->
}); });
function setDashboards(type?: string) { 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 list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
const arr = list.reduce((prev: (DashboardItem & { label: string; value: string })[], d: DashboardItem) => { const arr = list.reduce((prev: (DashboardItem & { label: string; value: string })[], d: DashboardItem) => {
if (d.layer === dashboardStore.layerId) { if (d.layer === dashboardStore.layerId) {
@@ -237,7 +237,7 @@ limitations under the License. -->
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
expressions: [""], expressions: [""],
typesOfMQE: [""], typesOfMQE: [""],
}); } as LayoutConfig);
states.metrics = [""]; states.metrics = [""];
states.metricTypes = [""]; states.metricTypes = [""];
defaultLen.value = 5; defaultLen.value = 5;
@@ -246,7 +246,7 @@ limitations under the License. -->
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
graph: chart, graph: chart,
}); } as LayoutConfig);
setDashboards(chart.type); setDashboards(chart.type);
states.dashboardName = ""; states.dashboardName = "";
defaultLen.value = 10; defaultLen.value = 10;
@@ -260,7 +260,7 @@ limitations under the License. -->
} }
async function queryMetricsWithExpressions() { async function queryMetricsWithExpressions() {
const { expressions, metricConfig, i } = dashboardStore.selectedGrid; const { expressions, metricConfig, i } = dashboardStore.selectedGrid as LayoutConfig;
if (!(expressions && expressions[0])) { if (!(expressions && expressions[0])) {
return emit("update", {}); return emit("update", {});
} }
@@ -272,7 +272,7 @@ limitations under the License. -->
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
typesOfMQE: states.metricTypes, typesOfMQE: states.metricTypes,
}); } as LayoutConfig);
emit("update", params.source || {}); emit("update", params.source || {});
if (states.isTopList) { if (states.isTopList) {
const values: any = Object.values(params.source)[0]; const values: any = Object.values(params.source)[0];
@@ -292,7 +292,7 @@ limitations under the License. -->
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
valueRelatedDashboard: states.valueRelatedDashboard, valueRelatedDashboard: states.valueRelatedDashboard,
}); } as LayoutConfig);
} }
function changeDashboard(opt: { value: string }[]) { function changeDashboard(opt: { value: string }[]) {
@@ -302,13 +302,13 @@ limitations under the License. -->
states.dashboardName = opt[0].value; states.dashboardName = opt[0].value;
} }
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid?.graph,
dashboardName: states.dashboardName, dashboardName: states.dashboardName,
}; };
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
graph, graph,
}); } as LayoutConfig);
} }
function addMetric() { function addMetric() {
states.metrics.push(""); states.metrics.push("");
@@ -350,7 +350,7 @@ limitations under the License. -->
states.metrics.splice(index, 1); states.metrics.splice(index, 1);
states.metricTypes.splice(index, 1); states.metricTypes.splice(index, 1);
states.tips.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; const metricConfig = config[index] ? config.splice(index, 1) : config;
let p = {}; let p = {};
if (states.isList) { if (states.isList) {
@@ -369,7 +369,7 @@ limitations under the License. -->
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
...p, ...p,
metricConfig, metricConfig,
}); } as LayoutConfig);
queryMetrics(); queryMetrics();
} }
@@ -381,7 +381,7 @@ limitations under the License. -->
labelsIndex: "", labelsIndex: "",
sortOrder: "DES", sortOrder: "DES",
}; };
if (!dashboardStore.selectedGrid.metricConfig || !dashboardStore.selectedGrid.metricConfig[index]) { if (!dashboardStore.selectedGrid?.metricConfig || !dashboardStore.selectedGrid?.metricConfig[index]) {
currentMetricConfig.value = n; currentMetricConfig.value = n;
return; return;
} }
@@ -397,7 +397,7 @@ limitations under the License. -->
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
expressions: states.metrics, expressions: states.metrics,
}); } as LayoutConfig);
if (params) { if (params) {
await queryMetrics(); await queryMetrics();
} }
@@ -410,7 +410,7 @@ limitations under the License. -->
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
subExpressions: states.subMetrics, subExpressions: states.subMetrics,
subTypesOfMQE: states.subMetricTypes, subTypesOfMQE: states.subMetricTypes,
}); } as LayoutConfig);
if (params) { if (params) {
await queryMetrics(); await queryMetrics();
} }

View File

@@ -86,7 +86,7 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { SortOrder, ExpressionResultType, ListChartTypes } from "@/views/dashboard/data"; import { SortOrder, ExpressionResultType, ListChartTypes } from "@/views/dashboard/data";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { MetricConfigOpt } from "@/types/dashboard"; import type { MetricConfigOpt, LayoutConfig } from "@/types/dashboard";
/*global defineEmits, defineProps */ /*global defineEmits, defineProps */
const props = defineProps({ const props = defineProps({
@@ -103,13 +103,15 @@ limitations under the License. -->
...props.currentMetricConfig, ...props.currentMetricConfig,
topN: props.currentMetricConfig.topN || 10, topN: props.currentMetricConfig.topN || 10,
}); });
const metricTypes = computed(() => dashboardStore.selectedGrid.typesOfMQE || []); const metricTypes = computed(() => dashboardStore.selectedGrid?.typesOfMQE || []);
const isList = computed(() => { const isList = computed(() => {
const graph = dashboardStore.selectedGrid.graph || {}; const graph = dashboardStore.selectedGrid?.graph || {};
return ListChartTypes.includes(graph.type); return ListChartTypes.includes(graph.type || "");
}); });
const isTopn = computed(() => 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 }) { function updateConfig(index: number, param: { [key: string]: string }) {
@@ -120,13 +122,13 @@ limitations under the License. -->
changeConfigs(index, { [key]: decodeURIComponent(param[key]) }); changeConfigs(index, { [key]: decodeURIComponent(param[key]) });
} }
function changeConfigs(index: number, param: { [key: string]: string | number }) { function changeConfigs(index: number, param: { [key: string]: string | number }) {
const metricConfig = dashboardStore.selectedGrid.metricConfig || []; const metricConfig = dashboardStore.selectedGrid?.metricConfig || [];
metricConfig[index] = { ...metricConfig[index], ...param }; metricConfig[index] = { ...metricConfig[index], ...param };
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
metricConfig, metricConfig,
}); } as LayoutConfig);
emit("update"); emit("update");
} }
watch( watch(

View File

@@ -34,11 +34,12 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Content from "../related/async-profiling/Content.vue"; import Content from "../related/async-profiling/Content.vue";
import Header from "../related/async-profiling/Header.vue"; import Header from "../related/async-profiling/Header.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps*/ /*global defineProps*/
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -36,11 +36,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Content from "../related/continuous-profiling/Content.vue"; import Content from "../related/continuous-profiling/Content.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -31,15 +31,17 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { PropType } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Header from "../related/demand-log/Header.vue"; import Header from "../related/demand-log/Header.vue";
import Content from "../related/demand-log/Content.vue"; import Content from "../related/demand-log/Content.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object, type: Object as PropType<LayoutConfig>,
default: () => ({}), default: () => ({}),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -34,11 +34,12 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Header from "../related/ebpf/Header.vue"; import Header from "../related/ebpf/Header.vue";
import Content from "../related/ebpf/Content.vue"; import Content from "../related/ebpf/Content.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -36,15 +36,17 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { PropType } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Header from "../related/event/Header.vue"; import Header from "../related/event/Header.vue";
import Content from "../related/event/Content.vue"; import Content from "../related/event/Content.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object, type: Object as PropType<LayoutConfig>,
default: () => ({}), default: () => ({}),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -33,11 +33,11 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Content from "../related/network-profiling/Content.vue"; import Content from "../related/network-profiling/Content.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -34,11 +34,12 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Header from "../related/profile/Header.vue"; import Header from "../related/profile/Header.vue";
import Content from "../related/profile/Content.vue"; import Content from "../related/profile/Content.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, 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); const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i);
dashboardStore.setActiveTabIndex(activeTabIndex.value); dashboardStore.setActiveTabIndex(activeTabIndex.value);
if (dashboardStore.layout[l].children.length) { if (dashboardStore.layout[l]?.children?.length) {
const tab = dashboardStore.layout[l].children[activeTabIndex.value]; const tab = dashboardStore.layout[l].children[activeTabIndex.value];
dashboardStore.setCurrentTabItems( dashboardStore.setCurrentTabItems(
tab.enable === false ? [] : dashboardStore.layout[l].children[activeTabIndex.value].children, 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(); queryExpressions();
@@ -177,7 +177,7 @@ limitations under the License. -->
dashboardStore.selectWidget(props.data); dashboardStore.selectWidget(props.data);
dashboardStore.setActiveTabIndex(idx); dashboardStore.setActiveTabIndex(idx);
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i); 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; needQuery.value = true;
if (route.params.activeTabIndex) { if (route.params.activeTabIndex) {
let p = location.href.split("/tab/")[0]; let p = location.href.split("/tab/")[0];
@@ -192,10 +192,10 @@ limitations under the License. -->
function deleteTabItem(e: Event, idx: number) { function deleteTabItem(e: Event, idx: number) {
e.stopPropagation(); e.stopPropagation();
dashboardStore.removeTabItem(props.data, idx); dashboardStore.removeTabItem(props.data, idx);
const kids = dashboardStore.layout[l].children[0]; const kids = dashboardStore.layout[l]?.children?.[0];
const arr = (kids && kids.children) || []; const arr = (kids && kids.children) || [];
dashboardStore.setCurrentTabItems(arr); dashboardStore.setCurrentTabItems(arr);
dashboardStore.activeGridItem(0); dashboardStore.activeGridItem("0");
activeTabIndex.value = 0; activeTabIndex.value = 0;
needQuery.value = true; needQuery.value = true;
} }
@@ -226,7 +226,7 @@ limitations under the License. -->
} }
function layoutUpdatedEvent() { function layoutUpdatedEvent() {
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i); 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) { function getStringWidth(s: string) {
const dom = document.createElement("span"); 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 index = (props.data.children || []).findIndex((tab: any) => tab.enable !== false) || 0;
const items = ((props.data.children || [])[index] || {}).children; const items = ((props.data.children || [])[index] || {}).children;
dashboardStore.setCurrentTabItems(items || []); dashboardStore.setCurrentTabItems(items || []);
dashboardStore.activeGridItem(0); dashboardStore.activeGridItem("0");
activeTabIndex.value = index; activeTabIndex.value = index;
dashboardStore.setActiveTabIndex(activeTabIndex.value); dashboardStore.setActiveTabIndex(activeTabIndex.value);
needQuery.value = true; needQuery.value = true;
@@ -324,7 +324,7 @@ limitations under the License. -->
dashboardStore.activeGridItem(props.data.i); dashboardStore.activeGridItem(props.data.i);
dashboardStore.selectWidget(props.data); dashboardStore.selectWidget(props.data);
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i); 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; needQuery.value = true;
if (route.params.activeTabIndex) { if (route.params.activeTabIndex) {
let p = location.href.split("/tab/")[0]; let p = location.href.split("/tab/")[0];

View File

@@ -33,11 +33,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Content from "../related/task-timeline/Content.vue"; import Content from "../related/task-timeline/Content.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -58,18 +58,19 @@ limitations under the License. -->
import { TextColors } from "@/views/dashboard/data"; import { TextColors } from "@/views/dashboard/data";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data"; import { Themes } from "@/constants/data";
import type { LayoutConfig, TextConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },
}); });
const { t } = useI18n(); const { t } = useI18n();
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const graph = computed(() => props.data.graph || {}); const graph = computed(() => (props.data.graph as TextConfig) || {});
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const backgroundColor = computed( const backgroundColor = computed(

View File

@@ -50,11 +50,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { validateAndSanitizeUrl } from "@/utils/validateAndSanitizeUrl"; import { validateAndSanitizeUrl } from "@/utils/validateAndSanitizeUrl";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -63,17 +63,18 @@ limitations under the License. -->
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { TextColors } from "@/views/dashboard/data"; import { TextColors } from "@/views/dashboard/data";
import type { LayoutConfig, TimeRangeConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },
}); });
const { t } = useI18n(); const { t } = useI18n();
const graph = computed(() => props.data.graph || {}); const graph = computed(() => (props.data.graph as TimeRangeConfig) || {});
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const content = computed(() => { const content = computed(() => {

View File

@@ -37,11 +37,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import Topology from "../related/topology/Index.vue"; import Topology from "../related/topology/Index.vue";
import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -53,11 +53,12 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { mutationObserver } from "@/utils/mutation"; import { mutationObserver } from "@/utils/mutation";
import type { LayoutConfig } from "@/types/dashboard";
/* global defineProps */ /* global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object as PropType<any>, type: Object as PropType<LayoutConfig>,
default: () => ({ graph: {} }), default: () => ({ graph: {} }),
}, },
activeIndex: { type: String, default: "" }, activeIndex: { type: String, default: "" },

View File

@@ -80,7 +80,7 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardQueryProcessor } from "@/hooks/useExpressionsProcessor"; import { useDashboardQueryProcessor } from "@/hooks/useExpressionsProcessor";
import { ListChartTypes } from "../data"; import { ListChartTypes } from "../data";
import type { EventParams } from "@/types/dashboard"; import type { EventParams, DashboardItem } from "@/types/dashboard";
import getDashboard from "@/hooks/useDashboardsSession"; import getDashboard from "@/hooks/useDashboardsSession";
const props = { const props = {
@@ -141,7 +141,7 @@ limitations under the License. -->
} }
} }
function clickHandle(params: EventParams | any) { 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) || []; const associate = (props.data.associate && props.data.associate) || [];
for (const item of associate) { for (const item of associate) {
@@ -170,7 +170,7 @@ limitations under the License. -->
return; return;
} }
const chart = dashboardStore.selectedGrid.graph || {}; const chart = dashboardStore.selectedGrid.graph || {};
if (ListChartTypes.includes(chart.type)) { if (ListChartTypes.includes(chart.type || "")) {
return; return;
} }
queryMetrics(); queryMetrics();

View File

@@ -192,7 +192,7 @@ limitations under the License. -->
return; return;
} }
router.push( 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() { async function searchList() {

View File

@@ -208,7 +208,7 @@ limitations under the License. -->
return; return;
} }
router.push( router.push(
`/dashboard/${dashboard.layer}/${dashboard.entity}/${selectorStore.currentService.id}/${ `/dashboard/${dashboard.layer}/${dashboard.entity}/${selectorStore.currentService?.id}/${
scope.row.id scope.row.id
}/${dashboard.name.split(" ").join("-")}`, }/${dashboard.name.split(" ").join("-")}`,
); );

View File

@@ -85,6 +85,10 @@ limitations under the License. -->
import type { MetricConfigOpt } from "@/types/dashboard"; import type { MetricConfigOpt } from "@/types/dashboard";
import ColumnGraph from "./components/ColumnGraph.vue"; import ColumnGraph from "./components/ColumnGraph.vue";
interface ServiceWithGroup extends Service {
merge: boolean;
group: string;
}
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
data: { data: {
@@ -115,12 +119,12 @@ limitations under the License. -->
const chartLoading = ref<boolean>(false); const chartLoading = ref<boolean>(false);
const currentPage = ref<number>(1); const currentPage = ref<number>(1);
const pageSize = 10; const pageSize = 10;
const services = ref<Service[]>([]); const services = ref<ServiceWithGroup[]>([]);
const colMetrics = ref<string[]>([]); const colMetrics = ref<string[]>([]);
const colSubMetrics = ref<string[]>([]); const colSubMetrics = ref<string[]>([]);
const searchText = ref<string>(""); const searchText = ref<string>("");
const groups = ref<any>({}); const groups = ref<any>({});
const sortServices = ref<(Service & { merge: boolean })[]>([]); const sortServices = ref<ServiceWithGroup[]>([]);
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []); const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
const typesOfMQE = ref<string[]>(props.config.typesOfMQE || []); const typesOfMQE = ref<string[]>(props.config.typesOfMQE || []);
@@ -144,12 +148,12 @@ limitations under the License. -->
return 1; return 1;
} }
return 0; return 0;
}); }) as ServiceWithGroup[];
const s = sortServices.value.filter((d: Service, index: number) => index < pageSize); const s = sortServices.value.filter((d: ServiceWithGroup, index: number) => index < pageSize);
setServices(s); setServices(s);
} }
function setServices(arr: (Service & { merge: boolean })[]) { function setServices(arr: ServiceWithGroup[]) {
groups.value = {}; groups.value = {};
const map: { [key: string]: any[] } = arr.reduce((result: { [key: string]: any[] }, item: any) => { const map: { [key: string]: any[] } = arr.reduce((result: { [key: string]: any[] }, item: any) => {
item.group = item.group || ""; item.group = item.group || "";
@@ -191,11 +195,11 @@ limitations under the License. -->
router.push(path); router.push(path);
} }
async function queryServiceMetrics(arr: Service[]) { async function queryServiceMetrics(arr: ServiceWithGroup[]) {
if (!arr.length) { if (!arr.length) {
return; return;
} }
const currentServices = arr.map((d: Service) => { const currentServices = arr.map((d: ServiceWithGroup) => {
return { return {
id: d.id, id: d.id,
value: d.value, value: d.value,
@@ -203,13 +207,13 @@ limitations under the License. -->
layers: d.layers, layers: d.layers,
group: d.group, group: d.group,
normal: d.normal, normal: d.normal,
merge: d.merge, merge: d.merge || false,
shortName: d.shortName, shortName: d.shortName,
}; };
}); });
queryServiceExpressions(currentServices); queryServiceExpressions(currentServices);
} }
async function queryServiceExpressions(currentServices: Service[]) { async function queryServiceExpressions(currentServices: ServiceWithGroup[]) {
const expressions = props.config.expressions || []; const expressions = props.config.expressions || [];
const subExpressions = props.config.subExpressions || []; const subExpressions = props.config.subExpressions || [];
@@ -254,7 +258,7 @@ limitations under the License. -->
if (searchText.value) { if (searchText.value) {
services = sortServices.value.filter((d: { label: string }) => d.label.includes(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) { if (index >= (currentPage.value - 1) * pageSize && index < pageSize * currentPage.value) {
return d; return d;
} }

View File

@@ -70,13 +70,12 @@ limitations under the License. -->
import { TextColors, MetricCatalog } from "@/views/dashboard/data"; import { TextColors, MetricCatalog } from "@/views/dashboard/data";
import Trace from "@/views/dashboard/related/trace/Index.vue"; import Trace from "@/views/dashboard/related/trace/Index.vue";
import { WidgetType, QueryOrders, Status, RefIdTypes, ExpressionResultType } from "@/views/dashboard/data"; 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({ const props = defineProps({
data: { data: {
type: Object as PropType<{ type: Object as PropType<TopListData>,
[key: string]: { name: string; value: number; refId: string; owner: object }[];
}>,
default: () => ({}), default: () => ({}),
}, },
config: { config: {
@@ -84,7 +83,7 @@ limitations under the License. -->
color: string; color: string;
expressions: string[]; expressions: string[];
typesOfMQE: string[]; typesOfMQE: string[];
relatedTrace: any; relatedTrace: RelatedTrace;
valueRelatedDashboard: string; valueRelatedDashboard: string;
}>, }>,
default: () => ({ color: "purple" }), default: () => ({ color: "purple" }),
@@ -94,28 +93,29 @@ limitations under the License. -->
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const showTrace = ref<boolean>(false); 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, type: WidgetType.Trace,
}); });
const refIdType = computed( const refIdType = computed(
() => (props.config.relatedTrace && props.config.relatedTrace.refIdType) || RefIdTypes[0].value, () => (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( const available = computed(
() => Array.isArray(props.data[key.value]) && props.data[key.value][0] && props.data[key.value][0].value, () => Array.isArray(props.data[key.value]) && props.data[key.value][0] && props.data[key.value][0].value,
); );
const maxValue = computed(() => { const maxValue = computed(() => {
if (!(props.data[key.value] && props.data[key.value].length)) { if (!props.data[key.value].length) {
return 0; 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); return Math.max.apply(null, temp);
}); });
function handleClick(i: string) { function handleClick(i: string) {
copy(i); copy(i);
} }
function viewTrace(item: { name: string; refId: string; value: unknown; owner: object }) { function viewTrace(item: TopListItem) {
const filters = { const filters: Filters = {
...item, ...item,
queryOrder: QueryOrders[1].value, queryOrder: QueryOrders[1].value,
status: Status[2].value, status: Status[2].value,
@@ -130,7 +130,7 @@ limitations under the License. -->
}; };
showTrace.value = true; showTrace.value = true;
} }
function viewDashboard(item: Recordable) { function viewDashboard(item: TopListItem) {
const { owner } = item; const { owner } = item;
let path; let path;
if (owner.scope === MetricCatalog.SERVICE) { if (owner.scope === MetricCatalog.SERVICE) {

View File

@@ -85,12 +85,13 @@ limitations under the License. -->
} }
} }
if (item.type === WidgetType.Tab) { if (item.type === WidgetType.Tab) {
const index = isNaN(item.activedTabIndex) ? 0 : item.activedTabIndex; const index = isNaN(item.activedTabIndex as number) ? 0 : (item.activedTabIndex as number);
widgets.push( if (item.children && item.children[index]) {
...item.children[index].children.filter( const list = item.children[index]?.children.filter(
(d: LayoutConfig) => d.type === WidgetType.Widget && !ListChartTypes.includes(d.graph?.type || ""), (d: LayoutConfig) => d.type === WidgetType.Widget && !ListChartTypes.includes(d.graph?.type || ""),
), );
); widgets.push(...list);
}
} }
} }
const configList = widgets.map((d: LayoutConfig) => ({ const configList = widgets.map((d: LayoutConfig) => ({

View File

@@ -168,6 +168,7 @@ limitations under the License. -->
import type { Option } from "@/types/app"; import type { Option } from "@/types/app";
import InstanceMap from "@/views/dashboard/related/topology/pod/InstanceMap.vue"; import InstanceMap from "@/views/dashboard/related/topology/pod/InstanceMap.vue";
import HierarchyMap from "@/views/dashboard/related/topology/service/HierarchyMap.vue"; import HierarchyMap from "@/views/dashboard/related/topology/service/HierarchyMap.vue";
import { Process, Instance, Endpoint } from "@/types/selector";
const { t } = useI18n(); const { t } = useI18n();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
@@ -175,7 +176,7 @@ limitations under the License. -->
const topologyStore = useTopologyStore(); const topologyStore = useTopologyStore();
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const route = useRoute(); const route = useRoute();
const params = route?.params || {}; const params: any = route?.params || {};
const toolIcons = ref<{ name: string; content: string; id: WidgetType }[]>(AllTools); const toolIcons = ref<{ name: string; content: string; id: WidgetType }[]>(AllTools);
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const showHierarchy = ref<boolean>(false); const showHierarchy = ref<boolean>(false);
@@ -252,7 +253,8 @@ limitations under the License. -->
ElMessage.error(json.errors); ElMessage.error(json.errors);
return; return;
} }
let currentService, currentDestService; let currentService = null,
currentDestService = null;
if (states.currentService) { if (states.currentService) {
for (const d of selectorStore.services) { for (const d of selectorStore.services) {
if (d.value === states.currentService) { if (d.value === states.currentService) {
@@ -274,22 +276,22 @@ limitations under the License. -->
} }
selectorStore.setCurrentService(currentService); selectorStore.setCurrentService(currentService);
selectorStore.setCurrentDestService(currentDestService); selectorStore.setCurrentDestService(currentDestService);
states.currentService = selectorStore.currentService && selectorStore.currentService.value; states.currentService = selectorStore.currentService?.value || "";
states.currentDestService = selectorStore.currentDestService && selectorStore.currentDestService.value; states.currentDestService = selectorStore.currentDestService?.value || "";
} }
async function setSourceSelector() { async function setSourceSelector() {
await selectorStore.getService(String(params.serviceId)); await selectorStore.getService(String(params.serviceId));
states.currentService = selectorStore.currentService.value; states.currentService = selectorStore.currentService?.value || "";
const e = String(params.entity).split("Relation")[0]; 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() { async function setDestSelector() {
await selectorStore.getService(String(params.destServiceId), true); await selectorStore.getService(String(params.destServiceId), true);
states.currentDestService = selectorStore.currentDestService.value; states.currentDestService = selectorStore.currentDestService?.value || "";
await fetchPods(String(params.entity), selectorStore.currentDestService.id, true); await fetchPods(String(params.entity), selectorStore.currentDestService?.id || "", true);
} }
async function getServices() { async function getServices() {
@@ -341,14 +343,14 @@ limitations under the License. -->
EntityType[8].value, EntityType[8].value,
].includes(dashboardStore.entity) ].includes(dashboardStore.entity)
) { ) {
await fetchPods(e, selectorStore.currentService.id, true); await fetchPods(e, selectorStore.currentService?.id || "", true);
} }
if (!selectorStore.currentDestService) { if (!selectorStore.currentDestService) {
return; return;
} }
states.currentDestService = selectorStore.currentDestService.value; states.currentDestService = selectorStore.currentDestService.value;
if ([EntityType[5].value, EntityType[6].value, EntityType[7].value].includes(dashboardStore.entity)) { 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.currentPod = "";
states.currentProcess = ""; states.currentProcess = "";
const e = dashboardStore.entity.split("Relation")[0]; const e = dashboardStore.entity.split("Relation")[0];
fetchPods(e, selectorStore.currentService.id, true); fetchPods(e, selectorStore.currentService?.id, true);
} else { } else {
selectorStore.setCurrentService(null); selectorStore.setCurrentService(null);
} }
@@ -373,7 +375,7 @@ limitations under the License. -->
selectorStore.setCurrentDestPod(null); selectorStore.setCurrentDestPod(null);
states.currentDestPod = ""; states.currentDestPod = "";
states.currentDestProcess = ""; states.currentDestProcess = "";
fetchPods(dashboardStore.entity, selectorStore.currentDestService.id, true); fetchPods(dashboardStore.entity, selectorStore.currentDestService?.id || "", true);
} else { } else {
selectorStore.setCurrentDestService(null); selectorStore.setCurrentDestService(null);
} }
@@ -395,12 +397,12 @@ limitations under the License. -->
} }
} }
function changeDestProcess(pod: Option[]) { function changeDestProcess(pod: Process[]) {
selectorStore.setCurrentDestProcess(pod[0] || null); selectorStore.setCurrentDestProcess(pod[0]);
states.currentDestProcess = pod[0].label || ""; states.currentDestProcess = pod[0].label || "";
} }
function changeProcess(pod: Option[]) { function changeProcess(pod: Process[]) {
selectorStore.setCurrentProcess(pod[0] || null); selectorStore.setCurrentProcess(pod[0] || null);
states.currentProcess = pod[0].label || ""; states.currentProcess = pod[0].label || "";
} }
@@ -447,7 +449,10 @@ limitations under the License. -->
dashboardStore.addControl(id); 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; let resp;
switch (type) { switch (type) {
case EntityType[2].value: case EntityType[2].value:
@@ -517,11 +522,11 @@ limitations under the License. -->
async function fetchProcess(setPod: boolean) { async function fetchProcess(setPod: boolean) {
const resp = await selectorStore.getProcesses({ const resp = await selectorStore.getProcesses({
instanceId: selectorStore.currentPod.id, instanceId: selectorStore.currentPod?.id || "",
}); });
if (setPod) { if (setPod) {
const process = selectorStore.currentProcess?.id || params.processId || selectorStore.processes[0].id; 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) { if (currentProcess) {
selectorStore.setCurrentProcess(currentProcess); selectorStore.setCurrentProcess(currentProcess);
states.currentProcess = currentProcess.label; states.currentProcess = currentProcess.label;
@@ -534,7 +539,7 @@ limitations under the License. -->
} }
async function fetchDestProcess(setPod: boolean) { async function fetchDestProcess(setPod: boolean) {
const resp = await selectorStore.getProcesses({ const resp = await selectorStore.getProcesses({
instanceId: selectorStore.currentDestPod.id, instanceId: selectorStore.currentDestPod?.id,
isRelation: true, isRelation: true,
}); });
if (setPod) { if (setPod) {
@@ -572,7 +577,7 @@ limitations under the License. -->
return; return;
} }
const destPod = selectorStore.currentDestPod?.id || params.destPodId || selectorStore.destPods[0].id; 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) { if (!currentDestPod) {
states.currentDestPod = ""; states.currentDestPod = "";
selectorStore.setCurrentDestPod(null); selectorStore.setCurrentDestPod(null);
@@ -604,7 +609,7 @@ limitations under the License. -->
return; return;
} }
const pod = selectorStore.currentPod?.id || params.podId || selectorStore.pods[0].id; 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) { if (!currentPod) {
selectorStore.setCurrentPod(null); selectorStore.setCurrentPod(null);
states.currentPod = ""; states.currentPod = "";
@@ -651,13 +656,13 @@ limitations under the License. -->
const param = { const param = {
keyword: query, keyword: query,
}; };
fetchPods(EntityType[2].value, selectorStore.currentService.id, false, param); fetchPods(EntityType[2].value, selectorStore.currentService?.id, false, param);
} }
function searchDestPods(query: string) { function searchDestPods(query: string) {
const param = { const param = {
keyword: query, keyword: query,
}; };
fetchPods(EntityType[6].value, selectorStore.currentDestService.id, false, param); fetchPods(EntityType[6].value, selectorStore.currentDestService?.id, false, param);
} }
function viewTopology() { function viewTopology() {
showHierarchy.value = true; showHierarchy.value = true;

View File

@@ -35,12 +35,12 @@ limitations under the License. -->
import EBPFStack from "@/views/dashboard/related/ebpf/components/EBPFStack.vue"; import EBPFStack from "@/views/dashboard/related/ebpf/components/EBPFStack.vue";
import { ComponentType } from "./components/data"; import { ComponentType } from "./components/data";
const asyncProfilingStore = useAsyncProfilingStore(); const asyncProfilingStore: ReturnType<typeof useAsyncProfilingStore> = useAsyncProfilingStore();
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
onMounted(async () => { onMounted(async () => {
const resp = await asyncProfilingStore.getServiceInstances({ serviceId: selectorStore.currentService.id }); const resp = await asyncProfilingStore.getServiceInstances({ serviceId: selectorStore.currentService?.id || "" });
if (resp && resp.errors) { if (resp?.errors) {
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
} }
}); });

View File

@@ -50,7 +50,7 @@ limitations under the License. -->
const serviceInstanceIds = ref<string[]>([]); const serviceInstanceIds = ref<string[]>([]);
const selectedEventType = ref<string>(""); const selectedEventType = ref<string>("");
const eventTypes = computed(() => const eventTypes = computed(() =>
(asyncProfilingStore.selectedTask.events ?? []) (asyncProfilingStore.selectedTask?.events || [])
.map((d: string) => { .map((d: string) => {
if (d === ProfilingEvents[1]) { if (d === ProfilingEvents[1]) {
return [ return [
@@ -65,7 +65,7 @@ limitations under the License. -->
); );
const instances = computed(() => const instances = computed(() =>
asyncProfilingStore.instances.filter((d: Instance) => 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() { async function analyzeProfiling() {
const instanceIds = asyncProfilingStore.instances const instanceIds = (asyncProfilingStore.instances || [])
.filter((d: Instance) => (serviceInstanceIds.value ?? []).includes(d.value)) .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({ const res = await asyncProfilingStore.getAsyncProfilingAnalyze({
instanceIds, instanceIds,
taskId: asyncProfilingStore.selectedTask.id, taskId: asyncProfilingStore.selectedTask?.id || "",
eventType: (EventsMap as any)[selectedEventType.value], eventType: (EventsMap as any)[selectedEventType.value],
}); });
if (res.data && res.data.errors) { if (res.data && res.data.errors) {
@@ -95,7 +95,7 @@ limitations under the License. -->
} }
watch( watch(
() => asyncProfilingStore.selectedTask.successInstanceIds, () => asyncProfilingStore.selectedTask?.successInstanceIds,
() => { () => {
serviceInstanceIds.value = []; serviceInstanceIds.value = [];
selectedEventType.value = ""; selectedEventType.value = "";

View File

@@ -114,6 +114,7 @@ limitations under the License. -->
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { DurationOptions, ProfilingEvents } from "./data"; import { DurationOptions, ProfilingEvents } from "./data";
import type { AsyncProfileTaskCreationRequest } from "@/types/async-profiling";
/* global defineEmits */ /* global defineEmits */
const emits = defineEmits(["close"]); const emits = defineEmits(["close"]);
@@ -165,12 +166,12 @@ limitations under the License. -->
} }
const params = { const params = {
serviceId: selectorStore.currentService.id, serviceId: selectorStore.currentService?.id,
serviceInstanceIds: serviceInstanceIds.value, serviceInstanceIds: serviceInstanceIds.value,
duration: finalDuration, duration: finalDuration,
events: asyncEvents.value, events: asyncEvents.value,
execArgs: execArgs.value, execArgs: execArgs.value,
}; } as AsyncProfileTaskCreationRequest;
loading.value = true; loading.value = true;
const res = await asyncProfilingStore.createTask(params); const res = await asyncProfilingStore.createTask(params);
loading.value = false; loading.value = false;

View File

@@ -26,7 +26,7 @@ limitations under the License. -->
@click="changeTask(i)" @click="changeTask(i)"
:key="index" :key="index"
:class="{ :class="{
selected: asyncProfilingStore.selectedTask.id === i.id, selected: asyncProfilingStore.selectedTask?.id === i.id,
}" }"
> >
<td class="profile-td"> <td class="profile-td">
@@ -50,7 +50,7 @@ limitations under the License. -->
</div> </div>
</div> </div>
<el-dialog v-model="showDetail" :destroy-on-close="true" fullscreen @closed="showDetail = false"> <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> <div>
<h5 class="mb-10">{{ t("task") }}.</h5> <h5 class="mb-10">{{ t("task") }}.</h5>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
@@ -67,20 +67,15 @@ limitations under the License. -->
</div> </div>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("duration") }}:</span> <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>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("events") }}:</span> <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> </div>
<div> <div>
<h5 <h5 class="mb-5 mt-10" v-show="asyncProfilingStore.selectedTask?.logs?.length"> {{ t("logs") }}. </h5>
class="mb-5 mt-10"
v-show="asyncProfilingStore.selectedTask.logs && asyncProfilingStore.selectedTask.logs.length"
>
{{ t("logs") }}.
</h5>
<div v-for="(i, index) in Object.keys(instanceLogs)" :key="index"> <div v-for="(i, index) in Object.keys(instanceLogs)" :key="index">
<div class="sm"> <div class="sm">
<span class="mr-10 grey">{{ t("instance") }}:</span> <span class="mr-10 grey">{{ t("instance") }}:</span>
@@ -128,7 +123,8 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { useAsyncProfilingStore } from "@/store/modules/async-profiling"; 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 { ElMessage } from "element-plus";
import { dateFormat } from "@/utils/dateFormat"; import { dateFormat } from "@/utils/dateFormat";
import type { Instance, Service } from "@/types/selector"; import type { Instance, Service } from "@/types/selector";
@@ -156,13 +152,13 @@ limitations under the License. -->
} }
} }
async function changeTask(item: TaskListItem) { async function changeTask(item: AsyncProfilingTask) {
if (item.id !== asyncProfilingStore.selectedTask.id) { if (item.id !== asyncProfilingStore.selectedTask?.id) {
asyncProfilingStore.setAnalyzeTrees([]); asyncProfilingStore.setAnalyzeTrees([]);
asyncProfilingStore.setSelectedTask(item); asyncProfilingStore.setSelectedTask(item);
} }
service.value = (selectorStore.services.filter((s: Service) => s.id === item.serviceId)[0] ?? {}).label; 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) { if (res.errors) {
ElMessage.error(res.errors); ElMessage.error(res.errors);

View File

@@ -19,38 +19,38 @@ limitations under the License. -->
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("taskId") }}:</span> <span class="g-sm-4 grey">{{ t("taskId") }}:</span>
<span class="g-sm-8 wba"> <span class="g-sm-8 wba">
{{ details.taskId }} {{ details?.taskId || "" }}
</span> </span>
</div> </div>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("service") }}:</span> <span class="g-sm-4 grey">{{ t("service") }}:</span>
<span class="g-sm-8 wba"> <span class="g-sm-8 wba">
{{ details.serviceName }} {{ details?.serviceName || "" }}
</span> </span>
</div> </div>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("labels") }}:</span> <span class="g-sm-4 grey">{{ t("labels") }}:</span>
<span class="g-sm-8 wba"> <span class="g-sm-8 wba">
{{ details.processLabels.join(";") }} {{ details?.processLabels?.join(";") }}
</span> </span>
</div> </div>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("monitorTime") }}:</span> <span class="g-sm-4 grey">{{ t("monitorTime") }}:</span>
<span class="g-sm-8 wba"> <span class="g-sm-8 wba">
{{ dateFormat(details.taskStartTime) }} {{ dateFormat(details?.taskStartTime || NaN) }}
</span> </span>
</div> </div>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("monitorDuration") }}:</span> <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>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("triggerType") }}:</span> <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>
<div class="mb-10 clear item"> <div class="mb-10 clear item">
<span class="g-sm-4 grey">{{ t("targetType") }}:</span> <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> </div>
</div> </div>
@@ -61,10 +61,10 @@ limitations under the License. -->
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import type { EBPFTaskList } from "@/types/ebpf"; import type { EBPFTaskList } from "@/types/ebpf";
/*global defineProps */ /*global defineProps, Nullable */
defineProps({ defineProps({
details: { details: {
type: Object as PropType<EBPFTaskList>, type: Object as PropType<Nullable<EBPFTaskList>>,
default: () => ({}), default: () => ({}),
}, },
}); });

View File

@@ -84,6 +84,7 @@ limitations under the License. -->
import router from "@/router"; import router from "@/router";
import { HeaderLabels, HeaderChildLabels } from "../data"; import { HeaderLabels, HeaderChildLabels } from "../data";
import { EntityType } from "../../../data"; import { EntityType } from "../../../data";
import type { Instance } from "@/types/selector";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
@@ -97,14 +98,14 @@ limitations under the License. -->
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
const continousProfilingStore = useContinousProfilingStore(); const continousProfilingStore = useContinousProfilingStore();
const pageSize = 10; const pageSize = 10;
const currentInstances = ref<MonitorInstance[]>([]); const currentInstances = ref<Instance[]>([]);
function viewProcessDashboard(process: MonitorProcess, instance: MonitorInstance) { function viewProcessDashboard(process: MonitorProcess, instance: MonitorInstance) {
if (!props.config.processDashboardName) { if (!props.config.processDashboardName) {
return; return;
} }
router.push( 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; return;
} }
router.push( 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) { 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) { if (index >= (pageIndex - 1) * pageSize && index < pageIndex * pageSize) {
return d; return d;
} }
@@ -129,7 +130,7 @@ limitations under the License. -->
() => continousProfilingStore.instances, () => continousProfilingStore.instances,
() => { () => {
currentInstances.value = continousProfilingStore.instances.filter( 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 <td
class="profile-td" class="profile-td"
:class="{ :class="{
selected: continousProfilingStore.selectedStrategy.id === i.id, selected: continousProfilingStore.selectedStrategy?.id === i.id,
}" }"
v-if="i.type" v-if="i.type"
> >
@@ -81,7 +81,7 @@ limitations under the License. -->
const { t } = useI18n(); const { t } = useI18n();
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
const continousProfilingStore = useContinousProfilingStore(); const continousProfilingStore: ReturnType<typeof useContinousProfilingStore> = useContinousProfilingStore();
const updateStrategies = ref<boolean>(false); const updateStrategies = ref<boolean>(false);
const inProcess = ref<boolean>(false); const inProcess = ref<boolean>(false);

View File

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

View File

@@ -152,7 +152,7 @@ limitations under the License. -->
if (!(state.instance.id || (selectorStore.currentPod && selectorStore.currentPod.id))) { if (!(state.instance.id || (selectorStore.currentPod && selectorStore.currentPod.id))) {
return; 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) { if (resp.errors) {
disabled.value = true; disabled.value = true;
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
@@ -193,7 +193,7 @@ limitations under the License. -->
function searchLogs() { function searchLogs() {
let instance = ""; let instance = "";
if (dashboardStore.entity === EntityType[3].value) { if (dashboardStore.entity === EntityType[3].value) {
instance = selectorStore.currentPod.id; instance = selectorStore.currentPod?.id || "";
} }
const serviceInstanceId = instance || (state.instance && state.instance.id) || ""; const serviceInstanceId = instance || (state.instance && state.instance.id) || "";
demandLogStore.setLogCondition({ demandLogStore.setLogCondition({
@@ -247,6 +247,7 @@ limitations under the License. -->
const keywordsOfContentList = keywordsOfContent.value || []; const keywordsOfContentList = keywordsOfContent.value || [];
keywordsOfContentList.splice(index, 1); keywordsOfContentList.splice(index, 1);
demandLogStore.setLogCondition({ demandLogStore.setLogCondition({
...demandLogStore.conditions,
keywordsOfContent: keywordsOfContentList, keywordsOfContent: keywordsOfContentList,
}); });
contentStr.value = ""; contentStr.value = "";
@@ -262,12 +263,14 @@ limitations under the License. -->
if (type === "keywordsOfContent") { if (type === "keywordsOfContent") {
keywordsOfContent.value.push(contentStr.value); keywordsOfContent.value.push(contentStr.value);
demandLogStore.setLogCondition({ demandLogStore.setLogCondition({
...demandLogStore.conditions,
[type]: keywordsOfContent.value, [type]: keywordsOfContent.value,
}); });
contentStr.value = ""; contentStr.value = "";
} else if (type === "excludingKeywordsOfContent") { } else if (type === "excludingKeywordsOfContent") {
excludingKeywordsOfContent.value.push(excludingContentStr.value); excludingKeywordsOfContent.value.push(excludingContentStr.value);
demandLogStore.setLogCondition({ demandLogStore.setLogCondition({
...demandLogStore.conditions,
[type]: excludingKeywordsOfContent.value, [type]: excludingKeywordsOfContent.value,
}); });
excludingContentStr.value = ""; excludingContentStr.value = "";
@@ -277,6 +280,7 @@ limitations under the License. -->
function removeExcludeContent(index: number) { function removeExcludeContent(index: number) {
excludingKeywordsOfContent.value.splice(index, 1); excludingKeywordsOfContent.value.splice(index, 1);
demandLogStore.setLogCondition({ demandLogStore.setLogCondition({
...demandLogStore.conditions,
excludingKeywordsOfContent: excludingKeywordsOfContent.value, excludingKeywordsOfContent: excludingKeywordsOfContent.value,
}); });
excludingContentStr.value = ""; excludingContentStr.value = "";
@@ -297,7 +301,7 @@ limitations under the License. -->
() => { () => {
if (dashboardStore.entity === EntityType[0].value) { if (dashboardStore.entity === EntityType[0].value) {
fetchSelectors(); fetchSelectors();
demandLogStore.setLogs(""); demandLogStore.setLogs([]);
} }
}, },
); );
@@ -306,7 +310,7 @@ limitations under the License. -->
() => { () => {
if (dashboardStore.entity === EntityType[3].value) { if (dashboardStore.entity === EntityType[3].value) {
fetchSelectors(); fetchSelectors();
demandLogStore.setLogs(""); demandLogStore.setLogs([]);
} }
}, },
); );

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