test_organization_events_geo.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. from django.urls import reverse
  2. from sentry.testutils import APITestCase, SnubaTestCase
  3. from sentry.testutils.helpers.datetime import before_now, iso_format
  4. class OrganizationEventsGeoEndpointTest(APITestCase, SnubaTestCase):
  5. def setUp(self):
  6. super().setUp()
  7. self.min_ago = iso_format(before_now(minutes=1))
  8. self.features = {}
  9. def do_request(self, query, features=None):
  10. if features is None:
  11. features = {"organizations:dashboards-basic": True}
  12. features.update(self.features)
  13. self.login_as(user=self.user)
  14. url = reverse(
  15. "sentry-api-0-organization-events-geo",
  16. kwargs={"organization_slug": self.organization.slug},
  17. )
  18. with self.feature(features):
  19. return self.client.get(url, query, format="json")
  20. def test_no_projects(self):
  21. response = self.do_request({})
  22. assert response.status_code == 200, response.data
  23. assert len(response.data) == 0
  24. def test_no_field(self):
  25. query = {
  26. "field": [],
  27. "project": [self.project.id],
  28. }
  29. response = self.do_request(query)
  30. assert response.status_code == 400
  31. assert response.data["detail"] == "No column selected"
  32. def test_require_aggregate_field(self):
  33. query = {
  34. "field": ["i_am_a_tag"],
  35. "project": [self.project.id],
  36. }
  37. response = self.do_request(query)
  38. assert response.status_code == 400
  39. assert response.data["detail"] == "Functions may only be given"
  40. def test_happy_path(self):
  41. other_project = self.create_project()
  42. self.store_event(
  43. data={"event_id": "a" * 32, "environment": "staging", "timestamp": self.min_ago},
  44. project_id=self.project.id,
  45. )
  46. self.store_event(
  47. data={"event_id": "b" * 32, "environment": "staging", "timestamp": self.min_ago},
  48. project_id=other_project.id,
  49. )
  50. self.store_event(
  51. data={
  52. "event_id": "c" * 32,
  53. "environment": "production",
  54. "timestamp": self.min_ago,
  55. "user": {
  56. "email": "foo@example.com",
  57. "id": "123",
  58. "ip_address": "127.0.0.1",
  59. "username": "foo",
  60. "geo": {"country_code": "CA", "region": "Canada"},
  61. },
  62. },
  63. project_id=self.project.id,
  64. )
  65. query = {
  66. "project": [self.project.id],
  67. "field": ["count()"],
  68. "statsPeriod": "24h",
  69. }
  70. response = self.do_request(query)
  71. assert response.status_code == 200, response.data
  72. assert len(response.data["data"]) == 1
  73. assert response.data["data"] == [{"count": 1, "geo.country_code": "CA"}]
  74. # Expect no pagination
  75. assert "Link" not in response
  76. def test_only_use_last_field(self):
  77. self.store_event(
  78. data={
  79. "event_id": "a" * 32,
  80. "environment": "staging",
  81. "timestamp": self.min_ago,
  82. "user": {
  83. "email": "foo@example.com",
  84. "id": "123",
  85. "ip_address": "127.0.0.1",
  86. "username": "foo",
  87. "geo": {"country_code": "CA", "region": "Canada"},
  88. },
  89. },
  90. project_id=self.project.id,
  91. )
  92. query = {
  93. "project": [self.project.id],
  94. "field": ["p75()", "count()"],
  95. "statsPeriod": "24h",
  96. }
  97. response = self.do_request(query)
  98. assert response.status_code == 200, response.data
  99. assert len(response.data["data"]) == 1
  100. assert response.data["data"] == [{"count": 1, "geo.country_code": "CA"}]
  101. def test_orderby(self):
  102. def get_mock_data(index, geo):
  103. return {
  104. "event_id": str(index) * 32,
  105. "environment": "staging",
  106. "timestamp": self.min_ago,
  107. "user": {
  108. "email": "foo@example.com",
  109. "id": "123",
  110. "ip_address": "127.0.0.1",
  111. "username": "foo",
  112. "geo": geo,
  113. },
  114. }
  115. self.store_event(
  116. data=get_mock_data(0, {"country_code": "CA", "region": "Canada"}),
  117. project_id=self.project.id,
  118. )
  119. self.store_event(
  120. data=get_mock_data(1, {"country_code": "BR", "region": "Brazil"}),
  121. project_id=self.project.id,
  122. )
  123. self.store_event(
  124. data=get_mock_data(2, {"country_code": "BR", "region": "Brazil"}),
  125. project_id=self.project.id,
  126. )
  127. self.store_event(
  128. data=get_mock_data(3, {"country_code": "BR", "region": "Brazil"}),
  129. project_id=self.project.id,
  130. )
  131. self.store_event(
  132. data=get_mock_data(4, {"country_code": "JP", "region": "Japan"}),
  133. project_id=self.project.id,
  134. )
  135. self.store_event(
  136. data=get_mock_data(5, {"country_code": "JP", "region": "Japan"}),
  137. project_id=self.project.id,
  138. )
  139. query = {
  140. "project": [self.project.id],
  141. "field": ["count()"],
  142. "statsPeriod": "24h",
  143. "sort": "-count",
  144. }
  145. response = self.do_request(query)
  146. assert response.status_code == 200, response.data
  147. assert len(response.data["data"]) == 3
  148. assert response.data["data"] == [
  149. {"count": 3, "geo.country_code": "BR"},
  150. {"count": 2, "geo.country_code": "JP"},
  151. {"count": 1, "geo.country_code": "CA"},
  152. ]
  153. query = {
  154. "project": [self.project.id],
  155. "field": ["count()"],
  156. "statsPeriod": "24h",
  157. }
  158. response = self.do_request(query)
  159. assert response.status_code == 200, response.data
  160. assert len(response.data["data"]) == 3
  161. assert response.data["data"] == [
  162. {"count": 1, "geo.country_code": "CA"},
  163. {"count": 2, "geo.country_code": "JP"},
  164. {"count": 3, "geo.country_code": "BR"},
  165. ]
  166. class OrganizationEventsGeoEndpointTestWithSnql(OrganizationEventsGeoEndpointTest):
  167. def setUp(self):
  168. super().setUp()
  169. self.features["organizations:discover-use-snql"] = True