test_organization_group_index_stats.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import uuid
  2. from sentry.issues.grouptype import ProfileFileIOGroupType
  3. from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
  4. from sentry.testutils import APITestCase, SnubaTestCase
  5. from sentry.testutils.helpers import parse_link_header
  6. from sentry.testutils.helpers.datetime import before_now, iso_format
  7. from sentry.testutils.silo import region_silo_test
  8. from tests.sentry.issues.test_utils import OccurrenceTestMixin
  9. @region_silo_test
  10. class GroupListTest(APITestCase, SnubaTestCase, OccurrenceTestMixin):
  11. endpoint = "sentry-api-0-organization-group-index-stats"
  12. def setUp(self):
  13. super().setUp()
  14. self.min_ago = before_now(minutes=1)
  15. def _parse_links(self, header):
  16. # links come in {url: {...attrs}}, but we need {rel: {...attrs}}
  17. links = {}
  18. for url, attrs in parse_link_header(header).items():
  19. links[attrs["rel"]] = attrs
  20. attrs["href"] = url
  21. return links
  22. def get_response(self, *args, **kwargs):
  23. if not args:
  24. org = self.project.organization.slug
  25. else:
  26. org = args[0]
  27. return super().get_response(org, **kwargs)
  28. def test_simple(self):
  29. self.store_event(
  30. data={"timestamp": iso_format(before_now(seconds=500)), "fingerprint": ["group-1"]},
  31. project_id=self.project.id,
  32. )
  33. group_a = self.store_event(
  34. data={"timestamp": iso_format(before_now(seconds=1)), "fingerprint": ["group-a"]},
  35. project_id=self.project.id,
  36. ).group
  37. self.store_event(
  38. data={"timestamp": iso_format(before_now(seconds=2)), "fingerprint": ["group-b"]},
  39. project_id=self.project.id,
  40. )
  41. group_c = self.store_event(
  42. data={"timestamp": iso_format(before_now(seconds=3)), "fingerprint": ["group-c"]},
  43. project_id=self.project.id,
  44. ).group
  45. self.login_as(user=self.user)
  46. response = self.get_response(query="is:unresolved", groups=[group_a.id, group_c.id])
  47. response_data = sorted(response.data, key=lambda x: x["firstSeen"], reverse=True)
  48. assert response.status_code == 200
  49. assert len(response_data) == 2
  50. assert int(response_data[0]["id"]) == group_a.id
  51. assert int(response_data[1]["id"]) == group_c.id
  52. assert "title" not in response_data[0]
  53. assert "hasSeen" not in response_data[0]
  54. assert "stats" in response_data[0]
  55. assert "firstSeen" in response_data[0]
  56. assert "lastSeen" in response_data[0]
  57. assert "count" in response_data[0]
  58. assert "userCount" in response_data[0]
  59. assert "lifetime" in response_data[0]
  60. assert "filtered" in response_data[0]
  61. def test_issue_platform_issue(self):
  62. event_id = uuid.uuid4().hex
  63. occurrence_data = self.build_occurrence_data(
  64. event_id=event_id, project_id=self.project.id, type=ProfileFileIOGroupType.type_id
  65. )
  66. occurrence, group_info = process_event_and_issue_occurrence(
  67. occurrence_data,
  68. {
  69. "event_id": event_id,
  70. "fingerprint": ["group-1"],
  71. "project_id": self.project.id,
  72. "timestamp": before_now(minutes=1).isoformat(),
  73. },
  74. )
  75. profile_group = group_info.group
  76. self.login_as(user=self.user)
  77. response = self.get_response(
  78. query=f"issue:{profile_group.qualified_short_id}", groups=[profile_group.id]
  79. )
  80. response_data = sorted(response.data, key=lambda x: x["firstSeen"], reverse=True)
  81. assert response.status_code == 200
  82. assert len(response_data) == 1
  83. assert int(response_data[0]["id"]) == profile_group.id
  84. assert "title" not in response_data[0]
  85. assert "hasSeen" not in response_data[0]
  86. assert "stats" in response_data[0]
  87. assert "firstSeen" in response_data[0]
  88. assert "lastSeen" in response_data[0]
  89. assert "count" in response_data[0]
  90. assert "userCount" in response_data[0]
  91. assert "lifetime" in response_data[0]
  92. assert "filtered" in response_data[0]
  93. def test_issue_platform_mixed_issue_not_title(self):
  94. event_id = uuid.uuid4().hex
  95. occurrence_data = self.build_occurrence_data(
  96. event_id=event_id, project_id=self.project.id, type=ProfileFileIOGroupType.type_id
  97. )
  98. occurrence, group_info = process_event_and_issue_occurrence(
  99. occurrence_data,
  100. {
  101. "event_id": event_id,
  102. "fingerprint": ["group-a"],
  103. "project_id": self.project.id,
  104. "timestamp": before_now(minutes=1).isoformat(),
  105. },
  106. )
  107. profile_group = group_info.group
  108. error_event = self.store_event(
  109. data={"timestamp": iso_format(before_now(seconds=500)), "fingerprint": ["group-1"]},
  110. project_id=self.project.id,
  111. )
  112. error_group = error_event.group
  113. self.login_as(user=self.user)
  114. response = self.get_response(
  115. query=f"!title:{profile_group.title}", groups=[profile_group.id, error_group.id]
  116. )
  117. response_data = sorted(response.data, key=lambda x: x["firstSeen"], reverse=True)
  118. assert response.status_code == 200
  119. assert [int(grp["id"]) for grp in response_data] == [profile_group.id, error_group.id]
  120. for data in response_data:
  121. assert "title" not in data
  122. assert "hasSeen" not in data
  123. assert "stats" in data
  124. assert "firstSeen" in data
  125. assert "lastSeen" in data
  126. assert "count" in data
  127. assert "userCount" in data
  128. assert "lifetime" in data
  129. assert "filtered" in data
  130. def test_no_matching_groups(self):
  131. self.login_as(user=self.user)
  132. response = self.get_response(sort_by="date", limit=10, query="is:unresolved", groups=[1337])
  133. assert response.status_code == 400
  134. def test_simple_with_project(self):
  135. self.store_event(
  136. data={"timestamp": iso_format(before_now(seconds=500)), "fingerprint": ["group-1"]},
  137. project_id=self.project.id,
  138. )
  139. group_a = self.store_event(
  140. data={"timestamp": iso_format(before_now(seconds=1)), "fingerprint": ["group-a"]},
  141. project_id=self.project.id,
  142. ).group
  143. self.store_event(
  144. data={"timestamp": iso_format(before_now(seconds=2)), "fingerprint": ["group-b"]},
  145. project_id=self.project.id,
  146. )
  147. group_c = self.store_event(
  148. data={"timestamp": iso_format(before_now(seconds=3)), "fingerprint": ["group-c"]},
  149. project_id=self.project.id,
  150. ).group
  151. self.login_as(user=self.user)
  152. response = self.get_response(
  153. query=f"project:{self.project.slug}", groups=[group_a.id, group_c.id]
  154. )
  155. assert response.status_code == 200
  156. assert len(response.data) == 2
  157. def test_query_timestamp(self):
  158. self.store_event(
  159. data={"timestamp": iso_format(before_now(seconds=500)), "fingerprint": ["group-1"]},
  160. project_id=self.project.id,
  161. )
  162. event2 = self.store_event(
  163. data={"timestamp": iso_format(before_now(seconds=1)), "fingerprint": ["group-a"]},
  164. project_id=self.project.id,
  165. )
  166. self.store_event(
  167. data={"timestamp": iso_format(before_now(seconds=2)), "fingerprint": ["group-b"]},
  168. project_id=self.project.id,
  169. )
  170. event4 = self.store_event(
  171. data={"timestamp": iso_format(before_now(seconds=3)), "fingerprint": ["group-c"]},
  172. project_id=self.project.id,
  173. )
  174. group_a = event2.group
  175. group_c = event4.group
  176. self.login_as(user=self.user)
  177. response = self.get_response(
  178. query=f"timestamp:>{iso_format(before_now(seconds=3))} timestamp:<{iso_format(before_now(seconds=1))}",
  179. groups=[group_a.id, group_c.id],
  180. )
  181. assert response.status_code == 200
  182. assert len(response.data) == 2