eventSearch.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import {useCallback, useMemo} from 'react';
  2. import orderBy from 'lodash/orderBy';
  3. import {useFetchIssueTags} from 'sentry/actionCreators/group';
  4. import {fetchTagValues} from 'sentry/actionCreators/tags';
  5. import {SearchQueryBuilder} from 'sentry/components/searchQueryBuilder';
  6. import type {FilterKeySection} from 'sentry/components/searchQueryBuilder/types';
  7. import {t} from 'sentry/locale';
  8. import type {Group, Tag, TagCollection} from 'sentry/types/group';
  9. import {FieldKind, ISSUE_EVENT_PROPERTY_FIELDS} from 'sentry/utils/fields';
  10. import useApi from 'sentry/utils/useApi';
  11. import useOrganization from 'sentry/utils/useOrganization';
  12. import {Dataset} from 'sentry/views/alerts/rules/metric/types';
  13. import {ALL_EVENTS_EXCLUDED_TAGS} from 'sentry/views/issueDetails/groupEvents';
  14. import {mergeAndSortTagValues} from 'sentry/views/issueDetails/utils';
  15. import {makeGetIssueTagValues} from 'sentry/views/issueList/utils/getIssueTagValues';
  16. interface EventSearchProps {
  17. environments: string[];
  18. group: Group;
  19. handleSearch: (value: string) => void;
  20. query: string;
  21. className?: string;
  22. }
  23. function getFilterKeySections(tags: TagCollection): FilterKeySection[] {
  24. const allTags: Tag[] = Object.values(tags).filter(
  25. tag => !ALL_EVENTS_EXCLUDED_TAGS.includes(tag.key)
  26. );
  27. const eventFields = orderBy(
  28. allTags.filter(tag => tag.kind === FieldKind.EVENT_FIELD),
  29. ['key']
  30. ).map(tag => tag.key);
  31. const eventTags = orderBy(
  32. allTags.filter(tag => tag.kind === FieldKind.TAG),
  33. ['totalValues', 'key'],
  34. ['desc', 'asc']
  35. ).map(tag => tag.key);
  36. return [
  37. {
  38. value: FieldKind.EVENT_FIELD,
  39. label: t('Event Filters'),
  40. children: eventFields,
  41. },
  42. {
  43. value: FieldKind.TAG,
  44. label: t('Event Tags'),
  45. children: eventTags,
  46. },
  47. ];
  48. }
  49. export function EventSearch({
  50. className,
  51. query,
  52. group,
  53. environments,
  54. handleSearch,
  55. }: EventSearchProps) {
  56. const api = useApi();
  57. const organization = useOrganization();
  58. const {data = []} = useFetchIssueTags({
  59. orgSlug: organization.slug,
  60. groupId: group.id,
  61. environment: environments,
  62. });
  63. const filterKeys = useMemo<TagCollection>(() => {
  64. const tags = [
  65. ...data.map(tag => ({...tag, kind: FieldKind.TAG})),
  66. ...ISSUE_EVENT_PROPERTY_FIELDS.map(tag => ({
  67. key: tag,
  68. name: tag,
  69. kind: FieldKind.EVENT_FIELD,
  70. })),
  71. ].filter(tag => !ALL_EVENTS_EXCLUDED_TAGS.includes(tag.key));
  72. return tags.reduce<TagCollection>((acc, tag) => {
  73. acc[tag.key] = tag;
  74. return acc;
  75. }, {});
  76. }, [data]);
  77. const tagValueLoader = useCallback(
  78. async (key: string, search: string) => {
  79. const orgSlug = organization.slug;
  80. const projectIds = [group.project.id];
  81. const [eventsDatasetValues, issuePlatformDatasetValues] = await Promise.all([
  82. fetchTagValues({
  83. api,
  84. orgSlug,
  85. tagKey: key,
  86. search,
  87. projectIds,
  88. dataset: Dataset.ERRORS,
  89. }),
  90. fetchTagValues({
  91. api,
  92. orgSlug,
  93. tagKey: key,
  94. search,
  95. projectIds,
  96. dataset: Dataset.ISSUE_PLATFORM,
  97. }),
  98. ]);
  99. return mergeAndSortTagValues(eventsDatasetValues, issuePlatformDatasetValues);
  100. },
  101. [api, group.project.id, organization.slug]
  102. );
  103. const getTagValues = useMemo(
  104. () => makeGetIssueTagValues(tagValueLoader),
  105. [tagValueLoader]
  106. );
  107. const filterKeySections = useMemo(() => getFilterKeySections(filterKeys), [filterKeys]);
  108. return (
  109. <SearchQueryBuilder
  110. initialQuery={query}
  111. onSearch={handleSearch}
  112. filterKeys={filterKeys}
  113. filterKeySections={filterKeySections}
  114. getTagValues={getTagValues}
  115. placeholder={t('Search events...')}
  116. searchSource="issue_events_tab"
  117. className={className}
  118. />
  119. );
  120. }