123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- from django.urls import reverse
- from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
- from sentry.testutils import APITestCase, SnubaTestCase
- from sentry.testutils.cases import PerformanceIssueTestCase
- from sentry.testutils.helpers.datetime import before_now, iso_format
- from sentry.testutils.silo import region_silo_test
- from sentry.utils.samples import load_data
- from tests.sentry.issues.test_utils import OccurrenceTestMixin
- @region_silo_test
- class ProjectEventDetailsTest(APITestCase, SnubaTestCase):
- def setUp(self):
- super().setUp()
- self.login_as(user=self.user)
- self.setup_data()
- def setup_data(self):
- one_min_ago = iso_format(before_now(minutes=1))
- two_min_ago = iso_format(before_now(minutes=2))
- three_min_ago = iso_format(before_now(minutes=3))
- four_min_ago = iso_format(before_now(minutes=4))
- self.prev_event = self.store_event(
- data={"event_id": "a" * 32, "timestamp": four_min_ago, "fingerprint": ["group-1"]},
- project_id=self.project.id,
- )
- self.cur_event = self.store_event(
- data={"event_id": "b" * 32, "timestamp": three_min_ago, "fingerprint": ["group-1"]},
- project_id=self.project.id,
- )
- self.next_event = self.store_event(
- data={
- "event_id": "c" * 32,
- "timestamp": two_min_ago,
- "fingerprint": ["group-1"],
- "environment": "production",
- "tags": {"environment": "production"},
- },
- project_id=self.project.id,
- )
- self.cur_group = self.next_event.group
- # Event in different group
- self.store_event(
- data={
- "event_id": "d" * 32,
- "timestamp": one_min_ago,
- "fingerprint": ["group-2"],
- "environment": "production",
- "tags": {"environment": "production"},
- },
- project_id=self.project.id,
- )
- def test_simple(self):
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.cur_event.event_id,
- "project_slug": self.project.slug,
- "organization_slug": self.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json")
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.cur_event.event_id)
- assert response.data["nextEventID"] == str(self.next_event.event_id)
- assert response.data["previousEventID"] == str(self.prev_event.event_id)
- assert response.data["groupID"] == str(self.cur_group.id)
- def test_snuba_no_prev(self):
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.prev_event.event_id,
- "project_slug": self.project.slug,
- "organization_slug": self.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json")
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.prev_event.event_id)
- assert response.data["previousEventID"] is None
- assert response.data["nextEventID"] == self.cur_event.event_id
- assert response.data["groupID"] == str(self.cur_group.id)
- def test_snuba_with_environment(self):
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.cur_event.event_id,
- "project_slug": self.project.slug,
- "organization_slug": self.project.organization.slug,
- },
- )
- response = self.client.get(
- url, format="json", data={"environment": ["production", "staging"]}
- )
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.cur_event.event_id)
- assert response.data["previousEventID"] is None
- assert response.data["nextEventID"] == self.next_event.event_id
- assert response.data["groupID"] == str(self.cur_group.id)
- def test_ignores_different_group(self):
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.next_event.event_id,
- "project_slug": self.project.slug,
- "organization_slug": self.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json")
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.next_event.event_id)
- assert response.data["nextEventID"] is None
- @region_silo_test
- class ProjectEventDetailsGenericTest(OccurrenceTestMixin, ProjectEventDetailsTest):
- def setup_data(self):
- one_min_ago = iso_format(before_now(minutes=1))
- two_min_ago = iso_format(before_now(minutes=2))
- three_min_ago = iso_format(before_now(minutes=3))
- four_min_ago = iso_format(before_now(minutes=4))
- prev_event_id = "a" * 32
- self.prev_event, prev_group_info = process_event_and_issue_occurrence(
- self.build_occurrence_data(
- event_id=prev_event_id, project_id=self.project.id, fingerprint=["group-1"]
- ),
- {
- "event_id": prev_event_id,
- "project_id": self.project.id,
- "timestamp": four_min_ago,
- "message_timestamp": four_min_ago,
- },
- )
- cur_event_id = "b" * 32
- self.cur_event, cur_group_info = process_event_and_issue_occurrence(
- self.build_occurrence_data(
- event_id=cur_event_id, project_id=self.project.id, fingerprint=["group-1"]
- ),
- {
- "event_id": cur_event_id,
- "project_id": self.project.id,
- "timestamp": three_min_ago,
- "message_timestamp": three_min_ago,
- },
- )
- self.cur_group = cur_group_info.group
- next_event_id = "c" * 32
- self.next_event, next_group_info = process_event_and_issue_occurrence(
- self.build_occurrence_data(
- event_id=next_event_id, project_id=self.project.id, fingerprint=["group-1"]
- ),
- {
- "event_id": next_event_id,
- "project_id": self.project.id,
- "timestamp": two_min_ago,
- "message_timestamp": two_min_ago,
- "tags": {"environment": "production"},
- },
- )
- unrelated_event_id = "d" * 32
- process_event_and_issue_occurrence(
- self.build_occurrence_data(
- event_id=unrelated_event_id, project_id=self.project.id, fingerprint=["group-2"]
- ),
- {
- "event_id": unrelated_event_id,
- "project_id": self.project.id,
- "timestamp": one_min_ago,
- "message_timestamp": one_min_ago,
- "tags": {"environment": "production"},
- },
- )[0]
- def test_generic_event_with_occurrence(self):
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.cur_event.event_id,
- "project_slug": self.project.slug,
- "organization_slug": self.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json", data={"group_id": self.cur_group.id})
- assert response.status_code == 200, response.content
- assert response.data["id"] == self.cur_event.event_id
- assert response.data["occurrence"] is not None
- assert response.data["occurrence"]["id"] == self.cur_event.id
- @region_silo_test
- class ProjectEventDetailsTransactionTest(APITestCase, SnubaTestCase, PerformanceIssueTestCase):
- def setUp(self):
- super().setUp()
- self.login_as(user=self.user)
- project = self.create_project()
- one_min_ago = before_now(minutes=1)
- two_min_ago = before_now(minutes=2)
- three_min_ago = before_now(minutes=3)
- four_min_ago = before_now(minutes=4)
- self.prev_transaction_event = self.create_performance_issue(
- event_data=load_data(
- event_id="a" * 32,
- platform="transaction-n-plus-one",
- timestamp=four_min_ago,
- start_timestamp=four_min_ago,
- ),
- project_id=project.id,
- )
- self.group = self.prev_transaction_event.group
- self.cur_transaction_event = self.create_performance_issue(
- event_data=load_data(
- event_id="b" * 32,
- platform="transaction-n-plus-one",
- timestamp=three_min_ago,
- start_timestamp=three_min_ago,
- ),
- project_id=project.id,
- )
- self.next_transaction_event = self.create_performance_issue(
- event_data=load_data(
- event_id="c" * 32,
- platform="transaction-n-plus-one",
- timestamp=two_min_ago,
- start_timestamp=two_min_ago,
- ),
- project_id=project.id,
- )
- self.create_performance_issue(
- event_data=load_data(
- event_id="d" * 32,
- platform="transaction-n-plus-one",
- timestamp=one_min_ago,
- start_timestamp=one_min_ago,
- ),
- fingerprint="other_group",
- project_id=project.id,
- )
- def test_transaction_event(self):
- """Test that you can look up a transaction event w/ a prev and next event"""
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.cur_transaction_event.event_id,
- "project_slug": self.cur_transaction_event.project.slug,
- "organization_slug": self.cur_transaction_event.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json", data={"group_id": self.group.id})
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.cur_transaction_event.event_id)
- assert response.data["nextEventID"] == str(self.next_transaction_event.event_id)
- assert response.data["previousEventID"] == str(self.prev_transaction_event.event_id)
- assert response.data["groupID"] == str(self.cur_transaction_event.group.id)
- def test_no_previous_event(self):
- """Test the case in which there is no previous event"""
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.prev_transaction_event.event_id,
- "project_slug": self.prev_transaction_event.project.slug,
- "organization_slug": self.prev_transaction_event.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json", data={"group_id": self.group.id})
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.prev_transaction_event.event_id)
- assert response.data["previousEventID"] is None
- assert response.data["nextEventID"] == self.cur_transaction_event.event_id
- assert response.data["groupID"] == str(self.prev_transaction_event.group.id)
- def test_ignores_different_group(self):
- """Test that a different group's events aren't attributed to the one that was passed"""
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.next_transaction_event.event_id,
- "project_slug": self.next_transaction_event.project.slug,
- "organization_slug": self.next_transaction_event.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json", data={"group_id": self.group.id})
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.next_transaction_event.event_id)
- assert response.data["nextEventID"] is None
- def test_no_group_id(self):
- """Test the case where a group_id was not passed"""
- url = reverse(
- "sentry-api-0-project-event-details",
- kwargs={
- "event_id": self.cur_transaction_event.event_id,
- "project_slug": self.cur_transaction_event.project.slug,
- "organization_slug": self.cur_transaction_event.project.organization.slug,
- },
- )
- response = self.client.get(url, format="json")
- assert response.status_code == 200, response.content
- assert response.data["id"] == str(self.cur_transaction_event.event_id)
- assert response.data["previousEventID"] is None
- assert response.data["nextEventID"] is None
- assert response.data["groupID"] is None
- @region_silo_test
- class ProjectEventJsonEndpointTest(APITestCase, SnubaTestCase):
- def setUp(self):
- super().setUp()
- self.login_as(user=self.user)
- self.event_id = "c" * 32
- self.fingerprint = ["group_2"]
- self.min_ago = iso_format(before_now(minutes=1))
- self.event = self.store_event(
- data={
- "event_id": self.event_id,
- "timestamp": self.min_ago,
- "fingerprint": self.fingerprint,
- "user": {"email": self.user.email},
- },
- project_id=self.project.id,
- )
- self.url = reverse(
- "sentry-api-0-event-json",
- kwargs={
- "organization_slug": self.organization.slug,
- "project_slug": self.project.slug,
- "event_id": self.event_id,
- },
- )
- def assert_event(self, data):
- assert data["event_id"] == self.event_id
- assert data["user"]["email"] == self.user.email
- assert data["datetime"][:19] == self.min_ago
- assert data["fingerprint"] == self.fingerprint
- def test_simple(self):
- response = self.client.get(self.url, format="json")
- assert response.status_code == 200, response.content
- self.assert_event(response.data)
- def test_event_does_not_exist(self):
- self.url = reverse(
- "sentry-api-0-event-json",
- kwargs={
- "organization_slug": self.organization.slug,
- "project_slug": self.project.slug,
- "event_id": "no" * 16,
- },
- )
- response = self.client.get(self.url, format="json")
- assert response.status_code == 404, response.content
- assert response.data == {"detail": "Event not found"}
- def test_user_unauthorized(self):
- user = self.create_user()
- self.login_as(user)
- response = self.client.get(self.url, format="json")
- assert response.status_code == 403, response.content
- assert response.data == {"detail": "You do not have permission to perform this action."}
- def test_project_not_associated_with_event(self):
- project2 = self.create_project(organization=self.organization)
- url = reverse(
- "sentry-api-0-event-json",
- kwargs={
- "organization_slug": self.organization.slug,
- "project_slug": project2.slug,
- "event_id": self.event_id,
- },
- )
- response = self.client.get(url, format="json")
- assert response.status_code == 404, response.content
- assert response.data == {"detail": "Event not found"}
|