mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-01 04:32:03 +08:00
fix: enable custom aggregate interval for all data sources across application (#5074)
* fix: step interval not working for logs alerts * fix: build issues * fix: do not auto update the step interval when user enters some value * feat: remove initial default 60 from step interval * feat: revert last change * fix: step interval mapping * fix: remove initial default 60 from step interval * Revert "fix: remove initial default 60 from step interval" This reverts commit d23ce5e7e2860f37d433070d16793ceab85ed614. * chore: fix backend * chore: remove backend changes * feat: enable the aggregate every interval across product * fix: handle full view and landing view changes --------- Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
parent
af8907d4f8
commit
dc294ff6d5
@ -174,8 +174,8 @@ export const initialQueryBuilderFormValues: IBuilderQuery = {
|
|||||||
sourceNames: alphabet,
|
sourceNames: alphabet,
|
||||||
}),
|
}),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
having: [],
|
|
||||||
stepInterval: 60,
|
stepInterval: 60,
|
||||||
|
having: [],
|
||||||
limit: null,
|
limit: null,
|
||||||
orderBy: [],
|
orderBy: [],
|
||||||
groupBy: [],
|
groupBy: [],
|
||||||
|
@ -22,7 +22,6 @@ import PlotTag from 'container/NewWidget/LeftContainer/WidgetGraph/PlotTag';
|
|||||||
import { BuilderUnitsFilter } from 'container/QueryBuilder/filters';
|
import { BuilderUnitsFilter } from 'container/QueryBuilder/filters';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||||
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
|
||||||
import { MESSAGE, useIsFeatureDisabled } from 'hooks/useFeatureFlag';
|
import { MESSAGE, useIsFeatureDisabled } from 'hooks/useFeatureFlag';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
@ -70,7 +69,7 @@ function FormAlertRules({
|
|||||||
// init namespace for translations
|
// init namespace for translations
|
||||||
const { t } = useTranslation('alerts');
|
const { t } = useTranslation('alerts');
|
||||||
|
|
||||||
const { minTime, maxTime, selectedTime: globalSelectedInterval } = useSelector<
|
const { selectedTime: globalSelectedInterval } = useSelector<
|
||||||
AppState,
|
AppState,
|
||||||
GlobalReducer
|
GlobalReducer
|
||||||
>((state) => state.globalTime);
|
>((state) => state.globalTime);
|
||||||
@ -191,7 +190,9 @@ function FormAlertRules({
|
|||||||
}
|
}
|
||||||
const query: Query = { ...currentQuery, queryType: val };
|
const query: Query = { ...currentQuery, queryType: val };
|
||||||
|
|
||||||
redirectWithQueryBuilderData(updateStepInterval(query, maxTime, minTime));
|
// update step interval is removed from here as if the user enters
|
||||||
|
// any value we will use that rather than auto update
|
||||||
|
redirectWithQueryBuilderData(query);
|
||||||
};
|
};
|
||||||
const { notifications } = useNotifications();
|
const { notifications } = useNotifications();
|
||||||
|
|
||||||
@ -540,7 +541,7 @@ function FormAlertRules({
|
|||||||
queryCategory={currentQuery.queryType}
|
queryCategory={currentQuery.queryType}
|
||||||
setQueryCategory={onQueryCategoryChange}
|
setQueryCategory={onQueryCategoryChange}
|
||||||
alertType={alertType || AlertTypes.METRICS_BASED_ALERT}
|
alertType={alertType || AlertTypes.METRICS_BASED_ALERT}
|
||||||
runQuery={handleRunQuery}
|
runQuery={(): void => handleRunQuery(true)}
|
||||||
alertDef={alertDef}
|
alertDef={alertDef}
|
||||||
panelType={panelType || PANEL_TYPES.TIME_SERIES}
|
panelType={panelType || PANEL_TYPES.TIME_SERIES}
|
||||||
key={currentQuery.queryType}
|
key={currentQuery.queryType}
|
||||||
|
@ -15,7 +15,6 @@ import {
|
|||||||
} from 'container/NewWidget/RightContainer/timeItems';
|
} from 'container/NewWidget/RightContainer/timeItems';
|
||||||
import PanelWrapper from 'container/PanelWrapper/PanelWrapper';
|
import PanelWrapper from 'container/PanelWrapper/PanelWrapper';
|
||||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||||
import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
|
||||||
import { useChartMutable } from 'hooks/useChartMutable';
|
import { useChartMutable } from 'hooks/useChartMutable';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
||||||
@ -71,7 +70,7 @@ function FullView({
|
|||||||
enum: widget?.timePreferance || 'GLOBAL_TIME',
|
enum: widget?.timePreferance || 'GLOBAL_TIME',
|
||||||
});
|
});
|
||||||
|
|
||||||
const updatedQuery = useStepInterval(widget?.query);
|
const updatedQuery = widget?.query;
|
||||||
|
|
||||||
const [requestData, setRequestData] = useState<GetQueryResultsProps>(() => {
|
const [requestData, setRequestData] = useState<GetQueryResultsProps>(() => {
|
||||||
if (widget.panelTypes !== PANEL_TYPES.LIST) {
|
if (widget.panelTypes !== PANEL_TYPES.LIST) {
|
||||||
|
@ -3,7 +3,6 @@ import { QueryParams } from 'constants/query';
|
|||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
|
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||||
import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
|
||||||
import { useIntersectionObserver } from 'hooks/useIntersectionObserver';
|
import { useIntersectionObserver } from 'hooks/useIntersectionObserver';
|
||||||
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
||||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||||
@ -90,7 +89,7 @@ function GridCardGraph({
|
|||||||
}
|
}
|
||||||
}, [toScrollWidgetId, setToScrollWidgetId, widget.id]);
|
}, [toScrollWidgetId, setToScrollWidgetId, widget.id]);
|
||||||
|
|
||||||
const updatedQuery = useStepInterval(widget?.query);
|
const updatedQuery = widget?.query;
|
||||||
|
|
||||||
const isEmptyWidget =
|
const isEmptyWidget =
|
||||||
widget?.id === PANEL_TYPES.EMPTY_WIDGET || isEmpty(widget);
|
widget?.id === PANEL_TYPES.EMPTY_WIDGET || isEmpty(widget);
|
||||||
|
@ -47,7 +47,7 @@ function LogExplorerQuerySection({
|
|||||||
const isTable = panelTypes === PANEL_TYPES.TABLE;
|
const isTable = panelTypes === PANEL_TYPES.TABLE;
|
||||||
const isList = panelTypes === PANEL_TYPES.LIST;
|
const isList = panelTypes === PANEL_TYPES.LIST;
|
||||||
const config: QueryBuilderProps['filterConfigs'] = {
|
const config: QueryBuilderProps['filterConfigs'] = {
|
||||||
stepInterval: { isHidden: isTable, isDisabled: true },
|
stepInterval: { isHidden: isTable, isDisabled: false },
|
||||||
having: { isHidden: isList, isDisabled: true },
|
having: { isHidden: isList, isDisabled: true },
|
||||||
filters: {
|
filters: {
|
||||||
customKey: 'body',
|
customKey: 'body',
|
||||||
|
@ -12,7 +12,6 @@ import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interface
|
|||||||
import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys';
|
import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||||
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import { defaultTo } from 'lodash-es';
|
import { defaultTo } from 'lodash-es';
|
||||||
@ -33,7 +32,6 @@ import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
|||||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { EQueryType } from 'types/common/dashboard';
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
|
||||||
|
|
||||||
import ClickHouseQueryContainer from './QueryBuilder/clickHouse';
|
import ClickHouseQueryContainer from './QueryBuilder/clickHouse';
|
||||||
import PromQLQueryContainer from './QueryBuilder/promQL';
|
import PromQLQueryContainer from './QueryBuilder/promQL';
|
||||||
@ -46,10 +44,6 @@ function QuerySection({
|
|||||||
const urlQuery = useUrlQuery();
|
const urlQuery = useUrlQuery();
|
||||||
const { registerShortcut, deregisterShortcut } = useKeyboardHotkeys();
|
const { registerShortcut, deregisterShortcut } = useKeyboardHotkeys();
|
||||||
|
|
||||||
const { minTime, maxTime } = useSelector<AppState, GlobalReducer>(
|
|
||||||
(state) => state.globalTime,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { featureResponse } = useSelector<AppState, AppReducer>(
|
const { featureResponse } = useSelector<AppState, AppReducer>(
|
||||||
(state) => state.app,
|
(state) => state.app,
|
||||||
);
|
);
|
||||||
@ -80,8 +74,6 @@ function QuerySection({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedQuery = updateStepInterval(query, maxTime, minTime);
|
|
||||||
|
|
||||||
const selectedWidgetIndex = getSelectedWidgetIndex(
|
const selectedWidgetIndex = getSelectedWidgetIndex(
|
||||||
selectedDashboard,
|
selectedDashboard,
|
||||||
selectedWidget.id,
|
selectedWidget.id,
|
||||||
@ -102,18 +94,16 @@ function QuerySection({
|
|||||||
...previousWidgets,
|
...previousWidgets,
|
||||||
{
|
{
|
||||||
...selectedWidget,
|
...selectedWidget,
|
||||||
query: updatedQuery,
|
query,
|
||||||
},
|
},
|
||||||
...nextWidgets,
|
...nextWidgets,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
redirectWithQueryBuilderData(updatedQuery);
|
redirectWithQueryBuilderData(query);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
selectedDashboard,
|
selectedDashboard,
|
||||||
maxTime,
|
|
||||||
minTime,
|
|
||||||
selectedWidget,
|
selectedWidget,
|
||||||
setSelectedDashboard,
|
setSelectedDashboard,
|
||||||
redirectWithQueryBuilderData,
|
redirectWithQueryBuilderData,
|
||||||
@ -137,7 +127,7 @@ function QuerySection({
|
|||||||
|
|
||||||
const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
|
const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
|
||||||
const config: QueryBuilderProps['filterConfigs'] = {
|
const config: QueryBuilderProps['filterConfigs'] = {
|
||||||
stepInterval: { isHidden: false, isDisabled: true },
|
stepInterval: { isHidden: false, isDisabled: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
@ -22,7 +22,6 @@ import { QueryHistoryState } from 'container/LiveLogs/types';
|
|||||||
import NewExplorerCTA from 'container/NewExplorerCTA';
|
import NewExplorerCTA from 'container/NewExplorerCTA';
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import GetMinMax from 'lib/getMinMax';
|
import GetMinMax from 'lib/getMinMax';
|
||||||
import getTimeString from 'lib/getTimeString';
|
import getTimeString from 'lib/getTimeString';
|
||||||
@ -315,8 +314,6 @@ function DateTimeSelection({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { maxTime, minTime } = GetMinMax(value, getTime());
|
|
||||||
|
|
||||||
if (!isLogsExplorerPage) {
|
if (!isLogsExplorerPage) {
|
||||||
urlQuery.delete('startTime');
|
urlQuery.delete('startTime');
|
||||||
urlQuery.delete('endTime');
|
urlQuery.delete('endTime');
|
||||||
@ -333,7 +330,8 @@ function DateTimeSelection({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// the second boolean param directs the qb about the time change so to merge the query and retain the current state
|
// the second boolean param directs the qb about the time change so to merge the query and retain the current state
|
||||||
initQueryBuilderData(updateStepInterval(stagedQuery, maxTime, minTime), true);
|
// we removed update step interval to stop auto updating the value on time change
|
||||||
|
initQueryBuilderData(stagedQuery, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRefreshHandler = (): void => {
|
const onRefreshHandler = (): void => {
|
||||||
@ -383,8 +381,6 @@ function DateTimeSelection({
|
|||||||
|
|
||||||
setIsValidteRelativeTime(true);
|
setIsValidteRelativeTime(true);
|
||||||
|
|
||||||
const { maxTime, minTime } = GetMinMax(dateTimeStr, getTime());
|
|
||||||
|
|
||||||
if (!isLogsExplorerPage) {
|
if (!isLogsExplorerPage) {
|
||||||
urlQuery.delete('startTime');
|
urlQuery.delete('startTime');
|
||||||
urlQuery.delete('endTime');
|
urlQuery.delete('endTime');
|
||||||
@ -400,7 +396,8 @@ function DateTimeSelection({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the second boolean param directs the qb about the time change so to merge the query and retain the current state
|
// the second boolean param directs the qb about the time change so to merge the query and retain the current state
|
||||||
initQueryBuilderData(updateStepInterval(stagedQuery, maxTime, minTime), true);
|
// we removed update step interval to stop auto updating the value on time change
|
||||||
|
initQueryBuilderData(stagedQuery, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCustomOrIntervalTime = (
|
const getCustomOrIntervalTime = (
|
||||||
|
@ -19,7 +19,7 @@ function QuerySection(): JSX.Element {
|
|||||||
const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
|
const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
|
||||||
const isList = panelTypes === PANEL_TYPES.LIST;
|
const isList = panelTypes === PANEL_TYPES.LIST;
|
||||||
const config: QueryBuilderProps['filterConfigs'] = {
|
const config: QueryBuilderProps['filterConfigs'] = {
|
||||||
stepInterval: { isHidden: false, isDisabled: true },
|
stepInterval: { isHidden: false, isDisabled: false },
|
||||||
limit: { isHidden: isList, isDisabled: true },
|
limit: { isHidden: isList, isDisabled: true },
|
||||||
having: { isHidden: isList, isDisabled: true },
|
having: { isHidden: isList, isDisabled: true },
|
||||||
};
|
};
|
||||||
@ -56,7 +56,7 @@ function QuerySection(): JSX.Element {
|
|||||||
version="v3" // setting this to v3 as we this is rendered in logs explorer
|
version="v3" // setting this to v3 as we this is rendered in logs explorer
|
||||||
actions={
|
actions={
|
||||||
<ButtonWrapper>
|
<ButtonWrapper>
|
||||||
<Button onClick={handleRunQuery} type="primary">
|
<Button onClick={(): void => handleRunQuery()} type="primary">
|
||||||
Run Query
|
Run Query
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonWrapper>
|
</ButtonWrapper>
|
||||||
|
@ -8,6 +8,7 @@ export const updateStepInterval = (
|
|||||||
query: Widgets['query'],
|
query: Widgets['query'],
|
||||||
maxTime: number,
|
maxTime: number,
|
||||||
minTime: number,
|
minTime: number,
|
||||||
|
shallUpdateStepInterval?: boolean,
|
||||||
): Widgets['query'] => {
|
): Widgets['query'] => {
|
||||||
const stepInterval = getStep({
|
const stepInterval = getStep({
|
||||||
start: minTime,
|
start: minTime,
|
||||||
@ -15,6 +16,14 @@ export const updateStepInterval = (
|
|||||||
inputFormat: 'ns',
|
inputFormat: 'ns',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getStepInterval(customInterval: number): number {
|
||||||
|
// if user enters some value then auto update should never come
|
||||||
|
if (shallUpdateStepInterval) {
|
||||||
|
return customInterval;
|
||||||
|
}
|
||||||
|
return stepInterval;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...query,
|
...query,
|
||||||
builder: {
|
builder: {
|
||||||
@ -22,7 +31,7 @@ export const updateStepInterval = (
|
|||||||
queryData:
|
queryData:
|
||||||
query?.builder?.queryData?.map((item) => ({
|
query?.builder?.queryData?.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
stepInterval,
|
stepInterval: getStepInterval(item.stepInterval),
|
||||||
})) || [],
|
})) || [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -752,26 +752,30 @@ export function QueryBuilderProvider({
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRunQuery = useCallback(() => {
|
const handleRunQuery = useCallback(
|
||||||
redirectWithQueryBuilderData({
|
(shallUpdateStepInterval?: boolean) => {
|
||||||
...{
|
redirectWithQueryBuilderData({
|
||||||
...currentQuery,
|
...{
|
||||||
...updateStepInterval(
|
...currentQuery,
|
||||||
{
|
...updateStepInterval(
|
||||||
builder: currentQuery.builder,
|
{
|
||||||
clickhouse_sql: currentQuery.clickhouse_sql,
|
builder: currentQuery.builder,
|
||||||
promql: currentQuery.promql,
|
clickhouse_sql: currentQuery.clickhouse_sql,
|
||||||
id: currentQuery.id,
|
promql: currentQuery.promql,
|
||||||
queryType,
|
id: currentQuery.id,
|
||||||
unit: currentQuery.unit,
|
queryType,
|
||||||
},
|
unit: currentQuery.unit,
|
||||||
maxTime,
|
},
|
||||||
minTime,
|
maxTime,
|
||||||
),
|
minTime,
|
||||||
},
|
!!shallUpdateStepInterval,
|
||||||
queryType,
|
),
|
||||||
});
|
},
|
||||||
}, [currentQuery, queryType, maxTime, minTime, redirectWithQueryBuilderData]);
|
queryType,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[currentQuery, queryType, maxTime, minTime, redirectWithQueryBuilderData],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!compositeQueryParam) return;
|
if (!compositeQueryParam) return;
|
||||||
|
@ -222,7 +222,7 @@ export type QueryBuilderContextType = {
|
|||||||
redirectToUrl?: typeof ROUTES[keyof typeof ROUTES],
|
redirectToUrl?: typeof ROUTES[keyof typeof ROUTES],
|
||||||
shallStringify?: boolean,
|
shallStringify?: boolean,
|
||||||
) => void;
|
) => void;
|
||||||
handleRunQuery: () => void;
|
handleRunQuery: (shallUpdateStepInterval?: boolean) => void;
|
||||||
resetQuery: (newCurrentQuery?: QueryState) => void;
|
resetQuery: (newCurrentQuery?: QueryState) => void;
|
||||||
handleOnUnitsChange: (units: Format['id']) => void;
|
handleOnUnitsChange: (units: Format['id']) => void;
|
||||||
updateAllQueriesOperators: (
|
updateAllQueriesOperators: (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user