test_group.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import uuid
  2. from unittest.mock import patch
  3. from sentry.issues.grouptype import PerformanceNPlusOneGroupType, ProfileFileIOGroupType
  4. from sentry.models.group import Group
  5. from sentry.testutils.cases import PerformanceIssueTestCase, SnubaTestCase, TestCase
  6. from sentry.testutils.helpers.datetime import before_now, iso_format
  7. from sentry.testutils.silo import region_silo_test
  8. from sentry.utils.samples import load_data
  9. from tests.sentry.issues.test_utils import OccurrenceTestMixin
  10. @region_silo_test
  11. class GroupTestSnuba(TestCase, SnubaTestCase, PerformanceIssueTestCase, OccurrenceTestMixin):
  12. def test_get_oldest_latest_for_environments(self):
  13. project = self.create_project()
  14. min_ago = iso_format(before_now(minutes=1))
  15. self.store_event(
  16. data={
  17. "event_id": "a" * 32,
  18. "environment": "production",
  19. "timestamp": min_ago,
  20. "fingerprint": ["group-1"],
  21. },
  22. project_id=project.id,
  23. )
  24. self.store_event(
  25. data={
  26. "event_id": "b" * 32,
  27. "environment": "production",
  28. "timestamp": min_ago,
  29. "fingerprint": ["group-1"],
  30. },
  31. project_id=project.id,
  32. )
  33. self.store_event(
  34. data={"event_id": "c" * 32, "timestamp": min_ago, "fingerprint": ["group-1"]},
  35. project_id=project.id,
  36. )
  37. group = Group.objects.first()
  38. assert group.get_latest_event_for_environments().event_id == "c" * 32
  39. assert group.get_latest_event_for_environments(["staging"]) is None
  40. assert group.get_latest_event_for_environments(["production"]).event_id == "b" * 32
  41. assert group.get_oldest_event_for_environments().event_id == "a" * 32
  42. assert (
  43. group.get_oldest_event_for_environments(["staging", "production"]).event_id == "a" * 32
  44. )
  45. assert group.get_oldest_event_for_environments(["staging"]) is None
  46. def test_perf_issue(self):
  47. group_fingerprint = f"{PerformanceNPlusOneGroupType.type_id}-group1"
  48. event_data_1 = load_data("transaction-n-plus-one", fingerprint=[group_fingerprint])
  49. event_data_1["timestamp"] = iso_format(before_now(seconds=10))
  50. event_data_1["start_timestamp"] = iso_format(before_now(seconds=11))
  51. event_data_1["event_id"] = "d" * 32
  52. event_data_2 = load_data("transaction-n-plus-one", fingerprint=[group_fingerprint])
  53. event_data_2["timestamp"] = iso_format(before_now(seconds=20))
  54. event_data_2["start_timestamp"] = iso_format(before_now(seconds=21))
  55. event_data_2["event_id"] = "f" * 32
  56. event_data_3 = load_data("transaction-n-plus-one", fingerprint=[group_fingerprint])
  57. event_data_3["timestamp"] = iso_format(before_now(seconds=30))
  58. event_data_3["start_timestamp"] = iso_format(before_now(seconds=31))
  59. event_data_3["event_id"] = "f" * 32
  60. transaction_event_1 = self.create_performance_issue(
  61. event_data=event_data_1, fingerprint=group_fingerprint
  62. )
  63. self.create_performance_issue(event_data=event_data_2, fingerprint=group_fingerprint)
  64. self.create_performance_issue(event_data=event_data_3, fingerprint=group_fingerprint)
  65. perf_group = transaction_event_1.group
  66. assert perf_group.get_latest_event_for_environments().event_id == "d" * 32
  67. assert perf_group.get_oldest_event_for_environments().event_id == "f" * 32
  68. def test_error_issue_get_helpful_for_environments(self):
  69. project = self.create_project()
  70. min_ago = iso_format(before_now(minutes=1))
  71. replay_id = uuid.uuid4().hex
  72. event_all_helpful_params = self.store_event(
  73. data={
  74. "event_id": "a" * 32,
  75. "timestamp": min_ago,
  76. "fingerprint": ["group-1"],
  77. "contexts": {
  78. "replay": {"replay_id": replay_id},
  79. "trace": {
  80. "sampled": True,
  81. "span_id": "babaae0d4b7512d9",
  82. "trace_id": "a7d67cf796774551a95be6543cacd459",
  83. },
  84. },
  85. "errors": [],
  86. },
  87. project_id=project.id,
  88. assert_no_errors=False,
  89. )
  90. self.store_event(
  91. data={
  92. "event_id": "b" * 32,
  93. "timestamp": min_ago,
  94. "fingerprint": ["group-1"],
  95. "contexts": {
  96. "replay": {"replay_id": replay_id},
  97. },
  98. "errors": [{"type": "one"}, {"type": "two"}],
  99. },
  100. project_id=project.id,
  101. assert_no_errors=False,
  102. )
  103. event_none_helpful_params = self.store_event(
  104. data={"event_id": "c" * 32, "timestamp": min_ago, "fingerprint": ["group-1"]},
  105. project_id=project.id,
  106. )
  107. group = Group.objects.first()
  108. assert (
  109. group.get_recommended_event_for_environments().event_id
  110. == event_all_helpful_params.event_id
  111. )
  112. assert (
  113. group.get_latest_event_for_environments().event_id == event_none_helpful_params.event_id
  114. )
  115. assert (
  116. group.get_oldest_event_for_environments().event_id == event_all_helpful_params.event_id
  117. )
  118. def test_perf_issue_helpful(self):
  119. group_fingerprint = f"{PerformanceNPlusOneGroupType.type_id}-group1"
  120. transaction_event_data_with_all_helpful = load_data(
  121. "transaction-n-plus-one", fingerprint=[group_fingerprint]
  122. )
  123. transaction_event_data_with_all_helpful["timestamp"] = iso_format(before_now(seconds=10))
  124. transaction_event_data_with_all_helpful["start_timestamp"] = iso_format(
  125. before_now(seconds=11)
  126. )
  127. transaction_event_data_with_all_helpful["event_id"] = "d" * 32
  128. transaction_event_data_with_all_helpful["contexts"].update(
  129. {"profile": {"profile_id": uuid.uuid4().hex}}
  130. )
  131. transaction_event_data_with_all_helpful["contexts"].update(
  132. {"replay": {"replay_id": uuid.uuid4().hex}}
  133. )
  134. transaction_event_data_with_all_helpful["contexts"]["trace"]["sampled"] = True
  135. transaction_event_data_with_all_helpful["errors"] = []
  136. transaction_event_data_with_none_helpful = load_data(
  137. "transaction-n-plus-one", fingerprint=[group_fingerprint]
  138. )
  139. transaction_event_data_with_none_helpful["timestamp"] = iso_format(before_now(seconds=20))
  140. transaction_event_data_with_none_helpful["start_timestamp"] = iso_format(
  141. before_now(seconds=21)
  142. )
  143. transaction_event_data_with_none_helpful["event_id"] = "f" * 32
  144. transaction_event_1 = self.create_performance_issue(
  145. event_data=transaction_event_data_with_all_helpful, fingerprint=group_fingerprint
  146. )
  147. transaction_event_2 = self.create_performance_issue(
  148. event_data=transaction_event_data_with_none_helpful, fingerprint=group_fingerprint
  149. )
  150. perf_group = transaction_event_1.group
  151. assert (
  152. perf_group.get_recommended_event_for_environments().event_id
  153. == transaction_event_1.event_id
  154. )
  155. assert (
  156. perf_group.get_latest_event_for_environments().event_id == transaction_event_1.event_id
  157. )
  158. assert (
  159. perf_group.get_oldest_event_for_environments().event_id == transaction_event_2.event_id
  160. )
  161. def test_profile_issue_helpful(self):
  162. event_id_1 = uuid.uuid4().hex
  163. occurrence, _ = self.process_occurrence(
  164. event_id=event_id_1,
  165. project_id=self.project.id,
  166. event_data={
  167. "fingerprint": ["group-1"],
  168. "timestamp": before_now(minutes=2).isoformat(),
  169. "contexts": {
  170. "profile": {"profile_id": uuid.uuid4().hex},
  171. "replay": {"replay_id": uuid.uuid4().hex},
  172. "trace": {
  173. "sampled": True,
  174. "span_id": "babaae0d4b7512d9",
  175. "trace_id": "a7d67cf796774551a95be6543cacd459",
  176. },
  177. },
  178. "errors": [],
  179. },
  180. )
  181. event_id_2 = uuid.uuid4().hex
  182. occurrence_2, _ = self.process_occurrence(
  183. event_id=event_id_2,
  184. project_id=self.project.id,
  185. event_data={
  186. "fingerprint": ["group-1"],
  187. "timestamp": before_now(minutes=1).isoformat(),
  188. },
  189. )
  190. group = Group.objects.first()
  191. group.update(type=ProfileFileIOGroupType.type_id)
  192. group_event = group.get_recommended_event_for_environments()
  193. assert group_event.event_id == occurrence.event_id
  194. self.assert_occurrences_identical(group_event.occurrence, occurrence)
  195. assert group.get_latest_event_for_environments().event_id == occurrence_2.event_id
  196. assert group.get_oldest_event_for_environments().event_id == occurrence.event_id
  197. @patch("sentry.quotas.backend.get_event_retention")
  198. def test_get_recommended_event_for_environments_retention_limit(self, mock_get_event_retention):
  199. """
  200. If last_seen is outside of the retention limit, falls back to the latest event behavior.
  201. """
  202. mock_get_event_retention.return_value = 90
  203. project = self.create_project()
  204. outside_retention_date = before_now(days=91)
  205. event = self.store_event(
  206. data={
  207. "event_id": "a" * 32,
  208. "timestamp": iso_format(outside_retention_date),
  209. "fingerprint": ["group-1"],
  210. "contexts": {},
  211. "errors": [],
  212. },
  213. project_id=project.id,
  214. assert_no_errors=False,
  215. )
  216. group = Group.objects.first()
  217. group.last_seen = before_now(days=91)
  218. assert group.get_recommended_event_for_environments().event_id == event.event_id