Skip to content

[pull] master from getsentry:master#1805

Merged
pull[bot] merged 50 commits intoKingDEV95:masterfrom
getsentry:master
Mar 18, 2026
Merged

[pull] master from getsentry:master#1805
pull[bot] merged 50 commits intoKingDEV95:masterfrom
getsentry:master

Conversation

@pull
Copy link

@pull pull bot commented Mar 18, 2026

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 : )

BYK and others added 30 commits March 18, 2026 15:56
## 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
Follow up to #110785 and
#110381 to write and update the
owner on a workflow if that data is passed to the legacy endpoint and we
have the feature flag flipped so that we single write.

---------

Co-authored-by: Josh Callender <1569818+saponifi3d@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.
…flag (#110629)

Recreates #110522. ~Blocked on Node.js 24 being added to our internal
images, then internally using Node.js 24 instead of Node.js 22.~

Fixes ENG-7039.
…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.
wmak and others added 20 commits March 18, 2026 15:13
- 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.
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"
/>
@pull pull bot locked and limited conversation to collaborators Mar 18, 2026
@pull pull bot added the ⤵️ pull label Mar 18, 2026
@pull pull bot merged commit 559d1d6 into KingDEV95:master Mar 18, 2026
15 of 21 checks passed
@github-actions github-actions bot added Scope: Frontend Automatically applied to PRs that change frontend components Scope: Backend Automatically applied to PRs that change backend components labels Mar 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

⤵️ pull Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.