Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions packages/node/src/integrations/tracing/redis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ const instrumentRedisModule = generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`
*/
export const instrumentRedis = Object.assign(
(): void => {
// When diagnostics-channel injection is opted in, orchestrion owns ioredis
// `<5.11.0`, so skip the OTel ioredis monkey-patch to avoid double instrumentation.
// On Node without `tracingChannel` (<18.19) orchestrion can't run, so keep the
// OTel patch there — otherwise ioredis `<5.11.0` would not be traced at all.
// When diagnostics-channel injection is opted in, orchestrion fully owns the older
// ioredis (`<5.11.0`) and redis/node-redis (`<5.12.0`) ranges — commands, connect, and
// batches — so skip both OTel monkey-patches to avoid double instrumentation. On Node
// without `tracingChannel` (<18.19) orchestrion can't run, so keep the OTel patches there.
if (!isDiagnosticsChannelInjectionEnabled() || !dc.tracingChannel) {
instrumentIORedis();
instrumentRedisModule();
}
instrumentRedisModule();
// node-redis >= 5.12.0 and ioredis >= 5.11.0 publish via diagnostics_channel.
// `bindTracingChannelToSpan` (inside the subscriber) makes the span the active
// OTel context via `bindStore`, which needs the Sentry OTel context manager to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
channelIntegrations,
ioredisChannelIntegration,
redisChannelIntegration,
detectOrchestrionSetup,
} from '@sentry/server-utils/orchestrion';
import { registerDiagnosticsChannelInjection } from '@sentry/server-utils/orchestrion/register';
Expand Down Expand Up @@ -51,12 +52,14 @@ export function experimentalUseDiagnosticsChannelInjection(): void {
const replacedOtelIntegrationNames = integrations.map(i => i.name);

return {
// ioredis is wired here rather than in the shared `channelIntegrations` registry: it needs
// the node redis cache `responseHook`, and it only partially replaces the composite OTel
// `Redis` integration (which also covers node-redis and ioredis >=5.11 native diagnostics_channel).
// So it's added to the integration set but kept OUT of `replacedOtelIntegrationNames` — `Redis`
// must stay; its ioredis <5.11 monkey-patch is gated off in `redisIntegration` instead.
integrations: [...integrations, ioredisChannelIntegration({ responseHook: cacheResponseHook })],
// ioredis and redis are wired separately (not in `channelIntegrations`): they need the node
// redis cache `responseHook` and only partially replace the composite OTel `Redis` integration,
// so they're kept OUT of `replacedOtelIntegrationNames` — `Redis` must stay (batch + >=5.11 native DC).
integrations: [
...integrations,
ioredisChannelIntegration({ responseHook: cacheResponseHook }),
redisChannelIntegration({ responseHook: cacheResponseHook }),
],
replacedOtelIntegrationNames,
register: registerDiagnosticsChannelInjection,
detect: detectOrchestrionSetup,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@ describe('instrumentRedis ioredis gating', () => {
expect(instrumentCalls).toContain('Redis.Redis');
});

it('skips the OTel ioredis monkey-patch when diagnostics-channel injection is enabled', () => {
it('skips both OTel monkey-patches when diagnostics-channel injection is enabled', () => {
injection.enabled = true;

instrumentRedis();

// ioredis is owned by orchestrion; node-redis is still instrumented by OTel.
expect(instrumentCalls).not.toContain('Redis.IORedis');
expect(instrumentCalls).toContain('Redis.Redis');
expect(instrumentCalls).not.toContain('Redis.Redis');
});
});
Loading
Loading