Files
signoz/frontend/src/container/CreateAlertV2/QuerySection/QuerySection.tsx
Ashwin Bhatkal 021f1c5775 fix: handle cancel functionality for Run Query Button (#10958)
* fix: add ERR_CANCELED retry skip and new query key constants

* refactor: add disabled prop and handleCancelQuery to shared query components (#10959)

* refactor: add disabled prop and handleCancelQuery to shared query components

* feat: add cancel query support to alert rule editing (#10960)

* feat: add cancel query support to alert rule editing

* feat: add cancel query support to CreateAlertV2 (#10961)

* feat: add cancel query support to CreateAlertV2

* feat: add cancel query and AbortSignal support to MetricsExplorer Explorer (#10962)

* feat: add cancel query and AbortSignal support to MetricsExplorer Explorer

* feat: add cancel query support to MetricsExplorer Inspect (#10963)

* feat: add cancel query support to MetricsExplorer Inspect

* feat: add cancel query support to MetricsExplorer Summary (#10964)

* feat: add cancel query support to MetricsExplorer Summary

* feat: add cancel query support to MeterExplorer and dashboard widgets (#10965)

* feat: add cancel query support to MeterExplorer and dashboard widgets

* feat: add cancel query support to Logs, Traces, Exceptions and API Monitoring (#10972)

* feat: add cancel query support to Logs, Traces, Errors, and API Monitoring

* refactor: remove deprecated props and enforce strict query cancel interfaces (#10974)

* refactor: remove deprecated props and enforce strict query cancel interfaces

* fix: metrics explorer inspect cancel and run query bugs (#10975)

* fix: metrics explorer inspect cancel and run query bugs

* fix: api monitoring cancel and run query bugs (#10984)

* feat: add cancelled query placeholder UI to alerts, explorers, exceptions, and api monitoring (#10988)

* feat: add cancel query support to MeterExplorer and dashboard widgets

* fix: api monitoring cancel and run query bugs

* feat: add cancelled query placeholder UI to alerts, explorers, exceptions, and api monitoring

* fix: cancelled placeholder for alert v2 and metrics inspect, use css modules

* fix: cancelled placeholder race condition in metrics inspect auto-reset

* fix: prioritize cancelled state over loading in metrics inspect content

* fix: keep query builder rendered and match graph view height in inspect fallback

* feat: add cancelled query placeholder to logs, traces, and dashboard widgets (#11007)

* feat: add cancelled query placeholder to logs, traces, and dashboard widgets

* fix: reset cancel on run and swap only chart body in widget graph

* fix: use constants for max retry count (#11049)

* fix: use semantic tokens
2026-04-23 06:58:50 +00:00

171 lines
5.0 KiB
TypeScript

import { useCallback, useEffect, useMemo, useState } from 'react';
import { useQueryClient } from 'react-query';
import { Button } from 'antd';
import classNames from 'classnames';
import { YAxisSource } from 'components/YAxisUnitSelector/types';
import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import QuerySectionComponent from 'container/FormAlertRules/QuerySection';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { getMetricNameFromQueryData } from 'hooks/useGetYAxisUnit';
import useUrlQuery from 'hooks/useUrlQuery';
import { BarChart2, DraftingCompass, FileText, ScrollText } from 'lucide-react';
import { AlertTypes } from 'types/api/alerts/alertTypes';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import { useCreateAlertState } from '../context';
import Stepper from '../Stepper';
import ChartPreview from './ChartPreview';
import { buildAlertDefForChartPreview } from './utils';
import './styles.scss';
function QuerySection(): JSX.Element {
const {
currentQuery,
stagedQuery,
handleRunQuery,
redirectWithQueryBuilderData,
} = useQueryBuilder();
const { alertType, setAlertType, thresholdState } = useCreateAlertState();
const urlQuery = useUrlQuery();
const alertDef = buildAlertDefForChartPreview({ alertType, thresholdState });
const onQueryCategoryChange = (queryType: EQueryType): void => {
const query: Query = { ...currentQuery, queryType };
redirectWithQueryBuilderData(query);
};
const source = useMemo(() => urlQuery.get(QueryParams.source) as YAxisSource, [
urlQuery,
]);
const didQueryChange = useMemo(() => {
if (alertType !== AlertTypes.METRICS_BASED_ALERT) {
return false;
}
const selectedQueryName = thresholdState.selectedQuery;
const currentQueryData = currentQuery.builder.queryData.find(
(query) => query.queryName === selectedQueryName,
);
const stagedQueryData = stagedQuery?.builder.queryData.find(
(query) => query.queryName === selectedQueryName,
);
if (!currentQueryData || !stagedQueryData) {
return false;
}
const currentQueryKey = getMetricNameFromQueryData(currentQueryData);
const stagedQueryKey = getMetricNameFromQueryData(stagedQueryData);
return currentQueryKey !== stagedQueryKey;
}, [currentQuery, alertType, thresholdState, stagedQuery]);
const queryClient = useQueryClient();
const [isLoadingQueries, setIsLoadingQueries] = useState(false);
const [isCancelled, setIsCancelled] = useState(false);
useEffect(() => {
if (isLoadingQueries) {
setIsCancelled(false);
}
}, [isLoadingQueries]);
const handleCancelQuery = useCallback(() => {
queryClient.cancelQueries([REACT_QUERY_KEY.ALERT_RULES_CHART_PREVIEW]);
setIsCancelled(true);
}, [queryClient]);
const runQueryHandler = useCallback(() => {
setIsCancelled(false);
queryClient.invalidateQueries([REACT_QUERY_KEY.ALERT_RULES_CHART_PREVIEW]);
// Reset the source param when the query is changed
// Then manually run the query
if (source === YAxisSource.DASHBOARDS && didQueryChange) {
redirectWithQueryBuilderData(currentQuery, {
[QueryParams.source]: null,
});
} else {
handleRunQuery();
}
}, [
currentQuery,
didQueryChange,
handleRunQuery,
queryClient,
redirectWithQueryBuilderData,
source,
]);
const tabs = [
{
label: 'Metrics',
icon: <BarChart2 size={14} data-testid="metrics-view" />,
value: AlertTypes.METRICS_BASED_ALERT,
},
{
label: 'Logs',
icon: <ScrollText size={14} data-testid="logs-view" />,
value: AlertTypes.LOGS_BASED_ALERT,
},
{
label: 'Traces',
icon: <DraftingCompass size={14} data-testid="traces-view" />,
value: AlertTypes.TRACES_BASED_ALERT,
},
{
label: 'Exceptions',
icon: <FileText size={14} data-testid="exceptions-view" />,
value: AlertTypes.EXCEPTIONS_BASED_ALERT,
},
];
return (
<div className="query-section">
<Stepper stepNumber={1} label="Define the query" />
<ChartPreview
alertDef={alertDef}
source={source}
isCancelled={isCancelled}
onFetchingStateChange={setIsLoadingQueries}
/>
<div className="query-section-tabs">
<div className="query-section-query-actions">
{tabs.map((tab) => (
<Button
key={tab.value}
className={classNames('list-view-tab', 'explorer-view-option', {
'active-tab': alertType === tab.value,
})}
onClick={(): void => {
setAlertType(tab.value as AlertTypes);
}}
>
{tab.icon}
{tab.label}
</Button>
))}
</div>
</div>
<QuerySectionComponent
queryCategory={currentQuery.queryType}
setQueryCategory={onQueryCategoryChange}
alertType={alertType}
runQuery={runQueryHandler}
isLoadingQueries={isLoadingQueries}
handleCancelQuery={handleCancelQuery}
alertDef={alertDef}
panelType={PANEL_TYPES.TIME_SERIES}
key={currentQuery.queryType}
ruleId=""
hideTitle
/>
</div>
);
}
export default QuerySection;