feat(subscriptions): Send the organization id for all subscriptions - #122733
feat(subscriptions): Send the organization id for all subscriptions#122733phacops wants to merge 2 commits into
Conversation
Only the metrics entity subscriptions sent an organization, via get_entity_extra_params, so Snuba could not attribute error or transaction subscription queries to an organization and fell back to a placeholder. Send it for every SnQL subscription. Metrics entities still send their own value, which continues to take precedence.
Sending a real organization for every subscription is handled in getsentry/sentry#122733, so the placeholder now only covers subscriptions stored before that change.
It holds an id, so name it accordingly. The legacy organization key that metrics entities send via get_entity_extra_params is unchanged.
| # Snuba attributes the resulting queries to this organization. Metrics entities | ||
| # additionally send a legacy `organization` key via get_entity_extra_params, | ||
| # which their subscription processors are configured with. | ||
| "organization_id": subscription.project.organization_id, |
There was a problem hiding this comment.
Bug: A deployment order dependency could cause subscription creation to fail if Snuba rejects the new organization_id field before it's updated to support it.
Severity: MEDIUM
Suggested Fix
To mitigate the deployment order risk, consider adding a feature flag or another form of forward compatibility check. This would allow the new organization_id field to be sent only when the corresponding Snuba version is known to be deployed, preventing subscription creation failures if Sentry is deployed first.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/sentry/snuba/tasks.py#L279-L282
Potential issue: The code adds an `organization_id` field to the payload for creating
Snuba subscriptions, which depends on a corresponding update in the Snuba service. If
this Sentry code is deployed before the Snuba update, Snuba might reject requests
containing the unknown field with a 4xx error. This would cause the
`_create_snql_in_snuba` function to raise a `SnubaError`, leading to the failure of the
subscription creation task. As a result, new alert subscriptions would fail to be
created and remain in a "CREATING" state until the Snuba service is updated.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Verified against current Snuba master (dffa2b529) — this is a false positive, and Sentry-first deploy is safe.
SnQLSubscriptionData.from_dict has no allowlist rejection path. Unrecognized keys are swept into metadata rather than refused:
for key in data:
if key not in SUBSCRIPTION_DATA_PAYLOAD_KEYS:
metadata[key] = data[key]The /subscriptions endpoint does no JSON-schema validation of the body either — it just calls SubscriptionDataCodec.decode. I ran the payload this PR sends against unmodified Snuba master:
OK events: metadata={'organization_id': 4567}
OK metrics_counters: metadata={'organization_id': 4567, 'organization': 4567}
So no 4xx, no SnubaError, no subscriptions stuck in CREATING. Old Snuba silently ignores the field, which makes this inert-until-supported rather than breaking.
Deploy order still matters for correctness (not safety): until getsentry/snuba#8400 lands, Snuba ignores organization_id for the events entity, so attribution keeps using the placeholder. That PR also adds an AddColumnCondition fallback so the metrics entities accept either key. It should merge first, but a Sentry-first deploy degrades gracefully rather than failing.
Pull request was closed
Snuba attributes subscription queries to an organization using a field in the subscription creation payload, but only the metrics entity subscriptions send one —
BaseMetricsEntitySubscription.get_entity_extra_params()returnsorganization, while the events and transactions implementations return{}. Error and transaction subscriptions therefore reach Snuba with no organization at all, and their queries fall back to a placeholder. Those are also the subscriptions that hit Snuba's post-replacement consistency processor, where per-organization behavior is being introduced._create_snql_in_snubaalready has the value on hand, so sendorganization_idfor every SnQL subscription. Metrics entities keep sending their ownorganizationviaget_entity_extra_params(), which is spread later in the dict and stays authoritative.Depends on getsentry/snuba#8400, which teaches Snuba to read the new key, persist it for entities that have no organization subscription processor, and accept either spelling in the metrics entities'
AddColumnCondition. That PR must be deployed first — the metrics processors raise when their configured key is missing, so the fallback needs to be live before this ships.Deploying this first is safe but useless rather than harmful: Snuba sweeps unrecognized payload keys into subscription metadata rather than rejecting them, and the
/subscriptionsendpoint does no schema validation of the body, so an older Snuba silently ignores the field. Verified against Snubamaster— no 4xx, noSnubaError, no subscriptions stranded inCREATING.Existing subscriptions keep their stored payloads until they are recreated, so attribution fills in over time rather than immediately.