Skip to content

ref(redis): expose diagnostics-channel subscription as an integration - #21963

Merged
logaretm merged 2 commits into
developfrom
awad/redis-dc-integration-plugin
Jul 7, 2026
Merged

ref(redis): expose diagnostics-channel subscription as an integration#21963
logaretm merged 2 commits into
developfrom
awad/redis-dc-integration-plugin

Conversation

@logaretm

@logaretmlogaretm commented Jul 4, 2026

Copy link
Copy Markdown
Member

The redis diagnostics-channel work exported a raw subscribeRedisDiagnosticChannels from @sentry/server-utils that node and deno called directly. That predated the extendIntegration API, so this brings it in line with the other integrations.

I don't think this is a breaking change because server-utils is a private-ish package for us.

While in here I dropped a few things that were only there to work around the raw export:

  • the subscribed guard, since there's now a single deduped setupOnce caller, so it guarded a path that can't happen
  • the activeUnbinds array and _resetRedisDiagnosticChannelsForTesting export, which only existed so tests could detach handlers between runs. The subscriber tests now subscribe once in beforeAll and lean on process isolation, same as the graphql tests

I left the enclosing-span behavior alone for now (redis still creates spans without an active parent, unlike mysql2). Happy to argue that separately.

Stop exporting the raw subscribeRedisDiagnosticChannels from @sentry/server-utils
and expose a redisIntegration plugin instead, mirroring the mysql2 and graphql
subscribers. The node and deno integrations now extend that base plugin rather
than calling subscribe directly (the raw export predated the extendIntegration API).
Drop the redundant subscribed guard, the activeUnbinds bookkeeping, the module-level
response hook, and the _resetRedisDiagnosticChannelsForTesting export. The subscriber
has a single deduped setupOnce caller, so the guard protected a path that can't occur;
the response hook is captured via closure. Tests subscribe once in beforeAll and rely
on process isolation instead of unbind/reset, matching the graphql subscriber tests.
@logaretm
logaretm requested a review from a team as a code ownerJuly 4, 2026 04:44
@logaretm
logaretm requested review from JPeer264, andreiborza and mydea and removed request for a teamJuly 4, 2026 04:44

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit aa0e0d1. Configure here.

// `bindTracingChannelToSpan` (inside the subscriber) makes the span the active
// OTel context via `bindStore`, which needs the Sentry OTel context manager to
// be registered — `initOpenTelemetry()` does that after integration `setupOnce`,
// so defer to the next tick.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preload skips Redis channel subscribe

Medium Severity

Diagnostics-channel Redis subscription moved into redisIntegrationsetupOnce, but instrumentRedis (still invoked from preloadOpenTelemetry) no longer registers those handlers. Preload-only or preload-before-init flows can run Redis against node-redis/ioredis ≥5.11 without ever subscribing, so native channel tracing stays off until full SDK init.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit aa0e0d1. Configure here.

@github-actions

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.24 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.01 kB--
@sentry/browser (incl. Tracing, Profiling)51.01 kB--
@sentry/browser (incl. Tracing, Replay)85.49 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.1 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.19 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.84 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.51 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.11 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.24 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.54 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.77 kB--
CDN Bundle (incl. Tracing, Replay)85.7 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.49 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.78 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.96 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.93 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.59 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed264.97 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed268.93 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.68 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.62 kB--
@sentry/nextjs (client)50.95 kB--
@sentry/sveltekit (client)46.65 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.73 kB--
@sentry/node-core63.2 kB--
@sentry/node123.14 kB-0.05%-58 B 🔽
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB-0.01%-1 B 🔽
@sentry/node - without tracing74.24 kB-0.01%-1 B 🔽
@sentry/aws-serverless85.02 kB--
@sentry/cloudflare (withSentry) - minified181.56 kB--
@sentry/cloudflare (withSentry)449.18 kB--

View base workflow run

@logaretm
logaretm requested a review from isaacsJuly 6, 2026 18:05

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation LGTM. I added couple of concerns.

});

describe('idempotency', () => {
it('does not re-subscribe on a second call, but updates the response hook', async () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Why was this removed?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setupOnce guarantees that, this was a unit test that tested the subscription only happening once which wouldn't pass now since the "install once" is handled by the integration wrapper not the sub function.

*/

export { mongooseIntegration } from './mongoose';
export {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: I know you meant that this is private-ish, still I would vote to keep these here as it is a public package (even though it is highly unlikely that someone used it. I think deprecating these exports would be a better way IMO

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the opposite, semver guarantees on previously internal was never promised. So I'm exercising that here to align with the other integrations. WDYT? Maybe we can sample more opinions?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

semver guarantees on previously internal was never promised

That is correct, do we set this promise somewhere for this package now? It'd be good to clarify in general what counts as "internal" now

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double checked. We set this in our README, so I think we're good here

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks! We also said this here, but no one reads that i think.

if (subscribed) return;
subscribed = true;

try {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q/l: Any reason why the try/catch block got removed? I think keeping it wouldn't harm

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions never throw, so a reset/re-install behavior was never going to happen, so it is redundant.

isaacs thought so too in other PRs so I'm applying them here. I don't mind having a try/catch tbh just in case but I think we need to consistently do or don't do them.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya I cross-checked true. Thanks for confirming

@logaretm
logaretm merged commit 5b945a6 into developJul 7, 2026
388 of 390 checks passed
@logaretm
logaretm deleted the awad/redis-dc-integration-plugin branch July 7, 2026 16:07
chargome added a commit that referenced this pull request Jul 8, 2026
…instrumentation-redis-to-orchestrion
Resolve conflict in redis integration: keep this branch's skip-both-OTel-patches
logic (branch adds orchestrion redisConfig for node-redis <5.12.0), adopt develop's
extendIntegration structure where the diagnostics-channel subscription is handled by
the shared server-utils redisChannelIntegration (#21963).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@logaretm@JPeer264