@sentry/effect 10.44.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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +48 -0
  3. package/build/cjs/client/index.js +44 -0
  4. package/build/cjs/client/index.js.map +1 -0
  5. package/build/cjs/client/sdk.js +23 -0
  6. package/build/cjs/client/sdk.js.map +1 -0
  7. package/build/cjs/index.client.js +27 -0
  8. package/build/cjs/index.client.js.map +1 -0
  9. package/build/cjs/index.server.js +27 -0
  10. package/build/cjs/index.server.js.map +1 -0
  11. package/build/cjs/logger.js +43 -0
  12. package/build/cjs/logger.js.map +1 -0
  13. package/build/cjs/metrics.js +120 -0
  14. package/build/cjs/metrics.js.map +1 -0
  15. package/build/cjs/server/index.js +44 -0
  16. package/build/cjs/server/index.js.map +1 -0
  17. package/build/cjs/server/sdk.js +23 -0
  18. package/build/cjs/server/sdk.js.map +1 -0
  19. package/build/cjs/tracer.js +145 -0
  20. package/build/cjs/tracer.js.map +1 -0
  21. package/build/esm/client/index.js +41 -0
  22. package/build/esm/client/index.js.map +1 -0
  23. package/build/esm/client/sdk.js +21 -0
  24. package/build/esm/client/sdk.js.map +1 -0
  25. package/build/esm/index.client.js +7 -0
  26. package/build/esm/index.client.js.map +1 -0
  27. package/build/esm/index.server.js +7 -0
  28. package/build/esm/index.server.js.map +1 -0
  29. package/build/esm/logger.js +41 -0
  30. package/build/esm/logger.js.map +1 -0
  31. package/build/esm/metrics.js +118 -0
  32. package/build/esm/metrics.js.map +1 -0
  33. package/build/esm/package.json +1 -0
  34. package/build/esm/server/index.js +41 -0
  35. package/build/esm/server/index.js.map +1 -0
  36. package/build/esm/server/sdk.js +21 -0
  37. package/build/esm/server/sdk.js.map +1 -0
  38. package/build/esm/tracer.js +143 -0
  39. package/build/esm/tracer.js.map +1 -0
  40. package/build/types/client/index.d.ts +33 -0
  41. package/build/types/client/index.d.ts.map +1 -0
  42. package/build/types/client/sdk.d.ts +10 -0
  43. package/build/types/client/sdk.d.ts.map +1 -0
  44. package/build/types/index.client.d.ts +7 -0
  45. package/build/types/index.client.d.ts.map +1 -0
  46. package/build/types/index.server.d.ts +7 -0
  47. package/build/types/index.server.d.ts.map +1 -0
  48. package/build/types/index.types.d.ts +16 -0
  49. package/build/types/index.types.d.ts.map +1 -0
  50. package/build/types/logger.d.ts +6 -0
  51. package/build/types/logger.d.ts.map +1 -0
  52. package/build/types/metrics.d.ts +17 -0
  53. package/build/types/metrics.d.ts.map +1 -0
  54. package/build/types/server/index.d.ts +34 -0
  55. package/build/types/server/index.d.ts.map +1 -0
  56. package/build/types/server/sdk.d.ts +10 -0
  57. package/build/types/server/sdk.d.ts.map +1 -0
  58. package/build/types/tracer.d.ts +6 -0
  59. package/build/types/tracer.d.ts.map +1 -0
  60. package/build/types-ts3.8/client/index.d.ts +33 -0
  61. package/build/types-ts3.8/client/sdk.d.ts +10 -0
  62. package/build/types-ts3.8/index.client.d.ts +7 -0
  63. package/build/types-ts3.8/index.server.d.ts +7 -0
  64. package/build/types-ts3.8/index.types.d.ts +16 -0
  65. package/build/types-ts3.8/logger.d.ts +6 -0
  66. package/build/types-ts3.8/metrics.d.ts +17 -0
  67. package/build/types-ts3.8/server/index.d.ts +34 -0
  68. package/build/types-ts3.8/server/sdk.d.ts +10 -0
  69. package/build/types-ts3.8/tracer.d.ts +6 -0
  70. package/package.json +99 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Functional Software Inc. dba Sentry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Official Sentry SDK for Effect.ts (Alpha)
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@sentry/effect.svg)](https://www.npmjs.com/package/@sentry/effect)
4
+ [![npm dm](https://img.shields.io/npm/dm/@sentry/effect.svg)](https://www.npmjs.com/package/@sentry/effect)
5
+ [![npm dt](https://img.shields.io/npm/dt/@sentry/effect.svg)](https://www.npmjs.com/package/@sentry/effect)
6
+
7
+ > NOTICE: This package is in alpha state and may be subject to breaking changes.
8
+
9
+ ## Getting Started
10
+
11
+ This SDK does not have docs yet. Stay tuned.
12
+
13
+ ## Usage
14
+
15
+ ```typescript
16
+ import * as Sentry from '@sentry/effect/server';
17
+ import { NodeRuntime } from '@effect/platform-node';
18
+ import { Layer, Logger } from 'effect';
19
+ import { HttpLive } from './Http.js';
20
+
21
+ const SentryLive = Layer.mergeAll(
22
+ Sentry.effectLayer({
23
+ dsn: '__DSN__',
24
+ tracesSampleRate: 1.0,
25
+ enableLogs: true,
26
+ }),
27
+ Layer.setTracer(Sentry.SentryEffectTracer),
28
+ Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger),
29
+ Sentry.SentryEffectMetricsLayer,
30
+ );
31
+
32
+ const MainLive = HttpLive.pipe(Layer.provide(SentryLive));
33
+ MainLive.pipe(Layer.launch, NodeRuntime.runMain);
34
+ ```
35
+
36
+ The `effectLayer` function initializes Sentry. To enable Effect instrumentation, compose with:
37
+
38
+ - `Layer.setTracer(Sentry.SentryEffectTracer)` - Effect spans traced as Sentry spans
39
+ - `Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger)` - Effect logs forwarded to Sentry
40
+ - `Sentry.SentryEffectMetricsLayer` - Effect metrics sent to Sentry
41
+
42
+ ## Links
43
+
44
+ <!-- - [Official SDK Docs](https://docs.sentry.io/platforms/javascript/guides/effect/) -->
45
+
46
+ - [Sentry.io](https://sentry.io/?utm_source=github&utm_medium=npm_effect)
47
+ - [Sentry Discord Server](https://discord.gg/Ww9hbqr)
48
+ - [Stack Overflow](https://stackoverflow.com/questions/tagged/sentry)
@@ -0,0 +1,44 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const Layer = require('effect/Layer');
4
+ const sdk = require('./sdk.js');
5
+
6
+ /**
7
+ * Options for the Sentry Effect client layer.
8
+ */
9
+
10
+ /**
11
+ * Creates an Effect Layer that initializes Sentry for browser clients.
12
+ *
13
+ * To enable Effect tracing, logs, or metrics, compose with the respective layers:
14
+ * - `Layer.setTracer(Sentry.SentryEffectTracer)` for tracing
15
+ * - `Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger)` for logs
16
+ * - `Sentry.SentryEffectMetricsLayer` for metrics
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import * as Sentry from '@sentry/effect/client';
21
+ * import { Layer, Logger, LogLevel } from 'effect';
22
+ *
23
+ * const SentryLive = Layer.mergeAll(
24
+ * Sentry.effectLayer({
25
+ * dsn: '__DSN__',
26
+ * integrations: [Sentry.browserTracingIntegration()],
27
+ * tracesSampleRate: 1.0,
28
+ * }),
29
+ * Layer.setTracer(Sentry.SentryEffectTracer),
30
+ * Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger),
31
+ * );
32
+ * ```
33
+ */
34
+ function effectLayer(options) {
35
+ return Layer.suspend(() => {
36
+ sdk.init(options);
37
+
38
+ return Layer.empty;
39
+ });
40
+ }
41
+
42
+ exports.init = sdk.init;
43
+ exports.effectLayer = effectLayer;
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/client/index.ts"],"sourcesContent":["import type { BrowserOptions } from '@sentry/browser';\nimport type * as EffectLayer from 'effect/Layer';\nimport { empty as emptyLayer, suspend as suspendLayer } from 'effect/Layer';\nimport { init } from './sdk';\n\nexport { init } from './sdk';\n\n/**\n * Options for the Sentry Effect client layer.\n */\nexport type EffectClientLayerOptions = BrowserOptions;\n\n/**\n * Creates an Effect Layer that initializes Sentry for browser clients.\n *\n * To enable Effect tracing, logs, or metrics, compose with the respective layers:\n * - `Layer.setTracer(Sentry.SentryEffectTracer)` for tracing\n * - `Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger)` for logs\n * - `Sentry.SentryEffectMetricsLayer` for metrics\n *\n * @example\n * ```typescript\n * import * as Sentry from '@sentry/effect/client';\n * import { Layer, Logger, LogLevel } from 'effect';\n *\n * const SentryLive = Layer.mergeAll(\n * Sentry.effectLayer({\n * dsn: '__DSN__',\n * integrations: [Sentry.browserTracingIntegration()],\n * tracesSampleRate: 1.0,\n * }),\n * Layer.setTracer(Sentry.SentryEffectTracer),\n * Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger),\n * );\n * ```\n */\nexport function effectLayer(options: EffectClientLayerOptions): EffectLayer.Layer<never, never, never> {\n return suspendLayer(() => {\n init(options);\n\n return emptyLayer;\n });\n}\n"],"names":["suspendLayer","init","emptyLayer"],"mappings":";;;;;AAOA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW,CAAC,OAAO,EAAoE;AACvG,EAAE,OAAOA,aAAY,CAAC,MAAM;AAC5B,IAAIC,QAAI,CAAC,OAAO,CAAC;;AAEjB,IAAI,OAAOC,WAAU;AACrB,EAAE,CAAC,CAAC;AACJ;;;;;"}
@@ -0,0 +1,23 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const browser = require('@sentry/browser');
4
+ const core = require('@sentry/core');
5
+
6
+ /**
7
+ * Initializes the Sentry Effect SDK for browser clients.
8
+ *
9
+ * @param options - Configuration options for the SDK
10
+ * @returns The initialized Sentry client, or undefined if initialization failed
11
+ */
12
+ function init(options) {
13
+ const opts = {
14
+ ...options,
15
+ };
16
+
17
+ core.applySdkMetadata(opts, 'effect', ['effect', 'browser']);
18
+
19
+ return browser.init(opts);
20
+ }
21
+
22
+ exports.init = init;
23
+ //# sourceMappingURL=sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/client/sdk.ts"],"sourcesContent":["import type { BrowserOptions } from '@sentry/browser';\nimport { init as initBrowser } from '@sentry/browser';\nimport type { Client } from '@sentry/core';\nimport { applySdkMetadata } from '@sentry/core';\n\n/**\n * Initializes the Sentry Effect SDK for browser clients.\n *\n * @param options - Configuration options for the SDK\n * @returns The initialized Sentry client, or undefined if initialization failed\n */\nexport function init(options: BrowserOptions): Client | undefined {\n const opts = {\n ...options,\n };\n\n applySdkMetadata(opts, 'effect', ['effect', 'browser']);\n\n return initBrowser(opts);\n}\n"],"names":["applySdkMetadata","initBrowser"],"mappings":";;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAsC;AAClE,EAAE,MAAM,OAAO;AACf,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAEA,qBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;;AAEzD,EAAE,OAAOC,YAAW,CAAC,IAAI,CAAC;AAC1B;;;;"}
@@ -0,0 +1,27 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const browser = require('@sentry/browser');
4
+ const index = require('./client/index.js');
5
+ const tracer = require('./tracer.js');
6
+ const logger = require('./logger.js');
7
+ const metrics = require('./metrics.js');
8
+ const sdk = require('./client/sdk.js');
9
+
10
+
11
+
12
+ exports.effectLayer = index.effectLayer;
13
+ exports.SentryEffectTracer = tracer.SentryEffectTracer;
14
+ exports.SentryEffectLogger = logger.SentryEffectLogger;
15
+ exports.SentryEffectMetricsLayer = metrics.SentryEffectMetricsLayer;
16
+ exports.init = sdk.init;
17
+ Object.prototype.hasOwnProperty.call(browser, '__proto__') &&
18
+ !Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
19
+ Object.defineProperty(exports, '__proto__', {
20
+ enumerable: true,
21
+ value: browser['__proto__']
22
+ });
23
+
24
+ Object.keys(browser).forEach(k => {
25
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = browser[k];
26
+ });
27
+ //# sourceMappingURL=index.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,27 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const light = require('@sentry/node-core/light');
4
+ const index = require('./server/index.js');
5
+ const tracer = require('./tracer.js');
6
+ const logger = require('./logger.js');
7
+ const metrics = require('./metrics.js');
8
+ const sdk = require('./server/sdk.js');
9
+
10
+
11
+
12
+ exports.effectLayer = index.effectLayer;
13
+ exports.SentryEffectTracer = tracer.SentryEffectTracer;
14
+ exports.SentryEffectLogger = logger.SentryEffectLogger;
15
+ exports.SentryEffectMetricsLayer = metrics.SentryEffectMetricsLayer;
16
+ exports.init = sdk.init;
17
+ Object.prototype.hasOwnProperty.call(light, '__proto__') &&
18
+ !Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
19
+ Object.defineProperty(exports, '__proto__', {
20
+ enumerable: true,
21
+ value: light['__proto__']
22
+ });
23
+
24
+ Object.keys(light).forEach(k => {
25
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = light[k];
26
+ });
27
+ //# sourceMappingURL=index.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,43 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const Logger = require('effect/Logger');
5
+
6
+ /**
7
+ * Effect Logger that sends logs to Sentry.
8
+ */
9
+ const SentryEffectLogger = Logger.make(({ logLevel, message }) => {
10
+ let msg;
11
+ if (typeof message === 'string') {
12
+ msg = message;
13
+ } else if (Array.isArray(message) && message.length === 1) {
14
+ const firstElement = message[0];
15
+ msg = typeof firstElement === 'string' ? firstElement : JSON.stringify(firstElement);
16
+ } else {
17
+ msg = JSON.stringify(message);
18
+ }
19
+
20
+ switch (logLevel._tag) {
21
+ case 'Fatal':
22
+ core.logger.fatal(msg);
23
+ break;
24
+ case 'Error':
25
+ core.logger.error(msg);
26
+ break;
27
+ case 'Warning':
28
+ core.logger.warn(msg);
29
+ break;
30
+ case 'Info':
31
+ core.logger.info(msg);
32
+ break;
33
+ case 'Debug':
34
+ core.logger.debug(msg);
35
+ break;
36
+ case 'Trace':
37
+ core.logger.trace(msg);
38
+ break;
39
+ }
40
+ });
41
+
42
+ exports.SentryEffectLogger = SentryEffectLogger;
43
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sources":["../../src/logger.ts"],"sourcesContent":["import { logger as sentryLogger } from '@sentry/core';\nimport * as Logger from 'effect/Logger';\n\n/**\n * Effect Logger that sends logs to Sentry.\n */\nexport const SentryEffectLogger = Logger.make(({ logLevel, message }) => {\n let msg: string;\n if (typeof message === 'string') {\n msg = message;\n } else if (Array.isArray(message) && message.length === 1) {\n const firstElement = message[0];\n msg = typeof firstElement === 'string' ? firstElement : JSON.stringify(firstElement);\n } else {\n msg = JSON.stringify(message);\n }\n\n switch (logLevel._tag) {\n case 'Fatal':\n sentryLogger.fatal(msg);\n break;\n case 'Error':\n sentryLogger.error(msg);\n break;\n case 'Warning':\n sentryLogger.warn(msg);\n break;\n case 'Info':\n sentryLogger.info(msg);\n break;\n case 'Debug':\n sentryLogger.debug(msg);\n break;\n case 'Trace':\n sentryLogger.trace(msg);\n break;\n case 'All':\n case 'None':\n break;\n default:\n logLevel satisfies never;\n }\n});\n"],"names":["sentryLogger"],"mappings":";;;;;AAGA;AACA;AACA;AACO,MAAM,kBAAA,GAAqB,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAA,EAAS,KAAK;AACzE,EAAE,IAAI,GAAG;AACT,EAAE,IAAI,OAAO,OAAA,KAAY,QAAQ,EAAE;AACnC,IAAI,GAAA,GAAM,OAAO;AACjB,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAA,IAAK,OAAO,CAAC,MAAA,KAAW,CAAC,EAAE;AAC7D,IAAI,MAAM,YAAA,GAAe,OAAO,CAAC,CAAC,CAAC;AACnC,IAAI,GAAA,GAAM,OAAO,YAAA,KAAiB,QAAA,GAAW,YAAA,GAAe,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;AACxF,EAAE,OAAO;AACT,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;AACjC,EAAE;;AAEF,EAAE,QAAQ,QAAQ,CAAC,IAAI;AACvB,IAAI,KAAK,OAAO;AAChB,MAAMA,WAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AACN,IAAI,KAAK,OAAO;AAChB,MAAMA,WAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AACN,IAAI,KAAK,SAAS;AAClB,MAAMA,WAAY,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5B,MAAM;AACN,IAAI,KAAK,MAAM;AACf,MAAMA,WAAY,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5B,MAAM;AACN,IAAI,KAAK,OAAO;AAChB,MAAMA,WAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AACN,IAAI,KAAK,OAAO;AAChB,MAAMA,WAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AAMN;AACA,CAAC;;;;"}
@@ -0,0 +1,120 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const Effect = require('effect/Effect');
5
+ const Layer = require('effect/Layer');
6
+ const Metric = require('effect/Metric');
7
+ const MetricKeyType = require('effect/MetricKeyType');
8
+ const MetricState = require('effect/MetricState');
9
+ const Schedule = require('effect/Schedule');
10
+
11
+ function labelsToAttributes(labels) {
12
+ return labels.reduce((acc, label) => ({ ...acc, [label.key]: label.value }), {});
13
+ }
14
+
15
+ function sendMetricToSentry(pair) {
16
+ const { metricKey, metricState } = pair;
17
+ const name = metricKey.name;
18
+ const attributes = labelsToAttributes(metricKey.tags);
19
+
20
+ if (MetricState.isCounterState(metricState)) {
21
+ const value = Number(metricState.count);
22
+ core.metrics.count(name, value, { attributes });
23
+ } else if (MetricState.isGaugeState(metricState)) {
24
+ const value = Number(metricState.value);
25
+ core.metrics.gauge(name, value, { attributes });
26
+ } else if (MetricState.isHistogramState(metricState)) {
27
+ core.metrics.gauge(`${name}.sum`, metricState.sum, { attributes });
28
+ core.metrics.gauge(`${name}.count`, metricState.count, { attributes });
29
+ core.metrics.gauge(`${name}.min`, metricState.min, { attributes });
30
+ core.metrics.gauge(`${name}.max`, metricState.max, { attributes });
31
+ } else if (MetricState.isSummaryState(metricState)) {
32
+ core.metrics.gauge(`${name}.sum`, metricState.sum, { attributes });
33
+ core.metrics.gauge(`${name}.count`, metricState.count, { attributes });
34
+ core.metrics.gauge(`${name}.min`, metricState.min, { attributes });
35
+ core.metrics.gauge(`${name}.max`, metricState.max, { attributes });
36
+ } else if (MetricState.isFrequencyState(metricState)) {
37
+ for (const [word, count] of metricState.occurrences) {
38
+ core.metrics.count(name, count, {
39
+ attributes: { ...attributes, word },
40
+ });
41
+ }
42
+ }
43
+ }
44
+
45
+ function getMetricId(pair) {
46
+ const tags = pair.metricKey.tags.map(t => `${t.key}=${t.value}`).join(',');
47
+ return `${pair.metricKey.name}:${tags}`;
48
+ }
49
+
50
+ function sendDeltaMetricToSentry(
51
+ pair,
52
+ previousCounterValues,
53
+ ) {
54
+ const { metricKey, metricState } = pair;
55
+ const name = metricKey.name;
56
+ const attributes = labelsToAttributes(metricKey.tags);
57
+ const metricId = getMetricId(pair);
58
+
59
+ if (MetricState.isCounterState(metricState)) {
60
+ const currentValue = Number(metricState.count);
61
+
62
+ const previousValue = previousCounterValues.get(metricId) ?? 0;
63
+ const delta = currentValue - previousValue;
64
+
65
+ if (delta > 0) {
66
+ core.metrics.count(name, delta, { attributes });
67
+ }
68
+
69
+ previousCounterValues.set(metricId, currentValue);
70
+ } else {
71
+ sendMetricToSentry(pair);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Flushes all Effect metrics to Sentry.
77
+ * @param previousCounterValues - Map tracking previous counter values for delta calculation
78
+ */
79
+ function flushMetricsToSentry(previousCounterValues) {
80
+ const snapshot = Metric.unsafeSnapshot();
81
+
82
+ snapshot.forEach((pair) => {
83
+ if (MetricKeyType.isCounterKey(pair.metricKey.keyType)) {
84
+ sendDeltaMetricToSentry(pair, previousCounterValues);
85
+ } else {
86
+ sendMetricToSentry(pair);
87
+ }
88
+ });
89
+ }
90
+
91
+ function createMetricsReporterEffect(previousCounterValues) {
92
+ const schedule = Schedule.spaced('10 seconds');
93
+
94
+ return Effect.repeat(
95
+ Effect.sync(() => flushMetricsToSentry(previousCounterValues)),
96
+ schedule,
97
+ ).pipe(Effect.asVoid, Effect.interruptible);
98
+ }
99
+
100
+ /**
101
+ * Effect Layer that periodically flushes metrics to Sentry.
102
+ * The layer manages its own state for delta counter calculations,
103
+ * which is automatically cleaned up when the layer is finalized.
104
+ */
105
+ const SentryEffectMetricsLayer = Layer.scopedDiscard(
106
+ Effect.gen(function* () {
107
+ const previousCounterValues = new Map();
108
+
109
+ yield* Effect.acquireRelease(Effect.void, () =>
110
+ Effect.sync(() => {
111
+ previousCounterValues.clear();
112
+ }),
113
+ );
114
+
115
+ yield* Effect.forkScoped(createMetricsReporterEffect(previousCounterValues));
116
+ }),
117
+ );
118
+
119
+ exports.SentryEffectMetricsLayer = SentryEffectMetricsLayer;
120
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sources":["../../src/metrics.ts"],"sourcesContent":["import { metrics as sentryMetrics } from '@sentry/core';\nimport * as Effect from 'effect/Effect';\nimport type * as Layer from 'effect/Layer';\nimport { scopedDiscard } from 'effect/Layer';\nimport * as Metric from 'effect/Metric';\nimport * as MetricKeyType from 'effect/MetricKeyType';\nimport type * as MetricPair from 'effect/MetricPair';\nimport * as MetricState from 'effect/MetricState';\nimport * as Schedule from 'effect/Schedule';\n\ntype MetricAttributes = Record<string, string>;\n\nfunction labelsToAttributes(labels: ReadonlyArray<{ key: string; value: string }>): MetricAttributes {\n return labels.reduce((acc, label) => ({ ...acc, [label.key]: label.value }), {});\n}\n\nfunction sendMetricToSentry(pair: MetricPair.MetricPair.Untyped): void {\n const { metricKey, metricState } = pair;\n const name = metricKey.name;\n const attributes = labelsToAttributes(metricKey.tags);\n\n if (MetricState.isCounterState(metricState)) {\n const value = Number(metricState.count);\n sentryMetrics.count(name, value, { attributes });\n } else if (MetricState.isGaugeState(metricState)) {\n const value = Number(metricState.value);\n sentryMetrics.gauge(name, value, { attributes });\n } else if (MetricState.isHistogramState(metricState)) {\n sentryMetrics.gauge(`${name}.sum`, metricState.sum, { attributes });\n sentryMetrics.gauge(`${name}.count`, metricState.count, { attributes });\n sentryMetrics.gauge(`${name}.min`, metricState.min, { attributes });\n sentryMetrics.gauge(`${name}.max`, metricState.max, { attributes });\n } else if (MetricState.isSummaryState(metricState)) {\n sentryMetrics.gauge(`${name}.sum`, metricState.sum, { attributes });\n sentryMetrics.gauge(`${name}.count`, metricState.count, { attributes });\n sentryMetrics.gauge(`${name}.min`, metricState.min, { attributes });\n sentryMetrics.gauge(`${name}.max`, metricState.max, { attributes });\n } else if (MetricState.isFrequencyState(metricState)) {\n for (const [word, count] of metricState.occurrences) {\n sentryMetrics.count(name, count, {\n attributes: { ...attributes, word },\n });\n }\n }\n}\n\nfunction getMetricId(pair: MetricPair.MetricPair.Untyped): string {\n const tags = pair.metricKey.tags.map(t => `${t.key}=${t.value}`).join(',');\n return `${pair.metricKey.name}:${tags}`;\n}\n\nfunction sendDeltaMetricToSentry(\n pair: MetricPair.MetricPair.Untyped,\n previousCounterValues: Map<string, number>,\n): void {\n const { metricKey, metricState } = pair;\n const name = metricKey.name;\n const attributes = labelsToAttributes(metricKey.tags);\n const metricId = getMetricId(pair);\n\n if (MetricState.isCounterState(metricState)) {\n const currentValue = Number(metricState.count);\n\n const previousValue = previousCounterValues.get(metricId) ?? 0;\n const delta = currentValue - previousValue;\n\n if (delta > 0) {\n sentryMetrics.count(name, delta, { attributes });\n }\n\n previousCounterValues.set(metricId, currentValue);\n } else {\n sendMetricToSentry(pair);\n }\n}\n\n/**\n * Flushes all Effect metrics to Sentry.\n * @param previousCounterValues - Map tracking previous counter values for delta calculation\n */\nfunction flushMetricsToSentry(previousCounterValues: Map<string, number>): void {\n const snapshot = Metric.unsafeSnapshot();\n\n snapshot.forEach((pair: MetricPair.MetricPair.Untyped) => {\n if (MetricKeyType.isCounterKey(pair.metricKey.keyType)) {\n sendDeltaMetricToSentry(pair, previousCounterValues);\n } else {\n sendMetricToSentry(pair);\n }\n });\n}\n\n/**\n * Creates a metrics flusher with its own isolated state for delta tracking.\n * Useful for testing scenarios where you need to control the lifecycle.\n * @internal\n */\nexport function createMetricsFlusher(): {\n flush: () => void;\n clear: () => void;\n} {\n const previousCounterValues = new Map<string, number>();\n return {\n flush: () => flushMetricsToSentry(previousCounterValues),\n clear: () => previousCounterValues.clear(),\n };\n}\n\nfunction createMetricsReporterEffect(previousCounterValues: Map<string, number>): Effect.Effect<void, never, never> {\n const schedule = Schedule.spaced('10 seconds');\n\n return Effect.repeat(\n Effect.sync(() => flushMetricsToSentry(previousCounterValues)),\n schedule,\n ).pipe(Effect.asVoid, Effect.interruptible);\n}\n\n/**\n * Effect Layer that periodically flushes metrics to Sentry.\n * The layer manages its own state for delta counter calculations,\n * which is automatically cleaned up when the layer is finalized.\n */\nexport const SentryEffectMetricsLayer: Layer.Layer<never, never, never> = scopedDiscard(\n Effect.gen(function* () {\n const previousCounterValues = new Map<string, number>();\n\n yield* Effect.acquireRelease(Effect.void, () =>\n Effect.sync(() => {\n previousCounterValues.clear();\n }),\n );\n\n yield* Effect.forkScoped(createMetricsReporterEffect(previousCounterValues));\n }),\n);\n"],"names":["sentryMetrics","scopedDiscard"],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const Layer = require('effect/Layer');
4
+ const sdk = require('./sdk.js');
5
+
6
+ /**
7
+ * Options for the Sentry Effect server layer.
8
+ */
9
+
10
+ /**
11
+ * Creates an Effect Layer that initializes Sentry for Node.js servers.
12
+ *
13
+ * To enable Effect tracing, logs, or metrics, compose with the respective layers:
14
+ * - `Layer.setTracer(Sentry.SentryEffectTracer)` for tracing
15
+ * - `Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger)` for logs
16
+ * - `Sentry.SentryEffectMetricsLayer` for metrics
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import * as Sentry from '@sentry/effect/server';
21
+ * import { NodeRuntime } from '@effect/platform-node';
22
+ * import { Layer, Logger } from 'effect';
23
+ * import { HttpLive } from './Http.js';
24
+ *
25
+ * const SentryLive = Layer.mergeAll(
26
+ * Sentry.effectLayer({ dsn: '__DSN__' }),
27
+ * Layer.setTracer(Sentry.SentryEffectTracer),
28
+ * Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger),
29
+ * );
30
+ *
31
+ * const MainLive = HttpLive.pipe(Layer.provide(SentryLive));
32
+ * MainLive.pipe(Layer.launch, NodeRuntime.runMain);
33
+ * ```
34
+ */
35
+ function effectLayer(options) {
36
+ return Layer.suspend(() => {
37
+ sdk.init(options);
38
+ return Layer.empty;
39
+ });
40
+ }
41
+
42
+ exports.init = sdk.init;
43
+ exports.effectLayer = effectLayer;
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/server/index.ts"],"sourcesContent":["import type { NodeOptions } from '@sentry/node-core/light';\nimport type * as EffectLayer from 'effect/Layer';\nimport { empty as emptyLayer, suspend as suspendLayer } from 'effect/Layer';\nimport { init } from './sdk';\n\nexport { init } from './sdk';\n\n/**\n * Options for the Sentry Effect server layer.\n */\nexport type EffectServerLayerOptions = NodeOptions;\n\n/**\n * Creates an Effect Layer that initializes Sentry for Node.js servers.\n *\n * To enable Effect tracing, logs, or metrics, compose with the respective layers:\n * - `Layer.setTracer(Sentry.SentryEffectTracer)` for tracing\n * - `Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger)` for logs\n * - `Sentry.SentryEffectMetricsLayer` for metrics\n *\n * @example\n * ```typescript\n * import * as Sentry from '@sentry/effect/server';\n * import { NodeRuntime } from '@effect/platform-node';\n * import { Layer, Logger } from 'effect';\n * import { HttpLive } from './Http.js';\n *\n * const SentryLive = Layer.mergeAll(\n * Sentry.effectLayer({ dsn: '__DSN__' }),\n * Layer.setTracer(Sentry.SentryEffectTracer),\n * Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger),\n * );\n *\n * const MainLive = HttpLive.pipe(Layer.provide(SentryLive));\n * MainLive.pipe(Layer.launch, NodeRuntime.runMain);\n * ```\n */\nexport function effectLayer(options: EffectServerLayerOptions): EffectLayer.Layer<never, never, never> {\n return suspendLayer(() => {\n init(options);\n return emptyLayer;\n });\n}\n"],"names":["suspendLayer","init","emptyLayer"],"mappings":";;;;;AAOA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW,CAAC,OAAO,EAAoE;AACvG,EAAE,OAAOA,aAAY,CAAC,MAAM;AAC5B,IAAIC,QAAI,CAAC,OAAO,CAAC;AACjB,IAAI,OAAOC,WAAU;AACrB,EAAE,CAAC,CAAC;AACJ;;;;;"}
@@ -0,0 +1,23 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const light = require('@sentry/node-core/light');
5
+
6
+ /**
7
+ * Initializes the Sentry Effect SDK for Node.js servers.
8
+ *
9
+ * @param options - Configuration options for the SDK
10
+ * @returns The initialized Sentry client, or undefined if initialization failed
11
+ */
12
+ function init(options) {
13
+ const opts = {
14
+ ...options,
15
+ };
16
+
17
+ core.applySdkMetadata(opts, 'effect', ['effect', 'node-light']);
18
+
19
+ return light.init(opts);
20
+ }
21
+
22
+ exports.init = init;
23
+ //# sourceMappingURL=sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import type { Client } from '@sentry/core';\nimport { applySdkMetadata } from '@sentry/core';\nimport type { NodeOptions } from '@sentry/node-core/light';\nimport { init as initNode } from '@sentry/node-core/light';\n\n/**\n * Initializes the Sentry Effect SDK for Node.js servers.\n *\n * @param options - Configuration options for the SDK\n * @returns The initialized Sentry client, or undefined if initialization failed\n */\nexport function init(options: NodeOptions): Client | undefined {\n const opts = {\n ...options,\n };\n\n applySdkMetadata(opts, 'effect', ['effect', 'node-light']);\n\n return initNode(opts);\n}\n"],"names":["applySdkMetadata","initNode"],"mappings":";;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAmC;AAC/D,EAAE,MAAM,OAAO;AACf,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAEA,qBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;;AAE5D,EAAE,OAAOC,UAAQ,CAAC,IAAI,CAAC;AACvB;;;;"}
@@ -0,0 +1,145 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const Exit = require('effect/Exit');
5
+ const Option = require('effect/Option');
6
+ const EffectTracer = require('effect/Tracer');
7
+
8
+ function deriveOrigin(name) {
9
+ if (name.startsWith('http.server') || name.startsWith('http.client')) {
10
+ return 'auto.http.effect';
11
+ }
12
+
13
+ return 'auto.function.effect';
14
+ }
15
+
16
+ const SENTRY_SPAN_SYMBOL = Symbol.for('@sentry/effect.SentrySpan');
17
+
18
+ function nanosToHrTime(nanos) {
19
+ const seconds = Number(nanos / BigInt(1000000000));
20
+ const remainingNanos = Number(nanos % BigInt(1000000000));
21
+ return [seconds, remainingNanos];
22
+ }
23
+
24
+ function isSentrySpan(span) {
25
+ return SENTRY_SPAN_SYMBOL in span;
26
+ }
27
+
28
+ class SentrySpanWrapper {
29
+
30
+ constructor(
31
+ name,
32
+ parent,
33
+ context,
34
+ links,
35
+ startTime,
36
+ kind,
37
+ existingSpan,
38
+ ) {this.name = name;this.context = context;this.kind = kind;
39
+ this[SENTRY_SPAN_SYMBOL] = true ;
40
+ this._tag = 'Span' ;
41
+ this.attributes = new Map();
42
+ this.parent = parent;
43
+ this.links = [...links];
44
+ this.sentrySpan = existingSpan;
45
+
46
+ const spanContext = this.sentrySpan.spanContext();
47
+ this.spanId = spanContext.spanId;
48
+ this.traceId = spanContext.traceId;
49
+ this.sampled = this.sentrySpan.isRecording();
50
+ this.status = {
51
+ _tag: 'Started',
52
+ startTime,
53
+ };
54
+ }
55
+
56
+ attribute(key, value) {
57
+ if (!this.sentrySpan.isRecording()) {
58
+ return;
59
+ }
60
+
61
+ this.sentrySpan.setAttribute(key, value );
62
+ this.attributes.set(key, value);
63
+ }
64
+
65
+ addLinks(links) {
66
+ this.links.push(...links);
67
+ }
68
+
69
+ end(endTime, exit) {
70
+ this.status = {
71
+ _tag: 'Ended',
72
+ endTime,
73
+ exit,
74
+ startTime: this.status.startTime,
75
+ };
76
+
77
+ if (!this.sentrySpan.isRecording()) {
78
+ return;
79
+ }
80
+
81
+ if (Exit.isFailure(exit)) {
82
+ const cause = exit.cause;
83
+ const message =
84
+ cause._tag === 'Fail' ? String(cause.error) : cause._tag === 'Die' ? String(cause.defect) : 'internal_error';
85
+ this.sentrySpan.setStatus({ code: 2, message });
86
+ } else {
87
+ this.sentrySpan.setStatus({ code: 1 });
88
+ }
89
+
90
+ this.sentrySpan.end(nanosToHrTime(endTime));
91
+ }
92
+
93
+ event(name, startTime, attributes) {
94
+ if (!this.sentrySpan.isRecording()) {
95
+ return;
96
+ }
97
+
98
+ this.sentrySpan.addEvent(name, attributes , nanosToHrTime(startTime));
99
+ }
100
+ }
101
+
102
+ function createSentrySpan(
103
+ name,
104
+ parent,
105
+ context,
106
+ links,
107
+ startTime,
108
+ kind,
109
+ ) {
110
+ const parentSentrySpan =
111
+ Option.isSome(parent) && isSentrySpan(parent.value) ? parent.value.sentrySpan : (core.getActiveSpan() ?? null);
112
+
113
+ const newSpan = core.startInactiveSpan({
114
+ name,
115
+ startTime: nanosToHrTime(startTime),
116
+ attributes: {
117
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: deriveOrigin(name),
118
+ },
119
+ ...(parentSentrySpan ? { parentSpan: parentSentrySpan } : {}),
120
+ });
121
+
122
+ return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);
123
+ }
124
+
125
+ const makeSentryTracer = () =>
126
+ EffectTracer.make({
127
+ span(name, parent, context, links, startTime, kind) {
128
+ return createSentrySpan(name, parent, context, links, startTime, kind);
129
+ },
130
+ context(execution, fiber) {
131
+ const currentSpan = fiber.currentSpan;
132
+ if (currentSpan === undefined || !isSentrySpan(currentSpan)) {
133
+ return execution();
134
+ }
135
+ return core.withActiveSpan(currentSpan.sentrySpan, execution);
136
+ },
137
+ });
138
+
139
+ /**
140
+ * Effect Layer that sets up the Sentry tracer for Effect spans.
141
+ */
142
+ const SentryEffectTracer = makeSentryTracer();
143
+
144
+ exports.SentryEffectTracer = SentryEffectTracer;
145
+ //# sourceMappingURL=tracer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.js","sources":["../../src/tracer.ts"],"sourcesContent":["import type { Span } from '@sentry/core';\nimport { getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan, 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 {\n if (name.startsWith('http.server') || name.startsWith('http.client')) {\n return 'auto.http.effect';\n }\n\n return 'auto.function.effect';\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\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\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\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 cause = exit.cause;\n const message =\n cause._tag === 'Fail' ? String(cause.error) : cause._tag === 'Die' ? String(cause.defect) : '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\nfunction createSentrySpan(\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 newSpan = startInactiveSpan({\n name,\n startTime: nanosToHrTime(startTime),\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: deriveOrigin(name),\n },\n ...(parentSentrySpan ? { parentSpan: parentSentrySpan } : {}),\n });\n\n return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);\n}\n\nconst makeSentryTracer = (): EffectTracer.Tracer =>\n EffectTracer.make({\n span(name, parent, context, links, startTime, kind) {\n return createSentrySpan(name, parent, context, links, startTime, kind);\n },\n context(execution, fiber) {\n const currentSpan = fiber.currentSpan;\n if (currentSpan === undefined || !isSentrySpan(currentSpan)) {\n return execution();\n }\n return withActiveSpan(currentSpan.sentrySpan, execution);\n },\n });\n\n/**\n * Effect Layer that sets up the Sentry tracer for Effect spans.\n */\nexport const SentryEffectTracer = makeSentryTracer();\n"],"names":["getActiveSpan","startInactiveSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","withActiveSpan"],"mappings":"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"}