test_group.py 9.9 KB

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