Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(project-create): Add origin to analytics event #86088

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/sentry/analytics/events/project_created.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class ProjectCreatedEvent(analytics.Event):
analytics.Attribute("user_id", required=False),
analytics.Attribute("default_user_id"),
analytics.Attribute("organization_id"),
analytics.Attribute("origin", required=False),
analytics.Attribute("project_id"),
analytics.Attribute("platform", required=False),
analytics.Attribute("updated_empty_state", required=False),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,14 @@ def post(self, request: Request, organization: Organization) -> Response:
"organization": team.organization,
"target_object": project.id,
}

if request.data.get("origin"):
origin = request.data.get("origin")
if origin:
self.create_audit_entry(
**common_audit_data,
event=audit_log.get_event_id("PROJECT_ADD_WITH_ORIGIN"),
data={
**project.get_audit_log_data(),
"origin": request.data.get("origin"),
"origin": origin,
},
)
else:
Expand All @@ -205,6 +205,7 @@ def post(self, request: Request, organization: Organization) -> Response:
project=project,
user=request.user,
default_rules=result.get("default_rules", True),
origin=origin,
sender=self,
)
self.create_audit_entry(
Expand Down
6 changes: 4 additions & 2 deletions src/sentry/api/endpoints/team_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,14 @@ def post(self, request: Request, team: Team) -> Response:
"target_object": project.id,
}

if request.data.get("origin"):
origin = request.data.get("origin")
if origin:
self.create_audit_entry(
**common_audit_data,
event=audit_log.get_event_id("PROJECT_ADD_WITH_ORIGIN"),
data={
**project.get_audit_log_data(),
"origin": request.data.get("origin"),
"origin": origin,
},
)
else:
Expand All @@ -250,6 +251,7 @@ def post(self, request: Request, team: Team) -> Response:
project=project,
user=request.user,
default_rules=result.get("default_rules", True),
origin=origin,
sender=self,
)

Expand Down
3 changes: 2 additions & 1 deletion src/sentry/receivers/onboarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@


@project_created.connect(weak=False)
def record_new_project(project, user=None, user_id=None, **kwargs):
def record_new_project(project, user=None, user_id=None, origin=None, **kwargs):

scope = sentry_sdk.get_current_scope()
scope.set_extra("project_id", project.id)
Expand Down Expand Up @@ -90,6 +90,7 @@ def record_new_project(project, user=None, user_id=None, **kwargs):
user_id=user_id,
default_user_id=default_user_id,
organization_id=project.organization_id,
origin=origin,
project_id=project.id,
platform=project.platform,
updated_empty_state=features.has(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import re
from unittest.mock import patch
from unittest import mock
from unittest.mock import Mock, patch

from django.utils.text import slugify

Expand All @@ -14,6 +15,7 @@
from sentry.models.project import Project
from sentry.models.rule import Rule
from sentry.models.team import Team
from sentry.signals import project_created
from sentry.testutils.cases import APITestCase
from sentry.testutils.helpers.features import with_feature

Expand Down Expand Up @@ -282,3 +284,36 @@ def test_disable_member_project_creation(self):
name="foo",
status_code=201,
)

@with_feature(["organizations:team-roles"])
@patch(
"sentry.api.endpoints.organization_projects_experiment.OrganizationProjectsExperimentEndpoint.create_audit_entry"
)
def test_create_project_with_origin(self, create_audit_entry):
signal_handler = Mock()
project_created.connect(signal_handler)

response = self.get_success_response(
self.organization.slug,
name="foo",
origin="ui",
status_code=201,
)

project = Project.objects.get(id=response.data["id"])
# Verify audit log was created
create_audit_entry.assert_any_call(
request=mock.ANY,
organization=self.organization,
target_object=project.id,
event=1154,
data={
**project.get_audit_log_data(),
"origin": "ui",
},
)

# Verify origin is passed to project_created signal
assert signal_handler.call_count == 1
assert signal_handler.call_args[1]["origin"] == "ui"
project_created.disconnect(signal_handler)
10 changes: 9 additions & 1 deletion tests/sentry/api/endpoints/test_team_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from sentry.models.project import Project
from sentry.models.rule import Rule
from sentry.notifications.types import FallthroughChoiceType
from sentry.signals import alert_rule_created
from sentry.signals import alert_rule_created, project_created
from sentry.slug.errors import DEFAULT_SLUG_ERROR_MESSAGE
from sentry.testutils.cases import APITestCase
from sentry.testutils.helpers.options import override_options
Expand Down Expand Up @@ -356,6 +356,9 @@ def test_builtin_symbol_sources_not_electron(self):

@patch("sentry.api.endpoints.team_projects.TeamProjectsEndpoint.create_audit_entry")
def test_create_project_with_origin(self, create_audit_entry):
signal_handler = Mock()
project_created.connect(signal_handler)

response = self.get_success_response(
self.organization.slug,
self.team.slug,
Expand All @@ -379,3 +382,8 @@ def test_create_project_with_origin(self, create_audit_entry):
"origin": "ui",
},
)

# Verify origin is passed to project_created signal
assert signal_handler.call_count == 1
assert signal_handler.call_args[1]["origin"] == "ui"
project_created.disconnect(signal_handler)
27 changes: 27 additions & 0 deletions tests/sentry/receivers/test_onboarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,32 @@ def test_project_created(self):
)
assert task is not None

@patch("sentry.analytics.record")
def test_project_created_with_origin(self, record_analytics):
project = self.create_project()
project_created.send(
project=project, user=self.user, default_rules=False, sender=type(project), origin="ui"
)

task = OrganizationOnboardingTask.objects.get(
organization=self.organization,
task=OnboardingTask.FIRST_PROJECT,
status=OnboardingTaskStatus.COMPLETE,
)
assert task is not None

# Verify origin is passed to analytics event
record_analytics.assert_called_with(
"project.created",
user_id=self.user.id,
default_user_id=self.organization.default_owner_id,
organization_id=self.organization.id,
project_id=project.id,
platform=project.platform,
updated_empty_state=False,
origin="ui",
)

def test_first_event_received(self):
now = timezone.now()
project = self.create_project(first_event=now, platform="javascript")
Expand Down Expand Up @@ -834,6 +860,7 @@ def test_new_onboarding_complete(self, record_analytics):
project_id=project.id,
platform=project.platform,
updated_empty_state=False,
origin=None,
)

# Set up tracing
Expand Down
Loading