mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2026-04-19 19:19:43 +00:00
feat: add coldStage to the Duration (#521)
This commit is contained in:
2660
package-lock.json
generated
2660
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -49,11 +49,11 @@
|
||||
"@types/d3-tip": "^3.5.5",
|
||||
"@types/echarts": "^4.9.12",
|
||||
"@types/jsdom": "^20.0.1",
|
||||
"@types/node": "^18.11.12",
|
||||
"@types/node": "^22.19.10",
|
||||
"@types/three": "^0.131.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"@vitest/coverage-v8": "^3.0.6",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"@vue/eslint-config-prettier": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.0",
|
||||
"@vue/test-utils": "^2.2.6",
|
||||
@@ -84,7 +84,7 @@
|
||||
"vite": "^6.4.1",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vitest": "^3.0.5",
|
||||
"vitest": "^4.0.18",
|
||||
"vue-tsc": "^2.2.2"
|
||||
},
|
||||
"browserslist": [
|
||||
|
||||
@@ -28,18 +28,22 @@ export function useDuration() {
|
||||
start: getLocalTime(appStore.utc, durationRow.start),
|
||||
end: getLocalTime(appStore.utc, durationRow.end),
|
||||
step: durationRow.step,
|
||||
coldStage: appStore.coldStageMode,
|
||||
};
|
||||
}
|
||||
function getDurationTime(): DurationTime {
|
||||
const appStore = useAppStoreWithOut();
|
||||
const { start, step, end } = getDuration();
|
||||
return {
|
||||
start: dateFormatStep(start, step, true),
|
||||
end: dateFormatStep(end, step, true),
|
||||
step: step,
|
||||
step,
|
||||
coldStage: appStore.coldStageMode,
|
||||
};
|
||||
}
|
||||
function setDurationRow(data: Duration) {
|
||||
durationRow = data;
|
||||
const appStore = useAppStoreWithOut();
|
||||
durationRow = { ...data, coldStage: appStore.coldStageMode };
|
||||
}
|
||||
function getMaxRange(day: number) {
|
||||
if (day === undefined || day === null) {
|
||||
|
||||
@@ -54,10 +54,10 @@ limitations under the License. -->
|
||||
<el-switch
|
||||
v-model="coldStage"
|
||||
inline-prompt
|
||||
active-text="Active Data"
|
||||
inactive-text="Cold Data"
|
||||
active-text="Cold Excluded"
|
||||
inactive-text="Cold Only"
|
||||
@change="changeDataMode"
|
||||
width="90px"
|
||||
width="105px"
|
||||
/>
|
||||
</span>
|
||||
<span class="ml-5" ref="themeSwitchRef">
|
||||
@@ -174,7 +174,20 @@ limitations under the License. -->
|
||||
async function setTTL() {
|
||||
await getMetricsTTL();
|
||||
await getRecordsTTL();
|
||||
changeDataMode();
|
||||
// Initialize TTL handling without triggering duration update
|
||||
if (coldStage.value) {
|
||||
handleMetricsTTL({
|
||||
minute: appStore.metricsTTL?.coldMinute ?? NaN,
|
||||
hour: appStore.metricsTTL?.coldHour ?? NaN,
|
||||
day: appStore.metricsTTL?.coldDay ?? NaN,
|
||||
});
|
||||
} else {
|
||||
handleMetricsTTL({
|
||||
minute: appStore.metricsTTL?.minute ?? NaN,
|
||||
hour: appStore.metricsTTL?.hour ?? NaN,
|
||||
day: appStore.metricsTTL?.day ?? NaN,
|
||||
});
|
||||
}
|
||||
}
|
||||
async function getRecordsTTL() {
|
||||
const resp = await appStore.queryRecordsTTL();
|
||||
|
||||
@@ -82,6 +82,7 @@ describe("App Store", () => {
|
||||
expect(store.durationRow.start).toBeInstanceOf(Date);
|
||||
expect(store.durationRow.end).toBeInstanceOf(Date);
|
||||
expect(store.durationRow.step).toBe(TimeType.MINUTE_TIME);
|
||||
expect(store.durationRow.coldStage).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -94,6 +95,7 @@ describe("App Store", () => {
|
||||
expect(duration.start).toBeInstanceOf(Date);
|
||||
expect(duration.end).toBeInstanceOf(Date);
|
||||
expect(duration.step).toBe(TimeType.MINUTE_TIME);
|
||||
expect(duration.coldStage).toBe(false);
|
||||
});
|
||||
|
||||
it("should return correct duration time", () => {
|
||||
@@ -104,6 +106,7 @@ describe("App Store", () => {
|
||||
expect(durationTime.start).toBe("2023-01-01 12:00");
|
||||
expect(durationTime.end).toBe("2023-01-01 12:00");
|
||||
expect(durationTime.step).toBe(TimeType.MINUTE_TIME);
|
||||
expect(durationTime.coldStage).toBe(false);
|
||||
});
|
||||
|
||||
it("should calculate interval unix correctly for MINUTE", () => {
|
||||
@@ -156,7 +159,7 @@ describe("App Store", () => {
|
||||
|
||||
store.setDuration(newDuration);
|
||||
|
||||
expect(store.durationRow).toEqual(newDuration);
|
||||
expect(store.durationRow).toEqual({ ...newDuration, coldStage: false });
|
||||
});
|
||||
|
||||
it("should update duration row correctly", () => {
|
||||
@@ -169,7 +172,7 @@ describe("App Store", () => {
|
||||
|
||||
store.updateDurationRow(newDuration);
|
||||
|
||||
expect(store.durationRow).toEqual(newDuration);
|
||||
expect(store.durationRow).toEqual({ ...newDuration, coldStage: false });
|
||||
});
|
||||
|
||||
it("should set max range correctly", () => {
|
||||
@@ -231,6 +234,55 @@ describe("App Store", () => {
|
||||
expect(store.coldStageMode).toBe(true);
|
||||
});
|
||||
|
||||
it("should set duration with coldStage when coldStageMode is enabled", () => {
|
||||
const store = appStore();
|
||||
store.setColdStageMode(true);
|
||||
|
||||
const newDuration = {
|
||||
start: new Date("2023-01-01"),
|
||||
end: new Date("2023-01-02"),
|
||||
step: "HOUR",
|
||||
};
|
||||
|
||||
store.setDuration(newDuration);
|
||||
|
||||
expect(store.durationRow).toEqual({ ...newDuration, coldStage: true });
|
||||
expect(store.duration.coldStage).toBe(true);
|
||||
});
|
||||
|
||||
it("should update duration row with coldStage when coldStageMode is enabled", () => {
|
||||
const store = appStore();
|
||||
store.setColdStageMode(true);
|
||||
|
||||
const newDuration = {
|
||||
start: new Date("2023-02-01"),
|
||||
end: new Date("2023-02-02"),
|
||||
step: "DAY",
|
||||
};
|
||||
|
||||
store.updateDurationRow(newDuration);
|
||||
|
||||
expect(store.durationRow).toEqual({ ...newDuration, coldStage: true });
|
||||
expect(store.duration.coldStage).toBe(true);
|
||||
});
|
||||
|
||||
it("should return correct duration time with coldStage when coldStageMode is enabled", () => {
|
||||
const store = appStore();
|
||||
store.setColdStageMode(true);
|
||||
|
||||
// Need to update duration row after setting cold stage mode
|
||||
const newDuration = {
|
||||
start: new Date("2023-01-01"),
|
||||
end: new Date("2023-01-02"),
|
||||
step: "HOUR",
|
||||
};
|
||||
store.setDuration(newDuration);
|
||||
|
||||
const durationTime = store.durationTime;
|
||||
|
||||
expect(durationTime.coldStage).toBe(true);
|
||||
});
|
||||
|
||||
it("should set reload timer correctly", () => {
|
||||
const store = appStore();
|
||||
const mockTimer = setInterval(() => {
|
||||
|
||||
@@ -18,7 +18,9 @@ import { defineStore } from "pinia";
|
||||
import { store } from "@/store";
|
||||
import graphql from "@/graphql";
|
||||
import type { Alarm } from "@/types/alarm";
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
import { useDuration } from "@/hooks/useDuration";
|
||||
|
||||
const { getDurationTime } = useDuration();
|
||||
|
||||
interface AlarmState {
|
||||
loading: boolean;
|
||||
@@ -48,10 +50,14 @@ export const alarmStore = defineStore({
|
||||
return res.data;
|
||||
},
|
||||
async getAlarmTagKeys() {
|
||||
return await graphql.query("queryAlarmTagKeys").params({ duration: useAppStoreWithOut().durationTime });
|
||||
return await graphql
|
||||
.query("queryAlarmTagKeys")
|
||||
.params({ duration: { ...getDurationTime(), coldStage: undefined } });
|
||||
},
|
||||
async getAlarmTagValues(tagKey: string) {
|
||||
return await graphql.query("queryAlarmTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
||||
return await graphql
|
||||
.query("queryAlarmTagValues")
|
||||
.params({ tagKey, duration: { ...getDurationTime(), coldStage: undefined } });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -46,6 +46,7 @@ export const InitializationDurationRow = {
|
||||
start: new Date(new Date().getTime() - 1800000),
|
||||
end: new Date(),
|
||||
step: TimeType.MINUTE_TIME,
|
||||
coldStage: false,
|
||||
};
|
||||
|
||||
export const appStore = defineStore({
|
||||
@@ -62,7 +63,7 @@ export const appStore = defineStore({
|
||||
reloadTimer: null,
|
||||
allMenus: [],
|
||||
theme: Themes.Dark,
|
||||
coldStageMode: false,
|
||||
coldStageMode: InitializationDurationRow.coldStage || false,
|
||||
maxRange: [],
|
||||
metricsTTL: null,
|
||||
recordsTTL: null,
|
||||
@@ -73,6 +74,7 @@ export const appStore = defineStore({
|
||||
start: getLocalTime(this.utc, this.durationRow.start),
|
||||
end: getLocalTime(this.utc, this.durationRow.end),
|
||||
step: this.durationRow.step,
|
||||
coldStage: this.durationRow.coldStage,
|
||||
};
|
||||
},
|
||||
durationTime(): DurationTime {
|
||||
@@ -80,6 +82,7 @@ export const appStore = defineStore({
|
||||
start: dateFormatStep(this.duration.start, this.duration.step, true),
|
||||
end: dateFormatStep(this.duration.end, this.duration.step, true),
|
||||
step: this.duration.step,
|
||||
coldStage: this.duration.coldStage,
|
||||
};
|
||||
},
|
||||
intervalUnix(): number[] {
|
||||
@@ -124,10 +127,10 @@ export const appStore = defineStore({
|
||||
},
|
||||
actions: {
|
||||
setDuration(data: Duration): void {
|
||||
this.durationRow = data;
|
||||
this.durationRow = { ...data, coldStage: this.coldStageMode };
|
||||
},
|
||||
updateDurationRow(data: Duration) {
|
||||
this.durationRow = data;
|
||||
this.durationRow = { ...data, coldStage: this.coldStageMode };
|
||||
},
|
||||
setMaxRange(times: Date[]) {
|
||||
this.maxRange = times;
|
||||
|
||||
@@ -152,10 +152,14 @@ export const logStore = defineStore({
|
||||
return response;
|
||||
},
|
||||
async getLogTagKeys() {
|
||||
return await graphql.query("queryLogTagKeys").params({ duration: useAppStoreWithOut().durationTime });
|
||||
return await graphql
|
||||
.query("queryLogTagKeys")
|
||||
.params({ duration: { ...getDurationTime(), coldStage: undefined } });
|
||||
},
|
||||
async getLogTagValues(tagKey: string) {
|
||||
return await graphql.query("queryLogTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
||||
return await graphql
|
||||
.query("queryLogTagValues")
|
||||
.params({ tagKey, duration: { ...getDurationTime(), coldStage: undefined } });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -237,10 +237,14 @@ export const traceStore = defineStore({
|
||||
return response;
|
||||
},
|
||||
async getTagKeys() {
|
||||
return await graphql.query("queryTraceTagKeys").params({ duration: useAppStoreWithOut().durationTime });
|
||||
return await graphql
|
||||
.query("queryTraceTagKeys")
|
||||
.params({ duration: { ...getDurationTime(), coldStage: undefined } });
|
||||
},
|
||||
async getTagValues(tagKey: string) {
|
||||
return await graphql.query("queryTraceTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
||||
return await graphql
|
||||
.query("queryTraceTagValues")
|
||||
.params({ tagKey, duration: { ...getDurationTime(), coldStage: undefined } });
|
||||
},
|
||||
async getHasQueryTracesV2Support() {
|
||||
const response = await graphql.query("queryHasQueryTracesV2Support").params({});
|
||||
|
||||
@@ -36,25 +36,29 @@ Object.defineProperty(window, "matchMedia", {
|
||||
});
|
||||
|
||||
// Mock ResizeObserver
|
||||
global.ResizeObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}));
|
||||
globalThis.ResizeObserver = class ResizeObserver {
|
||||
observe = vi.fn();
|
||||
unobserve = vi.fn();
|
||||
disconnect = vi.fn();
|
||||
};
|
||||
|
||||
// Mock IntersectionObserver
|
||||
global.IntersectionObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}));
|
||||
globalThis.IntersectionObserver = class IntersectionObserver {
|
||||
root = null;
|
||||
rootMargin = "";
|
||||
thresholds = [];
|
||||
observe = vi.fn();
|
||||
unobserve = vi.fn();
|
||||
disconnect = vi.fn();
|
||||
takeRecords = vi.fn(() => []);
|
||||
} as any;
|
||||
|
||||
// Mock requestAnimationFrame
|
||||
global.requestAnimationFrame = vi.fn((cb: FrameRequestCallback) => {
|
||||
globalThis.requestAnimationFrame = vi.fn((cb: FrameRequestCallback) => {
|
||||
const id = setTimeout(cb, 0);
|
||||
return id as unknown as number;
|
||||
});
|
||||
global.cancelAnimationFrame = vi.fn();
|
||||
globalThis.cancelAnimationFrame = vi.fn();
|
||||
|
||||
// Configure Vue Test Utils
|
||||
config.global.plugins = [ElementPlus];
|
||||
|
||||
@@ -22,11 +22,13 @@ export interface Duration {
|
||||
start: Date;
|
||||
end: Date;
|
||||
step: string;
|
||||
coldStage?: boolean;
|
||||
}
|
||||
export interface DurationTime {
|
||||
start: string;
|
||||
end: string;
|
||||
step: string;
|
||||
coldStage?: boolean;
|
||||
}
|
||||
export type Paging = {
|
||||
pageNum: number;
|
||||
|
||||
@@ -539,8 +539,8 @@ limitations under the License. -->
|
||||
cancelButtonText: "Cancel",
|
||||
inputValue: row.name,
|
||||
})
|
||||
.then(({ value }) => {
|
||||
updateName(row, value);
|
||||
.then(() => {
|
||||
updateName(row);
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
@@ -549,8 +549,8 @@ limitations under the License. -->
|
||||
});
|
||||
});
|
||||
}
|
||||
async function updateName(d: DashboardItem, value: string) {
|
||||
if (new RegExp(/\s/).test(value)) {
|
||||
async function updateName(d: DashboardItem) {
|
||||
if (new RegExp(/\s/).test(d.name)) {
|
||||
ElMessage.error("The name cannot contain spaces, carriage returns, etc");
|
||||
return;
|
||||
}
|
||||
@@ -559,7 +559,7 @@ limitations under the License. -->
|
||||
const c = {
|
||||
...JSON.parse(layout).configuration,
|
||||
...d,
|
||||
name: value,
|
||||
name: d.name,
|
||||
};
|
||||
delete c.id;
|
||||
delete c.filters;
|
||||
@@ -575,7 +575,7 @@ limitations under the License. -->
|
||||
}
|
||||
dashboardStore.setCurrentDashboard({
|
||||
...d,
|
||||
name: value,
|
||||
name: d.name,
|
||||
});
|
||||
dashboards.value = dashboardStore.dashboards.map((item: DashboardItem) => {
|
||||
if (dashboardStore.currentDashboard?.id === item.id) {
|
||||
|
||||
Reference in New Issue
Block a user