useFullSpanFromTrace.tsx 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import type {Entry, EntrySpans} from 'sentry/types/event';
  2. import {EntryType} from 'sentry/types/event';
  3. import type {Sort} from 'sentry/utils/discover/fields';
  4. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  5. import {useEventDetails} from 'sentry/views/starfish/queries/useEventDetails';
  6. import {useIndexedSpans} from 'sentry/views/starfish/queries/useIndexedSpans';
  7. import {SpanIndexedField} from 'sentry/views/starfish/types';
  8. const DEFAULT_SORT: Sort[] = [{field: 'timestamp', kind: 'desc'}];
  9. // NOTE: Fetching the top one is a bit naive, but works for now. A better
  10. // approach might be to fetch several at a time, and let the hook consumer
  11. // decide how to display them
  12. export function useFullSpanFromTrace(
  13. group?: string,
  14. sorts?: Sort[],
  15. enabled: boolean = true,
  16. extraFilters: Record<string, string> = {}
  17. ) {
  18. const filters = {...extraFilters};
  19. if (group) {
  20. filters[SpanIndexedField.SPAN_GROUP] = group;
  21. }
  22. // TODO: we're using all SpanIndexedFields here, but maybe we should only use what we need?
  23. // Truncate to 20 fields otherwise discover will complain.
  24. const fields = Object.values(SpanIndexedField).slice(0, 20);
  25. const indexedSpansResponse = useIndexedSpans({
  26. search: MutableSearch.fromQueryObject(filters),
  27. sorts: sorts || DEFAULT_SORT,
  28. limit: 1,
  29. enabled,
  30. fields,
  31. referrer: 'api.starfish.full-span-from-trace',
  32. });
  33. const firstIndexedSpan = indexedSpansResponse.data?.[0];
  34. const eventDetailsResponse = useEventDetails({
  35. eventId: firstIndexedSpan?.[SpanIndexedField.TRANSACTION_ID],
  36. projectSlug: firstIndexedSpan?.[SpanIndexedField.PROJECT],
  37. });
  38. const spanEntry = eventDetailsResponse.data?.entries.find(
  39. (entry: Entry): entry is EntrySpans => {
  40. return entry.type === EntryType.SPANS;
  41. }
  42. );
  43. const fullSpan = spanEntry?.data?.find(
  44. span => span.span_id === firstIndexedSpan?.[SpanIndexedField.ID]
  45. );
  46. // N.B. There isn't a great pattern for us to merge the responses together,
  47. // so we're only merging the three most important properties
  48. return {
  49. isLoading: indexedSpansResponse.isLoading || eventDetailsResponse.isLoading,
  50. isFetching: indexedSpansResponse.isFetching || eventDetailsResponse.isFetching,
  51. isError: indexedSpansResponse.isError || eventDetailsResponse.isError,
  52. data: fullSpan,
  53. };
  54. }