From bd9211afdaa0323e01d9ed187eec9d0880a6701a Mon Sep 17 00:00:00 2001 From: ktx-vaidehi <134508096+ktx-vaidehi@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:58:49 +0530 Subject: [PATCH] fix: dashboard restrict save when alias as timestamp (#9294) - #9290 --------- Co-authored-by: ktx-abhay --- .../dashboard/usePanelDataLoader.ts | 7 +++++++ web/src/composables/useDashboardPanel.ts | 5 +++-- web/src/plugins/logs/Index.vue | 9 --------- .../dashboard/convertDataIntoUnitValue.ts | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/web/src/composables/dashboard/usePanelDataLoader.ts b/web/src/composables/dashboard/usePanelDataLoader.ts index d729e421c9..278efce1c9 100644 --- a/web/src/composables/dashboard/usePanelDataLoader.ts +++ b/web/src/composables/dashboard/usePanelDataLoader.ts @@ -21,6 +21,7 @@ import { onMounted, onUnmounted, toRaw, + nextTick, } from "vue"; import queryService from "../../services/search"; import { useStore } from "vuex"; @@ -1023,6 +1024,9 @@ export const usePanelDataLoader = ( message: `Alias '${store.state.zoConfig.timestamp_column || "_timestamp"}' is not allowed.`, code: "400", }; + addTraceId("tempTraceId"); + await nextTick(); + removeTraceId("tempTraceId"); state.loading = false; // Skip this iteration and continue with next query/time shift continue; @@ -1301,6 +1305,9 @@ export const usePanelDataLoader = ( code: "400", }; state.loading = false; + addTraceId("tempTraceId"); + await nextTick(); + removeTraceId("tempTraceId"); // Skip executing this query and move to next continue; } diff --git a/web/src/composables/useDashboardPanel.ts b/web/src/composables/useDashboardPanel.ts index 5b5d5746ed..0c9edef395 100644 --- a/web/src/composables/useDashboardPanel.ts +++ b/web/src/composables/useDashboardPanel.ts @@ -27,6 +27,7 @@ import { extractFields, getStreamNameFromQuery } from "@/utils/query/sqlUtils"; import { validatePanel } from "@/utils/dashboard/convertDataIntoUnitValue"; import useValuesWebSocket from "./dashboard/useValuesWebSocket"; import queryService from "@/services/search"; +import logsUtils from "./useLogs/logsUtils"; const colors = [ "#5960b2", @@ -2997,7 +2998,7 @@ const useDashboardPanelData = (pageKey: string = "dashboard") => { }, { deep: true }, ); - +const { checkTimestampAlias } = logsUtils(); // Replace the existing validatePanel function with a wrapper that calls the generic function const validatePanelWrapper = ( errors: string[], @@ -3007,7 +3008,7 @@ const useDashboardPanelData = (pageKey: string = "dashboard") => { ...selectedStreamFieldsBasedOnUserDefinedSchema.value, ...dashboardPanelData.meta.stream.vrlFunctionFieldList, ...dashboardPanelData.meta.stream.customQueryFields, - ], pageKey); + ], pageKey, store, checkTimestampAlias); }; const VARIABLE_PLACEHOLDER = "substituteValue"; diff --git a/web/src/plugins/logs/Index.vue b/web/src/plugins/logs/Index.vue index 249d922a76..4dd926fcd8 100644 --- a/web/src/plugins/logs/Index.vue +++ b/web/src/plugins/logs/Index.vue @@ -2137,15 +2137,6 @@ export default defineComponent({ variablesAndPanelsDataLoadingState.fieldsExtractionLoading = false; return null; } - - // validate that timestamp column is not used as an alias - if (!checkTimestampAlias(logsPageQuery)) { - showErrorNotification( - `Alias '${store.state.zoConfig.timestamp_column || "_timestamp"}' is not allowed.`, - ); - variablesAndPanelsDataLoadingState.fieldsExtractionLoading = false; - return null; - } /* ------------------------------------------------------------- */ /* 1) Fetch schema for the user query */ diff --git a/web/src/utils/dashboard/convertDataIntoUnitValue.ts b/web/src/utils/dashboard/convertDataIntoUnitValue.ts index bdeabc0141..4e016cb626 100644 --- a/web/src/utils/dashboard/convertDataIntoUnitValue.ts +++ b/web/src/utils/dashboard/convertDataIntoUnitValue.ts @@ -1034,6 +1034,8 @@ export const validatePanel = ( isFieldsValidationRequired: boolean = true, allStreamFields: any[] = [], pageKey: string = "dashboard", + store: any, + checkTimestampAlias: any, ) => { // Get current query index const currentQueryIndex = panelData?.layout?.currentQueryIndex || 0; @@ -1044,6 +1046,22 @@ export const validatePanel = ( // Validate panel content based on type validatePanelContentByType(panelData?.data, errors); + // Validate timestamp alias for SQL queries with custom query mode + if (panelData?.data?.queryType === "sql") { + const timestampColumn = + store.state.zoConfig.timestamp_column || "_timestamp"; + + panelData?.data?.queries?.forEach((queryObj: any, index: number) => { + if (queryObj?.query && queryObj?.customQuery) { + if (!checkTimestampAlias(queryObj.query)) { + errors.push( + `Alias '${timestampColumn}' is not allowed.`, + ); + } + } + }); + } + if (isPromQLMode) { // 1. Chart type: only specific chart types are supported for PromQL const allowedChartTypes = [