useFullSpanFromTrace.tsx 2.3 KB

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