Skip to content

Commit 7ed7721

Browse files
authored
feat(effect): Export layers for browser | setTracer in buildEffectTracer (#19816)
This changes three things in one go: - Export `SentryEffectTracer`, `SentryEffectLogger` and `SentryEffectMetricsLayer` for bundle sizes in the browser (and node if they want to go that route) - Respect `tracesSampleRate` when using `Sentry.effectLayer`, so tracing is only added when needed - Moving `setTracer` outside of `SentryEffectTracerLayer` to make it Effect native, where users could call `setTracer` on their own if they want to
1 parent d5efd68 commit 7ed7721

File tree

7 files changed

+41
-26
lines changed

7 files changed

+41
-26
lines changed

packages/effect/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const MainLive = HttpLive.pipe(
2222
Layer.provide(
2323
Sentry.effectLayer({
2424
dsn: '__DSN__',
25+
tracesSampleRate: 1.0,
2526
enableLogs: true,
2627
enableEffectLogs: true,
2728
enableEffectMetrics: true,

packages/effect/src/index.client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ export * from '@sentry/browser';
55

66
export { effectLayer, init } from './client/index';
77
export type { EffectClientLayerOptions } from './client/index';
8+
9+
export { SentryEffectTracer } from './tracer';
10+
export { SentryEffectLogger } from './logger';
11+
export { SentryEffectMetricsLayer } from './metrics';

packages/effect/src/index.server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ export * from '@sentry/node-core/light';
22

33
export { effectLayer, init } from './server/index';
44
export type { EffectServerLayerOptions } from './server/index';
5+
6+
export { SentryEffectTracer } from './tracer';
7+
export { SentryEffectLogger } from './logger';
8+
export { SentryEffectMetricsLayer } from './metrics';

packages/effect/src/tracer.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import {
88
} from '@sentry/core';
99
import type * as Context from 'effect/Context';
1010
import * as Exit from 'effect/Exit';
11-
import type * as Layer from 'effect/Layer';
12-
import { setTracer } from 'effect/Layer';
1311
import * as Option from 'effect/Option';
1412
import * as EffectTracer from 'effect/Tracer';
1513

@@ -198,4 +196,4 @@ const makeSentryTracer = (): EffectTracer.Tracer =>
198196
/**
199197
* Effect Layer that sets up the Sentry tracer for Effect spans.
200198
*/
201-
export const SentryEffectTracerLayer: Layer.Layer<never, never, never> = setTracer(makeSentryTracer());
199+
export const SentryEffectTracer = makeSentryTracer();

packages/effect/src/utils/buildEffectLayer.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import type { Client } from '@sentry/core';
1+
import { hasSpansEnabled, type Client } from '@sentry/core';
22
import type * as EffectLayer from 'effect/Layer';
3-
import { empty as emptyLayer, provideMerge } from 'effect/Layer';
3+
import { empty as emptyLayer, provideMerge, setTracer } from 'effect/Layer';
44
import { defaultLogger, replace as replaceLogger } from 'effect/Logger';
55
import { SentryEffectLogger } from '../logger';
66
import { SentryEffectMetricsLayer } from '../metrics';
7-
import { SentryEffectTracerLayer } from '../tracer';
7+
import { SentryEffectTracer } from '../tracer';
88

99
export interface EffectLayerBaseOptions {
1010
enableEffectLogs?: boolean;
@@ -27,10 +27,15 @@ export function buildEffectLayer<T extends EffectLayerBaseOptions>(
2727
}
2828

2929
const clientOptions = client.getOptions();
30+
const hasSpans = hasSpansEnabled(clientOptions);
3031
const enableMetrics = clientOptions.enableMetrics ?? clientOptions._experiments?.enableMetrics ?? true;
3132
const enableLogs = clientOptions.enableLogs ?? clientOptions._experiments?.enableLogs ?? false;
3233
const { enableEffectLogs = false, enableEffectMetrics = false } = options;
33-
let layer: EffectLayer.Layer<never, never, never> = SentryEffectTracerLayer;
34+
let layer = emptyLayer;
35+
36+
if (hasSpans) {
37+
layer = layer.pipe(provideMerge(setTracer(SentryEffectTracer)));
38+
}
3439

3540
if (enableEffectLogs && enableLogs) {
3641
const effectLogger = replaceLogger(defaultLogger, SentryEffectLogger);

packages/effect/test/buildEffectLayer.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ describe('buildEffectLayer', () => {
136136
}),
137137
);
138138
startInactiveSpanSpy.mockRestore();
139-
}).pipe(Effect.provide(buildEffectLayer({}, createClient()))),
139+
}).pipe(Effect.provide(buildEffectLayer({}, createClient({ tracesSampleRate: 1.0 })))),
140140
);
141141
});
142142

packages/effect/test/tracer.test.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ import { describe, expect, it } from '@effect/vitest';
22
import * as sentryCore from '@sentry/core';
33
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
44
import { Effect } from 'effect';
5+
import { setTracer } from 'effect/Layer';
56
import { afterEach, vi } from 'vitest';
6-
import { SentryEffectTracerLayer } from '../src/tracer';
7+
import { SentryEffectTracer } from '../src/tracer';
78

8-
describe('SentryEffectTracerLayer', () => {
9+
const SentryTracerLayer = setTracer(SentryEffectTracer);
10+
11+
describe('SentryEffectTracer', () => {
912
afterEach(() => {
1013
vi.restoreAllMocks();
1114
});
@@ -22,15 +25,15 @@ describe('SentryEffectTracerLayer', () => {
2225
);
2326

2427
expect(capturedSpanName).toBe('effect-span-executed');
25-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
28+
}).pipe(Effect.provide(SentryTracerLayer)),
2629
);
2730

2831
it.effect('creates spans with correct attributes', () =>
2932
Effect.gen(function* () {
3033
const result = yield* Effect.withSpan('my-operation')(Effect.succeed('success'));
3134

3235
expect(result).toBe('success');
33-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
36+
}).pipe(Effect.provide(SentryTracerLayer)),
3437
);
3538

3639
it.effect('handles nested spans', () =>
@@ -43,7 +46,7 @@ describe('SentryEffectTracerLayer', () => {
4346
);
4447

4548
expect(result).toBe('outer-inner-result');
46-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
49+
}).pipe(Effect.provide(SentryTracerLayer)),
4750
);
4851

4952
it.effect('propagates span context through Effect fibers', () =>
@@ -60,7 +63,7 @@ describe('SentryEffectTracerLayer', () => {
6063
);
6164

6265
expect(results).toEqual(['parent-start', 'child-1', 'child-2', 'parent-end']);
63-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
66+
}).pipe(Effect.provide(SentryTracerLayer)),
6467
);
6568

6669
it.effect('handles span failures correctly', () =>
@@ -70,7 +73,7 @@ describe('SentryEffectTracerLayer', () => {
7073
);
7174

7275
expect(result).toBe('caught: expected-error');
73-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
76+
}).pipe(Effect.provide(SentryTracerLayer)),
7477
);
7578

7679
it.effect('handles span with defects (die)', () =>
@@ -80,7 +83,7 @@ describe('SentryEffectTracerLayer', () => {
8083
);
8184

8285
expect(result).toBe('caught-defect: defect-value');
83-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
86+
}).pipe(Effect.provide(SentryTracerLayer)),
8487
);
8588

8689
it.effect('works with Effect.all for parallel operations', () =>
@@ -94,7 +97,7 @@ describe('SentryEffectTracerLayer', () => {
9497
);
9598

9699
expect(results).toEqual([1, 2, 3]);
97-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
100+
}).pipe(Effect.provide(SentryTracerLayer)),
98101
);
99102

100103
it.effect('supports span annotations', () =>
@@ -105,7 +108,7 @@ describe('SentryEffectTracerLayer', () => {
105108
);
106109

107110
expect(result).toBe('annotated');
108-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
111+
}).pipe(Effect.provide(SentryTracerLayer)),
109112
);
110113

111114
it.effect('sets span status to ok on success', () =>
@@ -128,7 +131,7 @@ describe('SentryEffectTracerLayer', () => {
128131
expect(setStatusCalls).toContainEqual({ code: 1 });
129132

130133
mockStartInactiveSpan.mockRestore();
131-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
134+
}).pipe(Effect.provide(SentryTracerLayer)),
132135
);
133136

134137
it.effect('sets span status to error on failure', () =>
@@ -151,7 +154,7 @@ describe('SentryEffectTracerLayer', () => {
151154
expect(setStatusCalls).toContainEqual({ code: 2, message: 'test-error' });
152155

153156
mockStartInactiveSpan.mockRestore();
154-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
157+
}).pipe(Effect.provide(SentryTracerLayer)),
155158
);
156159

157160
it.effect('sets span status to error on defect', () =>
@@ -174,7 +177,7 @@ describe('SentryEffectTracerLayer', () => {
174177
expect(setStatusCalls).toContainEqual({ code: 2, message: 'fatal-defect' });
175178

176179
mockStartInactiveSpan.mockRestore();
177-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
180+
}).pipe(Effect.provide(SentryTracerLayer)),
178181
);
179182

180183
it.effect('propagates Sentry span context via withActiveSpan', () =>
@@ -195,7 +198,7 @@ describe('SentryEffectTracerLayer', () => {
195198
expect(withActiveSpanCalls.length).toBeGreaterThan(0);
196199

197200
mockWithActiveSpan.mockRestore();
198-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
201+
}).pipe(Effect.provide(SentryTracerLayer)),
199202
);
200203

201204
it.effect('sets origin to auto.function.effect for regular spans', () =>
@@ -220,7 +223,7 @@ describe('SentryEffectTracerLayer', () => {
220223
expect(capturedAttributes?.[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]).toBe('auto.function.effect');
221224

222225
mockStartInactiveSpan.mockRestore();
223-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
226+
}).pipe(Effect.provide(SentryTracerLayer)),
224227
);
225228

226229
it.effect('sets origin to auto.http.effect for http.server spans', () =>
@@ -245,7 +248,7 @@ describe('SentryEffectTracerLayer', () => {
245248
expect(capturedAttributes?.[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]).toBe('auto.http.effect');
246249

247250
mockStartInactiveSpan.mockRestore();
248-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
251+
}).pipe(Effect.provide(SentryTracerLayer)),
249252
);
250253

251254
it.effect('sets origin to auto.http.effect for http.client spans', () =>
@@ -270,7 +273,7 @@ describe('SentryEffectTracerLayer', () => {
270273
expect(capturedAttributes?.[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]).toBe('auto.http.effect');
271274

272275
mockStartInactiveSpan.mockRestore();
273-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
276+
}).pipe(Effect.provide(SentryTracerLayer)),
274277
);
275278

276279
it.effect('uses transaction name from isolation scope for http.server spans', () =>
@@ -301,6 +304,6 @@ describe('SentryEffectTracerLayer', () => {
301304

302305
mockStartInactiveSpan.mockRestore();
303306
mockGetIsolationScope.mockRestore();
304-
}).pipe(Effect.provide(SentryEffectTracerLayer)),
307+
}).pipe(Effect.provide(SentryTracerLayer)),
305308
);
306309
});

0 commit comments

Comments
 (0)