test_organization_metrics_meta.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. import pytest
  2. from django.urls import reverse
  3. from sentry.testutils import MetricsEnhancedPerformanceTestCase
  4. from sentry.testutils.helpers.datetime import before_now, iso_format
  5. from sentry.testutils.silo import region_silo_test
  6. pytestmark = pytest.mark.sentry_metrics
  7. @region_silo_test
  8. class OrganizationMetricsCompatiblity(MetricsEnhancedPerformanceTestCase):
  9. def setUp(self):
  10. super().setUp()
  11. self.min_ago = before_now(minutes=1)
  12. self.two_min_ago = before_now(minutes=2)
  13. self.features = {
  14. "organizations:performance-use-metrics": True,
  15. }
  16. self.login_as(user=self.user)
  17. self.project.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
  18. # Don't create any txn on this, don't set its DS rules, it shouldn't show up anywhere
  19. self.bad_project = self.create_project()
  20. def test_unparameterized_transactions(self):
  21. # Make current project incompatible
  22. self.store_transaction_metric(
  23. 1, tags={"transaction": "<< unparameterized >>"}, timestamp=self.min_ago
  24. )
  25. url = reverse(
  26. "sentry-api-0-organization-metrics-compatibility",
  27. kwargs={"organization_slug": self.project.organization.slug},
  28. )
  29. response = self.client.get(url, format="json")
  30. assert response.status_code == 200, response.content
  31. assert response.data["incompatible_projects"] == [self.project.id, self.bad_project.id]
  32. assert response.data["compatible_projects"] == []
  33. assert response.data["dynamic_sampling_projects"] == [self.project.id]
  34. def test_null_transaction(self):
  35. # Make current project incompatible
  36. self.store_transaction_metric(1, tags={}, timestamp=self.min_ago)
  37. url = reverse(
  38. "sentry-api-0-organization-metrics-compatibility",
  39. kwargs={"organization_slug": self.project.organization.slug},
  40. )
  41. response = self.client.get(url, format="json")
  42. assert response.status_code == 200, response.content
  43. assert response.data["incompatible_projects"] == [self.project.id, self.bad_project.id]
  44. assert response.data["compatible_projects"] == []
  45. assert response.data["dynamic_sampling_projects"] == [self.project.id]
  46. def test_no_transaction(self):
  47. # Make current project incompatible by having nothing
  48. url = reverse(
  49. "sentry-api-0-organization-metrics-compatibility",
  50. kwargs={"organization_slug": self.project.organization.slug},
  51. )
  52. response = self.client.get(url, format="json")
  53. assert response.status_code == 200, response.content
  54. assert response.data["incompatible_projects"] == [self.project.id, self.bad_project.id]
  55. assert response.data["compatible_projects"] == []
  56. assert response.data["dynamic_sampling_projects"] == [self.project.id]
  57. def test_has_transaction(self):
  58. self.store_transaction_metric(
  59. 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago
  60. )
  61. url = reverse(
  62. "sentry-api-0-organization-metrics-compatibility",
  63. kwargs={"organization_slug": self.project.organization.slug},
  64. )
  65. response = self.client.get(url, format="json")
  66. assert response.status_code == 200, response.content
  67. assert response.data["incompatible_projects"] == [self.bad_project.id]
  68. assert response.data["compatible_projects"] == [self.project.id]
  69. assert response.data["dynamic_sampling_projects"] == [self.project.id]
  70. def test_multiple_projects(self):
  71. project2 = self.create_project()
  72. project2.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
  73. project3 = self.create_project()
  74. project3.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
  75. # Not setting DS, it shouldn't show up
  76. project4 = self.create_project()
  77. self.store_transaction_metric(
  78. 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago
  79. )
  80. self.store_transaction_metric(
  81. 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago, project=project4.id
  82. )
  83. self.store_transaction_metric(
  84. 1,
  85. tags={"transaction": "<< unparameterized >>"},
  86. timestamp=self.min_ago,
  87. project=project2.id,
  88. )
  89. self.store_transaction_metric(
  90. 1,
  91. tags={},
  92. timestamp=self.min_ago,
  93. project=project3.id,
  94. )
  95. self.store_event(
  96. data={"timestamp": iso_format(self.min_ago), "transaction": "foo_transaction"},
  97. project_id=self.project.id,
  98. )
  99. url = reverse(
  100. "sentry-api-0-organization-metrics-compatibility",
  101. kwargs={"organization_slug": self.project.organization.slug},
  102. )
  103. response = self.client.get(url, format="json")
  104. assert response.status_code == 200, response.content
  105. assert response.data["incompatible_projects"] == sorted(
  106. [project2.id, project3.id, project4.id, self.bad_project.id]
  107. )
  108. assert response.data["compatible_projects"] == [self.project.id]
  109. assert response.data["dynamic_sampling_projects"] == [
  110. self.project.id,
  111. project2.id,
  112. project3.id,
  113. ]
  114. def test_no_ds(self):
  115. url = reverse(
  116. "sentry-api-0-organization-metrics-compatibility",
  117. kwargs={"organization_slug": self.project.organization.slug},
  118. )
  119. response = self.client.get(url, data={"project": [self.bad_project.id]}, format="json")
  120. assert response.status_code == 200, response.content
  121. assert response.data["dynamic_sampling_projects"] == []
  122. assert response.data["incompatible_projects"] == []
  123. assert response.data["compatible_projects"] == []
  124. @region_silo_test
  125. class OrganizationEventsMetricsSums(MetricsEnhancedPerformanceTestCase):
  126. def setUp(self):
  127. super().setUp()
  128. self.min_ago = before_now(minutes=1)
  129. self.two_min_ago = before_now(minutes=2)
  130. self.features = {
  131. "organizations:performance-use-metrics": True,
  132. }
  133. self.login_as(user=self.user)
  134. self.project.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
  135. # Don't create any txn on this, don't set its DS rules, it shouldn't show up anywhere
  136. self.create_project()
  137. def test_unparameterized_transactions(self):
  138. # Make current project incompatible
  139. self.store_transaction_metric(
  140. 1, tags={"transaction": "<< unparameterized >>"}, timestamp=self.min_ago
  141. )
  142. url = reverse(
  143. "sentry-api-0-organization-metrics-compatibility-sums",
  144. kwargs={"organization_slug": self.project.organization.slug},
  145. )
  146. response = self.client.get(url, format="json")
  147. assert response.status_code == 200, response.content
  148. assert response.data["sum"]["metrics"] == 1
  149. assert response.data["sum"]["metrics_unparam"] == 1
  150. assert response.data["sum"]["metrics_null"] == 0
  151. def test_null_transaction(self):
  152. # Make current project incompatible
  153. self.store_transaction_metric(1, tags={}, timestamp=self.min_ago)
  154. url = reverse(
  155. "sentry-api-0-organization-metrics-compatibility-sums",
  156. kwargs={"organization_slug": self.project.organization.slug},
  157. )
  158. response = self.client.get(url, format="json")
  159. assert response.status_code == 200, response.content
  160. assert response.data["sum"]["metrics"] == 1
  161. assert response.data["sum"]["metrics_unparam"] == 0
  162. assert response.data["sum"]["metrics_null"] == 1
  163. def test_no_transaction(self):
  164. # Make current project incompatible by having nothing
  165. url = reverse(
  166. "sentry-api-0-organization-metrics-compatibility-sums",
  167. kwargs={"organization_slug": self.project.organization.slug},
  168. )
  169. response = self.client.get(url, format="json")
  170. assert response.status_code == 200, response.content
  171. assert response.data["sum"]["metrics"] == 0
  172. assert response.data["sum"]["metrics_unparam"] == 0
  173. assert response.data["sum"]["metrics_null"] == 0
  174. def test_has_transaction(self):
  175. self.store_transaction_metric(
  176. 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago
  177. )
  178. url = reverse(
  179. "sentry-api-0-organization-metrics-compatibility-sums",
  180. kwargs={"organization_slug": self.project.organization.slug},
  181. )
  182. response = self.client.get(url, format="json")
  183. assert response.status_code == 200, response.content
  184. assert response.data["sum"]["metrics"] == 1
  185. assert response.data["sum"]["metrics_unparam"] == 0
  186. assert response.data["sum"]["metrics_null"] == 0
  187. def test_multiple_projects(self):
  188. project2 = self.create_project()
  189. project2.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
  190. project3 = self.create_project()
  191. project3.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
  192. # Not setting DS, it shouldn't show up
  193. project4 = self.create_project()
  194. self.store_transaction_metric(
  195. 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago
  196. )
  197. self.store_transaction_metric(
  198. 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago, project=project4.id
  199. )
  200. self.store_transaction_metric(
  201. 1,
  202. tags={"transaction": "<< unparameterized >>"},
  203. timestamp=self.min_ago,
  204. project=project2.id,
  205. )
  206. self.store_transaction_metric(
  207. 1,
  208. tags={},
  209. timestamp=self.min_ago,
  210. project=project3.id,
  211. )
  212. self.store_event(
  213. data={"timestamp": iso_format(self.min_ago), "transaction": "foo_transaction"},
  214. project_id=self.project.id,
  215. )
  216. url = reverse(
  217. "sentry-api-0-organization-events-metrics-compatibility",
  218. kwargs={"organization_slug": self.project.organization.slug},
  219. )
  220. response = self.client.get(url, format="json")
  221. assert response.status_code == 200, response.content
  222. # project 4 shouldn't show up in these sums
  223. assert response.data["sum"]["metrics"] == 3
  224. assert response.data["sum"]["metrics_unparam"] == 1
  225. assert response.data["sum"]["metrics_null"] == 1
  226. def test_counts_add_up_correctly(self):
  227. # Make current project incompatible
  228. for _ in range(2):
  229. self.store_transaction_metric(
  230. 1, tags={"transaction": "<< unparameterized >>"}, timestamp=self.min_ago
  231. )
  232. for _ in range(3):
  233. self.store_transaction_metric(1, tags={}, timestamp=self.min_ago)
  234. for _ in range(1):
  235. self.store_transaction_metric(1, tags={"transaction": "/foo"}, timestamp=self.min_ago)
  236. url = reverse(
  237. "sentry-api-0-organization-events-metrics-compatibility",
  238. kwargs={"organization_slug": self.project.organization.slug},
  239. )
  240. response = self.client.get(url, format="json")
  241. assert response.status_code == 200, response.content
  242. assert response.data["compatible_projects"] == []
  243. assert response.data["dynamic_sampling_projects"] == [self.project.id]
  244. assert response.data["sum"]["metrics"] == 6
  245. assert response.data["sum"]["metrics_unparam"] == 2
  246. assert response.data["sum"]["metrics_null"] == 3