Skip to content

feat(effect): Remove effectLayer auto composition#19823

Merged
JPeer264 merged 2 commits intojp/add-effect-sdkfrom
jp/add-effect-sdk-stack/9
Mar 17, 2026
Merged

feat(effect): Remove effectLayer auto composition#19823
JPeer264 merged 2 commits intojp/add-effect-sdkfrom
jp/add-effect-sdk-stack/9

Conversation

@JPeer264
Copy link
Member

@JPeer264 JPeer264 commented Mar 16, 2026

There are 2 changes in this PR:

  1. No auto-injection anymore
  2. Removal of the OP and the span names. We fully rely now on Effect as much as possible (related: feat(effect): Add @sentry/effect SDK (alpha) #19644 (comment))

About the removal of auto injection of traces, logs or metrics from the Sentry.effectLayer: this means that Sentry.effectLayer is only initializing the browser/node client. So the usages in comparison for logs and traces:

before:

Layer.provide(Sentry.effectLayer({
  dsn: '',
  tracesSampleRate: 1.0,
  enableLogs: true,
  enableEffectLogs: true,
}));

after:

import * as Layer from "effect/Layer";
import * as Logger from "effect/Logger"

Layer.mergeAll(
  Sentry.effectLayer({
    dsn: '',
    tracesSampleRate: 1.0,
    enableLogs: true,
  },
  Layer.setTracer(Sentry.SentryEffectTracer),
  Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger)
));

The benefit of this is to have a unified usage between browser and node, which also follows the usage of Effect, so users have to actively set the tracer with setTracer or replace the logger with Logger.replace. There is no extra opt-in via enableEffectLogs or enableEffectMetrics, this would also remove the confusion of not having the enableEffectTraces option (which didn't exist before, nor would have existed in any future versions)

This was discussed offline with @Lms24 to have this. In the first alpha we can always shift if there is the need, but this is now way cleaner. I ask myself now if Sentry.effectLayer is now the best function name.

@JPeer264 JPeer264 requested review from Lms24 and s1gr1d March 16, 2026 14:20
@JPeer264 JPeer264 self-assigned this Mar 16, 2026
const newSpan = startInactiveSpan({
name: spanName,
op: deriveOp(name, kind),
name,
Copy link

Choose a reason for hiding this comment

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

Missing SEMANTIC_ATTRIBUTE_SENTRY_OP in startInactiveSpan call

Medium Severity

The startInactiveSpan call no longer sets SEMANTIC_ATTRIBUTE_SENTRY_OP ('sentry.op'). The deriveOp function and the op parameter were removed as part of this PR. Per project rules, when calling any startSpan API, SEMANTIC_ATTRIBUTE_SENTRY_OP must always be set with a proper span op. The origin attribute is still correctly set, but the op attribute is missing entirely from the attributes object.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

@github-actions
Copy link
Contributor

github-actions bot commented Mar 16, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.64 kB added added
@sentry/browser - with treeshaking flags 24.14 kB added added
@sentry/browser (incl. Tracing) 42.62 kB added added
@sentry/browser (incl. Tracing, Profiling) 47.28 kB added added
@sentry/browser (incl. Tracing, Replay) 81.42 kB added added
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 71 kB added added
@sentry/browser (incl. Tracing, Replay with Canvas) 86.12 kB added added
@sentry/browser (incl. Tracing, Replay, Feedback) 98.37 kB added added
@sentry/browser (incl. Feedback) 42.45 kB added added
@sentry/browser (incl. sendFeedback) 30.31 kB added added
@sentry/browser (incl. FeedbackAsync) 35.36 kB added added
@sentry/browser (incl. Metrics) 26.92 kB added added
@sentry/browser (incl. Logs) 27.07 kB added added
@sentry/browser (incl. Metrics & Logs) 27.74 kB added added
@sentry/react 27.39 kB added added
@sentry/react (incl. Tracing) 44.95 kB added added
@sentry/vue 30.08 kB added added
@sentry/vue (incl. Tracing) 44.48 kB added added
@sentry/svelte 25.66 kB added added
CDN Bundle 28.27 kB added added
CDN Bundle (incl. Tracing) 43.5 kB added added
CDN Bundle (incl. Logs, Metrics) 29.13 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) 44.34 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) 68.2 kB added added
CDN Bundle (incl. Tracing, Replay) 80.32 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 81.22 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) 85.86 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 86.76 kB added added
CDN Bundle - uncompressed 82.56 kB added added
CDN Bundle (incl. Tracing) - uncompressed 128.5 kB added added
CDN Bundle (incl. Logs, Metrics) - uncompressed 85.43 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 131.37 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 209.06 kB added added
CDN Bundle (incl. Tracing, Replay) - uncompressed 245.35 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 248.21 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 258.26 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 261.11 kB added added
@sentry/nextjs (client) 47.37 kB added added
@sentry/sveltekit (client) 43.07 kB added added
@sentry/node-core 56.34 kB added added
@sentry/node 173.19 kB added added
@sentry/node - without tracing 96.35 kB added added
@sentry/aws-serverless 113.34 kB added added

Base automatically changed from jp/add-effect-sdk-stack/8 to jp/add-effect-sdk March 17, 2026 10:31
@JPeer264 JPeer264 force-pushed the jp/add-effect-sdk-stack/9 branch from 56f59d3 to cb6091d Compare March 17, 2026 10:33
Copy link

@cursor cursor bot left a comment

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.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

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

test('Sends an HTTP transaction', async ({ baseURL }) => {
const transactionEventPromise = waitForTransaction('effect-node', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
Copy link

Choose a reason for hiding this comment

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

Ambiguous E2E test transaction filters match wrong transactions

Medium Severity

The "Sends an HTTP transaction" and "Sends transaction for error route" tests both use the identical filter transactionEvent?.transaction === 'http.server GET' with no route-specific distinguishing criteria. Previously, filters included route paths like /test-success and /test-error. Now any http.server GET transaction satisfies both filters, making these tests flaky and unable to verify they received the transaction for the correct route.

Additional Locations (1)
Fix in Cursor Fix in Web

Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

Nice, thanks a lot for reworking the SDK setup. As you said, I think this sets a solid foundation and -- if necessary -- we can build on top of it.

expect(spans).toContainEqual(
expect.objectContaining({
description: 'custom-effect-span',
data: expect.objectContaining({
Copy link
Member

Choose a reason for hiding this comment

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

l: just checking, no action required: Does effect add any other attributes we could/should assert on?

(also, removing the op here sounds correct to me. Span kind doesn't map well to sentry ops and there's no internal op defined)

Copy link
Member Author

Choose a reason for hiding this comment

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

I added couple of more assertions to this specific test and removed the .toContainEqual in the file completely.

enableEffectLogs: true,
});
const SentryLive = Layer.mergeAll(
Sentry.effectLayer({
Copy link
Member

Choose a reason for hiding this comment

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

I think this is a fine setup and naming is also fine. To me (as an Effect noob), this signals that Sentry.effectLayer is the main one and the others are additional components. As long as we document this correctly, we should be good.

I have a question though: Does registering just the Sentry.effectLayer initialize error monitoring? This would be ideal, since errors should be part of the minimal Sentry setup. I believe you said for v4, we'll need an additional component for errors, which is also fine.

Copy link
Member Author

Choose a reason for hiding this comment

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

Does registering just the Sentry.effectLayer initialize error monitoring?

Theoretically it would do everything a Sentry.init would do, so if the process crashes or someone would throw an unhandled error then yes. Once we get support for the ErrorReporter in v4, we could think of auto adding this or adding it manually with the layer (currently leaning towards auto adding, but this is another discussion)

const newSpan = startInactiveSpan({
name: spanName,
op: deriveOp(name, kind),
name,
Copy link
Member

Choose a reason for hiding this comment

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

I think not adding an op is fine for the initial release. However, as discussed we should refine our deriveSpanName and deriveOp logic to make Effects' spans more Sentry-esque in the long run. For example, we need sentry.op and certain span names to make our Insights pages work correctly. This especially concerns http.server, http.client and db spans.

Again, for this release, I'd rather not have ops than incorrect ones though.

Comment on lines 109 to 113
@@ -117,10 +113,56 @@ describe.each([
expect(result).toBe(84);
Copy link
Member

Choose a reason for hiding this comment

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

l/q from an effect noob: does this test that our tracer works? Would it throw/not succeed if our tracer wasn't registered?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, it wouldn't really test if the tracer is not applied. This is more of a smoke test that the tracer wouldn't throw. The actual tests would be inside the E2E tests, I'll add a simple mechanism here to check if tracing is getting called

enableLogs: true,
}),
Layer.setTracer(Sentry.SentryEffectTracer),
Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger),
Copy link
Member

Choose a reason for hiding this comment

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

l: should we add the metrics layer here?

Copy link
Member Author

Choose a reason for hiding this comment

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

well said. Will add

@JPeer264 JPeer264 force-pushed the jp/add-effect-sdk-stack/9 branch from 587e9e2 to e8da292 Compare March 17, 2026 12:43
@JPeer264 JPeer264 requested a review from Lms24 March 17, 2026 12:44
@JPeer264 JPeer264 force-pushed the jp/add-effect-sdk-stack/9 branch from e8da292 to 6455f93 Compare March 17, 2026 12:49
Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

:shipit:

@JPeer264 JPeer264 merged commit 7eef9d9 into jp/add-effect-sdk Mar 17, 2026
34 checks passed
@JPeer264 JPeer264 deleted the jp/add-effect-sdk-stack/9 branch March 17, 2026 13:23
JPeer264 added a commit that referenced this pull request Mar 17, 2026
There are 2 changes in this PR:

1. No auto-injection anymore
2. Removal of the OP and the span names. We fully rely now on Effect as
much as possible (related:
#19644 (comment))

About the removal of auto injection of traces, logs or metrics from the
`Sentry.effectLayer`: this means that `Sentry.effectLayer` is **only**
initializing the browser/node client. So the usages in comparison for
logs and traces:

before:
```js
Layer.provide(Sentry.effectLayer({
  dsn: '',
  tracesSampleRate: 1.0,
  enableLogs: true,
  enableEffectLogs: true,
}));
```

after:

```js
import * as Layer from "effect/Layer";
import * as Logger from "effect/Logger"

Layer.mergeAll(
  Sentry.effectLayer({
    dsn: '',
    tracesSampleRate: 1.0,
    enableLogs: true,
  },
  Layer.setTracer(Sentry.SentryEffectTracer),
  Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger)
));
```

The benefit of this is to have a unified usage between browser and node,
which also follows the usage of Effect, so users have to actively set
the tracer with `setTracer` or replace the logger with `Logger.replace`.
There is no extra opt-in via `enableEffectLogs` or
`enableEffectMetrics`, this would also remove the confusion of not
having the `enableEffectTraces` option (which didn't exist before, nor
would have existed in any future versions)

This was discussed offline with @Lms24 to have this. In the first alpha
we can always shift if there is the need, but this is now way cleaner. I
ask myself now if `Sentry.effectLayer` is now the best function name.
Sign up for free to 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