mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-18 07:56:56 +00:00
* feat: while the funnel steps are invalid, handle auto save in local storage * chore: handle lightmode style in 'add span to funnel' modal * fix: don't save incomplete steps state in local storage if last saved configuration has valid steps * chore: close the 'Add span to funnel' modal on clicking save or discard * chore: deprecate the run funnel flow for unexecuted funnel * feat: change the funnel configuration save logic, and deprecate auto save * refactor: send all steps in the payload of analytics/overview * refactor: send all steps in the payload of analytics/steps (graph API) * chore: send all steps in the payload of analytics/steps/overview API * chore: send funnel steps with slow and error traces + deprecate the refetch on latency type change * chore: overall improvements * chore: change the save funnel icon + increase the width of funnel steps * fix: make the changes w.r.t. the updated funnel steps validation API + bugfixes * fix: remove funnelId from funnel results APIs * fix: handle edge case i.e. refetch funnel results on deleting a funnel step * chore: remove funnel steps configuration cache on removing funnel * chore: don't refetch the results on changing the latency type * fix: fix the edge cases of save funnel button being enabled even after saving the funnel steps * chore: remove the span count column from top traces tables * fix: fix the failing CI check by removing unnecessary props / fixing the types
290 lines
6.5 KiB
TypeScript
290 lines
6.5 KiB
TypeScript
import { NotificationInstance } from 'antd/es/notification/interface';
|
|
import {
|
|
createFunnel,
|
|
deleteFunnel,
|
|
ErrorTraceData,
|
|
FunnelOverviewPayload,
|
|
FunnelOverviewResponse,
|
|
FunnelStepsOverviewPayload,
|
|
FunnelStepsOverviewResponse,
|
|
FunnelStepsPayload,
|
|
FunnelStepsResponse,
|
|
getFunnelById,
|
|
getFunnelErrorTraces,
|
|
getFunnelOverview,
|
|
getFunnelsList,
|
|
getFunnelSlowTraces,
|
|
getFunnelSteps,
|
|
getFunnelStepsOverview,
|
|
renameFunnel,
|
|
RenameFunnelPayload,
|
|
saveFunnelDescription,
|
|
SlowTraceData,
|
|
updateFunnelSteps,
|
|
UpdateFunnelStepsPayload,
|
|
ValidateFunnelResponse,
|
|
validateFunnelSteps,
|
|
} from 'api/traceFunnels';
|
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
|
import { useFunnelContext } from 'pages/TracesFunnels/FunnelContext';
|
|
import {
|
|
useMutation,
|
|
UseMutationResult,
|
|
useQuery,
|
|
UseQueryResult,
|
|
} from 'react-query';
|
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
|
import {
|
|
CreateFunnelPayload,
|
|
CreateFunnelResponse,
|
|
FunnelData,
|
|
FunnelStepData,
|
|
} from 'types/api/traceFunnels';
|
|
|
|
export const useFunnelsList = (): UseQueryResult<
|
|
SuccessResponse<FunnelData[]> | ErrorResponse,
|
|
unknown
|
|
> =>
|
|
useQuery({
|
|
queryKey: [REACT_QUERY_KEY.GET_FUNNELS_LIST],
|
|
queryFn: () => getFunnelsList(),
|
|
refetchOnWindowFocus: true,
|
|
});
|
|
|
|
export const useFunnelDetails = ({
|
|
funnelId,
|
|
}: {
|
|
funnelId?: string;
|
|
}): UseQueryResult<SuccessResponse<FunnelData> | ErrorResponse, unknown> =>
|
|
useQuery({
|
|
queryKey: [REACT_QUERY_KEY.GET_FUNNEL_DETAILS, funnelId],
|
|
queryFn: () => getFunnelById(funnelId),
|
|
enabled: !!funnelId,
|
|
});
|
|
|
|
export const useCreateFunnel = (): UseMutationResult<
|
|
SuccessResponse<CreateFunnelResponse> | ErrorResponse,
|
|
Error,
|
|
CreateFunnelPayload
|
|
> =>
|
|
useMutation({
|
|
mutationFn: createFunnel,
|
|
});
|
|
|
|
export const useRenameFunnel = (): UseMutationResult<
|
|
SuccessResponse<FunnelData> | ErrorResponse,
|
|
Error,
|
|
RenameFunnelPayload
|
|
> =>
|
|
useMutation({
|
|
mutationFn: renameFunnel,
|
|
});
|
|
|
|
interface DeleteFunnelPayload {
|
|
id: string;
|
|
}
|
|
|
|
export const useDeleteFunnel = (): UseMutationResult<
|
|
SuccessResponse<FunnelData> | ErrorResponse,
|
|
Error,
|
|
DeleteFunnelPayload
|
|
> =>
|
|
useMutation({
|
|
mutationFn: deleteFunnel,
|
|
});
|
|
|
|
export const useUpdateFunnelSteps = (
|
|
funnelId: string,
|
|
notification: NotificationInstance,
|
|
): UseMutationResult<
|
|
SuccessResponse<FunnelData> | ErrorResponse,
|
|
Error,
|
|
UpdateFunnelStepsPayload
|
|
> =>
|
|
useMutation({
|
|
mutationFn: updateFunnelSteps,
|
|
mutationKey: [REACT_QUERY_KEY.UPDATE_FUNNEL_STEPS, funnelId],
|
|
|
|
onError: (error) => {
|
|
notification.error({
|
|
message: 'Failed to update funnel steps',
|
|
description: error.message,
|
|
});
|
|
},
|
|
});
|
|
|
|
export const useValidateFunnelSteps = ({
|
|
funnelId,
|
|
selectedTime,
|
|
startTime,
|
|
endTime,
|
|
enabled,
|
|
steps,
|
|
}: {
|
|
funnelId: string;
|
|
selectedTime: string;
|
|
startTime: number;
|
|
endTime: number;
|
|
enabled: boolean;
|
|
steps: FunnelStepData[];
|
|
}): UseQueryResult<
|
|
SuccessResponse<ValidateFunnelResponse> | ErrorResponse,
|
|
Error
|
|
> =>
|
|
useQuery({
|
|
queryFn: ({ signal }) =>
|
|
validateFunnelSteps(
|
|
{ start_time: startTime, end_time: endTime, steps },
|
|
signal,
|
|
),
|
|
queryKey: [
|
|
REACT_QUERY_KEY.VALIDATE_FUNNEL_STEPS,
|
|
funnelId,
|
|
selectedTime,
|
|
steps.map((step) => {
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
const { latency_type, ...rest } = step;
|
|
return rest;
|
|
}),
|
|
],
|
|
enabled,
|
|
staleTime: 0,
|
|
});
|
|
|
|
interface SaveFunnelDescriptionPayload {
|
|
funnel_id: string;
|
|
description: string;
|
|
timestamp: number;
|
|
}
|
|
|
|
export const useSaveFunnelDescription = (): UseMutationResult<
|
|
SuccessResponse<FunnelData> | ErrorResponse,
|
|
Error,
|
|
SaveFunnelDescriptionPayload
|
|
> =>
|
|
useMutation<
|
|
SuccessResponse<FunnelData> | ErrorResponse,
|
|
Error,
|
|
SaveFunnelDescriptionPayload
|
|
>({
|
|
mutationFn: saveFunnelDescription,
|
|
});
|
|
|
|
export const useFunnelOverview = (
|
|
funnelId: string,
|
|
payload: FunnelOverviewPayload,
|
|
): UseQueryResult<
|
|
SuccessResponse<FunnelOverviewResponse> | ErrorResponse,
|
|
Error
|
|
> => {
|
|
const {
|
|
selectedTime,
|
|
validTracesCount,
|
|
isUpdatingFunnel,
|
|
} = useFunnelContext();
|
|
return useQuery({
|
|
queryFn: ({ signal }) => getFunnelOverview(payload, signal),
|
|
queryKey: [
|
|
REACT_QUERY_KEY.GET_FUNNEL_OVERVIEW,
|
|
funnelId,
|
|
selectedTime,
|
|
payload.steps,
|
|
],
|
|
enabled: !!funnelId && validTracesCount > 0 && !isUpdatingFunnel,
|
|
});
|
|
};
|
|
|
|
export const useFunnelSlowTraces = (
|
|
funnelId: string,
|
|
payload: FunnelOverviewPayload,
|
|
): UseQueryResult<SuccessResponse<SlowTraceData> | ErrorResponse, Error> => {
|
|
const {
|
|
selectedTime,
|
|
validTracesCount,
|
|
isUpdatingFunnel,
|
|
} = useFunnelContext();
|
|
return useQuery<SuccessResponse<SlowTraceData> | ErrorResponse, Error>({
|
|
queryFn: ({ signal }) => getFunnelSlowTraces(payload, signal),
|
|
queryKey: [
|
|
REACT_QUERY_KEY.GET_FUNNEL_SLOW_TRACES,
|
|
funnelId,
|
|
selectedTime,
|
|
payload.step_start ?? '',
|
|
payload.step_end ?? '',
|
|
payload.steps,
|
|
],
|
|
enabled: !!funnelId && validTracesCount > 0 && !isUpdatingFunnel,
|
|
});
|
|
};
|
|
|
|
export const useFunnelErrorTraces = (
|
|
funnelId: string,
|
|
payload: FunnelOverviewPayload,
|
|
): UseQueryResult<SuccessResponse<ErrorTraceData> | ErrorResponse, Error> => {
|
|
const {
|
|
selectedTime,
|
|
validTracesCount,
|
|
isUpdatingFunnel,
|
|
} = useFunnelContext();
|
|
return useQuery({
|
|
queryFn: ({ signal }) => getFunnelErrorTraces(funnelId, payload, signal),
|
|
queryKey: [
|
|
REACT_QUERY_KEY.GET_FUNNEL_ERROR_TRACES,
|
|
funnelId,
|
|
selectedTime,
|
|
payload.step_start ?? '',
|
|
payload.step_end ?? '',
|
|
payload.steps,
|
|
],
|
|
enabled: !!funnelId && validTracesCount > 0 && !isUpdatingFunnel,
|
|
});
|
|
};
|
|
|
|
export function useFunnelStepsGraphData(
|
|
funnelId: string,
|
|
payload: FunnelStepsPayload,
|
|
): UseQueryResult<SuccessResponse<FunnelStepsResponse> | ErrorResponse, Error> {
|
|
const {
|
|
selectedTime,
|
|
validTracesCount,
|
|
isUpdatingFunnel,
|
|
} = useFunnelContext();
|
|
|
|
return useQuery({
|
|
queryFn: ({ signal }) => getFunnelSteps(payload, signal),
|
|
queryKey: [
|
|
REACT_QUERY_KEY.GET_FUNNEL_STEPS_GRAPH_DATA,
|
|
funnelId,
|
|
selectedTime,
|
|
payload.steps,
|
|
],
|
|
enabled: !!funnelId && validTracesCount > 0 && !isUpdatingFunnel,
|
|
});
|
|
}
|
|
|
|
export const useFunnelStepsOverview = (
|
|
funnelId: string,
|
|
payload: FunnelStepsOverviewPayload,
|
|
): UseQueryResult<
|
|
SuccessResponse<FunnelStepsOverviewResponse> | ErrorResponse,
|
|
Error
|
|
> => {
|
|
const {
|
|
selectedTime,
|
|
validTracesCount,
|
|
isUpdatingFunnel,
|
|
} = useFunnelContext();
|
|
return useQuery({
|
|
queryFn: ({ signal }) => getFunnelStepsOverview(payload, signal),
|
|
queryKey: [
|
|
REACT_QUERY_KEY.GET_FUNNEL_STEPS_OVERVIEW,
|
|
funnelId,
|
|
selectedTime,
|
|
payload.step_start ?? '',
|
|
payload.step_end ?? '',
|
|
payload.steps,
|
|
],
|
|
enabled: !!funnelId && validTracesCount > 0 && !isUpdatingFunnel,
|
|
});
|
|
};
|