@sentry/effect 11.2.0 → 11.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
3
  const browser = require('@sentry/core/browser');
4
4
  const tracer = require('../tracer.js');
5
5
 
6
- const SentryEffectTracer = tracer.makeSentryTracer((options) => browser.startInactiveSpan(options));
6
+ const SentryEffectTracer = tracer.makeSentryTracer((options) => browser.startInactiveSpan(options), false);
7
7
 
8
8
  exports.SentryEffectTracer = SentryEffectTracer;
9
9
  //# sourceMappingURL=tracer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sources":["../../../src/client/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core/browser';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans in browser clients.\n *\n * Wrapped in an arrow rather than passed by reference so the import binding is read per span. That\n * keeps the browser variant substitutable (mocks, bundler interop) exactly as it was when the tracer\n * called it directly.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options));\n"],"names":["makeSentryTracer","startInactiveSpan"],"mappings":";;;;;AAUO,MAAM,kBAAA,GAAqBA,uBAAA,CAAiB,CAAA,OAAA,KAAWC,yBAAA,CAAkB,OAAO,CAAC;;;;"}
1
+ {"version":3,"file":"tracer.js","sources":["../../../src/client/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core/browser';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans in browser clients.\n *\n * Wrapped in an arrow rather than passed by reference so the import binding is read per span. That\n * keeps the browser variant substitutable (mocks, bundler interop) exactly as it was when the tracer\n * called it directly.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options), false);\n"],"names":["makeSentryTracer","startInactiveSpan"],"mappings":";;;;;AAUO,MAAM,qBAAqBA,uBAAA,CAAiB,CAAA,OAAA,KAAWC,yBAAA,CAAkB,OAAO,GAAG,KAAK;;;;"}
@@ -2,7 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const browser = require('@sentry/browser');
4
4
  const index = require('./client/index.js');
5
- const tracer = require('./client/tracer.js');
5
+ const tracer$1 = require('./client/tracer.js');
6
+ const tracer = require('./tracer.js');
6
7
  const logger = require('./logger.js');
7
8
  const metrics = require('./metrics.js');
8
9
  const sdk = require('./client/sdk.js');
@@ -10,7 +11,8 @@ const sdk = require('./client/sdk.js');
10
11
 
11
12
 
12
13
  exports.effectLayer = index.effectLayer;
13
- exports.SentryEffectTracer = tracer.SentryEffectTracer;
14
+ exports.SentryEffectTracer = tracer$1.SentryEffectTracer;
15
+ exports.SentryEffectExternalSpanLayer = tracer.SentryEffectExternalSpanLayer;
14
16
  exports.SentryEffectLogger = logger.SentryEffectLogger;
15
17
  exports.SentryEffectMetricsLayer = metrics.SentryEffectMetricsLayer;
16
18
  exports.init = sdk.init;
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,7 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const node = require('@sentry/node');
4
4
  const index = require('./server/index.js');
5
- const tracer = require('./server/tracer.js');
5
+ const tracer$1 = require('./server/tracer.js');
6
+ const tracer = require('./tracer.js');
6
7
  const logger = require('./logger.js');
7
8
  const metrics = require('./metrics.js');
8
9
  const sdk = require('./server/sdk.js');
@@ -10,7 +11,8 @@ const sdk = require('./server/sdk.js');
10
11
 
11
12
 
12
13
  exports.effectLayer = index.effectLayer;
13
- exports.SentryEffectTracer = tracer.SentryEffectTracer;
14
+ exports.SentryEffectTracer = tracer$1.SentryEffectTracer;
15
+ exports.SentryEffectExternalSpanLayer = tracer.SentryEffectExternalSpanLayer;
14
16
  exports.SentryEffectLogger = logger.SentryEffectLogger;
15
17
  exports.SentryEffectMetricsLayer = metrics.SentryEffectMetricsLayer;
16
18
  exports.init = sdk.init;
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
3
  const core = require('@sentry/core');
4
4
  const tracer = require('../tracer.js');
5
5
 
6
- const SentryEffectTracer = tracer.makeSentryTracer((options) => core.startInactiveSpan(options));
6
+ const SentryEffectTracer = tracer.makeSentryTracer((options) => core.startInactiveSpan(options), true);
7
7
 
8
8
  exports.SentryEffectTracer = SentryEffectTracer;
9
9
  //# sourceMappingURL=tracer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sources":["../../../src/server/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans on the server.\n *\n * Deliberately the plain `@sentry/core` variant, not `@sentry/core/browser`: the browser one guards\n * every span start with a `getClient()` lookup to lazily install `spanStreamingIntegration`, which on\n * the server is pure overhead — `ServerRuntimeClient` already installs it eagerly.\n *\n * See `./client/tracer.ts` for why the call is wrapped in an arrow.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options));\n"],"names":["makeSentryTracer","startInactiveSpan"],"mappings":";;;;;AAYO,MAAM,kBAAA,GAAqBA,uBAAA,CAAiB,CAAA,OAAA,KAAWC,sBAAA,CAAkB,OAAO,CAAC;;;;"}
1
+ {"version":3,"file":"tracer.js","sources":["../../../src/server/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans on the server.\n *\n * Deliberately the plain `@sentry/core` variant, not `@sentry/core/browser`: the browser one guards\n * every span start with a `getClient()` lookup to lazily install `spanStreamingIntegration`, which on\n * the server is pure overhead — `ServerRuntimeClient` already installs it eagerly.\n *\n * Every parentless Effect span starts a new trace. A server process forks no propagation context on\n * its own, so without this every request, reactor and background job of the process would land in\n * one trace.\n *\n * See `./client/tracer.ts` for why the call is wrapped in an arrow.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options), true);\n"],"names":["makeSentryTracer","startInactiveSpan"],"mappings":";;;;;AAgBO,MAAM,qBAAqBA,uBAAA,CAAiB,CAAA,OAAA,KAAWC,sBAAA,CAAkB,OAAO,GAAG,IAAI;;;;"}
@@ -3,7 +3,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
3
  const attributes = require('@sentry/conventions/attributes');
4
4
  const op = require('@sentry/conventions/op');
5
5
  const core = require('@sentry/core');
6
+ const Context = require('effect/Context');
6
7
  const Exit = require('effect/Exit');
8
+ const Layer = require('effect/Layer');
7
9
  const Option = require('effect/Option');
8
10
  const EffectTracer = require('effect/Tracer');
9
11
 
@@ -13,6 +15,13 @@ function deriveOrigin(name) {
13
15
  }
14
16
  return void 0;
15
17
  }
18
+ const EFFECT_SPAN_SYMBOL = /* @__PURE__ */ Symbol.for("@sentry/effect.EffectSpan");
19
+ function markEffectSpan(span) {
20
+ core.addNonEnumerableProperty(span, EFFECT_SPAN_SYMBOL, true);
21
+ }
22
+ function isEffectSpan(span) {
23
+ return span[EFFECT_SPAN_SYMBOL] === true;
24
+ }
16
25
  function deriveOp(name) {
17
26
  if (name.startsWith("http.server")) {
18
27
  return op.HTTP_SERVER;
@@ -115,22 +124,6 @@ class SentrySpanWrapper {
115
124
  this.sentrySpan.addEvent(name, attributes, nanosToHrTime(startTime));
116
125
  }
117
126
  }
118
- function createSentrySpan(startInactiveSpan, name, parent, context, links, startTime, kind) {
119
- const parentSentrySpan = Option.isSome(parent) && isSentrySpan(parent.value) ? parent.value.sentrySpan : core.getActiveSpan() ?? null;
120
- const op = deriveOp(name);
121
- const origin = deriveOrigin(name);
122
- const newSpan = startInactiveSpan({
123
- name,
124
- startTime: nanosToHrTime(startTime),
125
- // Setting these to `undefined` would strip the core defaults instead of leaving them in place.
126
- attributes: {
127
- ...op && { [attributes.SENTRY_OP]: op },
128
- ...origin && { [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }
129
- },
130
- ...parentSentrySpan ? { parentSpan: parentSentrySpan } : {}
131
- });
132
- return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);
133
- }
134
127
  const isEffectV4 = (() => {
135
128
  try {
136
129
  const testExit = Exit.fail("test");
@@ -143,26 +136,102 @@ const isEffectV4 = (() => {
143
136
  return false;
144
137
  }
145
138
  })();
146
- const makeSentryTracerV3 = (startInactiveSpan) => {
139
+ const EXTERNAL_SPAN_KEY = "@sentry/effect/ExternalSpan";
140
+ const contextExports = Context;
141
+ const ExternalSpanFlag = isEffectV4 ? contextExports.Reference(EXTERNAL_SPAN_KEY, { defaultValue: () => false }) : contextExports.GenericTag(EXTERNAL_SPAN_KEY);
142
+ const SentryEffectExternalSpanLayer = Layer.succeed(ExternalSpanFlag, true);
143
+ let currentFiber;
144
+ function continuesExternalSpans(fiber) {
145
+ if (fiber.getRef) {
146
+ return fiber.getRef(ExternalSpanFlag);
147
+ }
148
+ return fiber.currentContext !== void 0 && Option.getOrElse(Context.getOption(fiber.currentContext, ExternalSpanFlag), () => false);
149
+ }
150
+ function getFiberSpan(fiber) {
151
+ return isEffectV4 ? fiber.cache?.span : fiber.currentSpan;
152
+ }
153
+ function withFiberContext(fiber, execution) {
154
+ const previousFiber = currentFiber;
155
+ currentFiber = fiber;
156
+ try {
157
+ const currentSpan = getFiberSpan(fiber);
158
+ if (currentSpan === void 0 || !isSentrySpan(currentSpan)) {
159
+ return execution();
160
+ }
161
+ return core.withActiveSpan(currentSpan.sentrySpan, execution);
162
+ } finally {
163
+ currentFiber = previousFiber;
164
+ }
165
+ }
166
+ function startSentrySpan(startInactiveSpan, options, parent, newTraceForRootSpans) {
167
+ if (Option.isSome(parent)) {
168
+ const parentSpan = parent.value;
169
+ if (isSentrySpan(parentSpan)) {
170
+ return startInactiveSpan({ ...options, parentSpan: parentSpan.sentrySpan });
171
+ }
172
+ if (currentFiber !== void 0 && continuesExternalSpans(currentFiber)) {
173
+ return core.withScope((scope) => {
174
+ scope.setPropagationContext({
175
+ traceId: parentSpan.traceId,
176
+ parentSpanId: parentSpan.spanId,
177
+ sampled: parentSpan.sampled,
178
+ sampleRand: core._INTERNAL_safeMathRandom()
179
+ });
180
+ return core.withActiveSpan(null, () => startInactiveSpan(options));
181
+ });
182
+ }
183
+ const enclosingSpan = currentFiber && getFiberSpan(currentFiber);
184
+ if (enclosingSpan !== void 0 && isSentrySpan(enclosingSpan)) {
185
+ return startInactiveSpan({ ...options, parentSpan: enclosingSpan.sentrySpan });
186
+ }
187
+ }
188
+ const activeSpan = core.getActiveSpan();
189
+ if (activeSpan && !isEffectSpan(activeSpan)) {
190
+ return startInactiveSpan({ ...options, parentSpan: activeSpan });
191
+ }
192
+ const isProcessTrace = core.getCurrentScope().getPropagationContext().traceId === core.getDefaultCurrentScope().getPropagationContext().traceId;
193
+ if (newTraceForRootSpans && isProcessTrace) {
194
+ return core.startNewTrace(() => startInactiveSpan(options));
195
+ }
196
+ return core.withActiveSpan(null, () => startInactiveSpan(options));
197
+ }
198
+ function createSentrySpan(startInactiveSpan, newTraceForRootSpans, name, parent, context, links, startTime, kind) {
199
+ const op = deriveOp(name);
200
+ const origin = deriveOrigin(name);
201
+ const newSpan = startSentrySpan(
202
+ startInactiveSpan,
203
+ {
204
+ name,
205
+ startTime: nanosToHrTime(startTime),
206
+ // Setting these to `undefined` would strip the core defaults instead of leaving them in place.
207
+ attributes: {
208
+ ...op && { [attributes.SENTRY_OP]: op },
209
+ ...origin && { [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }
210
+ }
211
+ },
212
+ parent,
213
+ newTraceForRootSpans
214
+ );
215
+ markEffectSpan(newSpan);
216
+ return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);
217
+ }
218
+ const makeSentryTracerV3 = (startInactiveSpan, newTraceForRootSpans) => {
147
219
  return EffectTracer.make({
148
220
  span(name, parent, context, links, startTime, kind) {
149
- return createSentrySpan(startInactiveSpan, name, parent, context, links, startTime, kind);
221
+ return createSentrySpan(startInactiveSpan, newTraceForRootSpans, name, parent, context, links, startTime, kind);
150
222
  },
151
223
  context(execution, fiber) {
152
- const currentSpan = fiber.currentSpan;
153
- if (currentSpan === void 0 || !isSentrySpan(currentSpan)) {
154
- return execution();
155
- }
156
- return core.withActiveSpan(currentSpan.sentrySpan, execution);
224
+ return withFiberContext(fiber, execution);
157
225
  }
158
226
  });
159
227
  };
160
- const makeSentryTracerV4 = (startInactiveSpan) => {
228
+ const makeSentryTracerV4 = (startInactiveSpan, newTraceForRootSpans) => {
161
229
  const EFFECT_EVALUATE = "~effect/Effect/evaluate";
162
230
  return EffectTracer.make({
163
231
  span(options) {
164
232
  return createSentrySpan(
165
233
  startInactiveSpan,
234
+ newTraceForRootSpans,
166
235
  options.name,
167
236
  options.parent,
168
237
  options.annotations,
@@ -172,17 +241,14 @@ const makeSentryTracerV4 = (startInactiveSpan) => {
172
241
  );
173
242
  },
174
243
  context(primitive, fiber) {
175
- const currentSpan = fiber.currentSpan;
176
- if (currentSpan === void 0 || !isSentrySpan(currentSpan)) {
177
- return primitive[EFFECT_EVALUATE](fiber);
178
- }
179
- return core.withActiveSpan(currentSpan.sentrySpan, () => primitive[EFFECT_EVALUATE](fiber));
244
+ return withFiberContext(fiber, () => primitive[EFFECT_EVALUATE](fiber));
180
245
  }
181
246
  });
182
247
  };
183
- function makeSentryTracer(startInactiveSpan) {
184
- return isEffectV4 ? makeSentryTracerV4(startInactiveSpan) : makeSentryTracerV3(startInactiveSpan);
248
+ function makeSentryTracer(startInactiveSpan, newTraceForRootSpans) {
249
+ return isEffectV4 ? makeSentryTracerV4(startInactiveSpan, newTraceForRootSpans) : makeSentryTracerV3(startInactiveSpan, newTraceForRootSpans);
185
250
  }
186
251
 
252
+ exports.SentryEffectExternalSpanLayer = SentryEffectExternalSpanLayer;
187
253
  exports.makeSentryTracer = makeSentryTracer;
188
254
  //# sourceMappingURL=tracer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sources":["../../src/tracer.ts"],"sourcesContent":["import { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT, HTTP_SERVER } from '@sentry/conventions/op';\nimport type { Span, StartSpanOptions } from '@sentry/core';\nimport { isObjectLike, getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, withActiveSpan } from '@sentry/core';\nimport type * as Context from 'effect/Context';\nimport * as Exit from 'effect/Exit';\nimport * as Option from 'effect/Option';\nimport * as EffectTracer from 'effect/Tracer';\n\nfunction deriveOrigin(name: string): string | undefined {\n if (name.startsWith('http.server') || name.startsWith('http.client')) {\n return 'auto.http.effect';\n }\n\n return undefined;\n}\n\n/**\n * Effect span names are chosen by whoever calls `Effect.withSpan`, so the name is the only signal\n * available. `@effect/platform` names its HTTP spans `http.server`/`http.client`, which map onto the\n * matching Sentry ops. Every other name comes from user code or a third-party library, whose semantics\n * we cannot infer, so op and origin stay unset and the span keeps the core defaults: no op, and a\n * `manual` origin.\n */\nfunction deriveOp(name: string): string | undefined {\n if (name.startsWith('http.server')) {\n return HTTP_SERVER;\n }\n\n if (name.startsWith('http.client')) {\n return HTTP_CLIENT;\n }\n\n return undefined;\n}\n\ntype HrTime = [number, number];\n\nconst SENTRY_SPAN_SYMBOL = Symbol.for('@sentry/effect.SentrySpan');\n\nfunction nanosToHrTime(nanos: bigint): HrTime {\n const seconds = Number(nanos / BigInt(1_000_000_000));\n const remainingNanos = Number(nanos % BigInt(1_000_000_000));\n return [seconds, remainingNanos];\n}\n\ninterface SentrySpanLike extends EffectTracer.Span {\n readonly [SENTRY_SPAN_SYMBOL]: true;\n readonly sentrySpan: Span;\n}\n\nfunction isSentrySpan(span: EffectTracer.AnySpan): span is SentrySpanLike {\n return SENTRY_SPAN_SYMBOL in span;\n}\n\nfunction getErrorMessage(exit: Exit.Exit<unknown, unknown>): string | undefined {\n if (!Exit.isFailure(exit)) {\n return undefined;\n }\n\n const cause = exit.cause as unknown;\n\n // Effect v4: cause.reasons is an array of Reason objects\n if (isObjectLike(cause) && 'reasons' in cause && Array.isArray((cause as { reasons: unknown }).reasons)) {\n const reasons = (cause as { reasons: Array<{ _tag?: string; error?: unknown; defect?: unknown }> }).reasons;\n for (const reason of reasons) {\n if (reason._tag === 'Fail' && reason.error !== undefined) {\n return String(reason.error);\n }\n if (reason._tag === 'Die' && reason.defect !== undefined) {\n return String(reason.defect);\n }\n }\n return 'internal_error';\n }\n\n // Effect v3: cause has _tag directly\n if (isObjectLike(cause) && '_tag' in cause) {\n const v3Cause = cause as { _tag: string; error?: unknown; defect?: unknown };\n if (v3Cause._tag === 'Fail') {\n return String(v3Cause.error);\n }\n if (v3Cause._tag === 'Die') {\n return String(v3Cause.defect);\n }\n }\n\n return 'internal_error';\n}\n\nclass SentrySpanWrapper implements SentrySpanLike {\n public readonly [SENTRY_SPAN_SYMBOL]: true;\n public readonly _tag: 'Span';\n public readonly spanId: string;\n public readonly traceId: string;\n public readonly attributes: Map<string, unknown>;\n public readonly sampled: boolean;\n public readonly parent: Option.Option<EffectTracer.AnySpan>;\n public readonly links: Array<EffectTracer.SpanLink>;\n public status: EffectTracer.SpanStatus;\n public readonly sentrySpan: Span;\n public readonly annotations: Context.Context<never>;\n\n public constructor(\n public readonly name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n public readonly context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n public readonly kind: EffectTracer.SpanKind,\n existingSpan: Span,\n ) {\n this[SENTRY_SPAN_SYMBOL] = true as const;\n this._tag = 'Span' as const;\n this.attributes = new Map<string, unknown>();\n this.parent = parent;\n this.links = [...links];\n this.sentrySpan = existingSpan;\n this.annotations = context;\n\n const spanContext = this.sentrySpan.spanContext();\n this.spanId = spanContext.spanId;\n this.traceId = spanContext.traceId;\n this.sampled = this.sentrySpan.isRecording();\n this.status = {\n _tag: 'Started',\n startTime,\n };\n }\n\n public attribute(key: string, value: unknown): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.setAttribute(key, value as Parameters<Span['setAttribute']>[1]);\n this.attributes.set(key, value);\n }\n\n public addLinks(links: ReadonlyArray<EffectTracer.SpanLink>): void {\n this.links.push(...links);\n }\n\n public end(endTime: bigint, exit: Exit.Exit<unknown, unknown>): void {\n this.status = {\n _tag: 'Ended',\n endTime,\n exit,\n startTime: this.status.startTime,\n };\n\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n if (Exit.isFailure(exit)) {\n const message = getErrorMessage(exit) ?? 'internal_error';\n this.sentrySpan.setStatus({ code: 2, message });\n } else {\n this.sentrySpan.setStatus({ code: 1 });\n }\n\n this.sentrySpan.end(nanosToHrTime(endTime));\n }\n\n public event(name: string, startTime: bigint, attributes?: Record<string, unknown>): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.addEvent(name, attributes as Parameters<Span['addEvent']>[1], nanosToHrTime(startTime));\n }\n}\n\n/**\n * The client and the server entry differ only in which `startInactiveSpan` they hand to\n * {@link makeSentryTracer}: the browser one from `@sentry/core`, which installs the span\n * streaming integration on first use, and the plain one from `@sentry/core`, which does not. Nothing\n * else about the tracer is platform-specific.\n */\nexport type StartInactiveSpan = (options: StartSpanOptions) => Span;\n\nfunction createSentrySpan(\n startInactiveSpan: StartInactiveSpan,\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n): SentrySpanLike {\n const parentSentrySpan =\n Option.isSome(parent) && isSentrySpan(parent.value) ? parent.value.sentrySpan : (getActiveSpan() ?? null);\n\n const op = deriveOp(name);\n const origin = deriveOrigin(name);\n\n const newSpan = startInactiveSpan({\n name,\n startTime: nanosToHrTime(startTime),\n // Setting these to `undefined` would strip the core defaults instead of leaving them in place.\n attributes: {\n ...(op && { [SENTRY_OP]: op }),\n ...(origin && { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }),\n },\n ...(parentSentrySpan ? { parentSpan: parentSentrySpan } : {}),\n });\n\n return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);\n}\n\n// Check if we're running Effect v4 by checking the Exit/Cause structure\n// In v4, causes have a 'reasons' array\n// In v3, causes have '_tag' directly on the cause object\nconst isEffectV4 = (() => {\n try {\n const testExit = Exit.fail('test') as unknown as { cause?: unknown };\n const cause = testExit.cause;\n // v4 causes have 'reasons' array, v3 causes have '_tag' directly\n if (isObjectLike(cause) && 'reasons' in cause) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n})();\n\nconst makeSentryTracerV3 = (startInactiveSpan: StartInactiveSpan): EffectTracer.Tracer => {\n // Effect v3 API: span(name, parent, context, links, startTime, kind)\n return EffectTracer.make({\n span(\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n ) {\n return createSentrySpan(startInactiveSpan, name, parent, context, links, startTime, kind);\n },\n context(execution: () => unknown, fiber: { currentSpan?: EffectTracer.AnySpan }) {\n const currentSpan = fiber.currentSpan;\n if (currentSpan === undefined || !isSentrySpan(currentSpan)) {\n return execution();\n }\n return withActiveSpan(currentSpan.sentrySpan, execution);\n },\n } as unknown as EffectTracer.Tracer);\n};\n\nconst makeSentryTracerV4 = (startInactiveSpan: StartInactiveSpan): EffectTracer.Tracer => {\n const EFFECT_EVALUATE = '~effect/Effect/evaluate' as const;\n\n return EffectTracer.make({\n span(options) {\n return createSentrySpan(\n startInactiveSpan,\n options.name,\n options.parent,\n options.annotations,\n options.links,\n options.startTime,\n options.kind,\n );\n },\n context(primitive, fiber) {\n const currentSpan = fiber.currentSpan;\n if (currentSpan === undefined || !isSentrySpan(currentSpan)) {\n return primitive[EFFECT_EVALUATE](fiber);\n }\n return withActiveSpan(currentSpan.sentrySpan, () => primitive[EFFECT_EVALUATE](fiber));\n },\n });\n};\n\n/**\n * Creates an Effect `Tracer` that records Effect spans as Sentry spans.\n *\n * Use the `SentryEffectTracer` exported from `@sentry/effect` rather than calling this directly — the\n * client and server entries each bind the right `startInactiveSpan` for their platform.\n */\nexport function makeSentryTracer(startInactiveSpan: StartInactiveSpan): EffectTracer.Tracer {\n return isEffectV4 ? makeSentryTracerV4(startInactiveSpan) : makeSentryTracerV3(startInactiveSpan);\n}\n"],"names":["HTTP_SERVER","HTTP_CLIENT","isObjectLike","getActiveSpan","SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","withActiveSpan"],"mappings":"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"}
1
+ {"version":3,"file":"tracer.js","sources":["../../src/tracer.ts"],"sourcesContent":["/* oxlint-disable max-lines */\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT, HTTP_SERVER } from '@sentry/conventions/op';\nimport type { Span, StartSpanOptions } from '@sentry/core';\nimport {\n _INTERNAL_safeMathRandom,\n addNonEnumerableProperty,\n getActiveSpan,\n getCurrentScope,\n getDefaultCurrentScope,\n isObjectLike,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startNewTrace,\n withActiveSpan,\n withScope,\n} from '@sentry/core';\nimport * as Context from 'effect/Context';\nimport * as Exit from 'effect/Exit';\nimport type * as EffectLayer from 'effect/Layer';\nimport { succeed as succeedLayer } from 'effect/Layer';\nimport * as Option from 'effect/Option';\nimport * as EffectTracer from 'effect/Tracer';\n\nfunction deriveOrigin(name: string): string | undefined {\n if (name.startsWith('http.server') || name.startsWith('http.client')) {\n return 'auto.http.effect';\n }\n\n return undefined;\n}\n\nconst EFFECT_SPAN_SYMBOL = Symbol.for('@sentry/effect.EffectSpan');\n\nfunction markEffectSpan(span: Span): void {\n addNonEnumerableProperty(span, EFFECT_SPAN_SYMBOL, true);\n}\n\n/**\n * Whether this tracer created the span. A brand rather than an attribute check, because an unsampled\n * span keeps no attributes.\n */\nfunction isEffectSpan(span: Span): boolean {\n return (span as { [EFFECT_SPAN_SYMBOL]?: boolean })[EFFECT_SPAN_SYMBOL] === true;\n}\n\n/**\n * Effect span names are chosen by whoever calls `Effect.withSpan`, so the name is the only signal\n * available. `@effect/platform` names its HTTP spans `http.server`/`http.client`, which map onto the\n * matching Sentry ops. Every other name comes from user code or a third-party library, whose semantics\n * we cannot infer, so op and origin stay unset and the span keeps the core defaults: no op, and a\n * `manual` origin.\n */\nfunction deriveOp(name: string): string | undefined {\n if (name.startsWith('http.server')) {\n return HTTP_SERVER;\n }\n\n if (name.startsWith('http.client')) {\n return HTTP_CLIENT;\n }\n\n return undefined;\n}\n\ntype HrTime = [number, number];\n\nconst SENTRY_SPAN_SYMBOL = Symbol.for('@sentry/effect.SentrySpan');\n\nfunction nanosToHrTime(nanos: bigint): HrTime {\n const seconds = Number(nanos / BigInt(1_000_000_000));\n const remainingNanos = Number(nanos % BigInt(1_000_000_000));\n return [seconds, remainingNanos];\n}\n\ninterface SentrySpanLike extends EffectTracer.Span {\n readonly [SENTRY_SPAN_SYMBOL]: true;\n readonly sentrySpan: Span;\n}\n\nfunction isSentrySpan(span: EffectTracer.AnySpan): span is SentrySpanLike {\n return SENTRY_SPAN_SYMBOL in span;\n}\n\nfunction getErrorMessage(exit: Exit.Exit<unknown, unknown>): string | undefined {\n if (!Exit.isFailure(exit)) {\n return undefined;\n }\n\n const cause = exit.cause as unknown;\n\n // Effect v4: cause.reasons is an array of Reason objects\n if (isObjectLike(cause) && 'reasons' in cause && Array.isArray((cause as { reasons: unknown }).reasons)) {\n const reasons = (cause as { reasons: Array<{ _tag?: string; error?: unknown; defect?: unknown }> }).reasons;\n for (const reason of reasons) {\n if (reason._tag === 'Fail' && reason.error !== undefined) {\n return String(reason.error);\n }\n if (reason._tag === 'Die' && reason.defect !== undefined) {\n return String(reason.defect);\n }\n }\n return 'internal_error';\n }\n\n // Effect v3: cause has _tag directly\n if (isObjectLike(cause) && '_tag' in cause) {\n const v3Cause = cause as { _tag: string; error?: unknown; defect?: unknown };\n if (v3Cause._tag === 'Fail') {\n return String(v3Cause.error);\n }\n if (v3Cause._tag === 'Die') {\n return String(v3Cause.defect);\n }\n }\n\n return 'internal_error';\n}\n\nclass SentrySpanWrapper implements SentrySpanLike {\n public readonly [SENTRY_SPAN_SYMBOL]: true;\n public readonly _tag: 'Span';\n public readonly spanId: string;\n public readonly traceId: string;\n public readonly attributes: Map<string, unknown>;\n public readonly sampled: boolean;\n public readonly parent: Option.Option<EffectTracer.AnySpan>;\n public readonly links: Array<EffectTracer.SpanLink>;\n public status: EffectTracer.SpanStatus;\n public readonly sentrySpan: Span;\n public readonly annotations: Context.Context<never>;\n\n public constructor(\n public readonly name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n public readonly context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n public readonly kind: EffectTracer.SpanKind,\n existingSpan: Span,\n ) {\n this[SENTRY_SPAN_SYMBOL] = true as const;\n this._tag = 'Span' as const;\n this.attributes = new Map<string, unknown>();\n this.parent = parent;\n this.links = [...links];\n this.sentrySpan = existingSpan;\n this.annotations = context;\n\n const spanContext = this.sentrySpan.spanContext();\n this.spanId = spanContext.spanId;\n this.traceId = spanContext.traceId;\n this.sampled = this.sentrySpan.isRecording();\n this.status = {\n _tag: 'Started',\n startTime,\n };\n }\n\n public attribute(key: string, value: unknown): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.setAttribute(key, value as Parameters<Span['setAttribute']>[1]);\n this.attributes.set(key, value);\n }\n\n public addLinks(links: ReadonlyArray<EffectTracer.SpanLink>): void {\n this.links.push(...links);\n }\n\n public end(endTime: bigint, exit: Exit.Exit<unknown, unknown>): void {\n this.status = {\n _tag: 'Ended',\n endTime,\n exit,\n startTime: this.status.startTime,\n };\n\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n if (Exit.isFailure(exit)) {\n const message = getErrorMessage(exit) ?? 'internal_error';\n this.sentrySpan.setStatus({ code: 2, message });\n } else {\n this.sentrySpan.setStatus({ code: 1 });\n }\n\n this.sentrySpan.end(nanosToHrTime(endTime));\n }\n\n public event(name: string, startTime: bigint, attributes?: Record<string, unknown>): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.addEvent(name, attributes as Parameters<Span['addEvent']>[1], nanosToHrTime(startTime));\n }\n}\n\n/**\n * The client and the server entry hand different `startInactiveSpan` functions to\n * {@link makeSentryTracer}: the browser one from `@sentry/core/browser`, which installs the span\n * streaming integration on first use, and the plain one from `@sentry/core`, which does not.\n */\nexport type StartInactiveSpan = (options: StartSpanOptions) => Span;\n\n// Check if we're running Effect v4 by checking the Exit/Cause structure\n// In v4, causes have a 'reasons' array\n// In v3, causes have '_tag' directly on the cause object\nconst isEffectV4 = (() => {\n try {\n const testExit = Exit.fail('test') as unknown as { cause?: unknown };\n const cause = testExit.cause;\n // v4 causes have 'reasons' array, v3 causes have '_tag' directly\n if (isObjectLike(cause) && 'reasons' in cause) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n})();\n\nconst EXTERNAL_SPAN_KEY = '@sentry/effect/ExternalSpan';\n\ninterface ContextExports {\n Reference: typeof Context.Reference;\n /** Only Effect v3 exports it. */\n GenericTag<Identifier, Service>(key: string): Context.Key<Identifier, Service>;\n}\n\n// Effect v4 has no `Context.GenericTag` and Effect v3 before 3.11 has no `Context.Reference`. Both are read\n// through a separate binding because bundlers fail the build on a namespace member the installed version lacks.\nconst contextExports = Context as unknown as ContextExports;\n\n/**\n * Whether the tracer continues the trace of a `Tracer.externalSpan` parent. Effect v4 has no `FiberRef`\n * and v3 before 3.11 has no `Context.Reference`, so the flag is a plain service in both. The cast is safe:\n * the tracer reads it with `getRef` only on a v4 fiber, where it is a reference, and with\n * `Context.getOption` on v3.\n */\nconst ExternalSpanFlag = (\n isEffectV4\n ? contextExports.Reference<boolean>(EXTERNAL_SPAN_KEY, { defaultValue: () => false })\n : contextExports.GenericTag<never, boolean>(EXTERNAL_SPAN_KEY)\n) as Context.Reference<boolean>;\n\n/**\n * Makes the tracer continue the trace of a `Tracer.externalSpan` parent instead of ignoring it. Provide it\n * next to the tracer layer to continue every external span in the runtime, or provide it to a single\n * effect with `Effect.provide` to continue only that one.\n */\nexport const SentryEffectExternalSpanLayer: EffectLayer.Layer<never> = succeedLayer(ExternalSpanFlag, true);\n\ninterface FiberLike {\n /** The span the fiber runs in. Only Effect v3 fibers have it. */\n readonly currentSpan?: EffectTracer.AnySpan | undefined;\n /** Holds `span`, the span the fiber runs in. Only Effect v4 fibers have it. */\n readonly cache?: { readonly span?: EffectTracer.AnySpan | undefined };\n /** Reads a reference with its default. Only Effect v4 fibers have it. */\n readonly getRef?: <A>(ref: Context.Reference<A>) => A;\n /** The services of the fiber. Only Effect v3 fibers have it. */\n readonly currentContext?: Context.Context<never>;\n}\n\n/**\n * The fiber whose operation is being evaluated. Effect hands the fiber to the `context` hook but not to\n * `span`, which runs synchronously inside it, so the hook keeps the fiber here for that extent.\n */\nlet currentFiber: FiberLike | undefined;\n\nfunction continuesExternalSpans(fiber: FiberLike): boolean {\n if (fiber.getRef) {\n return fiber.getRef(ExternalSpanFlag);\n }\n\n return (\n fiber.currentContext !== undefined &&\n Option.getOrElse(Context.getOption(fiber.currentContext, ExternalSpanFlag), () => false)\n );\n}\n\nfunction getFiberSpan(fiber: FiberLike): EffectTracer.AnySpan | undefined {\n return isEffectV4 ? fiber.cache?.span : fiber.currentSpan;\n}\n\nfunction withFiberContext<X>(fiber: FiberLike, execution: () => X): X {\n const previousFiber = currentFiber;\n currentFiber = fiber;\n try {\n const currentSpan = getFiberSpan(fiber);\n if (currentSpan === undefined || !isSentrySpan(currentSpan)) {\n return execution();\n }\n return withActiveSpan(currentSpan.sentrySpan, execution);\n } finally {\n currentFiber = previousFiber;\n }\n}\n\n/**\n * Starts the Sentry span for an Effect span, rooted or parented the way Effect asked for.\n *\n * - A parent this tracer created becomes the Sentry parent.\n * - Any other parent (`Tracer.externalSpan` bridging a trace this SDK did not start, such as an\n * OpenTelemetry span of another app in the same process or persisted trace state) is ignored unless\n * {@link SentryEffectExternalSpanLayer} is provided, so a span joins a foreign trace only when the user\n * asked for it. The span then nests where Effect would have put it without the `parent` option: under\n * the fiber's current span, or parentless. With the layer, the span continues that trace: it is a root\n * span whose `parent_span_id` is the external span. No dynamic sampling context is frozen, so the SDK\n * builds one from the client the way it does for a head-of-trace span.\n * - Without a parent, the span nests under a foreign active Sentry span (an `http.server` span from the\n * Node SDK, a pageload in the browser) but never under a span this tracer created: Effect's own parent\n * tracking is authoritative for those, so an active one is an enclosing `root: true` span or a span\n * leaked from another fiber through the async context. Effect reports `root: true` for every\n * parentless span, so the flag adds nothing and is not consulted.\n * - A root span starts a new trace when `newTraceForRootSpans` is set, unless the user set up the\n * current scope (`Sentry.continueTrace`, `Sentry.withScope`, an HTTP request's isolation scope).\n */\nfunction startSentrySpan(\n startInactiveSpan: StartInactiveSpan,\n options: StartSpanOptions,\n parent: Option.Option<EffectTracer.AnySpan>,\n newTraceForRootSpans: boolean,\n): Span {\n if (Option.isSome(parent)) {\n const parentSpan = parent.value;\n\n if (isSentrySpan(parentSpan)) {\n return startInactiveSpan({ ...options, parentSpan: parentSpan.sentrySpan });\n }\n\n if (currentFiber !== undefined && continuesExternalSpans(currentFiber)) {\n return withScope(scope => {\n scope.setPropagationContext({\n traceId: parentSpan.traceId,\n parentSpanId: parentSpan.spanId,\n sampled: parentSpan.sampled,\n sampleRand: _INTERNAL_safeMathRandom(),\n });\n return withActiveSpan(null, () => startInactiveSpan(options));\n });\n }\n\n const enclosingSpan = currentFiber && getFiberSpan(currentFiber);\n if (enclosingSpan !== undefined && isSentrySpan(enclosingSpan)) {\n return startInactiveSpan({ ...options, parentSpan: enclosingSpan.sentrySpan });\n }\n }\n\n const activeSpan = getActiveSpan();\n if (activeSpan && !isEffectSpan(activeSpan)) {\n return startInactiveSpan({ ...options, parentSpan: activeSpan });\n }\n\n // A scope the user forked (`continueTrace`, `withScope`, an isolation scope) carries its own trace id.\n // The scopes this tracer forks in `context()` clone the propagation context they were forked from, so\n // even when one leaks into another fiber through the async context it still carries the process-wide\n // trace id of the default scope.\n const isProcessTrace =\n getCurrentScope().getPropagationContext().traceId === getDefaultCurrentScope().getPropagationContext().traceId;\n if (newTraceForRootSpans && isProcessTrace) {\n return startNewTrace(() => startInactiveSpan(options));\n }\n\n return withActiveSpan(null, () => startInactiveSpan(options));\n}\n\nfunction createSentrySpan(\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n): SentrySpanLike {\n const op = deriveOp(name);\n const origin = deriveOrigin(name);\n\n const newSpan = startSentrySpan(\n startInactiveSpan,\n {\n name,\n startTime: nanosToHrTime(startTime),\n // Setting these to `undefined` would strip the core defaults instead of leaving them in place.\n attributes: {\n ...(op && { [SENTRY_OP]: op }),\n ...(origin && { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }),\n },\n },\n parent,\n newTraceForRootSpans,\n );\n markEffectSpan(newSpan);\n\n return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);\n}\n\nconst makeSentryTracerV3 = (\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n): EffectTracer.Tracer => {\n // Effect v3 API: span(name, parent, context, links, startTime, kind)\n return EffectTracer.make({\n span(\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n ) {\n return createSentrySpan(startInactiveSpan, newTraceForRootSpans, name, parent, context, links, startTime, kind);\n },\n context(execution: () => unknown, fiber: FiberLike) {\n return withFiberContext(fiber, execution);\n },\n } as unknown as EffectTracer.Tracer);\n};\n\nconst makeSentryTracerV4 = (\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n): EffectTracer.Tracer => {\n const EFFECT_EVALUATE = '~effect/Effect/evaluate' as const;\n\n return EffectTracer.make({\n span(options) {\n return createSentrySpan(\n startInactiveSpan,\n newTraceForRootSpans,\n options.name,\n options.parent,\n options.annotations,\n options.links,\n options.startTime,\n options.kind,\n );\n },\n context(primitive, fiber) {\n return withFiberContext(fiber, () => primitive[EFFECT_EVALUATE](fiber));\n },\n });\n};\n\n/**\n * Creates an Effect `Tracer` that records Effect spans as Sentry spans.\n *\n * Use the `SentryEffectTracer` exported from `@sentry/effect` rather than calling this directly — the\n * client and server entries each bind the right `startInactiveSpan` for their platform.\n *\n * `newTraceForRootSpans` is the one behavioural difference between the platforms: Effect gives every\n * parentless span a fresh trace id, and on a long-lived server nothing else forks the propagation\n * context, so the server tracer follows Effect and starts a new trace. In the browser the page trace is\n * the intended home of every span, so the client tracer keeps parentless spans in it.\n */\nexport function makeSentryTracer(\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n): EffectTracer.Tracer {\n return isEffectV4\n ? makeSentryTracerV4(startInactiveSpan, newTraceForRootSpans)\n : makeSentryTracerV3(startInactiveSpan, newTraceForRootSpans);\n}\n"],"names":["addNonEnumerableProperty","HTTP_SERVER","HTTP_CLIENT","isObjectLike","succeedLayer","withActiveSpan","withScope","_INTERNAL_safeMathRandom","getActiveSpan","getCurrentScope","getDefaultCurrentScope","startNewTrace","SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { startInactiveSpan } from '@sentry/core/browser';
2
2
  import { makeSentryTracer } from '../tracer.js';
3
3
 
4
- const SentryEffectTracer = makeSentryTracer((options) => startInactiveSpan(options));
4
+ const SentryEffectTracer = makeSentryTracer((options) => startInactiveSpan(options), false);
5
5
 
6
6
  export { SentryEffectTracer };
7
7
  //# sourceMappingURL=tracer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sources":["../../../src/client/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core/browser';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans in browser clients.\n *\n * Wrapped in an arrow rather than passed by reference so the import binding is read per span. That\n * keeps the browser variant substitutable (mocks, bundler interop) exactly as it was when the tracer\n * called it directly.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options));\n"],"names":[],"mappings":";;;AAUO,MAAM,kBAAA,GAAqB,gBAAA,CAAiB,CAAA,OAAA,KAAW,iBAAA,CAAkB,OAAO,CAAC;;;;"}
1
+ {"version":3,"file":"tracer.js","sources":["../../../src/client/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core/browser';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans in browser clients.\n *\n * Wrapped in an arrow rather than passed by reference so the import binding is read per span. That\n * keeps the browser variant substitutable (mocks, bundler interop) exactly as it was when the tracer\n * called it directly.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options), false);\n"],"names":[],"mappings":";;;AAUO,MAAM,qBAAqB,gBAAA,CAAiB,CAAA,OAAA,KAAW,iBAAA,CAAkB,OAAO,GAAG,KAAK;;;;"}
@@ -1,6 +1,7 @@
1
1
  export * from '@sentry/browser';
2
2
  export { effectLayer } from './client/index.js';
3
3
  export { SentryEffectTracer } from './client/tracer.js';
4
+ export { SentryEffectExternalSpanLayer } from './tracer.js';
4
5
  export { SentryEffectLogger } from './logger.js';
5
6
  export { SentryEffectMetricsLayer } from './metrics.js';
6
7
  export { init } from './client/sdk.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
1
+ {"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1,6 +1,7 @@
1
1
  export * from '@sentry/node';
2
2
  export { effectLayer } from './server/index.js';
3
3
  export { SentryEffectTracer } from './server/tracer.js';
4
+ export { SentryEffectExternalSpanLayer } from './tracer.js';
4
5
  export { SentryEffectLogger } from './logger.js';
5
6
  export { SentryEffectMetricsLayer } from './metrics.js';
6
7
  export { init } from './server/sdk.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
1
+ {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"11.2.0","sideEffects":false}
1
+ {"type":"module","version":"11.4.0","sideEffects":false}
@@ -1,7 +1,7 @@
1
1
  import { startInactiveSpan } from '@sentry/core';
2
2
  import { makeSentryTracer } from '../tracer.js';
3
3
 
4
- const SentryEffectTracer = makeSentryTracer((options) => startInactiveSpan(options));
4
+ const SentryEffectTracer = makeSentryTracer((options) => startInactiveSpan(options), true);
5
5
 
6
6
  export { SentryEffectTracer };
7
7
  //# sourceMappingURL=tracer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sources":["../../../src/server/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans on the server.\n *\n * Deliberately the plain `@sentry/core` variant, not `@sentry/core/browser`: the browser one guards\n * every span start with a `getClient()` lookup to lazily install `spanStreamingIntegration`, which on\n * the server is pure overhead — `ServerRuntimeClient` already installs it eagerly.\n *\n * See `./client/tracer.ts` for why the call is wrapped in an arrow.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options));\n"],"names":[],"mappings":";;;AAYO,MAAM,kBAAA,GAAqB,gBAAA,CAAiB,CAAA,OAAA,KAAW,iBAAA,CAAkB,OAAO,CAAC;;;;"}
1
+ {"version":3,"file":"tracer.js","sources":["../../../src/server/tracer.ts"],"sourcesContent":["import { startInactiveSpan } from '@sentry/core';\nimport { makeSentryTracer } from '../tracer';\n\n/**\n * Effect `Tracer` that records Effect spans as Sentry spans on the server.\n *\n * Deliberately the plain `@sentry/core` variant, not `@sentry/core/browser`: the browser one guards\n * every span start with a `getClient()` lookup to lazily install `spanStreamingIntegration`, which on\n * the server is pure overhead — `ServerRuntimeClient` already installs it eagerly.\n *\n * Every parentless Effect span starts a new trace. A server process forks no propagation context on\n * its own, so without this every request, reactor and background job of the process would land in\n * one trace.\n *\n * See `./client/tracer.ts` for why the call is wrapped in an arrow.\n */\nexport const SentryEffectTracer = makeSentryTracer(options => startInactiveSpan(options), true);\n"],"names":[],"mappings":";;;AAgBO,MAAM,qBAAqB,gBAAA,CAAiB,CAAA,OAAA,KAAW,iBAAA,CAAkB,OAAO,GAAG,IAAI;;;;"}
@@ -1,7 +1,9 @@
1
1
  import { SENTRY_OP } from '@sentry/conventions/attributes';
2
2
  import { HTTP_SERVER, HTTP_CLIENT } from '@sentry/conventions/op';
3
- import { isObjectLike, withActiveSpan, getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
3
+ import { isObjectLike, withActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, withScope, _INTERNAL_safeMathRandom, getActiveSpan, getCurrentScope, getDefaultCurrentScope, addNonEnumerableProperty, startNewTrace } from '@sentry/core';
4
+ import * as Context from 'effect/Context';
4
5
  import * as Exit from 'effect/Exit';
6
+ import { succeed } from 'effect/Layer';
5
7
  import * as Option from 'effect/Option';
6
8
  import * as EffectTracer from 'effect/Tracer';
7
9
 
@@ -11,6 +13,13 @@ function deriveOrigin(name) {
11
13
  }
12
14
  return void 0;
13
15
  }
16
+ const EFFECT_SPAN_SYMBOL = /* @__PURE__ */ Symbol.for("@sentry/effect.EffectSpan");
17
+ function markEffectSpan(span) {
18
+ addNonEnumerableProperty(span, EFFECT_SPAN_SYMBOL, true);
19
+ }
20
+ function isEffectSpan(span) {
21
+ return span[EFFECT_SPAN_SYMBOL] === true;
22
+ }
14
23
  function deriveOp(name) {
15
24
  if (name.startsWith("http.server")) {
16
25
  return HTTP_SERVER;
@@ -113,22 +122,6 @@ class SentrySpanWrapper {
113
122
  this.sentrySpan.addEvent(name, attributes, nanosToHrTime(startTime));
114
123
  }
115
124
  }
116
- function createSentrySpan(startInactiveSpan, name, parent, context, links, startTime, kind) {
117
- const parentSentrySpan = Option.isSome(parent) && isSentrySpan(parent.value) ? parent.value.sentrySpan : getActiveSpan() ?? null;
118
- const op = deriveOp(name);
119
- const origin = deriveOrigin(name);
120
- const newSpan = startInactiveSpan({
121
- name,
122
- startTime: nanosToHrTime(startTime),
123
- // Setting these to `undefined` would strip the core defaults instead of leaving them in place.
124
- attributes: {
125
- ...op && { [SENTRY_OP]: op },
126
- ...origin && { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }
127
- },
128
- ...parentSentrySpan ? { parentSpan: parentSentrySpan } : {}
129
- });
130
- return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);
131
- }
132
125
  const isEffectV4 = (() => {
133
126
  try {
134
127
  const testExit = Exit.fail("test");
@@ -141,26 +134,102 @@ const isEffectV4 = (() => {
141
134
  return false;
142
135
  }
143
136
  })();
144
- const makeSentryTracerV3 = (startInactiveSpan) => {
137
+ const EXTERNAL_SPAN_KEY = "@sentry/effect/ExternalSpan";
138
+ const contextExports = Context;
139
+ const ExternalSpanFlag = isEffectV4 ? contextExports.Reference(EXTERNAL_SPAN_KEY, { defaultValue: () => false }) : contextExports.GenericTag(EXTERNAL_SPAN_KEY);
140
+ const SentryEffectExternalSpanLayer = succeed(ExternalSpanFlag, true);
141
+ let currentFiber;
142
+ function continuesExternalSpans(fiber) {
143
+ if (fiber.getRef) {
144
+ return fiber.getRef(ExternalSpanFlag);
145
+ }
146
+ return fiber.currentContext !== void 0 && Option.getOrElse(Context.getOption(fiber.currentContext, ExternalSpanFlag), () => false);
147
+ }
148
+ function getFiberSpan(fiber) {
149
+ return isEffectV4 ? fiber.cache?.span : fiber.currentSpan;
150
+ }
151
+ function withFiberContext(fiber, execution) {
152
+ const previousFiber = currentFiber;
153
+ currentFiber = fiber;
154
+ try {
155
+ const currentSpan = getFiberSpan(fiber);
156
+ if (currentSpan === void 0 || !isSentrySpan(currentSpan)) {
157
+ return execution();
158
+ }
159
+ return withActiveSpan(currentSpan.sentrySpan, execution);
160
+ } finally {
161
+ currentFiber = previousFiber;
162
+ }
163
+ }
164
+ function startSentrySpan(startInactiveSpan, options, parent, newTraceForRootSpans) {
165
+ if (Option.isSome(parent)) {
166
+ const parentSpan = parent.value;
167
+ if (isSentrySpan(parentSpan)) {
168
+ return startInactiveSpan({ ...options, parentSpan: parentSpan.sentrySpan });
169
+ }
170
+ if (currentFiber !== void 0 && continuesExternalSpans(currentFiber)) {
171
+ return withScope((scope) => {
172
+ scope.setPropagationContext({
173
+ traceId: parentSpan.traceId,
174
+ parentSpanId: parentSpan.spanId,
175
+ sampled: parentSpan.sampled,
176
+ sampleRand: _INTERNAL_safeMathRandom()
177
+ });
178
+ return withActiveSpan(null, () => startInactiveSpan(options));
179
+ });
180
+ }
181
+ const enclosingSpan = currentFiber && getFiberSpan(currentFiber);
182
+ if (enclosingSpan !== void 0 && isSentrySpan(enclosingSpan)) {
183
+ return startInactiveSpan({ ...options, parentSpan: enclosingSpan.sentrySpan });
184
+ }
185
+ }
186
+ const activeSpan = getActiveSpan();
187
+ if (activeSpan && !isEffectSpan(activeSpan)) {
188
+ return startInactiveSpan({ ...options, parentSpan: activeSpan });
189
+ }
190
+ const isProcessTrace = getCurrentScope().getPropagationContext().traceId === getDefaultCurrentScope().getPropagationContext().traceId;
191
+ if (newTraceForRootSpans && isProcessTrace) {
192
+ return startNewTrace(() => startInactiveSpan(options));
193
+ }
194
+ return withActiveSpan(null, () => startInactiveSpan(options));
195
+ }
196
+ function createSentrySpan(startInactiveSpan, newTraceForRootSpans, name, parent, context, links, startTime, kind) {
197
+ const op = deriveOp(name);
198
+ const origin = deriveOrigin(name);
199
+ const newSpan = startSentrySpan(
200
+ startInactiveSpan,
201
+ {
202
+ name,
203
+ startTime: nanosToHrTime(startTime),
204
+ // Setting these to `undefined` would strip the core defaults instead of leaving them in place.
205
+ attributes: {
206
+ ...op && { [SENTRY_OP]: op },
207
+ ...origin && { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }
208
+ }
209
+ },
210
+ parent,
211
+ newTraceForRootSpans
212
+ );
213
+ markEffectSpan(newSpan);
214
+ return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);
215
+ }
216
+ const makeSentryTracerV3 = (startInactiveSpan, newTraceForRootSpans) => {
145
217
  return EffectTracer.make({
146
218
  span(name, parent, context, links, startTime, kind) {
147
- return createSentrySpan(startInactiveSpan, name, parent, context, links, startTime, kind);
219
+ return createSentrySpan(startInactiveSpan, newTraceForRootSpans, name, parent, context, links, startTime, kind);
148
220
  },
149
221
  context(execution, fiber) {
150
- const currentSpan = fiber.currentSpan;
151
- if (currentSpan === void 0 || !isSentrySpan(currentSpan)) {
152
- return execution();
153
- }
154
- return withActiveSpan(currentSpan.sentrySpan, execution);
222
+ return withFiberContext(fiber, execution);
155
223
  }
156
224
  });
157
225
  };
158
- const makeSentryTracerV4 = (startInactiveSpan) => {
226
+ const makeSentryTracerV4 = (startInactiveSpan, newTraceForRootSpans) => {
159
227
  const EFFECT_EVALUATE = "~effect/Effect/evaluate";
160
228
  return EffectTracer.make({
161
229
  span(options) {
162
230
  return createSentrySpan(
163
231
  startInactiveSpan,
232
+ newTraceForRootSpans,
164
233
  options.name,
165
234
  options.parent,
166
235
  options.annotations,
@@ -170,17 +239,13 @@ const makeSentryTracerV4 = (startInactiveSpan) => {
170
239
  );
171
240
  },
172
241
  context(primitive, fiber) {
173
- const currentSpan = fiber.currentSpan;
174
- if (currentSpan === void 0 || !isSentrySpan(currentSpan)) {
175
- return primitive[EFFECT_EVALUATE](fiber);
176
- }
177
- return withActiveSpan(currentSpan.sentrySpan, () => primitive[EFFECT_EVALUATE](fiber));
242
+ return withFiberContext(fiber, () => primitive[EFFECT_EVALUATE](fiber));
178
243
  }
179
244
  });
180
245
  };
181
- function makeSentryTracer(startInactiveSpan) {
182
- return isEffectV4 ? makeSentryTracerV4(startInactiveSpan) : makeSentryTracerV3(startInactiveSpan);
246
+ function makeSentryTracer(startInactiveSpan, newTraceForRootSpans) {
247
+ return isEffectV4 ? makeSentryTracerV4(startInactiveSpan, newTraceForRootSpans) : makeSentryTracerV3(startInactiveSpan, newTraceForRootSpans);
183
248
  }
184
249
 
185
- export { makeSentryTracer };
250
+ export { SentryEffectExternalSpanLayer, makeSentryTracer };
186
251
  //# sourceMappingURL=tracer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sources":["../../src/tracer.ts"],"sourcesContent":["import { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT, HTTP_SERVER } from '@sentry/conventions/op';\nimport type { Span, StartSpanOptions } from '@sentry/core';\nimport { isObjectLike, getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, withActiveSpan } from '@sentry/core';\nimport type * as Context from 'effect/Context';\nimport * as Exit from 'effect/Exit';\nimport * as Option from 'effect/Option';\nimport * as EffectTracer from 'effect/Tracer';\n\nfunction deriveOrigin(name: string): string | undefined {\n if (name.startsWith('http.server') || name.startsWith('http.client')) {\n return 'auto.http.effect';\n }\n\n return undefined;\n}\n\n/**\n * Effect span names are chosen by whoever calls `Effect.withSpan`, so the name is the only signal\n * available. `@effect/platform` names its HTTP spans `http.server`/`http.client`, which map onto the\n * matching Sentry ops. Every other name comes from user code or a third-party library, whose semantics\n * we cannot infer, so op and origin stay unset and the span keeps the core defaults: no op, and a\n * `manual` origin.\n */\nfunction deriveOp(name: string): string | undefined {\n if (name.startsWith('http.server')) {\n return HTTP_SERVER;\n }\n\n if (name.startsWith('http.client')) {\n return HTTP_CLIENT;\n }\n\n return undefined;\n}\n\ntype HrTime = [number, number];\n\nconst SENTRY_SPAN_SYMBOL = Symbol.for('@sentry/effect.SentrySpan');\n\nfunction nanosToHrTime(nanos: bigint): HrTime {\n const seconds = Number(nanos / BigInt(1_000_000_000));\n const remainingNanos = Number(nanos % BigInt(1_000_000_000));\n return [seconds, remainingNanos];\n}\n\ninterface SentrySpanLike extends EffectTracer.Span {\n readonly [SENTRY_SPAN_SYMBOL]: true;\n readonly sentrySpan: Span;\n}\n\nfunction isSentrySpan(span: EffectTracer.AnySpan): span is SentrySpanLike {\n return SENTRY_SPAN_SYMBOL in span;\n}\n\nfunction getErrorMessage(exit: Exit.Exit<unknown, unknown>): string | undefined {\n if (!Exit.isFailure(exit)) {\n return undefined;\n }\n\n const cause = exit.cause as unknown;\n\n // Effect v4: cause.reasons is an array of Reason objects\n if (isObjectLike(cause) && 'reasons' in cause && Array.isArray((cause as { reasons: unknown }).reasons)) {\n const reasons = (cause as { reasons: Array<{ _tag?: string; error?: unknown; defect?: unknown }> }).reasons;\n for (const reason of reasons) {\n if (reason._tag === 'Fail' && reason.error !== undefined) {\n return String(reason.error);\n }\n if (reason._tag === 'Die' && reason.defect !== undefined) {\n return String(reason.defect);\n }\n }\n return 'internal_error';\n }\n\n // Effect v3: cause has _tag directly\n if (isObjectLike(cause) && '_tag' in cause) {\n const v3Cause = cause as { _tag: string; error?: unknown; defect?: unknown };\n if (v3Cause._tag === 'Fail') {\n return String(v3Cause.error);\n }\n if (v3Cause._tag === 'Die') {\n return String(v3Cause.defect);\n }\n }\n\n return 'internal_error';\n}\n\nclass SentrySpanWrapper implements SentrySpanLike {\n public readonly [SENTRY_SPAN_SYMBOL]: true;\n public readonly _tag: 'Span';\n public readonly spanId: string;\n public readonly traceId: string;\n public readonly attributes: Map<string, unknown>;\n public readonly sampled: boolean;\n public readonly parent: Option.Option<EffectTracer.AnySpan>;\n public readonly links: Array<EffectTracer.SpanLink>;\n public status: EffectTracer.SpanStatus;\n public readonly sentrySpan: Span;\n public readonly annotations: Context.Context<never>;\n\n public constructor(\n public readonly name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n public readonly context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n public readonly kind: EffectTracer.SpanKind,\n existingSpan: Span,\n ) {\n this[SENTRY_SPAN_SYMBOL] = true as const;\n this._tag = 'Span' as const;\n this.attributes = new Map<string, unknown>();\n this.parent = parent;\n this.links = [...links];\n this.sentrySpan = existingSpan;\n this.annotations = context;\n\n const spanContext = this.sentrySpan.spanContext();\n this.spanId = spanContext.spanId;\n this.traceId = spanContext.traceId;\n this.sampled = this.sentrySpan.isRecording();\n this.status = {\n _tag: 'Started',\n startTime,\n };\n }\n\n public attribute(key: string, value: unknown): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.setAttribute(key, value as Parameters<Span['setAttribute']>[1]);\n this.attributes.set(key, value);\n }\n\n public addLinks(links: ReadonlyArray<EffectTracer.SpanLink>): void {\n this.links.push(...links);\n }\n\n public end(endTime: bigint, exit: Exit.Exit<unknown, unknown>): void {\n this.status = {\n _tag: 'Ended',\n endTime,\n exit,\n startTime: this.status.startTime,\n };\n\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n if (Exit.isFailure(exit)) {\n const message = getErrorMessage(exit) ?? 'internal_error';\n this.sentrySpan.setStatus({ code: 2, message });\n } else {\n this.sentrySpan.setStatus({ code: 1 });\n }\n\n this.sentrySpan.end(nanosToHrTime(endTime));\n }\n\n public event(name: string, startTime: bigint, attributes?: Record<string, unknown>): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.addEvent(name, attributes as Parameters<Span['addEvent']>[1], nanosToHrTime(startTime));\n }\n}\n\n/**\n * The client and the server entry differ only in which `startInactiveSpan` they hand to\n * {@link makeSentryTracer}: the browser one from `@sentry/core`, which installs the span\n * streaming integration on first use, and the plain one from `@sentry/core`, which does not. Nothing\n * else about the tracer is platform-specific.\n */\nexport type StartInactiveSpan = (options: StartSpanOptions) => Span;\n\nfunction createSentrySpan(\n startInactiveSpan: StartInactiveSpan,\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n): SentrySpanLike {\n const parentSentrySpan =\n Option.isSome(parent) && isSentrySpan(parent.value) ? parent.value.sentrySpan : (getActiveSpan() ?? null);\n\n const op = deriveOp(name);\n const origin = deriveOrigin(name);\n\n const newSpan = startInactiveSpan({\n name,\n startTime: nanosToHrTime(startTime),\n // Setting these to `undefined` would strip the core defaults instead of leaving them in place.\n attributes: {\n ...(op && { [SENTRY_OP]: op }),\n ...(origin && { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }),\n },\n ...(parentSentrySpan ? { parentSpan: parentSentrySpan } : {}),\n });\n\n return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);\n}\n\n// Check if we're running Effect v4 by checking the Exit/Cause structure\n// In v4, causes have a 'reasons' array\n// In v3, causes have '_tag' directly on the cause object\nconst isEffectV4 = (() => {\n try {\n const testExit = Exit.fail('test') as unknown as { cause?: unknown };\n const cause = testExit.cause;\n // v4 causes have 'reasons' array, v3 causes have '_tag' directly\n if (isObjectLike(cause) && 'reasons' in cause) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n})();\n\nconst makeSentryTracerV3 = (startInactiveSpan: StartInactiveSpan): EffectTracer.Tracer => {\n // Effect v3 API: span(name, parent, context, links, startTime, kind)\n return EffectTracer.make({\n span(\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n ) {\n return createSentrySpan(startInactiveSpan, name, parent, context, links, startTime, kind);\n },\n context(execution: () => unknown, fiber: { currentSpan?: EffectTracer.AnySpan }) {\n const currentSpan = fiber.currentSpan;\n if (currentSpan === undefined || !isSentrySpan(currentSpan)) {\n return execution();\n }\n return withActiveSpan(currentSpan.sentrySpan, execution);\n },\n } as unknown as EffectTracer.Tracer);\n};\n\nconst makeSentryTracerV4 = (startInactiveSpan: StartInactiveSpan): EffectTracer.Tracer => {\n const EFFECT_EVALUATE = '~effect/Effect/evaluate' as const;\n\n return EffectTracer.make({\n span(options) {\n return createSentrySpan(\n startInactiveSpan,\n options.name,\n options.parent,\n options.annotations,\n options.links,\n options.startTime,\n options.kind,\n );\n },\n context(primitive, fiber) {\n const currentSpan = fiber.currentSpan;\n if (currentSpan === undefined || !isSentrySpan(currentSpan)) {\n return primitive[EFFECT_EVALUATE](fiber);\n }\n return withActiveSpan(currentSpan.sentrySpan, () => primitive[EFFECT_EVALUATE](fiber));\n },\n });\n};\n\n/**\n * Creates an Effect `Tracer` that records Effect spans as Sentry spans.\n *\n * Use the `SentryEffectTracer` exported from `@sentry/effect` rather than calling this directly — the\n * client and server entries each bind the right `startInactiveSpan` for their platform.\n */\nexport function makeSentryTracer(startInactiveSpan: StartInactiveSpan): EffectTracer.Tracer {\n return isEffectV4 ? makeSentryTracerV4(startInactiveSpan) : makeSentryTracerV3(startInactiveSpan);\n}\n"],"names":[],"mappings":";;;;;;;AASA,SAAS,aAAa,IAAA,EAAkC;AACtD,EAAA,IAAI,KAAK,UAAA,CAAW,aAAa,KAAK,IAAA,CAAK,UAAA,CAAW,aAAa,CAAA,EAAG;AACpE,IAAA,OAAO,kBAAA;AAAA,EACT;AAEA,EAAA,OAAO,MAAA;AACT;AASA,SAAS,SAAS,IAAA,EAAkC;AAClD,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,aAAa,CAAA,EAAG;AAClC,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,aAAa,CAAA,EAAG;AAClC,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,OAAO,MAAA;AACT;AAIA,MAAM,kBAAA,mBAAqB,MAAA,CAAO,GAAA,CAAI,2BAA2B,CAAA;AAEjE,SAAS,cAAc,KAAA,EAAuB;AAC5C,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,GAAa,CAAC,CAAA;AACpD,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,GAAa,CAAC,CAAA;AAC3D,EAAA,OAAO,CAAC,SAAS,cAAc,CAAA;AACjC;AAOA,SAAS,aAAa,IAAA,EAAoD;AACxE,EAAA,OAAO,kBAAA,IAAsB,IAAA;AAC/B;AAEA,SAAS,gBAAgB,IAAA,EAAuD;AAC9E,EAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AACzB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AAGnB,EAAA,IAAI,YAAA,CAAa,KAAK,CAAA,IAAK,SAAA,IAAa,SAAS,KAAA,CAAM,OAAA,CAAS,KAAA,CAA+B,OAAO,CAAA,EAAG;AACvG,IAAA,MAAM,UAAW,KAAA,CAAmF,OAAA;AACpG,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,IAAI,MAAA,CAAO,IAAA,KAAS,MAAA,IAAU,MAAA,CAAO,UAAU,MAAA,EAAW;AACxD,QAAA,OAAO,MAAA,CAAO,OAAO,KAAK,CAAA;AAAA,MAC5B;AACA,MAAA,IAAI,MAAA,CAAO,IAAA,KAAS,KAAA,IAAS,MAAA,CAAO,WAAW,MAAA,EAAW;AACxD,QAAA,OAAO,MAAA,CAAO,OAAO,MAAM,CAAA;AAAA,MAC7B;AAAA,IACF;AACA,IAAA,OAAO,gBAAA;AAAA,EACT;AAGA,EAAA,IAAI,YAAA,CAAa,KAAK,CAAA,IAAK,MAAA,IAAU,KAAA,EAAO;AAC1C,IAAA,MAAM,OAAA,GAAU,KAAA;AAChB,IAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAQ;AAC3B,MAAA,OAAO,MAAA,CAAO,QAAQ,KAAK,CAAA;AAAA,IAC7B;AACA,IAAA,IAAI,OAAA,CAAQ,SAAS,KAAA,EAAO;AAC1B,MAAA,OAAO,MAAA,CAAO,QAAQ,MAAM,CAAA;AAAA,IAC9B;AAAA,EACF;AAEA,EAAA,OAAO,gBAAA;AACT;AAEA,MAAM,iBAAA,CAA4C;AAAA,EAazC,YACW,IAAA,EAChB,MAAA,EACgB,SAChB,KAAA,EACA,SAAA,EACgB,MAChB,YAAA,EACA;AAPgB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAGhB,IAAA,IAAA,CAAK,kBAAkB,CAAA,GAAI,IAAA;AAC3B,IAAA,IAAA,CAAK,IAAA,GAAO,MAAA;AACZ,IAAA,IAAA,CAAK,UAAA,uBAAiB,GAAA,EAAqB;AAC3C,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,KAAA,GAAQ,CAAC,GAAG,KAAK,CAAA;AACtB,IAAA,IAAA,CAAK,UAAA,GAAa,YAAA;AAClB,IAAA,IAAA,CAAK,WAAA,GAAc,OAAA;AAEnB,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,UAAA,CAAW,WAAA,EAAY;AAChD,IAAA,IAAA,CAAK,SAAS,WAAA,CAAY,MAAA;AAC1B,IAAA,IAAA,CAAK,UAAU,WAAA,CAAY,OAAA;AAC3B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,UAAA,CAAW,WAAA,EAAY;AAC3C,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,IAAA,EAAM,SAAA;AAAA,MACN;AAAA,KACF;AAAA,EACF;AAAA,EAEO,SAAA,CAAU,KAAa,KAAA,EAAsB;AAClD,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,WAAA,EAAY,EAAG;AAClC,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,UAAA,CAAW,YAAA,CAAa,GAAA,EAAK,KAA4C,CAAA;AAC9E,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EAChC;AAAA,EAEO,SAAS,KAAA,EAAmD;AACjE,IAAA,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAG,KAAK,CAAA;AAAA,EAC1B;AAAA,EAEO,GAAA,CAAI,SAAiB,IAAA,EAAyC;AACnE,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,IAAA,EAAM,OAAA;AAAA,MACN,OAAA;AAAA,MACA,IAAA;AAAA,MACA,SAAA,EAAW,KAAK,MAAA,CAAO;AAAA,KACzB;AAEA,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,WAAA,EAAY,EAAG;AAClC,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AACxB,MAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,IAAI,CAAA,IAAK,gBAAA;AACzC,MAAA,IAAA,CAAK,WAAW,SAAA,CAAU,EAAE,IAAA,EAAM,CAAA,EAAG,SAAS,CAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,UAAA,CAAW,SAAA,CAAU,EAAE,IAAA,EAAM,GAAG,CAAA;AAAA,IACvC;AAEA,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,aAAA,CAAc,OAAO,CAAC,CAAA;AAAA,EAC5C;AAAA,EAEO,KAAA,CAAM,IAAA,EAAc,SAAA,EAAmB,UAAA,EAA4C;AACxF,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,WAAA,EAAY,EAAG;AAClC,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,WAAW,QAAA,CAAS,IAAA,EAAM,UAAA,EAA+C,aAAA,CAAc,SAAS,CAAC,CAAA;AAAA,EACxG;AACF;AAUA,SAAS,iBACP,iBAAA,EACA,IAAA,EACA,QACA,OAAA,EACA,KAAA,EACA,WACA,IAAA,EACgB;AAChB,EAAA,MAAM,gBAAA,GACJ,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,IAAK,YAAA,CAAa,MAAA,CAAO,KAAK,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,UAAA,GAAc,eAAc,IAAK,IAAA;AAEtG,EAAA,MAAM,EAAA,GAAK,SAAS,IAAI,CAAA;AACxB,EAAA,MAAM,MAAA,GAAS,aAAa,IAAI,CAAA;AAEhC,EAAA,MAAM,UAAU,iBAAA,CAAkB;AAAA,IAChC,IAAA;AAAA,IACA,SAAA,EAAW,cAAc,SAAS,CAAA;AAAA;AAAA,IAElC,UAAA,EAAY;AAAA,MACV,GAAI,EAAA,IAAM,EAAE,CAAC,SAAS,GAAG,EAAA,EAAG;AAAA,MAC5B,GAAI,MAAA,IAAU,EAAE,CAAC,gCAAgC,GAAG,MAAA;AAAO,KAC7D;AAAA,IACA,GAAI,gBAAA,GAAmB,EAAE,UAAA,EAAY,gBAAA,KAAqB;AAAC,GAC5D,CAAA;AAED,EAAA,OAAO,IAAI,kBAAkB,IAAA,EAAM,MAAA,EAAQ,SAAS,KAAA,EAAO,SAAA,EAAW,MAAM,OAAO,CAAA;AACrF;AAKA,MAAM,cAAc,MAAM;AACxB,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA;AACjC,IAAA,MAAM,QAAQ,QAAA,CAAS,KAAA;AAEvB,IAAA,IAAI,YAAA,CAAa,KAAK,CAAA,IAAK,SAAA,IAAa,KAAA,EAAO;AAC7C,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF,CAAA,GAAG;AAEH,MAAM,kBAAA,GAAqB,CAAC,iBAAA,KAA8D;AAExF,EAAA,OAAO,aAAa,IAAA,CAAK;AAAA,IACvB,KACE,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,WACA,IAAA,EACA;AACA,MAAA,OAAO,iBAAiB,iBAAA,EAAmB,IAAA,EAAM,QAAQ,OAAA,EAAS,KAAA,EAAO,WAAW,IAAI,CAAA;AAAA,IAC1F,CAAA;AAAA,IACA,OAAA,CAAQ,WAA0B,KAAA,EAA+C;AAC/E,MAAA,MAAM,cAAc,KAAA,CAAM,WAAA;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAA,IAAa,CAAC,YAAA,CAAa,WAAW,CAAA,EAAG;AAC3D,QAAA,OAAO,SAAA,EAAU;AAAA,MACnB;AACA,MAAA,OAAO,cAAA,CAAe,WAAA,CAAY,UAAA,EAAY,SAAS,CAAA;AAAA,IACzD;AAAA,GACiC,CAAA;AACrC,CAAA;AAEA,MAAM,kBAAA,GAAqB,CAAC,iBAAA,KAA8D;AACxF,EAAA,MAAM,eAAA,GAAkB,yBAAA;AAExB,EAAA,OAAO,aAAa,IAAA,CAAK;AAAA,IACvB,KAAK,OAAA,EAAS;AACZ,MAAA,OAAO,gBAAA;AAAA,QACL,iBAAA;AAAA,QACA,OAAA,CAAQ,IAAA;AAAA,QACR,OAAA,CAAQ,MAAA;AAAA,QACR,OAAA,CAAQ,WAAA;AAAA,QACR,OAAA,CAAQ,KAAA;AAAA,QACR,OAAA,CAAQ,SAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACV;AAAA,IACF,CAAA;AAAA,IACA,OAAA,CAAQ,WAAW,KAAA,EAAO;AACxB,MAAA,MAAM,cAAc,KAAA,CAAM,WAAA;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAA,IAAa,CAAC,YAAA,CAAa,WAAW,CAAA,EAAG;AAC3D,QAAA,OAAO,SAAA,CAAU,eAAe,CAAA,CAAE,KAAK,CAAA;AAAA,MACzC;AACA,MAAA,OAAO,cAAA,CAAe,YAAY,UAAA,EAAY,MAAM,UAAU,eAAe,CAAA,CAAE,KAAK,CAAC,CAAA;AAAA,IACvF;AAAA,GACD,CAAA;AACH,CAAA;AAQO,SAAS,iBAAiB,iBAAA,EAA2D;AAC1F,EAAA,OAAO,UAAA,GAAa,kBAAA,CAAmB,iBAAiB,CAAA,GAAI,mBAAmB,iBAAiB,CAAA;AAClG;;;;"}
1
+ {"version":3,"file":"tracer.js","sources":["../../src/tracer.ts"],"sourcesContent":["/* oxlint-disable max-lines */\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT, HTTP_SERVER } from '@sentry/conventions/op';\nimport type { Span, StartSpanOptions } from '@sentry/core';\nimport {\n _INTERNAL_safeMathRandom,\n addNonEnumerableProperty,\n getActiveSpan,\n getCurrentScope,\n getDefaultCurrentScope,\n isObjectLike,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startNewTrace,\n withActiveSpan,\n withScope,\n} from '@sentry/core';\nimport * as Context from 'effect/Context';\nimport * as Exit from 'effect/Exit';\nimport type * as EffectLayer from 'effect/Layer';\nimport { succeed as succeedLayer } from 'effect/Layer';\nimport * as Option from 'effect/Option';\nimport * as EffectTracer from 'effect/Tracer';\n\nfunction deriveOrigin(name: string): string | undefined {\n if (name.startsWith('http.server') || name.startsWith('http.client')) {\n return 'auto.http.effect';\n }\n\n return undefined;\n}\n\nconst EFFECT_SPAN_SYMBOL = Symbol.for('@sentry/effect.EffectSpan');\n\nfunction markEffectSpan(span: Span): void {\n addNonEnumerableProperty(span, EFFECT_SPAN_SYMBOL, true);\n}\n\n/**\n * Whether this tracer created the span. A brand rather than an attribute check, because an unsampled\n * span keeps no attributes.\n */\nfunction isEffectSpan(span: Span): boolean {\n return (span as { [EFFECT_SPAN_SYMBOL]?: boolean })[EFFECT_SPAN_SYMBOL] === true;\n}\n\n/**\n * Effect span names are chosen by whoever calls `Effect.withSpan`, so the name is the only signal\n * available. `@effect/platform` names its HTTP spans `http.server`/`http.client`, which map onto the\n * matching Sentry ops. Every other name comes from user code or a third-party library, whose semantics\n * we cannot infer, so op and origin stay unset and the span keeps the core defaults: no op, and a\n * `manual` origin.\n */\nfunction deriveOp(name: string): string | undefined {\n if (name.startsWith('http.server')) {\n return HTTP_SERVER;\n }\n\n if (name.startsWith('http.client')) {\n return HTTP_CLIENT;\n }\n\n return undefined;\n}\n\ntype HrTime = [number, number];\n\nconst SENTRY_SPAN_SYMBOL = Symbol.for('@sentry/effect.SentrySpan');\n\nfunction nanosToHrTime(nanos: bigint): HrTime {\n const seconds = Number(nanos / BigInt(1_000_000_000));\n const remainingNanos = Number(nanos % BigInt(1_000_000_000));\n return [seconds, remainingNanos];\n}\n\ninterface SentrySpanLike extends EffectTracer.Span {\n readonly [SENTRY_SPAN_SYMBOL]: true;\n readonly sentrySpan: Span;\n}\n\nfunction isSentrySpan(span: EffectTracer.AnySpan): span is SentrySpanLike {\n return SENTRY_SPAN_SYMBOL in span;\n}\n\nfunction getErrorMessage(exit: Exit.Exit<unknown, unknown>): string | undefined {\n if (!Exit.isFailure(exit)) {\n return undefined;\n }\n\n const cause = exit.cause as unknown;\n\n // Effect v4: cause.reasons is an array of Reason objects\n if (isObjectLike(cause) && 'reasons' in cause && Array.isArray((cause as { reasons: unknown }).reasons)) {\n const reasons = (cause as { reasons: Array<{ _tag?: string; error?: unknown; defect?: unknown }> }).reasons;\n for (const reason of reasons) {\n if (reason._tag === 'Fail' && reason.error !== undefined) {\n return String(reason.error);\n }\n if (reason._tag === 'Die' && reason.defect !== undefined) {\n return String(reason.defect);\n }\n }\n return 'internal_error';\n }\n\n // Effect v3: cause has _tag directly\n if (isObjectLike(cause) && '_tag' in cause) {\n const v3Cause = cause as { _tag: string; error?: unknown; defect?: unknown };\n if (v3Cause._tag === 'Fail') {\n return String(v3Cause.error);\n }\n if (v3Cause._tag === 'Die') {\n return String(v3Cause.defect);\n }\n }\n\n return 'internal_error';\n}\n\nclass SentrySpanWrapper implements SentrySpanLike {\n public readonly [SENTRY_SPAN_SYMBOL]: true;\n public readonly _tag: 'Span';\n public readonly spanId: string;\n public readonly traceId: string;\n public readonly attributes: Map<string, unknown>;\n public readonly sampled: boolean;\n public readonly parent: Option.Option<EffectTracer.AnySpan>;\n public readonly links: Array<EffectTracer.SpanLink>;\n public status: EffectTracer.SpanStatus;\n public readonly sentrySpan: Span;\n public readonly annotations: Context.Context<never>;\n\n public constructor(\n public readonly name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n public readonly context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n public readonly kind: EffectTracer.SpanKind,\n existingSpan: Span,\n ) {\n this[SENTRY_SPAN_SYMBOL] = true as const;\n this._tag = 'Span' as const;\n this.attributes = new Map<string, unknown>();\n this.parent = parent;\n this.links = [...links];\n this.sentrySpan = existingSpan;\n this.annotations = context;\n\n const spanContext = this.sentrySpan.spanContext();\n this.spanId = spanContext.spanId;\n this.traceId = spanContext.traceId;\n this.sampled = this.sentrySpan.isRecording();\n this.status = {\n _tag: 'Started',\n startTime,\n };\n }\n\n public attribute(key: string, value: unknown): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.setAttribute(key, value as Parameters<Span['setAttribute']>[1]);\n this.attributes.set(key, value);\n }\n\n public addLinks(links: ReadonlyArray<EffectTracer.SpanLink>): void {\n this.links.push(...links);\n }\n\n public end(endTime: bigint, exit: Exit.Exit<unknown, unknown>): void {\n this.status = {\n _tag: 'Ended',\n endTime,\n exit,\n startTime: this.status.startTime,\n };\n\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n if (Exit.isFailure(exit)) {\n const message = getErrorMessage(exit) ?? 'internal_error';\n this.sentrySpan.setStatus({ code: 2, message });\n } else {\n this.sentrySpan.setStatus({ code: 1 });\n }\n\n this.sentrySpan.end(nanosToHrTime(endTime));\n }\n\n public event(name: string, startTime: bigint, attributes?: Record<string, unknown>): void {\n if (!this.sentrySpan.isRecording()) {\n return;\n }\n\n this.sentrySpan.addEvent(name, attributes as Parameters<Span['addEvent']>[1], nanosToHrTime(startTime));\n }\n}\n\n/**\n * The client and the server entry hand different `startInactiveSpan` functions to\n * {@link makeSentryTracer}: the browser one from `@sentry/core/browser`, which installs the span\n * streaming integration on first use, and the plain one from `@sentry/core`, which does not.\n */\nexport type StartInactiveSpan = (options: StartSpanOptions) => Span;\n\n// Check if we're running Effect v4 by checking the Exit/Cause structure\n// In v4, causes have a 'reasons' array\n// In v3, causes have '_tag' directly on the cause object\nconst isEffectV4 = (() => {\n try {\n const testExit = Exit.fail('test') as unknown as { cause?: unknown };\n const cause = testExit.cause;\n // v4 causes have 'reasons' array, v3 causes have '_tag' directly\n if (isObjectLike(cause) && 'reasons' in cause) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n})();\n\nconst EXTERNAL_SPAN_KEY = '@sentry/effect/ExternalSpan';\n\ninterface ContextExports {\n Reference: typeof Context.Reference;\n /** Only Effect v3 exports it. */\n GenericTag<Identifier, Service>(key: string): Context.Key<Identifier, Service>;\n}\n\n// Effect v4 has no `Context.GenericTag` and Effect v3 before 3.11 has no `Context.Reference`. Both are read\n// through a separate binding because bundlers fail the build on a namespace member the installed version lacks.\nconst contextExports = Context as unknown as ContextExports;\n\n/**\n * Whether the tracer continues the trace of a `Tracer.externalSpan` parent. Effect v4 has no `FiberRef`\n * and v3 before 3.11 has no `Context.Reference`, so the flag is a plain service in both. The cast is safe:\n * the tracer reads it with `getRef` only on a v4 fiber, where it is a reference, and with\n * `Context.getOption` on v3.\n */\nconst ExternalSpanFlag = (\n isEffectV4\n ? contextExports.Reference<boolean>(EXTERNAL_SPAN_KEY, { defaultValue: () => false })\n : contextExports.GenericTag<never, boolean>(EXTERNAL_SPAN_KEY)\n) as Context.Reference<boolean>;\n\n/**\n * Makes the tracer continue the trace of a `Tracer.externalSpan` parent instead of ignoring it. Provide it\n * next to the tracer layer to continue every external span in the runtime, or provide it to a single\n * effect with `Effect.provide` to continue only that one.\n */\nexport const SentryEffectExternalSpanLayer: EffectLayer.Layer<never> = succeedLayer(ExternalSpanFlag, true);\n\ninterface FiberLike {\n /** The span the fiber runs in. Only Effect v3 fibers have it. */\n readonly currentSpan?: EffectTracer.AnySpan | undefined;\n /** Holds `span`, the span the fiber runs in. Only Effect v4 fibers have it. */\n readonly cache?: { readonly span?: EffectTracer.AnySpan | undefined };\n /** Reads a reference with its default. Only Effect v4 fibers have it. */\n readonly getRef?: <A>(ref: Context.Reference<A>) => A;\n /** The services of the fiber. Only Effect v3 fibers have it. */\n readonly currentContext?: Context.Context<never>;\n}\n\n/**\n * The fiber whose operation is being evaluated. Effect hands the fiber to the `context` hook but not to\n * `span`, which runs synchronously inside it, so the hook keeps the fiber here for that extent.\n */\nlet currentFiber: FiberLike | undefined;\n\nfunction continuesExternalSpans(fiber: FiberLike): boolean {\n if (fiber.getRef) {\n return fiber.getRef(ExternalSpanFlag);\n }\n\n return (\n fiber.currentContext !== undefined &&\n Option.getOrElse(Context.getOption(fiber.currentContext, ExternalSpanFlag), () => false)\n );\n}\n\nfunction getFiberSpan(fiber: FiberLike): EffectTracer.AnySpan | undefined {\n return isEffectV4 ? fiber.cache?.span : fiber.currentSpan;\n}\n\nfunction withFiberContext<X>(fiber: FiberLike, execution: () => X): X {\n const previousFiber = currentFiber;\n currentFiber = fiber;\n try {\n const currentSpan = getFiberSpan(fiber);\n if (currentSpan === undefined || !isSentrySpan(currentSpan)) {\n return execution();\n }\n return withActiveSpan(currentSpan.sentrySpan, execution);\n } finally {\n currentFiber = previousFiber;\n }\n}\n\n/**\n * Starts the Sentry span for an Effect span, rooted or parented the way Effect asked for.\n *\n * - A parent this tracer created becomes the Sentry parent.\n * - Any other parent (`Tracer.externalSpan` bridging a trace this SDK did not start, such as an\n * OpenTelemetry span of another app in the same process or persisted trace state) is ignored unless\n * {@link SentryEffectExternalSpanLayer} is provided, so a span joins a foreign trace only when the user\n * asked for it. The span then nests where Effect would have put it without the `parent` option: under\n * the fiber's current span, or parentless. With the layer, the span continues that trace: it is a root\n * span whose `parent_span_id` is the external span. No dynamic sampling context is frozen, so the SDK\n * builds one from the client the way it does for a head-of-trace span.\n * - Without a parent, the span nests under a foreign active Sentry span (an `http.server` span from the\n * Node SDK, a pageload in the browser) but never under a span this tracer created: Effect's own parent\n * tracking is authoritative for those, so an active one is an enclosing `root: true` span or a span\n * leaked from another fiber through the async context. Effect reports `root: true` for every\n * parentless span, so the flag adds nothing and is not consulted.\n * - A root span starts a new trace when `newTraceForRootSpans` is set, unless the user set up the\n * current scope (`Sentry.continueTrace`, `Sentry.withScope`, an HTTP request's isolation scope).\n */\nfunction startSentrySpan(\n startInactiveSpan: StartInactiveSpan,\n options: StartSpanOptions,\n parent: Option.Option<EffectTracer.AnySpan>,\n newTraceForRootSpans: boolean,\n): Span {\n if (Option.isSome(parent)) {\n const parentSpan = parent.value;\n\n if (isSentrySpan(parentSpan)) {\n return startInactiveSpan({ ...options, parentSpan: parentSpan.sentrySpan });\n }\n\n if (currentFiber !== undefined && continuesExternalSpans(currentFiber)) {\n return withScope(scope => {\n scope.setPropagationContext({\n traceId: parentSpan.traceId,\n parentSpanId: parentSpan.spanId,\n sampled: parentSpan.sampled,\n sampleRand: _INTERNAL_safeMathRandom(),\n });\n return withActiveSpan(null, () => startInactiveSpan(options));\n });\n }\n\n const enclosingSpan = currentFiber && getFiberSpan(currentFiber);\n if (enclosingSpan !== undefined && isSentrySpan(enclosingSpan)) {\n return startInactiveSpan({ ...options, parentSpan: enclosingSpan.sentrySpan });\n }\n }\n\n const activeSpan = getActiveSpan();\n if (activeSpan && !isEffectSpan(activeSpan)) {\n return startInactiveSpan({ ...options, parentSpan: activeSpan });\n }\n\n // A scope the user forked (`continueTrace`, `withScope`, an isolation scope) carries its own trace id.\n // The scopes this tracer forks in `context()` clone the propagation context they were forked from, so\n // even when one leaks into another fiber through the async context it still carries the process-wide\n // trace id of the default scope.\n const isProcessTrace =\n getCurrentScope().getPropagationContext().traceId === getDefaultCurrentScope().getPropagationContext().traceId;\n if (newTraceForRootSpans && isProcessTrace) {\n return startNewTrace(() => startInactiveSpan(options));\n }\n\n return withActiveSpan(null, () => startInactiveSpan(options));\n}\n\nfunction createSentrySpan(\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n): SentrySpanLike {\n const op = deriveOp(name);\n const origin = deriveOrigin(name);\n\n const newSpan = startSentrySpan(\n startInactiveSpan,\n {\n name,\n startTime: nanosToHrTime(startTime),\n // Setting these to `undefined` would strip the core defaults instead of leaving them in place.\n attributes: {\n ...(op && { [SENTRY_OP]: op }),\n ...(origin && { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin }),\n },\n },\n parent,\n newTraceForRootSpans,\n );\n markEffectSpan(newSpan);\n\n return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);\n}\n\nconst makeSentryTracerV3 = (\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n): EffectTracer.Tracer => {\n // Effect v3 API: span(name, parent, context, links, startTime, kind)\n return EffectTracer.make({\n span(\n name: string,\n parent: Option.Option<EffectTracer.AnySpan>,\n context: Context.Context<never>,\n links: ReadonlyArray<EffectTracer.SpanLink>,\n startTime: bigint,\n kind: EffectTracer.SpanKind,\n ) {\n return createSentrySpan(startInactiveSpan, newTraceForRootSpans, name, parent, context, links, startTime, kind);\n },\n context(execution: () => unknown, fiber: FiberLike) {\n return withFiberContext(fiber, execution);\n },\n } as unknown as EffectTracer.Tracer);\n};\n\nconst makeSentryTracerV4 = (\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n): EffectTracer.Tracer => {\n const EFFECT_EVALUATE = '~effect/Effect/evaluate' as const;\n\n return EffectTracer.make({\n span(options) {\n return createSentrySpan(\n startInactiveSpan,\n newTraceForRootSpans,\n options.name,\n options.parent,\n options.annotations,\n options.links,\n options.startTime,\n options.kind,\n );\n },\n context(primitive, fiber) {\n return withFiberContext(fiber, () => primitive[EFFECT_EVALUATE](fiber));\n },\n });\n};\n\n/**\n * Creates an Effect `Tracer` that records Effect spans as Sentry spans.\n *\n * Use the `SentryEffectTracer` exported from `@sentry/effect` rather than calling this directly — the\n * client and server entries each bind the right `startInactiveSpan` for their platform.\n *\n * `newTraceForRootSpans` is the one behavioural difference between the platforms: Effect gives every\n * parentless span a fresh trace id, and on a long-lived server nothing else forks the propagation\n * context, so the server tracer follows Effect and starts a new trace. In the browser the page trace is\n * the intended home of every span, so the client tracer keeps parentless spans in it.\n */\nexport function makeSentryTracer(\n startInactiveSpan: StartInactiveSpan,\n newTraceForRootSpans: boolean,\n): EffectTracer.Tracer {\n return isEffectV4\n ? makeSentryTracerV4(startInactiveSpan, newTraceForRootSpans)\n : makeSentryTracerV3(startInactiveSpan, newTraceForRootSpans);\n}\n"],"names":["succeedLayer"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../../src/client/tracer.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,gCAA0D,CAAC"}
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../../src/client/tracer.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,gCAAiE,CAAC"}
@@ -2,6 +2,7 @@ export * from '@sentry/browser';
2
2
  export { effectLayer, init } from './client/index';
3
3
  export type { EffectClientLayerOptions } from './client/index';
4
4
  export { SentryEffectTracer } from './client/tracer';
5
+ export { SentryEffectExternalSpanLayer } from './tracer';
5
6
  export { SentryEffectLogger } from './logger';
6
7
  export { SentryEffectMetricsLayer } from './metrics';
7
8
  //# sourceMappingURL=index.client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../src/index.client.ts"],"names":[],"mappings":"AAGA,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../src/index.client.ts"],"names":[],"mappings":"AAGA,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC"}
@@ -2,6 +2,7 @@ export * from '@sentry/node';
2
2
  export { effectLayer, init } from './server/index';
3
3
  export type { EffectServerLayerOptions } from './server/index';
4
4
  export { SentryEffectTracer } from './server/tracer';
5
+ export { SentryEffectExternalSpanLayer } from './tracer';
5
6
  export { SentryEffectLogger } from './logger';
6
7
  export { SentryEffectMetricsLayer } from './metrics';
7
8
  //# sourceMappingURL=index.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.d.ts","sourceRoot":"","sources":["../../src/index.server.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.server.d.ts","sourceRoot":"","sources":["../../src/index.server.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC"}
@@ -5,6 +5,10 @@
5
5
  * every span start with a `getClient()` lookup to lazily install `spanStreamingIntegration`, which on
6
6
  * the server is pure overhead — `ServerRuntimeClient` already installs it eagerly.
7
7
  *
8
+ * Every parentless Effect span starts a new trace. A server process forks no propagation context on
9
+ * its own, so without this every request, reactor and background job of the process would land in
10
+ * one trace.
11
+ *
8
12
  * See `./client/tracer.ts` for why the call is wrapped in an arrow.
9
13
  */
10
14
  export declare const SentryEffectTracer: import("effect/Tracer").Tracer;
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../../src/server/tracer.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,gCAA0D,CAAC"}
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../../src/server/tracer.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,gCAAgE,CAAC"}
@@ -1,17 +1,28 @@
1
1
  import type { Span, StartSpanOptions } from '@sentry/core';
2
+ import type * as EffectLayer from 'effect/Layer';
2
3
  import * as EffectTracer from 'effect/Tracer';
3
4
  /**
4
- * The client and the server entry differ only in which `startInactiveSpan` they hand to
5
- * {@link makeSentryTracer}: the browser one from `@sentry/core`, which installs the span
6
- * streaming integration on first use, and the plain one from `@sentry/core`, which does not. Nothing
7
- * else about the tracer is platform-specific.
5
+ * The client and the server entry hand different `startInactiveSpan` functions to
6
+ * {@link makeSentryTracer}: the browser one from `@sentry/core/browser`, which installs the span
7
+ * streaming integration on first use, and the plain one from `@sentry/core`, which does not.
8
8
  */
9
9
  export type StartInactiveSpan = (options: StartSpanOptions) => Span;
10
+ /**
11
+ * Makes the tracer continue the trace of a `Tracer.externalSpan` parent instead of ignoring it. Provide it
12
+ * next to the tracer layer to continue every external span in the runtime, or provide it to a single
13
+ * effect with `Effect.provide` to continue only that one.
14
+ */
15
+ export declare const SentryEffectExternalSpanLayer: EffectLayer.Layer<never>;
10
16
  /**
11
17
  * Creates an Effect `Tracer` that records Effect spans as Sentry spans.
12
18
  *
13
19
  * Use the `SentryEffectTracer` exported from `@sentry/effect` rather than calling this directly — the
14
20
  * client and server entries each bind the right `startInactiveSpan` for their platform.
21
+ *
22
+ * `newTraceForRootSpans` is the one behavioural difference between the platforms: Effect gives every
23
+ * parentless span a fresh trace id, and on a long-lived server nothing else forks the propagation
24
+ * context, so the server tracer follows Effect and starts a new trace. In the browser the page trace is
25
+ * the intended home of every span, so the client tracer keeps parentless spans in it.
15
26
  */
16
- export declare function makeSentryTracer(startInactiveSpan: StartInactiveSpan): EffectTracer.Tracer;
27
+ export declare function makeSentryTracer(startInactiveSpan: StartInactiveSpan, newTraceForRootSpans: boolean): EffectTracer.Tracer;
17
28
  //# sourceMappingURL=tracer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../src/tracer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAK3D,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAuK9C;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAgGpE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,YAAY,CAAC,MAAM,CAE1F"}
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../src/tracer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAe3D,OAAO,KAAK,KAAK,WAAW,MAAM,cAAc,CAAC;AAGjD,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAqL9C;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;AA2CpE;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAwC,CAAC;AAmM5G;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,iBAAiB,EAAE,iBAAiB,EACpC,oBAAoB,EAAE,OAAO,GAC5B,YAAY,CAAC,MAAM,CAIrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/effect",
3
- "version": "11.2.0",
3
+ "version": "11.4.0",
4
4
  "description": "Official Sentry SDK for Effect",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/effect",
@@ -44,13 +44,13 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@sentry/browser": "11.2.0",
48
- "@sentry/conventions": "^0.24.0",
49
- "@sentry/core": "11.2.0",
50
- "@sentry/node": "11.2.0"
47
+ "@sentry/browser": "11.4.0",
48
+ "@sentry/conventions": "^0.25.0",
49
+ "@sentry/core": "11.4.0",
50
+ "@sentry/node": "11.4.0"
51
51
  },
52
52
  "peerDependencies": {
53
- "effect": "^3.0.0 || ^4.0.0-beta.50"
53
+ "effect": "^3.0.0 || ^4.0.0"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "effect": {
@@ -58,8 +58,8 @@
58
58
  }
59
59
  },
60
60
  "devDependencies": {
61
- "@effect/vitest": "^4.0.0-beta.50",
62
- "effect": "^4.0.0-beta.50"
61
+ "@effect/vitest": "^4.0.0",
62
+ "effect": "^4.0.0"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "run-p build:transpile build:types",