feat: added APM to new trace filter redirection (#5225)

This commit is contained in:
SagarRajput-7 2024-06-15 13:53:56 +05:30 committed by GitHub
parent e6ee5fc9e3
commit f824aa17dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 274 additions and 40 deletions

View File

@ -255,7 +255,7 @@ function FormAlertRules({
if ( if (
!currentQuery.builder.queryData || !currentQuery.builder.queryData ||
currentQuery.builder.queryData.length === 0 currentQuery.builder.queryData?.length === 0
) { ) {
notifications.error({ notifications.error({
message: 'Error', message: 'Error',

View File

@ -30,8 +30,8 @@ export const constructCompositeQuery = ({
}: GetDefaultCompositeQueryParams): Query => ({ }: GetDefaultCompositeQueryParams): Query => ({
...query, ...query,
builder: { builder: {
...query.builder, ...query?.builder,
queryData: query.builder.queryData.map((item) => ({ queryData: query?.builder?.queryData?.map((item) => ({
...initialQueryData, ...initialQueryData,
...item, ...item,
...customQueryData, ...customQueryData,

View File

@ -42,7 +42,7 @@ export const prepareQueryByFilter = (
...query, ...query,
builder: { builder: {
...query.builder, ...query.builder,
queryData: query.builder.queryData.map((item) => ({ queryData: query.builder.queryData?.map((item) => ({
...item, ...item,
filters: value ? getFilter(item.filters, tagFilter, value) : item.filters, filters: value ? getFilter(item.filters, tagFilter, value) : item.filters,
})), })),
@ -57,7 +57,7 @@ export const getQueryWithoutFilterId = (query: Query): Query => {
...query, ...query,
builder: { builder: {
...query.builder, ...query.builder,
queryData: query.builder.queryData.map((item) => ({ queryData: query.builder.queryData?.map((item) => ({
...item, ...item,
filters: { filters: {
...item.filters, ...item.filters,

View File

@ -40,7 +40,7 @@ export const getRequestData = ({
...query, ...query,
builder: { builder: {
...query.builder, ...query.builder,
queryData: query.builder.queryData.map((item) => ({ queryData: query.builder.queryData?.map((item) => ({
...item, ...item,
...paginateData, ...paginateData,
pageSize, pageSize,

View File

@ -27,6 +27,7 @@ import {
handleNonInQueryRange, handleNonInQueryRange,
onGraphClickHandler, onGraphClickHandler,
onViewTracePopupClick, onViewTracePopupClick,
useGetAPMToTracesQueries,
} from './util'; } from './util';
function DBCall(): JSX.Element { function DBCall(): JSX.Element {
@ -96,6 +97,11 @@ function DBCall(): JSX.Element {
[servicename, tagFilterItems], [servicename, tagFilterItems],
); );
const apmToTraceQuery = useGetAPMToTracesQueries({
servicename,
isDBCall: true,
});
return ( return (
<Row gutter={24}> <Row gutter={24}>
<Col span={12}> <Col span={12}>
@ -107,6 +113,7 @@ function DBCall(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
apmToTraceQuery,
})} })}
> >
View Traces View Traces
@ -139,6 +146,7 @@ function DBCall(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
apmToTraceQuery,
})} })}
> >
View Traces View Traces

View File

@ -27,6 +27,7 @@ import {
handleNonInQueryRange, handleNonInQueryRange,
onGraphClickHandler, onGraphClickHandler,
onViewTracePopupClick, onViewTracePopupClick,
useGetAPMToTracesQueries,
} from './util'; } from './util';
function External(): JSX.Element { function External(): JSX.Element {
@ -138,6 +139,11 @@ function External(): JSX.Element {
[servicename, tagFilterItems], [servicename, tagFilterItems],
); );
const apmToTraceQuery = useGetAPMToTracesQueries({
servicename,
isExternalCall: true,
});
return ( return (
<> <>
<Row gutter={24}> <Row gutter={24}>
@ -150,7 +156,7 @@ function External(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
isExternalCall: true, apmToTraceQuery,
})} })}
> >
View Traces View Traces
@ -184,7 +190,7 @@ function External(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
isExternalCall: true, apmToTraceQuery,
})} })}
> >
View Traces View Traces
@ -221,7 +227,7 @@ function External(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
isExternalCall: true, apmToTraceQuery,
})} })}
> >
View Traces View Traces
@ -255,7 +261,7 @@ function External(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
isExternalCall: true, apmToTraceQuery,
})} })}
> >
View Traces View Traces

View File

@ -22,6 +22,8 @@ import { useQuery } from 'react-query';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation, useParams } from 'react-router-dom'; import { useLocation, useParams } from 'react-router-dom';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
@ -43,6 +45,7 @@ import {
handleNonInQueryRange, handleNonInQueryRange,
onGraphClickHandler, onGraphClickHandler,
onViewTracePopupClick, onViewTracePopupClick,
useGetAPMToTracesQueries,
} from './util'; } from './util';
function Application(): JSX.Element { function Application(): JSX.Element {
@ -92,6 +95,8 @@ function Application(): JSX.Element {
convertRawQueriesToTraceSelectedTags(queries) || [], convertRawQueriesToTraceSelectedTags(queries) || [],
); );
const apmToTraceQuery = useGetAPMToTracesQueries({ servicename });
const tagFilterItems = useMemo( const tagFilterItems = useMemo(
() => () =>
handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [], handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [],
@ -159,7 +164,10 @@ function Application(): JSX.Element {
[dispatch, pathname, urlQuery], [dispatch, pathname, urlQuery],
); );
const onErrorTrackHandler = (timestamp: number): (() => void) => (): void => { const onErrorTrackHandler = (
timestamp: number,
apmToTraceQuery: Query,
): (() => void) => (): void => {
const currentTime = timestamp; const currentTime = timestamp;
const tPlusOne = timestamp + 60 * 1000; const tPlusOne = timestamp + 60 * 1000;
@ -170,15 +178,38 @@ function Application(): JSX.Element {
const avialableParams = routeConfig[ROUTES.TRACE]; const avialableParams = routeConfig[ROUTES.TRACE];
const queryString = getQueryString(avialableParams, urlParams); const queryString = getQueryString(avialableParams, urlParams);
history.replace( const JSONCompositeQuery = encodeURIComponent(
`${ JSON.stringify(apmToTraceQuery),
ROUTES.TRACE
}?selected={"serviceName":["${servicename}"],"status":["error"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&isFilterExclude={"serviceName":false,"status":false}&userSelectedFilter={"serviceName":["${servicename}"],"status":["error"]}&spanAggregateCurrentPage=1&${queryString.join(
'',
)}`,
); );
const newTraceExplorerPath = `${
ROUTES.TRACES_EXPLORER
}?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&${
QueryParams.compositeQuery
}=${JSONCompositeQuery}&${queryString.join('&')}`;
history.push(newTraceExplorerPath);
}; };
const errorTrackQuery = useGetAPMToTracesQueries({
servicename,
filters: [
{
id: uuid().slice(0, 8),
key: {
key: 'hasError',
dataType: DataTypes.bool,
type: 'tag',
isColumn: true,
isJSON: false,
id: 'hasError--bool--tag--true',
},
op: 'in',
value: ['true'],
},
],
});
return ( return (
<> <>
<Row gutter={24}> <Row gutter={24}>
@ -202,6 +233,7 @@ function Application(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
apmToTraceQuery,
})} })}
> >
View Traces View Traces
@ -229,6 +261,7 @@ function Application(): JSX.Element {
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
apmToTraceQuery,
})} })}
> >
View Traces View Traces
@ -245,7 +278,7 @@ function Application(): JSX.Element {
type="default" type="default"
size="small" size="small"
id="Error_button" id="Error_button"
onClick={onErrorTrackHandler(selectedTimeStamp)} onClick={onErrorTrackHandler(selectedTimeStamp, errorTrackQuery)}
> >
View Traces View Traces
</Button> </Button>

View File

@ -21,7 +21,11 @@ import { v4 as uuid } from 'uuid';
import { Button } from '../styles'; import { Button } from '../styles';
import { IServiceName } from '../types'; import { IServiceName } from '../types';
import { handleNonInQueryRange, onViewTracePopupClick } from '../util'; import {
handleNonInQueryRange,
onViewTracePopupClick,
useGetAPMToTracesQueries,
} from '../util';
function ServiceOverview({ function ServiceOverview({
onDragSelect, onDragSelect,
@ -69,6 +73,8 @@ function ServiceOverview({
const isQueryEnabled = const isQueryEnabled =
!topLevelOperationsIsLoading && topLevelOperationsRoute.length > 0; !topLevelOperationsIsLoading && topLevelOperationsRoute.length > 0;
const apmToTraceQuery = useGetAPMToTracesQueries({ servicename });
return ( return (
<> <>
<Button <Button
@ -79,6 +85,7 @@ function ServiceOverview({
servicename, servicename,
selectedTraceTags, selectedTraceTags,
timestamp: selectedTimeStamp, timestamp: selectedTimeStamp,
apmToTraceQuery,
})} })}
> >
View Traces View Traces

View File

@ -1,6 +1,10 @@
import { Tooltip, Typography } from 'antd'; import { Tooltip, Typography } from 'antd';
import { navigateToTrace } from 'container/MetricsApplication/utils'; import { navigateToTrace } from 'container/MetricsApplication/utils';
import { RowData } from 'lib/query/createTableColumnsFromQuery'; import { RowData } from 'lib/query/createTableColumnsFromQuery';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { v4 as uuid } from 'uuid';
import { useGetAPMToTracesQueries } from '../../util';
function ColumnWithLink({ function ColumnWithLink({
servicename, servicename,
@ -11,6 +15,25 @@ function ColumnWithLink({
}: LinkColumnProps): JSX.Element { }: LinkColumnProps): JSX.Element {
const text = record.toString(); const text = record.toString();
const apmToTraceQuery = useGetAPMToTracesQueries({
servicename,
filters: [
{
id: uuid().slice(0, 8),
key: {
key: 'name',
dataType: DataTypes.String,
type: 'tag',
isColumn: true,
isJSON: false,
id: 'name--string--tag--true',
},
op: 'in',
value: [text],
},
],
});
const handleOnClick = (operation: string) => (): void => { const handleOnClick = (operation: string) => (): void => {
navigateToTrace({ navigateToTrace({
servicename, servicename,
@ -18,6 +41,7 @@ function ColumnWithLink({
minTime, minTime,
maxTime, maxTime,
selectedTraceTags, selectedTraceTags,
apmToTraceQuery,
}); });
}; };

View File

@ -1,11 +1,20 @@
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { routeConfig } from 'container/SideNav/config'; import { routeConfig } from 'container/SideNav/config';
import { getQueryString } from 'container/SideNav/helper'; import { getQueryString } from 'container/SideNav/helper';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import history from 'lib/history'; import history from 'lib/history';
import { Dispatch, SetStateAction } from 'react'; import { traceFilterKeys } from 'pages/TracesExplorer/Filter/filterUtils';
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData'; import { Dispatch, SetStateAction, useMemo } from 'react';
import {
BaseAutocompleteData,
DataTypes,
} from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import { Tags } from 'types/reducer/trace'; import { Tags } from 'types/reducer/trace';
import { v4 as uuid } from 'uuid';
export const dbSystemTags: Tags[] = [ export const dbSystemTags: Tags[] = [
{ {
@ -21,13 +30,13 @@ interface OnViewTracePopupClickProps {
servicename: string | undefined; servicename: string | undefined;
selectedTraceTags: string; selectedTraceTags: string;
timestamp: number; timestamp: number;
isExternalCall?: boolean; apmToTraceQuery: Query;
} }
export function onViewTracePopupClick({ export function onViewTracePopupClick({
selectedTraceTags, selectedTraceTags,
servicename, servicename,
timestamp, timestamp,
isExternalCall, apmToTraceQuery,
}: OnViewTracePopupClickProps): VoidFunction { }: OnViewTracePopupClickProps): VoidFunction {
return (): void => { return (): void => {
const currentTime = timestamp; const currentTime = timestamp;
@ -40,13 +49,17 @@ export function onViewTracePopupClick({
const avialableParams = routeConfig[ROUTES.TRACE]; const avialableParams = routeConfig[ROUTES.TRACE];
const queryString = getQueryString(avialableParams, urlParams); const queryString = getQueryString(avialableParams, urlParams);
history.replace( const JSONCompositeQuery = encodeURIComponent(
`${ JSON.stringify(apmToTraceQuery),
ROUTES.TRACE
}?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"]}&spanAggregateCurrentPage=1${
isExternalCall ? '&spanKind=3' : ''
}&${queryString.join('&')}`,
); );
const newTraceExplorerPath = `${
ROUTES.TRACES_EXPLORER
}?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&${
QueryParams.compositeQuery
}=${JSONCompositeQuery}&${queryString.join('&')}`;
history.push(newTraceExplorerPath);
}; };
} }
@ -87,3 +100,104 @@ export const handleNonInQueryRange = (tags: TagFilterItem[]): TagFilterItem[] =>
} }
return tag; return tag;
}); });
export function handleQueryChange(
query: Query,
attributeKeys: BaseAutocompleteData,
serviceAttribute: string,
filters?: TagFilterItem[],
): Query {
const filterItem: TagFilterItem[] = [
{
id: uuid().slice(0, 8),
key: attributeKeys,
op: 'in',
value: serviceAttribute,
},
];
return {
...query,
builder: {
...query.builder,
queryData: query.builder.queryData?.map((item) => ({
...item,
filters: {
...item.filters,
items: [...item.filters.items, ...filterItem, ...(filters || [])],
},
})),
},
};
}
export function useGetAPMToTracesQueries({
servicename,
isExternalCall,
isDBCall,
filters,
}: {
servicename: string;
isExternalCall?: boolean;
isDBCall?: boolean;
filters?: TagFilterItem[];
}): Query {
const { updateAllQueriesOperators } = useQueryBuilder();
const finalFilters: TagFilterItem[] = [];
let spanKindFilter: TagFilterItem;
let dbCallFilter: TagFilterItem;
if (isExternalCall) {
spanKindFilter = {
id: uuid().slice(0, 8),
key: {
key: 'spanKind',
dataType: DataTypes.String,
type: 'tag',
isColumn: true,
isJSON: false,
id: 'spanKind--string--tag--true',
},
op: '=',
value: 'Client',
};
finalFilters.push(spanKindFilter);
}
if (isDBCall) {
dbCallFilter = {
id: uuid().slice(0, 8),
key: {
key: 'dbSystem',
dataType: DataTypes.String,
type: 'tag',
isColumn: true,
isJSON: false,
id: 'dbSystem--string--tag--true',
},
op: 'exists',
value: '',
};
finalFilters.push(dbCallFilter);
}
if (filters?.length) {
finalFilters.push(...filters);
}
return useMemo(() => {
const updatedQuery = updateAllQueriesOperators(
initialQueriesMap.traces,
PANEL_TYPES.TRACE,
DataSource.TRACES,
);
return handleQueryChange(
updatedQuery,
traceFilterKeys.serviceName,
servicename,
finalFilters,
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [servicename, updateAllQueriesOperators]);
}

View File

@ -12,9 +12,13 @@ import { useRef } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { v4 as uuid } from 'uuid';
import { IServiceName } from './Tabs/types'; import { IServiceName } from './Tabs/types';
import { useGetAPMToTracesQueries } from './Tabs/util';
import { import {
convertedTracesToDownloadData, convertedTracesToDownloadData,
getErrorRate, getErrorRate,
@ -38,18 +42,49 @@ function TopOperationsTable({
convertRawQueriesToTraceSelectedTags(queries) || [], convertRawQueriesToTraceSelectedTags(queries) || [],
); );
const apmToTraceQuery = useGetAPMToTracesQueries({ servicename });
const params = useParams<{ servicename: string }>(); const params = useParams<{ servicename: string }>();
const handleOnClick = (operation: string): void => { const handleOnClick = (operation: string): void => {
const { servicename: encodedServiceName } = params; const { servicename: encodedServiceName } = params;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const opFilter: TagFilterItem = {
id: uuid().slice(0, 8),
key: {
key: 'name',
dataType: DataTypes.String,
type: 'tag',
isColumn: true,
isJSON: false,
id: 'name--string--tag--true',
},
op: 'in',
value: [operation],
};
const preparedQuery: Query = {
...apmToTraceQuery,
builder: {
...apmToTraceQuery.builder,
queryData: apmToTraceQuery.builder.queryData?.map((item) => ({
...item,
filters: {
...item.filters,
items: [...item.filters.items, opFilter],
},
})),
},
};
navigateToTrace({ navigateToTrace({
servicename, servicename,
operation, operation,
minTime, minTime,
maxTime, maxTime,
selectedTraceTags, selectedTraceTags,
apmToTraceQuery: preparedQuery,
}); });
}; };

View File

@ -1,6 +1,6 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData'; import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { IServiceName } from './Tabs/types'; import { IServiceName } from './Tabs/types';
@ -19,6 +19,7 @@ export interface NavigateToTraceProps {
minTime: number; minTime: number;
maxTime: number; maxTime: number;
selectedTraceTags: string; selectedTraceTags: string;
apmToTraceQuery: Query;
} }
export interface DatabaseCallsRPSProps extends DatabaseCallProps { export interface DatabaseCallsRPSProps extends DatabaseCallProps {

View File

@ -18,15 +18,21 @@ export const navigateToTrace = ({
minTime, minTime,
maxTime, maxTime,
selectedTraceTags, selectedTraceTags,
apmToTraceQuery,
}: NavigateToTraceProps): void => { }: NavigateToTraceProps): void => {
const urlParams = new URLSearchParams(); const urlParams = new URLSearchParams();
urlParams.set(QueryParams.startTime, (minTime / 1000000).toString()); urlParams.set(QueryParams.startTime, (minTime / 1000000).toString());
urlParams.set(QueryParams.endTime, (maxTime / 1000000).toString()); urlParams.set(QueryParams.endTime, (maxTime / 1000000).toString());
history.push(
`${ const JSONCompositeQuery = encodeURIComponent(JSON.stringify(apmToTraceQuery));
ROUTES.TRACE
}?${urlParams.toString()}&selected={"serviceName":["${servicename}"],"operation":["${operation}"]}&filterToFetchData=["duration","status","serviceName","operation"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false,"operation":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"],"operation":["${operation}"]}&spanAggregateCurrentPage=1`, const newTraceExplorerPath = `${
); ROUTES.TRACES_EXPLORER
}?${urlParams.toString()}&selected={"serviceName":["${servicename}"],"operation":["${operation}"]}&filterToFetchData=["duration","status","serviceName","operation"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&${
QueryParams.compositeQuery
}=${JSONCompositeQuery}`;
history.push(newTraceExplorerPath);
}; };
export const getNearestHighestBucketValue = ( export const getNearestHighestBucketValue = (

View File

@ -4,7 +4,7 @@ export const prepareQueryWithDefaultTimestamp = (query: Query): Query => ({
...query, ...query,
builder: { builder: {
...query.builder, ...query.builder,
queryData: query.builder.queryData.map((item) => ({ queryData: query.builder.queryData?.map((item) => ({
...item, ...item,
orderBy: [{ columnName: 'timestamp', order: 'desc' }], orderBy: [{ columnName: 'timestamp', order: 'desc' }],
})), })),

View File

@ -148,13 +148,13 @@ export function QueryBuilderProvider({
const prepareQueryBuilderData = useCallback( const prepareQueryBuilderData = useCallback(
(query: Query): Query => { (query: Query): Query => {
const builder: QueryBuilderData = { const builder: QueryBuilderData = {
queryData: query.builder.queryData.map((item) => ({ queryData: query.builder.queryData?.map((item) => ({
...initialQueryBuilderFormValuesMap[ ...initialQueryBuilderFormValuesMap[
initialDataSource || DataSource.METRICS initialDataSource || DataSource.METRICS
], ],
...item, ...item,
})), })),
queryFormulas: query.builder.queryFormulas.map((item) => ({ queryFormulas: query.builder.queryFormulas?.map((item) => ({
...initialFormulaBuilderFormValues, ...initialFormulaBuilderFormValues,
...item, ...item,
})), })),
@ -236,7 +236,7 @@ export function QueryBuilderProvider({
const updateAllQueriesOperators = useCallback( const updateAllQueriesOperators = useCallback(
(query: Query, panelType: PANEL_TYPES, dataSource: DataSource): Query => { (query: Query, panelType: PANEL_TYPES, dataSource: DataSource): Query => {
const queryData = query.builder.queryData.map((item) => const queryData = query.builder.queryData?.map((item) =>
getElementWithActualOperator(item, dataSource, panelType), getElementWithActualOperator(item, dataSource, panelType),
); );
@ -682,7 +682,7 @@ export function QueryBuilderProvider({
: query.queryType; : query.queryType;
const builder = const builder =
!query.builder || query.builder.queryData.length === 0 !query.builder || query.builder.queryData?.length === 0
? initialQueryState.builder ? initialQueryState.builder
: query.builder; : query.builder;