Files
2024-02-15 17:01:50 +00:00

115 lines
3.1 KiB
TypeScript

import {useCallback, useEffect, useMemo, useState} from 'react';
import * as Sentry from '@sentry/react';
import type {Location} from 'history';
import type {Organization} from 'sentry/types';
import EventView from 'sentry/utils/discover/eventView';
import {doDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery';
import {decodeScalar} from 'sentry/utils/queryString';
import {DEFAULT_SORT} from 'sentry/utils/replays/fetchReplayList';
import useApi from 'sentry/utils/useApi';
import type {ReplayListLocationQuery} from 'sentry/views/replays/types';
import {REPLAY_LIST_FIELDS} from 'sentry/views/replays/types';
type Options = {
location: Location;
organization: Organization;
replayIdsEventView: EventView;
};
export type EventSpanData = {
'count()': number;
replayId: string;
'span_ops_breakdown.relative': string;
'spans.browser': null | number;
'spans.db': null | number;
'spans.http': null | number;
'spans.resource': null | number;
'spans.ui': null | number;
timestamp: string;
trace: string;
'transaction.duration': number;
};
type Return = {
data: null | {
events: EventSpanData[];
replayRecordsEventView: EventView;
};
fetchError: any;
isFetching: boolean;
pageLinks: null | string;
};
function useReplaysFromTransaction({
location,
organization,
replayIdsEventView,
}: Options): Return {
const api = useApi();
const [response, setResponse] = useState<{
events: EventSpanData[];
pageLinks: null | string;
replayIds: undefined | string[];
}>({events: [], pageLinks: null, replayIds: undefined});
const [fetchError, setFetchError] = useState<any>();
const {cursor} = location.query;
const fetchReplayIds = useCallback(async () => {
try {
const [{data}, _textStatus, resp] = await doDiscoverQuery<{data: EventSpanData[]}>(
api,
`/organizations/${organization.slug}/events/`,
replayIdsEventView.getEventsAPIPayload({
query: {cursor},
} as Location<ReplayListLocationQuery>)
);
setResponse({
pageLinks: resp?.getResponseHeader('Link') ?? '',
replayIds: data.map(record => String(record.replayId)),
events: data || [],
});
} catch (err) {
Sentry.captureException(err);
setFetchError(err);
}
}, [api, cursor, organization.slug, replayIdsEventView]);
const replayRecordsEventView = useMemo(() => {
if (!response.replayIds) {
return null;
}
return EventView.fromSavedQuery({
id: '',
name: '',
version: 2,
fields: REPLAY_LIST_FIELDS,
projects: [],
query: `id:[${String(response.replayIds)}]`,
orderby: decodeScalar(location.query.sort, DEFAULT_SORT),
});
}, [location.query.sort, response.replayIds]);
useEffect(() => {
fetchReplayIds();
}, [fetchReplayIds]);
return {
data: replayRecordsEventView
? {
events: response.events,
replayRecordsEventView,
}
: null,
fetchError,
isFetching: !fetchError && !response.replayIds,
pageLinks: response.pageLinks,
};
}
export default useReplaysFromTransaction;