[pull] master from getsentry:master#1805
Merged
pull[bot] merged 50 commits intoKingDEV95:masterfrom Mar 18, 2026
Merged
Conversation
## Problem All endpoints using `SimpleEventSerializer` suffer from N+1 nodestore/Bigtable lookups: `GroupEventsEndpoint`, `ProjectEventsEndpoint`, and `GroupHashesEndpoint`. ### Evidence from production traces Searching for `SimpleEventSerializer` spans >2s in the last 7 days shows widespread impact, with the worst at **22 seconds**: | Trace | Transaction | Duration | |---|---|---| | [`4c9c9a51...`](https://sentry.sentry.io/explore/traces/trace/4c9c9a51cf67459b871db190b5325cc1) | `/api/0/issues\|groups/{issue_id}/events/` | 22.2s | | [`cfda6d45...`](https://sentry.sentry.io/explore/traces/trace/cfda6d453fe7466da7648a625c02847c) | `/api/0/organizations/{org}/issues\|groups/{issue_id}/events/` | 21.8s | | [`70dba92a...`](https://sentry.sentry.io/explore/traces/trace/70dba92a9165454f83bca9005fa6c14f) | `/api/0/organizations/{org}/issues\|groups/{issue_id}/events/` | 21.7s | Here is a detailed breakdown of one representative trace ([`34432d12...`](https://sentry.sentry.io/explore/traces/trace/34432d124b9a4aca9fbc5d3dfe7a38c0/), span [`979c831f...`](https://sentry.sentry.io/explore/traces/trace/34432d124b9a4aca9fbc5d3dfe7a38c0/?node=span-979c831fb8154304)): | Operation | Count | Total Duration | Avg Duration | |---|---|---|---| | `bigtable.get` | 97 | 8,701ms | 89.7ms | | `nodestore.get` | 100 | 9,261ms | 92.6ms | ``` http.server 9,779ms └─ ratelimit.__call__ 9,758ms └─ http.client (gateway→region) 9,753ms └─ http.server 9,703ms └─ ratelimit.__call__ 9,684ms └─ GroupEventsEndpoint.get 9,591ms └─ paginate.on_results 9,466ms ← HERE └─ SimpleEventSerializer 9,466ms └─ get_attrs 9,423ms └─ 100× nodestore.get → bigtable.get ``` ### Root cause `SimpleEventSerializer.serialize()` accesses properties like `obj.tags`, `obj.message`, `obj.title`, and `obj.get_event_metadata()` that fall through to nodestore when the corresponding Snuba columns are missing from `_snuba_data`. Callers typically only provide a handful of Snuba columns (`id`, `project.id`, `issue.id`, `timestamp`), so every property access on every event triggers a separate lazy Bigtable fetch — an N+1 pattern. ## Fix Add `eventstore.backend.bind_nodes()` in `SimpleEventSerializer.get_attrs()` to batch-fetch all event bodies in a single `get_multi` → `BigtableKVStorage.read_rows(RowSet)` RPC before serialization begins. Placing the fix in the **serializer** rather than individual endpoints ensures **all callers benefit** — `GroupEventsEndpoint`, `ProjectEventsEndpoint`, `GroupHashesEndpoint`, and any future users. ### Rollback The `issues.group_events.batch_nodestore_enabled` option (default: `True`) can be set to `False` via configoptions for instant rollback without a deploy. ### Expected performance impact - **Before**: ~100 sequential Bigtable RPCs × ~93ms = **~9.3 seconds** - **After**: 1 batched Bigtable `read_rows` call = **~150–400ms** - **Improvement**: ~25–60× faster serialization ### Why this is safe - `bind_nodes()` is **idempotent** and well-exercised — `EventSerializer` (the full serializer) already relies on callers to use it - `SimpleEventSerializer` already handles nodestore-backed data correctly (it just wasn't pre-loaded) - **No API response shape changes** — the same data is returned, just fetched more efficiently - `bind_nodes` accesses `NodeData.id` (not `.data`) to collect node IDs, so it does **not** trigger lazy fetches itself ## Follow-up opportunity A deeper fix would add the missing columns (`title`, `culprit`, `location`, `platform`, `event.type`, `tags.key`, `tags.value`, `user.*`, `message`) to the Snuba queries and pass them through to `_snuba_data`. This would eliminate the nodestore round-trip entirely for `SimpleEventSerializer`. However, `message` and `get_event_metadata()` have **no Snuba fallback** in the `BaseEvent` model, so they'd need new fallback paths. That's a bigger change — this batching fix gives most of the speedup with minimal blast radius.
We allow setting arbitrary extra props in image manifest data. But we inadvertently strip those values when passing the manifest data to the frontend. This ensures we pass the extra props to the frontend and also preserve our first-class params.
Allow users to select different metrics in the y-axis for widgets. The code paths for updating the aggregates should be feature flagged so users without the feature flag will still see both metrics updating if they switch. This is because there's downstream work that needs to happen e.g. Open in Explore, group by field options, etc Essentially uses the index we pass along as the metric select row's identifier to update _just_ that single metric. The query works as expected, but⚠️ there is a bug where the labels aren't showing both series properly, I will make sure I fix that soon. For this case, it's sufficient to verify that the right `events-timeseries` request is being made when multiple metrics are selected and the other selected y-axes don't reset unexpectedly.
…0898) Pre-resolve stacktrace frame paths in Sentry before sending to Seer for autofix, using Sentry's existing code mapping + platform munging infrastructure. **What it does:** For each in-app stacktrace frame, applies `convert_stacktrace_frame_path_to_source_path` (which includes platform-specific munging for Java, Cocoa, Flutter) and sets `repo_name` directly on the frame dict in the serialized event before sending to Seer. **Motivation:** Large monorepos cause autofix to timeout because Seer's `_get_git_tree()` has to enumerate every file path via the GitHub API, which can require hundreds of recursive API calls when the tree is truncated. Sentry already has code mappings configured automatically / by users — by pre-resolving frames here, Seer can skip the tree fetch entirely. Gated behind the `organizations:autofix-send-code-mappings` feature flag. **Companion Seer PR:** getsentry/seer#5314 — adds an early-return in `process_stacktrace_paths` to skip the git tree fetch when all frames already have `repo_name` set. Without the Seer PR, frames would still be correctly attributed (Seer's per-frame `repo_name is None` check skips pre-resolved frames), but the tree would still be fetched unnecessarily. **Deploy the Seer PR first.** --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Migrates the `/settings/account/notifications/email` pages to new form system. - Replaces `styled` components with core layout components - Replaces `useLocation` with `useQueryState` - Removes dead code (`AccountNotificationsByOrganization` is not accessible) Barely any visual diff, big code cleanup. | Before | After | |--------|--------| | <img width="3024" height="1725" alt="email-before" src="https://github.com/user-attachments/assets/8d578e77-73fd-4280-88af-cca6aa77a1b2" /> | <img width="3024" height="1725" alt="email-after" src="https://github.com/user-attachments/assets/e36f9dfe-b137-4cb8-afaa-1161d69ec992" /> |
Fix nav link and superuser warning styles. I'm adding snapshot tests so we can avoid this in the future. These should also come in handy as I start to work on the page frame UI
…rects (#110498) Attempt to address some of the [remaining](https://sentry.sentry.io/explore/logs/?aggregateField=%7B%22groupBy%22%3A%22route%22%7D&aggregateField=%7B%22yAxes%22%3A%5B%22count%28message%29%22%5D%7D&logsFields=timestamp&logsFields=message&logsFields=route&logsQuery=message%3A%2AUnexpected%2Anavigation%2Aredirect%2A&logsSortBys=-timestamp&mode=aggregate&project=11276&statsPeriod=7d) redirect log messages --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jonas <JonasBa@users.noreply.github.com>
Follow up to #110785 to add the `owner` field to the `WorkflowSerializer` response now that we actually save and update it if passed. The front end can use it to display who owns the workflow/alert.
…lorer handoff (#110952) Had decided to skip installation path and use client directly because claude didn't have a webhook url, but then agents weren't persisting between runs. Now, we use the path and the url is unused safely. Updated tests to match
Updated header height of primary and secondary navigation to match page frame designs and modify the primary nav items to visually align with our tab components. https://github.com/user-attachments/assets/4f0c47b4-17be-46da-b064-f37d29d4d8bb All of the changes are gated behind a feature flag, and I've decided to split the link rendering into separate components as rendering different layout and variants has grown nasty. Eventually, the pageFrameLinks will just entirely replace the link implementation and the old code can be deleted
…10927) We currently allow org:read for OrganizationDataForwardingDetailsPermissin meaning any org member can read Data Forwarding settings which can include sensitive values. Going to gate this behind org:write for only managers and above. It's the same as we do for OrganizationAuditPermission. Team admins are still able to use the PUT, so no trouble there. I considered changing what we expose here, like letting members still see the forwarding but redacting the `config` in the serializer when you don't have a wide enough scope, but that's not particularly useful as a user workflow. Team admins can do what they need and manager+ can see the real config to troubleshoot.
<!-- Describe your PR here. --> <!-- Sentry employees and contractors can delete or ignore the following. --> ### Legal Boilerplate Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.
…isabled (#110947) Before we didn't do a great job explaining why Seer is disabled. This is one condition that we can explain better, and give people the button to recover from. **Before** <img width="1081" height="235" alt="SCR-20260317-omwu" src="https://github.com/user-attachments/assets/da7074f9-21dc-4a8b-8666-838a0acbccf0" /> **After - as an admin** <img width="1083" height="250" alt="SCR-20260317-osha" src="https://github.com/user-attachments/assets/86e7054d-690a-401b-a6d5-ea1e84390275" /> **After - without write permissions** <img width="1079" height="247" alt="SCR-20260317-osnx" src="https://github.com/user-attachments/assets/e7cd06b3-2eca-46cb-b429-6cd5591ea2e9" /> --------- Co-authored-by: Billy Vong <billyvg@users.noreply.github.com>
Update links to skip the redirect, and link directly to the correct seer docs pages Depends on getsentry/sentry-docs#16835
Apply the same visual treatment to the secondary nav when pageframe feature is enabled <img width="300" height="326" alt="CleanShot 2026-03-17 at 16 15 25" src="https://github.com/user-attachments/assets/1a363e47-8ae9-437e-b5b5-b4758cae52a5" /> --------- Co-authored-by: Claude <noreply@anthropic.com>
Currently at debug level; want to understand how often this is happening in production. Info does what we want there.
…onents (#110937) The `EventOrGroupHeader`, `EventOrGroupTitle`, and `EventOrGroupExtraDetails` components previously accepted `Event | Group | GroupTombstoneHelper` but were already only really used with groups. With `Event` removed from the interface, the `EventOrGroup` so i've tried to rename them: - `EventOrGroupHeader` → `GroupHeaderRow` - `EventOrGroupTitle` → `GroupTitle` - `EventOrGroupExtraDetails` → `GroupMetaRow` Updated tests to make assertions instead of just rendering. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ag (#111005) Remove the `search-query-builder-explicit-boolean-filters` feature flag from the explore attribute context and all consuming metric components. Boolean attribute filtering is now always enabled. The flag was guarding boolean attribute loading and the logic that filters overlapping number attributes when a boolean version exists. This is now the default behavior, so the flag checks, associated `useOrganization` calls, and the `EMPTY_STRING_SET` constant are removed. Affected areas: - `traceItemAttributeContext` — core context that manages attribute types - `metricsSearchBar`, `aggregatesTab`, `filter`, `groupBySelector` — metric components that had redundant flag guards on `useTraceItemAttributeKeys` for boolean types --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…gy of the API backport project (#111006) This doc is intended to document our current strategy, act as a place to discuss strategy/scope changes, and an easy references for agents when evaluating PRs involved in this project.
…ng (#110886) + Register schedule_context_engine_indexing_tasks as an hourly Celery beat task, offset by 30 minutes from the explorer index task to spread load. + Add get_allowed_org_ids_context_engine_indexing which uses md5 hashing to deterministically assign each org to one of 168 weekly slots (24h × 7d), ensuring stable, uniform distribution regardless of allowlist changes. Also fix the schedule_explorer_index docstring to say hourly not daily. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Claude Sonnet 4 <noreply@example.com>
) This PR handles the options provided when multiple metrics are selected. We've chosen to go the easier route at first because it's the baseline functionality across different datasets, e.g. spans. e.g. if we select multiple metrics we: - fetch all attributes instead of scoping them down - disable recent searches - we have to do this because we added a small hack to recent searches where we share the tracemetrics enum in the backend, but we have a hidden filter that prefixes the metric name. This doesn't work well with multiple metrics.
- this allows the trace-attribute endpoint to be used without an explicit trace attribute type (returning all types) - As well as allowing multiple types to be requested as well
This PR puts the text widget form in the widget builder. We hide everything except for the title field, display type selector, and description field. All of this uses the session state text content. I've also made sure that all the edit flows send the text content into the session state and have tried to set it up so that if we have other fields like this in the future, the logic for opening the widget builder can handle this in one place. NOTE: the add to dashboard flow doesn't work yet and i'm doing that in a separate PR because this one is already kind of hefty. examples: <img width="1252" height="1036" alt="image" src="https://github.com/user-attachments/assets/e5df5dec-c39b-46ac-9fd5-5859d8833d1a" /> <img width="1231" height="624" alt="image" src="https://github.com/user-attachments/assets/58e8ad7f-08d8-4d47-aaec-beee8a605bc9" /> Closes [DAIN-1321](https://linear.app/getsentry/issue/DAIN-1321/text-widget-builder-form)
…111010) Adding a checking in the delete and the put after the existing has_release_permission, will help prevent members from deleting releases they shouldn't have access to. This is in part a child problem of https://github.com/getsentry/sentry/blob/master/src/sentry/api/bases/organization.py#L735-L739 which I'm going to correct afterward.
## Summary - Coalesce `undefined` to `null` when looking up widget footer table values - `.find()` returns `undefined` on no match, but the variable is typed `number | null` — the `as number` cast hides this at compile time, causing runtime "Cannot read properties of undefined" errors downstream - Added `?? null` to both lookup paths to keep the value within its declared type Fixes DAIN-1366
It can get us into infinite loops.
Have decided to assume that most claude users will actually keep the default workspace name. This allows us to show a link to their session automatically and they only need to override it in the case that they use a different one. Have also decided to remove the second step in the pipeline as now we have defaults for both sections of the form and so users only need to override if they want to. Updated tests to match.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- We need all the sentry migrations to have ran first before we run this explore one so we don't get errors about missing columns
Change claude integration to return full response text as description on coding agent card. This is the backend half which will be followed up with a frontend change.
This mirrors [`get_access_token` in the GitHub integration](https://github.com/getsentry/sentry/blob/master/src/sentry/integrations/github/client.py#L325-L355). To be used in #110987
also fixes integration control middleware readme: there is no such method get_responses_from_outbox_creation() referenced by the doc -- it's most likely supposed to be get_response_from_webhookpayload()
Bumping sentry-protos version to 0.8.6 after the latest release from this [PR](getsentry/sentry-protos#184).
…egration proxy (#111030) ## Summary - Add explicit handling for `ApiUnauthorized` and `ApiRateLimitedError` exceptions in the integration proxy endpoint, with dedicated failure metric types and logging - Add a warning-level log with `exception_class` for unknown errors to improve debugging visibility Agent transcript: https://claudescope.sentry.dev/share/t1d06MXJhqJXHLiOQoJ3l_tYycfgtt9wBO3ypV3W-9w
nit, use different verb for events than for issues <img width="373" height="77" alt="Screenshot 2026-03-18 at 2 37 36 PM" src="https://github.com/user-attachments/assets/5f36c275-c7cf-46bc-8a30-1d3b2869370d" />
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )