def test_eventerror(self): event = self.store_event( data={ "event_id": "a" * 32, "timestamp": iso_format(before_now(minutes=1)), "stacktrace": ["ü"], }, project_id=self.project.id, assert_no_errors=False, ) result = serialize(event) assert len(result["errors"]) == 1 assert "data" in result["errors"][0] assert result["errors"][0]["type"] == EventError.INVALID_DATA assert result["errors"][0]["data"] == { "name": "stacktrace", "reason": "expected rawstacktrace", "value": ["\xfc"], } assert "startTimestamp" not in result assert "timestamp" not in result
def test_issueless( self, mock_signal, mock_process_resource_change_bound, mock_process_service_hook, mock_processor, ): min_ago = iso_format(before_now(minutes=1)) event = self.store_event( data={ "type": "transaction", "timestamp": min_ago, "start_timestamp": min_ago, "contexts": { "trace": { "trace_id": "b" * 32, "span_id": "c" * 16, "op": "" } }, }, project_id=self.project.id, ) cache_key = write_event_to_cache(event) post_process_group( is_new=True, is_regression=False, is_new_group_environment=True, cache_key=cache_key, ) mock_processor.assert_not_called() # NOQA mock_process_service_hook.assert_not_called() # NOQA mock_process_resource_change_bound.assert_not_called() # NOQA mock_signal.assert_called_once_with(sender=ANY, project=self.project, event=EventMatcher(event), primary_hash=None)
def test_content_encoding_deflate(self): kwargs = {"message": "hello", "timestamp": iso_format(before_now(seconds=1))} message = zlib.compress(json.dumps(kwargs)) key = self.projectkey.public_key secret = self.projectkey.secret_key with self.tasks(): resp = self.client.post( self.path, message, content_type="application/octet-stream", HTTP_CONTENT_ENCODING="deflate", HTTP_X_SENTRY_AUTH=get_auth_header("_postWithHeader", key, secret), ) assert resp.status_code == 200, resp.content event_id = json.loads(resp.content)["id"] instance = self.get_event(event_id) assert instance.message == "hello"
def test_transaction_threshold_modal(self, mock_now): mock_now.return_value = before_now().replace(tzinfo=pytz.utc) # Create a transaction event = make_event(load_data("transaction", timestamp=before_now(minutes=3))) self.store_event(data=event, project_id=self.project.id) self.store_event( data={ "transaction": "/country_by_code/", "message": "This is bad", "event_id": "b" * 32, "timestamp": iso_format(before_now(minutes=3)), }, project_id=self.project.id, ) with self.feature(FEATURES): self.browser.get(self.path) self.page.wait_until_loaded() self.browser.click('[data-test-id="set-transaction-threshold"]') self.browser.snapshot("transaction threshold modal")
def test_processes_resource_change_task_not_called_without_feature_flag( self, delay): event = self.store_event( data={ "message": "Foo bar", "level": "info", "timestamp": iso_format(timezone.now()) }, project_id=self.project.id, assert_no_errors=False, ) cache_key = write_event_to_cache(event) post_process_group( is_new=False, is_regression=False, is_new_group_environment=False, cache_key=cache_key, group_id=event.group_id, ) assert not delay.called
def test_empty_count_query(self): self.login_as(user=self.user) project = self.create_project() event = self.store_event( data={ "event_id": "a" * 32, "timestamp": iso_format(before_now(minutes=5)), "fingerprint": ["1123581321"], "user": { "email": "*****@*****.**" }, "tags": { "language": "C++" }, }, project_id=project.id, ) with self.feature("organizations:discover-basic"): response = self.client.get( self.url, format="json", data={ "field": ["count()"], "query": "issue.id:%d timestamp:>%s" % (event.group_id, self.min_ago), "statsPeriod": "14d", }, ) assert response.status_code == 200, response.content data = response.data["data"] assert len(data) == 1 assert data[0]["project.name"] == "" assert data[0]["count"] == 0 assert data[0]["latest_event"] == ""
def test_no_release(self): self.login_as(user=self.user) project = self.create_project() min_ago = iso_format(before_now(minutes=1)) event = self.store_event( data={"fingerprint": ["group1"], "timestamp": min_ago}, project_id=project.id ) url = reverse( "sentry-api-0-event-file-committers", kwargs={ "event_id": event.event_id, "project_slug": event.project.slug, "organization_slug": event.project.organization.slug, }, ) response = self.client.get(url, format="json") assert response.status_code == 404, response.content assert response.data["detail"] == "Release not found"
def test_get_oldest_latest_for_environments(self): project = self.create_project() min_ago = iso_format(before_now(minutes=1)) self.store_event( data={ "event_id": "a" * 32, "environment": "production", "timestamp": min_ago, "fingerprint": ["group-1"], }, project_id=project.id, ) self.store_event( data={ "event_id": "b" * 32, "environment": "production", "timestamp": min_ago, "fingerprint": ["group-1"], }, project_id=project.id, ) self.store_event( data={"event_id": "c" * 32, "timestamp": min_ago, "fingerprint": ["group-1"]}, project_id=project.id, ) group = Group.objects.first() assert group.get_latest_event_for_environments().event_id == "c" * 32 assert group.get_latest_event_for_environments(["staging"]) is None assert group.get_latest_event_for_environments(["production"]).event_id == "b" * 32 assert group.get_oldest_event_for_environments().event_id == "a" * 32 assert ( group.get_oldest_event_for_environments(["staging", "production"]).event_id == "a" * 32 ) assert group.get_oldest_event_for_environments(["staging"]) is None
def test_event_detail_view_from_errors_view(self, mock_now): mock_now.return_value = before_now().replace(tzinfo=pytz.utc) event_source = (("a", 1), ("b", 39), ("c", 69)) event_ids = [] event_data = load_data("javascript") event_data["fingerprint"] = ["group-1"] for id_prefix, offset in event_source: event_time = iso_format(before_now(minutes=offset)) event_data.update({ "timestamp": event_time, "received": event_time, "event_id": id_prefix * 32, "type": "error", }) event = self.store_event(data=event_data, project_id=self.project.id) event_ids.append(event.event_id) with self.feature(FEATURE_NAMES): # Get the list page self.browser.get(self.result_path + "?" + errors_query() + "&statsPeriod=24h") self.wait_until_loaded() # Click the event link to open the event detail view self.browser.element('[data-test-id="view-events"]').click() self.wait_until_loaded() self.browser.snapshot( "events-v2 - grouped error event detail view") # Check that the newest event is loaded first and that pagination # controls display display_id = self.browser.element('[data-test-id="event-id"]') assert event_ids[0] in display_id.text assert self.browser.element_exists_by_test_id("older-event") assert self.browser.element_exists_by_test_id("newer-event")
def test_simple(self, mock_eventstream): key = "foo" val = "bar" project = self.create_project() self.store_event( data={ "tags": { key: val }, "timestamp": iso_format(before_now(seconds=1)) }, project_id=project.id, ) self.login_as(user=self.user) eventstream_state = object() mock_eventstream.start_delete_tag = mock.Mock( return_value=eventstream_state) url = reverse( "sentry-api-0-project-tagkey-details", kwargs={ "organization_slug": project.organization.slug, "project_slug": project.slug, "key": key, }, ) response = self.client.delete(url) assert response.status_code == 204 mock_eventstream.start_delete_tag.assert_called_once_with( project.id, "foo") mock_eventstream.end_delete_tag.assert_called_once_with( eventstream_state)
def test_related_issues_transactions_with_quotes(self): self.login_as(user=self.user) project = self.create_project() event = self.store_event( data={ "event_id": "a" * 32, "timestamp": iso_format(before_now(minutes=1)), "transaction": '/beth/"sanchez"', }, project_id=project.id, ) url = reverse( "sentry-api-0-organization-related-issues", kwargs={"organization_slug": project.organization.slug}, ) response = self.client.get( url, {"transaction": '/beth/"sanchez"', "project": project.id}, format="json", ) assert response.status_code == 200, response.content assert len(response.data) == 1 assert response.data[0]["shortId"] == event.group.qualified_short_id assert int(response.data[0]["id"]) == event.group_id url = reverse( "sentry-api-0-organization-related-issues", kwargs={"organization_slug": project.organization.slug}, ) response = self.client.get( url, {"transaction": '/beth/\\"sanchez\\"', "project": project.id}, format="json", ) assert response.status_code == 200, response.content assert len(response.data) == 1 assert response.data[0]["shortId"] == event.group.qualified_short_id assert int(response.data[0]["id"]) == event.group_id
def test_no_commits(self): event = self.store_event( data={ "timestamp": iso_format(before_now(seconds=1)), "message": "Kaboom!", "stacktrace": { "frames": [ { "function": "handle_set_commits", "abs_path": "/usr/src/sentry/src/sentry/tasks.py", "module": "sentry.tasks", "in_app": True, "lineno": 30, "filename": "sentry/tasks.py", }, { "function": "set_commits", "abs_path": "/usr/src/sentry/src/sentry/models/release.py", "module": "sentry.models.release", "in_app": True, "lineno": 39, "filename": "sentry/models/release.py", }, ] }, "tags": { "sentry:release": self.release.version }, }, project_id=self.project.id, ) GroupRelease.objects.create(group_id=event.group.id, project_id=self.project.id, release_id=self.release.id) with self.assertRaises(Commit.DoesNotExist): get_serialized_event_file_committers(self.project, event)
def test_unfurl_discover_without_project_ids(self, mock_generate_chart): min_ago = iso_format(before_now(minutes=1)) self.store_event(data={ "fingerprint": ["group2"], "timestamp": min_ago }, project_id=self.project.id) self.store_event(data={ "fingerprint": ["group2"], "timestamp": min_ago }, project_id=self.project.id) url = f"https://sentry.io/organizations/{self.organization.slug}/discover/results/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All+Events&query=&sort=-timestamp&statsPeriod=24h" link_type, args = match_link(url) if not args or not link_type: raise Exception("Missing link_type/args") links = [ UnfurlableUrl(url=url, args=args), ] with self.feature([ "organizations:discover", "organizations:discover-basic", "organizations:chart-unfurls", ]): unfurls = link_handlers[link_type].fn(self.request, self.integration, links, self.user) assert unfurls[url] == build_discover_attachment( title=args["query"].get("name"), chart_url="chart-url") assert len(mock_generate_chart.mock_calls) == 1 chart_data = mock_generate_chart.call_args[0][1] assert chart_data["seriesName"] == "count()" assert len(chart_data["stats"]["data"]) == 288
def test_processes_resource_change_task_on_error_events(self, delay): event = self.store_event( data={ "message": "Foo bar", "exception": { "type": "Foo", "value": "shits on fiah yo" }, "level": "error", "timestamp": iso_format(timezone.now()), }, project_id=self.project.id, assert_no_errors=False, ) cache_key = write_event_to_cache(event) self.create_service_hook( project=self.project, organization=self.project.organization, actor=self.user, events=["error.created"], ) post_process_group( event=None, is_new=False, is_regression=False, is_new_group_environment=False, cache_key=cache_key, group_id=event.group_id, ) delay.assert_called_once_with( action="created", sender="Error", instance_id=event.event_id, instance=EventMatcher(event), )
def _run_test(self, minutes, data, passes, add_events=False): if not self.environment: self.environment = self.create_environment(name="prod") rule = self.get_rule(data=data, rule=Rule(environment_id=None)) environment_rule = self.get_rule( data=data, rule=Rule(environment_id=self.environment.id)) with freeze_time(before_now(minutes=0)): event = self.store_event( data={ "fingerprint": ["something_random"], "timestamp": iso_format(before_now(minutes=minutes)), "user": { "id": uuid4().hex }, }, project_id=self.project.id, ) if add_events: self.increment( event, data["value"] + 1, environment=self.environment.name, timestamp=now() - timedelta(minutes=minutes), ) self.increment( event, data["value"] + 1, timestamp=now() - timedelta(minutes=minutes), ) if passes: self.assertPasses(rule, event) self.assertPasses(environment_rule, event) else: self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event)
def test_errors(self, mock_now): mock_now.return_value = before_now().replace(tzinfo=pytz.utc) min_ago = iso_format(before_now(minutes=1)) self.store_event( data={ "event_id": "a" * 32, "message": "oh no", "timestamp": min_ago, "fingerprint": ["group-1"], }, project_id=self.project.id, assert_no_errors=False, ) self.store_event( data={ "event_id": "b" * 32, "message": "oh no", "timestamp": min_ago, "fingerprint": ["group-1"], }, project_id=self.project.id, assert_no_errors=False, ) self.store_event( data={ "event_id": "c" * 32, "message": "this is bad.", "timestamp": min_ago, "fingerprint": ["group-2"], }, project_id=self.project.id, assert_no_errors=False, ) with self.feature(FEATURE_NAMES): self.browser.get(self.path + "?" + error_view) self.wait_until_loaded() self.browser.snapshot("events-v2 - errors")
def setUp(self): super(ProjectUserReportListTest, self).setUp() self.min_ago = iso_format(before_now(minutes=1)) self.environment = self.create_environment(project=self.project, name="production") self.event = self.store_event( data={ "event_id": "a" * 32, "timestamp": self.min_ago, "environment": self.environment.name, }, project_id=self.project.id, ) self.environment2 = self.create_environment(project=self.project, name="staging") self.event2 = self.store_event( data={ "event_id": "b" * 32, "timestamp": self.min_ago, "environment": self.environment2.name, }, project_id=self.project.id, ) self.report = UserReport.objects.create( project_id=self.project.id, environment_id=self.environment.id, event_id="a" * 32, name="Foo", email="*****@*****.**", comments="Hello world", group_id=self.event.group.id, ) self.report2 = UserReport.objects.create( project_id=self.project.id, event_id="b" * 32, name="Foo", email="*****@*****.**", comments="Hello world", group_id=self.event.group.id, )
def test_group_expand_inbox(self): with self.feature("organizations:inbox"): self.login_as(user=self.user) event = self.store_event( data={"timestamp": iso_format(before_now(minutes=3))}, project_id=self.project.id, ) group = event.group add_group_to_inbox(group, GroupInboxReason.NEW) url = f"/api/0/issues/{group.id}/?expand=inbox" response = self.client.get(url, format="json") assert response.status_code == 200, response.content assert response.data["inbox"] is not None assert response.data["inbox"]["reason"] == GroupInboxReason.NEW.value assert response.data["inbox"]["reason_details"] is None remove_group_from_inbox(event.group) response = self.client.get(url, format="json") assert response.status_code == 200, response.content assert response.data["inbox"] is None
def test_with_data(self, mock_now): mock_now.return_value = before_now().replace(tzinfo=pytz.utc) # Create a transaction event = make_event( load_data("transaction", timestamp=before_now(minutes=1))) self.store_event(data=event, project_id=self.project.id) self.wait_for_event_count(self.project.id, 1) self.store_event( data={ "transaction": "/country_by_code/", "message": "This is bad", "event_id": "b" * 32, "timestamp": iso_format(before_now(minutes=1)), }, project_id=self.project.id, ) with self.feature(FEATURE_NAMES): self.browser.get(self.path) self.page.wait_until_loaded() self.browser.snapshot("performance summary - with data")
def test_tags_list(self, mock_timezone): self.store_event( data={ "event_id": "a" * 32, "message": "oh no", "level": "error", "timestamp": iso_format(event_time), }, project_id=self.project.id, assert_no_errors=False, ) self.browser.get(self.path) self.browser.wait_until_not(".loading-indicator") self.browser.snapshot("project settings - tags") self.browser.wait_until_test_id("tag-row") self.browser.click('[data-test-id="tag-row"] [data-test-id="delete"]') self.browser.wait_until("[role='dialog'] [data-test-id='confirm-button']") self.browser.click("[role='dialog'] [data-test-id='confirm-button']") self.browser.wait_until_not('[data-test-id="tag-row"]') self.browser.snapshot("project settings - tags - after remove")
def setUp(self): organization = self.create_organization() project = self.create_project(name="foo", organization=organization, teams=[]) key, value = "foo", "bar" self.store_event( data={ "event_id": "a" * 32, "tags": {key: value}, "timestamp": iso_format(before_now(seconds=1)), }, project_id=project.id, ) self.url = reverse( "sentry-api-0-project-tagkey-values", kwargs={ "organization_slug": organization.slug, "project_slug": project.slug, "key": key, }, ) self.login_as(user=self.user)
def test_enviroment_promoted_tag(self): for env in ("prod", "staging", None): self.store_event( data={ "message": "very bad", "type": "default", "environment": env, "timestamp": iso_format(before_now(minutes=2)), }, project_id=self.project.id, ) params = { "project_id": [self.project.id], "start": self.day_ago, "end": self.min_ago } result = discover.get_facets("", params) keys = {r.key for r in result} assert keys == {"environment", "level"} assert {"prod", "staging", None} == {f.value for f in result if f.key == "environment"} assert {1} == {f.count for f in result if f.key == "environment"}
def test_simple(self): self.store_event( data={"timestamp": iso_format(before_now(seconds=500)), "fingerprint": ["group-1"]}, project_id=self.project.id, ) group_a = self.create_group(checksum="a" * 32, status=GroupStatus.UNRESOLVED) self.create_group(checksum="b" * 32, status=GroupStatus.UNRESOLVED) group_c = self.create_group(checksum="c" * 32, status=GroupStatus.UNRESOLVED) self.login_as(user=self.user) response = self.get_response( sort_by="date", limit=10, query="is:unresolved", groups=[group_a.id, group_c.id] ) assert response.status_code == 200 assert len(response.data) == 2 assert int(response.data[0]["id"]) == group_a.id assert "title" not in response.data[0] assert "hasSeen" not in response.data[0] assert "stats" in response.data[0] assert "firstSeen" in response.data[0] assert "lastSeen" in response.data[0] assert "count" in response.data[0] assert "lifetime" in response.data[0] assert "filtered" in response.data[0]
def test_event_not_found__event_no_group(self): min_ago = iso_format(before_now(minutes=1)) event = self.store_event( data={ "type": "transaction", "transaction": "api.test", "timestamp": min_ago, "start_timestamp": min_ago, "spans": [], "contexts": { "trace": { "trace_id": "a" * 32, "span_id": "b" * 16 } }, }, project_id=self.project.id, ) url = reverse("sentry-project-event-redirect", args=[self.org.slug, self.project.slug, event.id]) resp = self.client.get(url) assert resp.status_code == 404
def test_simple(self): self.login_as(user=self.user) min_ago = iso_format(before_now(minutes=1)) event = self.store_event(data={"timestamp": min_ago}, project_id=self.project.id) group = event.group share_id = group.get_share_id() assert share_id is None GroupShare.objects.create(project_id=group.project_id, group=group) share_id = group.get_share_id() assert share_id is not None url = "/api/0/shared/issues/{}/".format(share_id) response = self.client.get(url, format="json") assert response.status_code == 200, response.content assert response.data["id"] == six.text_type(group.id) assert response.data["latestEvent"]["id"] == six.text_type(event.event_id) assert response.data["project"]["slug"] == group.project.slug assert response.data["project"]["organization"]["slug"] == group.organization.slug
def test_tags_list(self): self.store_event( data={ "event_id": "a" * 32, "message": "oh no", "level": "error", "timestamp": iso_format(event_time), }, project_id=self.project.id, assert_no_errors=False, ) self.browser.get(self.path) self.browser.wait_until_not(".loading-indicator") self.browser.snapshot("project settings - tags") self.browser.wait_until(".ref-tag-row") self.browser.click('.ref-tag-row [data-test-id="delete"]') self.browser.wait_until('.modal-footer [data-test-id="confirm-modal"]') self.browser.click('.modal-footer [data-test-id="confirm-modal"]') self.browser.wait_until_not(".ref-tag-row") self.browser.snapshot("project settings - tags - after remove")
def test_related_issues_no_transaction(self): self.login_as(user=self.user) project = self.create_project() self.store_event( data={ "timestamp": iso_format(before_now(minutes=1)), "transaction": "/beth/sanchez" }, project_id=project.id, ) url = reverse( "sentry-api-0-organization-related-issues", kwargs={"organization_slug": project.organization.slug}, ) response = self.client.get(url, format="json") assert response.status_code == 400, response.content assert ( response.data["detail"] == "Must provide one of ['transaction'] in order to find related events" )
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 create_message_event(template, parameters, environment, release, fingerprint="group1"): i = next(sequence) event_id = uuid.UUID(fields=(i, 0x0, 0x1000, 0x80, 0x80, 0x808080808080)).hex tags = [["color", next(tag_values)]] if release: tags.append(["sentry:release", release]) event = self.store_event( data={ "event_id": event_id, "message": template % parameters, "type": "default", "user": next(user_values), "tags": tags, "fingerprint": [fingerprint], "timestamp": iso_format(now + timedelta(seconds=i)), "environment": environment, "release": release, }, project_id=project.id, ) UserReport.objects.create( project_id=project.id, group_id=event.group.id, event_id=event_id, name="Log Hat", email="*****@*****.**", comments="Quack", ) features.record([event]) return event
def test_full_integration(self): one_min_ago = iso_format(before_now(minutes=1)) event = self.store_event( data={ "message": "hello", "exception": {"type": "Foo", "value": "uh oh"}, "level": "error", "timestamp": one_min_ago, }, project_id=self.project.id, assert_no_errors=False, ) action_data = { "id": "sentry.mail.actions.NotifyEmailAction", "targetType": "Member", "targetIdentifier": six.text_type(self.user.id), } condition_data = {"id": "sentry.rules.conditions.first_seen_event.FirstSeenEventCondition"} Rule.objects.filter(project=event.project).delete() Rule.objects.create( project=event.project, data={"conditions": [condition_data], "actions": [action_data]} ) with self.tasks(): post_process_group( is_new=True, is_regression=False, is_new_group_environment=False, cache_key=write_event_to_cache(event), group_id=event.group_id, ) assert len(mail.outbox) == 1 sent = mail.outbox[0] assert sent.to == [self.user.email] assert "uh oh" in sent.subject