Draft PR: Effect Integration for Sentry Node SDK#17432
Draft PR: Effect Integration for Sentry Node SDK#17432Divyanshu7001 wants to merge 1 commit intogetsentry:developfrom
Conversation
|
Just a quick note - @Divyanshu7001 the auto formatting on your machine resulted in lots of unrelated files being changed that make it more difficult to digest this PR. |
I was afraid of the same thing & thats why used github codespaces with no local settings all open for it. |
|
Thanks for creating this PR! And to make sure we don't forget to review the PR you can assign e.g. me as a reviewer when you are ready. |
marbemac
left a comment
There was a problem hiding this comment.
@Divyanshu7001, after actually looking at it, I don't understand how this is supposed to work. Most of the interfaces and methods used are not present in effect.
I created a custom effect tracer for Sentry over here, if you are interested -> https://github.com/marbemac/cloudflare-sentry-effect-tracing/blob/main/worker/effect-sentry-tracer.ts.
| onSpanStart?: (span: EffectSpan) => void; | ||
| onSpanEnd?: (span: EffectSpan, exit: EffectExit) => void; |
| export interface EffectTracer { | ||
| onSpanStart?: (span: EffectSpan) => void; | ||
| onSpanEnd?: (span: EffectSpan, exit: EffectExit) => void; | ||
| span<A>(name: string, f: () => A): A; |
There was a problem hiding this comment.
The span method on custom tracers takes 6 args, not 2.
| onSpanStart?: (span: EffectSpan) => void; | ||
| onSpanEnd?: (span: EffectSpan, exit: EffectExit) => void; | ||
| span<A>(name: string, f: () => A): A; | ||
| withSpan<A>(span: EffectSpan, f: () => A): A; |
There was a problem hiding this comment.
Where can you find this in the effect tracer interface?
| if (typeof Effect.Tracer.set === 'function') { | ||
| Effect.Tracer.set(sentryTracer); | ||
| } else if (typeof Effect.Tracer.register === 'function') { | ||
| Effect.Tracer.register(sentryTracer); | ||
| } else if (typeof Effect.Tracer.use === 'function') { | ||
| Effect.Tracer.use(sentryTracer); | ||
| } else { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Where did you find these methods on the effect tracer? I do not think they exist.
Co-Authored-By: Jan Peer Stöcklmair <jan.peer@sentry.io>
66549ef to
194e173
Compare
| name: span.name, | ||
| op: 'effect.span', | ||
| origin: 'auto.effect', | ||
| startTime: Number(span.startTime) / 1000000, // Convert nanoseconds to milliseconds |
There was a problem hiding this comment.
Bug: The Effect integration incorrectly converts span timestamps from nanoseconds to milliseconds instead of seconds, causing all reported span timings to be off by a factor of 1000.
Severity: HIGH
Suggested Fix
Update the timestamp conversion logic to divide the nanosecond value by 1_000_000_000 to correctly convert it to seconds, which is the unit expected by the Sentry startSpan function. The line should be changed to startTime: Number(span.startTime) / 1_000_000_000.
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: packages/node/src/integrations/tracing/effect/effectIntegration.ts#L85
Potential issue: The Effect integration converts span start times from nanoseconds to
milliseconds by dividing the `BigInt` timestamp by `1,000,000`. However, the Sentry
`startSpan` function expects a numeric timestamp to be in seconds. As a result, a
timestamp representing 1 second (`1000` milliseconds) will be interpreted by Sentry as
1000 seconds. This will cause all span start times and durations to be reported
incorrectly by a factor of 1000, making the tracing data unusable.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 6 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| startTime: Number(span.startTime), | ||
| endTime: span.endTime ? Number(span.endTime) : undefined, | ||
| }); | ||
| captureException(exit.cause); |
There was a problem hiding this comment.
Missing mechanism parameter in captureException calls
Medium Severity
The captureException calls at lines 50, 72, and 105 are missing the mechanism parameter with handled and type properties. Other integrations like connect.ts, express.ts, and fastify/index.ts properly include { mechanism: { handled: false, type: 'auto.middleware.connect' } }. The mechanism should use a type like 'auto.effect' to align with the span origin.
Additional Locations (2)
| onSpanStart?: (span: EffectSpan) => void; | ||
| onSpanEnd?: (span: EffectSpan, exit: EffectExit) => void; | ||
| span<A>(name: string, f: () => A): A; | ||
| withSpan<A>(span: EffectSpan, f: () => A): A; |
There was a problem hiding this comment.
Effect tracer interface method signatures are incorrect
High Severity
The EffectTracer type definitions don't match Effect's actual tracer API. PR reviewer @marbemac noted that the span method takes 6 arguments, not 2, and the withSpan method doesn't exist in Effect's tracer interface. The implementation in effectIntegration.ts uses these incorrect signatures, meaning the integration won't work correctly with the actual Effect library.
Additional Locations (1)
|
|
||
| // Set status based on span status | ||
| if (span.status && span.status.code !== 0) { | ||
| sentrySpan.setStatus('internal_error'); |
There was a problem hiding this comment.
setStatus called with incorrect argument type
High Severity
The setStatus calls pass a plain string 'internal_error' but Span.setStatus() expects a SpanStatus object with code (number: 0, 1, or 2) and optional message properties. Other integrations in the codebase correctly use span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' }). This will cause the span status to not be set correctly.
Additional Locations (1)
| if (span.status && span.status.code !== 0) { | ||
| sentrySpan.setStatus('internal_error'); | ||
| if (span.status.message) { | ||
| sentrySpan.setData('effect.status_message', span.status.message); |
There was a problem hiding this comment.
| op: 'effect.span', | ||
| origin: 'auto.effect', | ||
| startTime: Number(span.startTime) / 1000000, // Convert nanoseconds to milliseconds | ||
| data: span.attributes, |
There was a problem hiding this comment.
Span attributes silently ignored due to wrong property name
Medium Severity
The startSpan call passes data: span.attributes but StartSpanOptions expects attributes, not data. This means the Effect span's attributes will be silently dropped and not transferred to the Sentry span, resulting in loss of trace context.
| { | ||
| name, | ||
| op: 'effect.span', | ||
| origin: 'auto.effect', |
There was a problem hiding this comment.
Span origin ignored because passed as wrong property
Medium Severity
The origin: 'auto.effect' property is passed directly on the startSpan options object, but StartSpanOptions doesn't have an origin property. The origin must be set via attributes using SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN. All Effect spans will incorrectly have origin 'manual' instead of 'auto.effect'.
Additional Locations (1)
|
Alright a little update here. I was now rebasing the PR so it is easier to review. I had a quick look at it and given that we need to install "Effect" as a dependency gives me the signal that we might need to add our own sdk for it: I'll clarify this or, latest, next week how we go forward with this PR. |


1. Goal
This PR adds support for tracing Effect computations in the Sentry Node SDK. The goal is to automatically create Sentry spans for Effect operations and capture errors that occur within Effect computations as Sentry exceptions, providing better observability for users of the Effect library.
2. Pathway Taken
effectIntegration) and instrumentation (instrumentEffect) under@sentry/node.effectpackage as a dependency and provided type definitions for Effect’s tracer API.3. How the integration has happened and where it is included now
packages/node/src/integrations/tracing/effect/.4. How users should integrate Effect into their own project
Basic usage:
Sentry.effectIntegration()to your integrations array.5. Where am i stuck / need help
6. What is my thinking about these errors?
I think these errors are due to me not being able to setup the test environment properly as in most errors..the problem is just Span processes being undefined.
I would appreciate some pointers of where i am going wrong and how should i setup the test environment properly to test.
closes #17126