test_group_events.py 13 KB

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