test_group_events.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. from datetime import timedelta
  2. from django.utils import timezone
  3. from freezegun import freeze_time
  4. from sentry.testutils import APITestCase, SnubaTestCase
  5. from sentry.testutils.helpers.datetime import before_now, iso_format
  6. class GroupEventsTest(APITestCase, SnubaTestCase):
  7. def setUp(self):
  8. super().setUp()
  9. self.min_ago = before_now(minutes=1)
  10. def test_simple(self):
  11. self.login_as(user=self.user)
  12. event_1 = self.store_event(
  13. data={
  14. "event_id": "a" * 32,
  15. "fingerprint": ["1"],
  16. "timestamp": iso_format(self.min_ago),
  17. },
  18. project_id=self.project.id,
  19. )
  20. event_2 = self.store_event(
  21. data={
  22. "event_id": "b" * 32,
  23. "fingerprint": ["1"],
  24. "timestamp": iso_format(self.min_ago),
  25. },
  26. project_id=self.project.id,
  27. )
  28. url = f"/api/0/issues/{event_1.group.id}/events/"
  29. response = self.client.get(url, format="json")
  30. assert response.status_code == 200, response.content
  31. assert len(response.data) == 2
  32. assert sorted(map(lambda x: x["eventID"], response.data)) == sorted(
  33. [str(event_1.event_id), str(event_2.event_id)]
  34. )
  35. def test_tags(self):
  36. self.login_as(user=self.user)
  37. event_1 = self.store_event(
  38. data={
  39. "event_id": "a" * 32,
  40. "fingerprint": ["1"],
  41. "tags": {"foo": "baz", "bar": "buz"},
  42. "timestamp": iso_format(self.min_ago),
  43. },
  44. project_id=self.project.id,
  45. )
  46. event_2 = self.store_event(
  47. data={
  48. "event_id": "b" * 32,
  49. "fingerprint": ["1"],
  50. "tags": {"bar": "biz"},
  51. "timestamp": iso_format(before_now(seconds=61)),
  52. },
  53. project_id=self.project.id,
  54. )
  55. url = f"/api/0/issues/{event_1.group.id}/events/"
  56. response = self.client.get(url + "?query=foo:baz", format="json")
  57. assert response.status_code == 200, response.content
  58. assert len(response.data) == 1
  59. assert response.data[0]["eventID"] == str(event_1.event_id)
  60. response = self.client.get(url + "?query=!foo:baz", format="json")
  61. assert response.status_code == 200, response.content
  62. assert len(response.data) == 1
  63. assert response.data[0]["eventID"] == str(event_2.event_id)
  64. response = self.client.get(url + "?query=bar:biz", format="json")
  65. assert response.status_code == 200, response.content
  66. assert len(response.data) == 1
  67. assert response.data[0]["eventID"] == str(event_2.event_id)
  68. response = self.client.get(url + "?query=bar:biz%20foo:baz", format="json")
  69. assert response.status_code == 200, response.content
  70. assert len(response.data) == 0
  71. response = self.client.get(url + "?query=bar:buz%20foo:baz", format="json")
  72. assert response.status_code == 200, response.content
  73. assert len(response.data) == 1
  74. assert response.data[0]["eventID"] == str(event_1.event_id)
  75. response = self.client.get(url + "?query=bar:baz", format="json")
  76. assert response.status_code == 200, response.content
  77. assert len(response.data) == 0
  78. response = self.client.get(url + "?query=a:b", format="json")
  79. assert response.status_code == 200, response.content
  80. assert len(response.data) == 0
  81. response = self.client.get(url + "?query=bar:b", format="json")
  82. assert response.status_code == 200, response.content
  83. assert len(response.data) == 0
  84. response = self.client.get(url + "?query=bar:baz", format="json")
  85. assert response.status_code == 200, response.content
  86. assert len(response.data) == 0
  87. response = self.client.get(url + "?query=!bar:baz", format="json")
  88. assert response.status_code == 200, response.content
  89. assert len(response.data) == 2
  90. assert {e["eventID"] for e in response.data} == {event_1.event_id, event_2.event_id}
  91. def test_search_event_by_id(self):
  92. self.login_as(user=self.user)
  93. event_1 = self.store_event(
  94. data={
  95. "event_id": "a" * 32,
  96. "fingerprint": ["group-1"],
  97. "timestamp": iso_format(self.min_ago),
  98. },
  99. project_id=self.project.id,
  100. )
  101. self.store_event(
  102. data={
  103. "event_id": "b" * 32,
  104. "fingerprint": ["group-1"],
  105. "timestamp": iso_format(self.min_ago),
  106. },
  107. project_id=self.project.id,
  108. )
  109. url = f"/api/0/issues/{event_1.group.id}/events/?query={event_1.event_id}"
  110. response = self.client.get(url, format="json")
  111. assert response.status_code == 200, response.content
  112. assert len(response.data) == 1
  113. assert response.data[0]["eventID"] == event_1.event_id
  114. def test_search_event_by_message(self):
  115. self.login_as(user=self.user)
  116. event_1 = self.store_event(
  117. data={
  118. "event_id": "a" * 32,
  119. "fingerprint": ["group-1"],
  120. "message": "foo bar hello world",
  121. "timestamp": iso_format(self.min_ago),
  122. },
  123. project_id=self.project.id,
  124. )
  125. group = event_1.group
  126. event_2 = self.store_event(
  127. data={
  128. "event_id": "b" * 32,
  129. "fingerprint": ["group-1"],
  130. "message": "this bar hello world",
  131. "timestamp": iso_format(self.min_ago),
  132. },
  133. project_id=self.project.id,
  134. )
  135. assert group == event_2.group
  136. query_1 = "foo"
  137. query_2 = "hello+world"
  138. # Single Word Query
  139. url = f"/api/0/issues/{group.id}/events/?query={query_1}"
  140. response = self.client.get(url, format="json")
  141. assert response.status_code == 200, response.content
  142. assert len(response.data) == 1
  143. assert response.data[0]["eventID"] == event_1.event_id
  144. # Multiple Word Query
  145. url = f"/api/0/issues/{group.id}/events/?query={query_2}"
  146. response = self.client.get(url, format="json")
  147. assert response.status_code == 200, response.content
  148. assert len(response.data) == 2
  149. assert sorted(map(lambda x: x["eventID"], response.data)) == sorted(
  150. [str(event_1.event_id), str(event_2.event_id)]
  151. )
  152. def test_search_by_release(self):
  153. self.login_as(user=self.user)
  154. self.create_release(self.project, version="first-release")
  155. event_1 = self.store_event(
  156. data={
  157. "event_id": "a" * 32,
  158. "fingerprint": ["group-1"],
  159. "timestamp": iso_format(self.min_ago),
  160. "release": "first-release",
  161. },
  162. project_id=self.project.id,
  163. )
  164. url = f"/api/0/issues/{event_1.group.id}/events/?query=release:latest"
  165. response = self.client.get(url, format="json")
  166. assert response.status_code == 200, response.content
  167. assert len(response.data) == 1
  168. assert response.data[0]["eventID"] == event_1.event_id
  169. def test_environment(self):
  170. self.login_as(user=self.user)
  171. events = {}
  172. for name in ["production", "development"]:
  173. events[name] = self.store_event(
  174. data={
  175. "fingerprint": ["put-me-in-group1"],
  176. "timestamp": iso_format(self.min_ago),
  177. "environment": name,
  178. },
  179. project_id=self.project.id,
  180. )
  181. # Asserts that all are in the same group
  182. (group_id,) = {e.group.id for e in events.values()}
  183. url = f"/api/0/issues/{group_id}/events/"
  184. response = self.client.get(url + "?environment=production", format="json")
  185. assert response.status_code == 200, response.content
  186. assert set(map(lambda x: x["eventID"], response.data)) == {
  187. str(events["production"].event_id)
  188. }
  189. response = self.client.get(
  190. url, data={"environment": ["production", "development"]}, format="json"
  191. )
  192. assert response.status_code == 200, response.content
  193. assert set(map(lambda x: x["eventID"], response.data)) == {
  194. str(event.event_id) for event in events.values()
  195. }
  196. response = self.client.get(url + "?environment=invalid", format="json")
  197. assert response.status_code == 200, response.content
  198. assert response.data == []
  199. response = self.client.get(
  200. url + "?environment=production&query=environment:development", format="json"
  201. )
  202. assert response.status_code == 200, response.content
  203. assert response.data == []
  204. def test_filters_based_on_retention(self):
  205. self.login_as(user=self.user)
  206. self.store_event(
  207. data={"fingerprint": ["group_1"], "timestamp": iso_format(before_now(days=2))},
  208. project_id=self.project.id,
  209. )
  210. event_2 = self.store_event(
  211. data={"fingerprint": ["group_1"], "timestamp": iso_format(self.min_ago)},
  212. project_id=self.project.id,
  213. )
  214. group = event_2.group
  215. with self.options({"system.event-retention-days": 1}):
  216. response = self.client.get(f"/api/0/issues/{group.id}/events/")
  217. assert response.status_code == 200, response.content
  218. assert len(response.data) == 1
  219. assert sorted(map(lambda x: x["eventID"], response.data)) == sorted([str(event_2.event_id)])
  220. def test_search_event_has_tags(self):
  221. self.login_as(user=self.user)
  222. event = self.store_event(
  223. data={
  224. "timestamp": iso_format(self.min_ago),
  225. "message": "foo",
  226. "tags": {"logger": "python"},
  227. },
  228. project_id=self.project.id,
  229. )
  230. response = self.client.get(f"/api/0/issues/{event.group.id}/events/")
  231. assert response.status_code == 200, response.content
  232. assert len(response.data) == 1
  233. assert {"key": "logger", "value": "python"} in response.data[0]["tags"]
  234. @freeze_time()
  235. def test_date_filters(self):
  236. self.login_as(user=self.user)
  237. event_1 = self.store_event(
  238. data={"timestamp": iso_format(before_now(days=5)), "fingerprint": ["group-1"]},
  239. project_id=self.project.id,
  240. )
  241. event_2 = self.store_event(
  242. data={"timestamp": iso_format(before_now(days=1)), "fingerprint": ["group-1"]},
  243. project_id=self.project.id,
  244. )
  245. group = event_1.group
  246. assert group == event_2.group
  247. response = self.client.get(f"/api/0/issues/{group.id}/events/", data={"statsPeriod": "6d"})
  248. assert response.status_code == 200, response.content
  249. assert len(response.data) == 2
  250. assert sorted(map(lambda x: x["eventID"], response.data)) == sorted(
  251. [str(event_1.event_id), str(event_2.event_id)]
  252. )
  253. response = self.client.get(f"/api/0/issues/{group.id}/events/", data={"statsPeriod": "2d"})
  254. assert response.status_code == 200, response.content
  255. assert len(response.data) == 1
  256. assert response.data[0]["eventID"] == str(event_2.event_id)
  257. def test_invalid_period(self):
  258. self.login_as(user=self.user)
  259. first_seen = timezone.now() - timedelta(days=5)
  260. group = self.create_group(first_seen=first_seen)
  261. response = self.client.get(f"/api/0/issues/{group.id}/events/", data={"statsPeriod": "lol"})
  262. assert response.status_code == 400
  263. def test_invalid_query(self):
  264. self.login_as(user=self.user)
  265. first_seen = timezone.now() - timedelta(days=5)
  266. group = self.create_group(first_seen=first_seen)
  267. response = self.client.get(
  268. f"/api/0/issues/{group.id}/events/",
  269. data={"statsPeriod": "7d", "query": "foo(bar"},
  270. )
  271. assert response.status_code == 400
  272. def test_multiple_group(self):
  273. self.login_as(user=self.user)
  274. event_1 = self.store_event(
  275. data={
  276. "fingerprint": ["group_1"],
  277. "event_id": "a" * 32,
  278. "message": "foo",
  279. "timestamp": iso_format(self.min_ago),
  280. },
  281. project_id=self.project.id,
  282. )
  283. event_2 = self.store_event(
  284. data={
  285. "fingerprint": ["group_2"],
  286. "event_id": "b" * 32,
  287. "message": "group2",
  288. "timestamp": iso_format(self.min_ago),
  289. },
  290. project_id=self.project.id,
  291. )
  292. for event in (event_1, event_2):
  293. url = f"/api/0/issues/{event.group.id}/events/"
  294. response = self.client.get(url, format="json")
  295. assert response.status_code == 200, response.content
  296. assert len(response.data) == 1, response.data
  297. assert list(map(lambda x: x["eventID"], response.data)) == [str(event.event_id)]