246 lines
5.9 KiB
TypeScript

import { QueryParams } from 'constants/query';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import { routeConfig } from 'container/SideNav/config';
import { getQueryString } from 'container/SideNav/helper';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import history from 'lib/history';
import { prepareQueryWithDefaultTimestamp } from 'pages/LogsExplorer/utils';
import { traceFilterKeys } from 'pages/TracesExplorer/Filter/filterUtils';
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 { v4 as uuid } from 'uuid';
export const dbSystemTags: Tags[] = [
{
Key: 'db.system.(string)',
StringValues: [''],
NumberValues: [],
BoolValues: [],
Operator: 'Exists',
},
];
interface OnViewTracePopupClickProps {
servicename: string | undefined;
selectedTraceTags: string;
timestamp: number;
apmToTraceQuery: Query;
isViewLogsClicked?: boolean;
}
export function onViewTracePopupClick({
selectedTraceTags,
servicename,
timestamp,
apmToTraceQuery,
isViewLogsClicked,
}: OnViewTracePopupClickProps): VoidFunction {
return (): void => {
const currentTime = timestamp;
const tPlusOne = timestamp + 60;
const urlParams = new URLSearchParams(window.location.search);
urlParams.set(QueryParams.startTime, currentTime.toString());
urlParams.set(QueryParams.endTime, tPlusOne.toString());
urlParams.delete('relativeTime');
const avialableParams = routeConfig[ROUTES.TRACE];
const queryString = getQueryString(avialableParams, urlParams);
const JSONCompositeQuery = encodeURIComponent(
JSON.stringify(apmToTraceQuery),
);
const basePath = isViewLogsClicked
? ROUTES.LOGS_EXPLORER
: ROUTES.TRACES_EXPLORER;
const newPath = `${basePath}?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&${
QueryParams.compositeQuery
}=${JSONCompositeQuery}&${queryString.join('&')}`;
history.push(newPath);
};
}
export function onGraphClickHandler(
setSelectedTimeStamp: (n: number) => void | Dispatch<SetStateAction<number>>,
) {
return async (
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
type: string,
): Promise<void> => {
const id = `${type}_button`;
const buttonElement = document.getElementById(id);
if (xValue) {
if (buttonElement) {
buttonElement.style.display = 'block';
buttonElement.style.left = `${mouseX}px`;
buttonElement.style.top = `${mouseY}px`;
setSelectedTimeStamp(xValue);
}
} else if (buttonElement && buttonElement.style.display === 'block') {
buttonElement.style.display = 'none';
}
};
}
export const handleNonInQueryRange = (tags: TagFilterItem[]): TagFilterItem[] =>
tags.map((tag) => {
if (tag.op === 'Not IN') {
return {
...tag,
op: 'NIN',
};
}
return tag;
});
export function handleQueryChange(
query: Query,
attributeKeys: BaseAutocompleteData,
serviceAttribute: string,
filters?: TagFilterItem[],
logs?: boolean,
): Query {
const filterItem: TagFilterItem[] = [
{
id: uuid().slice(0, 8),
key: attributeKeys,
op: logs ? '=' : '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 useGetAPMToLogsQueries({
servicename,
filters,
}: {
servicename: string;
filters?: TagFilterItem[];
}): Query {
const finalFilters: TagFilterItem[] = [];
const { updateAllQueriesOperators } = useQueryBuilder();
let updatedQuery = updateAllQueriesOperators(
initialQueriesMap.logs,
PANEL_TYPES.LIST,
DataSource.LOGS,
);
const serviceName = {
id: 'service.name--string--resource--true',
dataType: DataTypes.String,
isColumn: true,
key: 'service.name',
type: 'resource',
isJSON: false,
};
if (filters?.length) {
finalFilters.push(...filters);
}
updatedQuery = prepareQueryWithDefaultTimestamp(updatedQuery);
return handleQueryChange(
updatedQuery,
serviceName,
servicename,
finalFilters,
true,
);
}
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]);
}