Skip to content

Commit

Permalink
Merge branch 'master' into jb/profiling/android-flamecharts
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasBa authored Mar 6, 2025
2 parents 735f66b + 31ae1da commit 993b04b
Show file tree
Hide file tree
Showing 122 changed files with 2,095 additions and 881 deletions.
2 changes: 1 addition & 1 deletion migrations_lockfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ remote_subscriptions: 0003_drop_remote_subscription

replays: 0004_index_together

sentry: 0837_create_groupsearchviewlastseen_table
sentry: 0838_backfill_groupsearchview_positions_to_gsvstarred

social_auth: 0002_default_auto_field

Expand Down
2 changes: 1 addition & 1 deletion requirements-base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ rfc3339-validator>=0.1.2
rfc3986-validator>=0.1.1
# [end] jsonschema format validators
sentry-arroyo>=2.19.9
sentry-kafka-schemas>=1.1.1
sentry-kafka-schemas>=1.1.2
sentry-ophio==1.0.0
sentry-protos>=0.1.62
sentry-redis-tools>=0.1.7
Expand Down
2 changes: 1 addition & 1 deletion requirements-dev-frozen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ sentry-devenv==1.16.0
sentry-forked-django-stubs==5.1.3.post2
sentry-forked-djangorestframework-stubs==3.15.3.post1
sentry-forked-email-reply-parser==0.5.12.post1
sentry-kafka-schemas==1.1.1
sentry-kafka-schemas==1.1.2
sentry-ophio==1.0.0
sentry-protos==0.1.62
sentry-redis-tools==0.1.7
Expand Down
2 changes: 1 addition & 1 deletion requirements-frozen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ rsa==4.8
s3transfer==0.10.0
sentry-arroyo==2.19.9
sentry-forked-email-reply-parser==0.5.12.post1
sentry-kafka-schemas==1.1.1
sentry-kafka-schemas==1.1.2
sentry-ophio==1.0.0
sentry-protos==0.1.62
sentry-redis-tools==0.1.7
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/accept_organization_invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
add_invite_details_to_session,
remove_invite_details_from_session,
)
from sentry.demo_mode.utils import is_demo_user
from sentry.models.authprovider import AuthProvider
from sentry.models.organizationmapping import OrganizationMapping
from sentry.models.organizationmembermapping import OrganizationMemberMapping
from sentry.organizations.services.organization import RpcUserInviteContext, organization_service
from sentry.types.region import RegionResolutionError, get_region_by_name
from sentry.utils import auth
from sentry.utils.demo_mode import is_demo_user

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/auth_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
from sentry.auth.providers.saml2.provider import handle_saml_single_logout
from sentry.auth.services.auth.impl import promote_request_rpc_user
from sentry.auth.superuser import SUPERUSER_ORG_ID
from sentry.demo_mode.utils import is_demo_user
from sentry.organizations.services.organization import organization_service
from sentry.types.ratelimit import RateLimit, RateLimitCategory
from sentry.users.api.serializers.user import DetailedSelfUserSerializer
from sentry.users.models.authenticator import Authenticator
from sentry.utils import auth, json, metrics
from sentry.utils.auth import DISABLE_SSO_CHECK_FOR_LOCAL_DEV, has_completed_sso, initiate_login
from sentry.utils.demo_mode import is_demo_user
from sentry.utils.settings import is_self_hosted

logger: logging.Logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/email_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import Endpoint, region_silo_endpoint
from sentry.api.serializers.rest_framework.base import CamelSnakeSerializer
from sentry.utils.demo_mode import is_demo_mode_enabled
from sentry.demo_mode.utils import is_demo_mode_enabled
from sentry.utils.marketo_client import MarketoClient

client = MarketoClient()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
from sentry.api.base import region_silo_endpoint
from sentry.api.bases.organization import OrganizationEndpoint
from sentry.auth.services.auth import auth_service
from sentry.demo_mode.utils import is_demo_user
from sentry.hybridcloud.models.outbox import outbox_context
from sentry.models.organizationmember import InviteStatus, OrganizationMember
from sentry.notifications.notifications.organization_request import JoinRequestNotification
from sentry.notifications.utils.tasks import async_send_notification
from sentry.signals import join_request_created
from sentry.types.ratelimit import RateLimit, RateLimitCategory
from sentry.users.api.parsers.email import AllowedEmailField
from sentry.utils.demo_mode import is_demo_user

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/setup_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from sentry.api.base import Endpoint, control_silo_endpoint
from sentry.api.serializers import serialize
from sentry.cache import default_cache
from sentry.utils.demo_mode import is_demo_user
from sentry.demo_mode.utils import is_demo_user

logger = logging.getLogger("sentry.api")
SETUP_WIZARD_CACHE_KEY = "setup-wizard-keys:v1:"
Expand Down
21 changes: 11 additions & 10 deletions src/sentry/api/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
from sentry.auth.staff import has_staff_option, is_active_staff
from sentry.auth.superuser import SUPERUSER_ORG_ID, is_active_superuser
from sentry.auth.system import is_system_auth
from sentry.demo_mode.utils import get_readonly_scopes, is_demo_mode_enabled, is_demo_user
from sentry.hybridcloud.rpc import extract_id_from
from sentry.models.orgauthtoken import is_org_auth_token_auth, update_org_auth_token_last_used
from sentry.organizations.services.organization import (
RpcOrganization,
RpcUserOrganizationContext,
organization_service,
)
from sentry.utils import auth, demo_mode
from sentry.utils import auth

if TYPE_CHECKING:
from rest_framework.views import APIView
Expand Down Expand Up @@ -300,9 +301,9 @@ def determine_access(

assert org_context is not None, "Failed to fetch organization in determine_access"

if demo_mode.is_demo_user(request.user):
if org_context.member and demo_mode.is_demo_mode_enabled():
readonly_scopes = demo_mode.get_readonly_scopes()
if is_demo_user(request.user):
if org_context.member and is_demo_mode_enabled():
readonly_scopes = get_readonly_scopes()
org_context.member.scopes = sorted(readonly_scopes)
request.access = access.from_request_org_and_scopes(
request=request,
Expand All @@ -315,15 +316,15 @@ def determine_access(
return super().determine_access(request, org_context)

def has_permission(self, request: Request, view: APIView) -> bool:
if demo_mode.is_demo_user(request.user):
if not demo_mode.is_demo_mode_enabled() or request.method not in SAFE_METHODS:
if is_demo_user(request.user):
if not is_demo_mode_enabled() or request.method not in SAFE_METHODS:
return False

return super().has_permission(request, view)

def has_object_permission(self, request: Request, view: APIView, obj: Any) -> bool:
if demo_mode.is_demo_user(request.user):
if not demo_mode.is_demo_mode_enabled() or request.method not in SAFE_METHODS:
if is_demo_user(request.user):
if not is_demo_mode_enabled() or request.method not in SAFE_METHODS:
return False

return super().has_object_permission(request, view, obj)
Expand All @@ -335,13 +336,13 @@ class SentryIsAuthenticated(IsAuthenticated):
"""

def has_permission(self, request: Request, view: APIView) -> bool:
if demo_mode.is_demo_user(request.user):
if is_demo_user(request.user):
return False

return super().has_permission(request, view)

def has_object_permission(self, request: Request, view: APIView, obj: Any) -> bool:
if demo_mode.is_demo_user(request.user):
if is_demo_user(request.user):
return False

return super().has_object_permission(request, view, obj)
14 changes: 13 additions & 1 deletion src/sentry/conf/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,11 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str:
Queue("outbox.control", routing_key="outbox.control", exchange=control_exchange),
Queue("webhook.control", routing_key="webhook.control", exchange=control_exchange),
Queue("relocation.control", routing_key="relocation.control", exchange=control_exchange),
Queue(
"release_registry.control",
routing_key="release_registry.control",
exchange=control_exchange,
),
]

CELERY_ISSUE_STATES_QUEUE = Queue(
Expand Down Expand Up @@ -999,6 +1004,7 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str:
Queue("check_new_issue_threshold_met", routing_key="check_new_issue_threshold_met"),
Queue("integrations_slack_activity_notify", routing_key="integrations_slack_activity_notify"),
Queue("demo_mode", routing_key="demo_mode"),
Queue("release_registry", routing_key="release_registry"),
]

from celery.schedules import crontab
Expand Down Expand Up @@ -1054,6 +1060,12 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str:
"schedule": timedelta(seconds=10),
"options": {"expires": 60, "queue": "webhook.control"},
},
"fetch-release-registry-data-control": {
"task": "sentry.tasks.release_registry.fetch_release_registry_data_control",
# Run every 5 minutes
"schedule": crontab(minute="*/5"),
"options": {"expires": 3600, "queue": "release_registry.control"},
},
}

# Most tasks run in the regions
Expand Down Expand Up @@ -1181,7 +1193,7 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str:
"task": "sentry.tasks.release_registry.fetch_release_registry_data",
# Run every 5 minutes
"schedule": crontab(minute="*/5"),
"options": {"expires": 3600},
"options": {"expires": 3600, "queue": "release_registry"},
},
"snuba-subscription-checker": {
"task": "sentry.snuba.tasks.subscription_checker",
Expand Down
55 changes: 30 additions & 25 deletions src/sentry/demo_mode/tasks.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from datetime import timedelta

import sentry_sdk
from django.db import router
from django.db.models import Q
from django.db.utils import IntegrityError
from django.utils import timezone

from sentry import options
from sentry.demo_mode.utils import get_demo_org, is_demo_mode_enabled
from sentry.models.artifactbundle import (
ArtifactBundle,
ProjectArtifactBundle,
Expand All @@ -15,7 +18,6 @@
from sentry.models.project import Project
from sentry.tasks.base import instrumented_task
from sentry.utils.db import atomic_transaction
from sentry.utils.demo_mode import get_demo_org, is_demo_mode_enabled


@instrumented_task(
Expand Down Expand Up @@ -63,33 +65,36 @@ def _sync_artifact_bundles(source_org: Organization, target_org: Organization, l


def _sync_artifact_bundle(source_artifact_bundle: ArtifactBundle, target_org: Organization):
with atomic_transaction(
using=(
router.db_for_write(ArtifactBundle),
router.db_for_write(FileBlobOwner),
router.db_for_write(ProjectArtifactBundle),
router.db_for_write(ReleaseArtifactBundle),
)
):
blobs = source_artifact_bundle.file.blobs.all()
for blob in blobs:
FileBlobOwner.objects.create(
try:
with atomic_transaction(
using=(
router.db_for_write(ArtifactBundle),
router.db_for_write(FileBlobOwner),
router.db_for_write(ProjectArtifactBundle),
router.db_for_write(ReleaseArtifactBundle),
)
):
blobs = source_artifact_bundle.file.blobs.all()
for blob in blobs:
FileBlobOwner.objects.get_or_create(
organization_id=target_org.id,
blob_id=blob.id,
)

target_artifact_bundle = ArtifactBundle.objects.create(
organization_id=target_org.id,
blob_id=blob.id,
bundle_id=source_artifact_bundle.bundle_id,
artifact_count=source_artifact_bundle.artifact_count,
date_last_modified=source_artifact_bundle.date_last_modified,
date_uploaded=source_artifact_bundle.date_uploaded,
file=source_artifact_bundle.file,
indexing_state=source_artifact_bundle.indexing_state,
)

target_artifact_bundle = ArtifactBundle.objects.create(
organization_id=target_org.id,
bundle_id=source_artifact_bundle.bundle_id,
artifact_count=source_artifact_bundle.artifact_count,
date_last_modified=source_artifact_bundle.date_last_modified,
date_uploaded=source_artifact_bundle.date_uploaded,
file=source_artifact_bundle.file,
indexing_state=source_artifact_bundle.indexing_state,
)

_sync_project_artifact_bundle(source_artifact_bundle, target_artifact_bundle)
_sync_release_artifact_bundle(source_artifact_bundle, target_artifact_bundle)
_sync_project_artifact_bundle(source_artifact_bundle, target_artifact_bundle)
_sync_release_artifact_bundle(source_artifact_bundle, target_artifact_bundle)
except IntegrityError as e:
sentry_sdk.capture_exception(e)


def _sync_project_artifact_bundle(
Expand Down
File renamed without changes.
6 changes: 2 additions & 4 deletions src/sentry/features/temporary.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ def register_temporary_features(manager: FeatureManager):
manager.add("organizations:gen-ai-features", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable disabling gitlab integrations when broken is detected
manager.add("organizations:gitlab-disable-on-broken", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Allow creating `GroupHashMetadata` records
manager.add("organizations:grouphash-metadata-creation", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Allow events with hybrid fingerprints to be sent to Seer for grouping
manager.add("organizations:grouping-hybrid-fingerprint-seer-usage", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Enable increased issue_owners rate limit for auto-assignment
Expand Down Expand Up @@ -158,6 +156,8 @@ def register_temporary_features(manager: FeatureManager):
manager.add("organizations:issue-search-snuba", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Enable issue stream table layout changes
manager.add("organizations:issue-stream-table-layout", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable issue view sharing
manager.add("organizations:issue-view-sharing", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
manager.add("organizations:large-debug-files", OrganizationFeature, FeatureHandlerStrategy.INTERNAL, api_expose=False)
manager.add("organizations:metric-issue-poc", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
manager.add("projects:metric-issue-creation", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
Expand Down Expand Up @@ -431,8 +431,6 @@ def register_temporary_features(manager: FeatureManager):
manager.add("organizations:uptime-create-issues", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Enables uptime related settings for projects and orgs
manager.add('organizations:uptime-settings', OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Disallows creation of uptime monitors
manager.add('organizations:uptime-create-disabled', OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enables detailed logging for uptime results
manager.add("organizations:uptime-detailed-logging", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
manager.add("organizations:use-metrics-layer", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
Expand Down
17 changes: 14 additions & 3 deletions src/sentry/grouping/ingest/grouphash_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,10 @@ def create_or_update_grouphash_metadata_if_needed(
logger.info(
"grouphash_metadata.creation_race_condition.record_exists",
extra={
"grouphash_metadata_id": grouphash_metadata.id,
"linked_metadata_id": grouphash.metadata.id if grouphash.metadata else None,
"grouphash_id": grouphash.id,
"grouphash_is_new": grouphash_is_new,
"grouphash_has_group": bool(grouphash.group_id),
"event_id": event.event_id,
"hash_basis": new_data["hash_basis"],
"hash": grouphash.hash,
},
)
Expand All @@ -162,6 +160,19 @@ def create_or_update_grouphash_metadata_if_needed(
event.should_skip_seer = True
return

# TODO: Temporary log to investigate race condition. Restricted to grouphashes without an
# assigned group because those are the only ones which might get sent to Seer.
if not grouphash.group_id:
logger.info(
"grouphash_metadata.creation_race_condition.no_group_id",
extra={
"grouphash_id": grouphash.id,
"grouphash_is_new": grouphash_is_new,
"event_id": event.event_id,
"hash": grouphash.hash,
},
)

db_hit_metadata = {"reason": "new_grouphash" if grouphash_is_new else "missing_metadata"}

if not grouphash_is_new:
Expand Down
Loading

0 comments on commit 993b04b

Please sign in to comment.