test_organization_tags.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. from unittest import mock
  2. from django.urls import reverse
  3. from sentry.testutils.cases import APITestCase, SnubaTestCase
  4. from sentry.testutils.helpers import apply_feature_flag_on_cls
  5. from sentry.testutils.helpers.datetime import before_now, iso_format
  6. from sentry.testutils.silo import region_silo_test
  7. @region_silo_test
  8. @apply_feature_flag_on_cls("organizations:javascript-console-error-tag")
  9. class OrganizationTagsTest(APITestCase, SnubaTestCase):
  10. def setUp(self):
  11. super().setUp()
  12. self.min_ago = iso_format(before_now(minutes=1))
  13. def test_simple(self):
  14. user = self.create_user()
  15. org = self.create_organization()
  16. team = self.create_team(organization=org)
  17. self.create_member(organization=org, user=user, teams=[team])
  18. self.login_as(user=user)
  19. project = self.create_project(organization=org, teams=[team])
  20. self.store_event(
  21. data={"event_id": "a" * 32, "tags": {"fruit": "apple"}, "timestamp": self.min_ago},
  22. project_id=project.id,
  23. )
  24. self.store_event(
  25. data={"event_id": "b" * 32, "tags": {"fruit": "orange"}, "timestamp": self.min_ago},
  26. project_id=project.id,
  27. )
  28. self.store_event(
  29. data={
  30. "event_id": "c" * 32,
  31. "tags": {"some_tag": "some_value"},
  32. "timestamp": self.min_ago,
  33. },
  34. project_id=project.id,
  35. )
  36. self.store_event(
  37. data={"event_id": "d" * 32, "tags": {"fruit": "orange"}, "timestamp": self.min_ago},
  38. project_id=project.id,
  39. )
  40. url = reverse("sentry-api-0-organization-tags", kwargs={"organization_slug": org.slug})
  41. response = self.client.get(url, format="json")
  42. assert response.status_code == 200, response.content
  43. data = response.data
  44. data.sort(key=lambda val: val["totalValues"], reverse=True)
  45. assert data == [
  46. {"name": "Level", "key": "level", "totalValues": 4},
  47. {"name": "Fruit", "key": "fruit", "totalValues": 3},
  48. {"name": "Some Tag", "key": "some_tag", "totalValues": 1},
  49. ]
  50. def test_no_projects(self):
  51. user = self.create_user()
  52. org = self.create_organization(owner=user)
  53. self.login_as(user=user)
  54. url = reverse("sentry-api-0-organization-tags", kwargs={"organization_slug": org.slug})
  55. response = self.client.get(url, format="json")
  56. assert response.status_code == 200, response.content
  57. assert response.data == []
  58. @mock.patch("sentry.utils.snuba.query", return_value={})
  59. def test_tag_caching(self, mock_snuba_query):
  60. user = self.create_user()
  61. org = self.create_organization()
  62. team = self.create_team(organization=org)
  63. self.create_member(organization=org, user=user, teams=[team])
  64. self.create_project(organization=org, teams=[team])
  65. self.login_as(user=user)
  66. with self.options({"snuba.tagstore.cache-tagkeys-rate": 1.0}):
  67. url = reverse("sentry-api-0-organization-tags", kwargs={"organization_slug": org.slug})
  68. response = self.client.get(url, {"use_cache": "1", "statsPeriod": "14d"}, format="json")
  69. assert response.status_code == 200, response.content
  70. assert mock_snuba_query.call_count == 1
  71. response = self.client.get(url, {"use_cache": "1", "statsPeriod": "14d"}, format="json")
  72. assert response.status_code == 200, response.content
  73. # Cause we're caching, we shouldn't call snuba again
  74. assert mock_snuba_query.call_count == 1
  75. @mock.patch("sentry.utils.snuba.query", return_value={})
  76. def test_different_statsperiod_caching(self, mock_snuba_query):
  77. user = self.create_user()
  78. org = self.create_organization()
  79. team = self.create_team(organization=org)
  80. self.create_member(organization=org, user=user, teams=[team])
  81. self.create_project(organization=org, teams=[team])
  82. self.login_as(user=user)
  83. with self.options({"snuba.tagstore.cache-tagkeys-rate": 1.0}):
  84. url = reverse("sentry-api-0-organization-tags", kwargs={"organization_slug": org.slug})
  85. response = self.client.get(url, {"use_cache": "1", "statsPeriod": "14d"}, format="json")
  86. assert response.status_code == 200, response.content
  87. # Empty cache, we should query snuba
  88. assert mock_snuba_query.call_count == 1
  89. response = self.client.get(url, {"use_cache": "1", "statsPeriod": "30d"}, format="json")
  90. assert response.status_code == 200, response.content
  91. # With a different statsPeriod, we shouldn't use cache and still query snuba
  92. assert mock_snuba_query.call_count == 2
  93. @mock.patch("sentry.utils.snuba.query", return_value={})
  94. def test_different_times_caching(self, mock_snuba_query):
  95. user = self.create_user()
  96. org = self.create_organization()
  97. team = self.create_team(organization=org)
  98. self.create_member(organization=org, user=user, teams=[team])
  99. self.create_project(organization=org, teams=[team])
  100. self.login_as(user=user)
  101. with self.options({"snuba.tagstore.cache-tagkeys-rate": 1.0}):
  102. start = iso_format(before_now(minutes=10))
  103. end = iso_format(before_now(minutes=5))
  104. url = reverse("sentry-api-0-organization-tags", kwargs={"organization_slug": org.slug})
  105. response = self.client.get(
  106. url, {"use_cache": "1", "start": start, "end": end}, format="json"
  107. )
  108. assert response.status_code == 200, response.content
  109. assert mock_snuba_query.call_count == 1
  110. # 5 minutes later, cache_key should be different
  111. start = iso_format(before_now(minutes=5))
  112. end = iso_format(before_now(minutes=0))
  113. response = self.client.get(
  114. url, {"use_cache": "1", "start": start, "end": end}, format="json"
  115. )
  116. assert response.status_code == 200, response.content
  117. assert mock_snuba_query.call_count == 2
  118. def test_different_times_retrieves_cache(self):
  119. user = self.create_user()
  120. org = self.create_organization()
  121. team = self.create_team(organization=org)
  122. self.create_member(organization=org, user=user, teams=[team])
  123. project = self.create_project(organization=org, teams=[team])
  124. with self.options({"snuba.tagstore.cache-tagkeys-rate": 1.0}):
  125. start = iso_format(before_now(minutes=10))
  126. middle = iso_format(before_now(minutes=5))
  127. end = iso_format(before_now(minutes=0))
  128. # Throw an event in the middle of the time window, since end might get rounded down a bit
  129. self.store_event(
  130. data={"event_id": "a" * 32, "tags": {"fruit": "apple"}, "timestamp": middle},
  131. project_id=project.id,
  132. )
  133. self.login_as(user=user)
  134. url = reverse("sentry-api-0-organization-tags", kwargs={"organization_slug": org.slug})
  135. response = self.client.get(
  136. url, {"use_cache": "1", "start": start, "end": end}, format="json"
  137. )
  138. original_data = response.data
  139. url = reverse("sentry-api-0-organization-tags", kwargs={"organization_slug": org.slug})
  140. response = self.client.get(
  141. url, {"use_cache": "1", "start": start, "end": end}, format="json"
  142. )
  143. cached_data = response.data
  144. assert original_data == cached_data