@sentry/effect 10.49.0 → 10.50.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.
- package/README.md +41 -7
- package/build/cjs/logger.js +19 -2
- package/build/cjs/logger.js.map +1 -1
- package/build/cjs/metrics.js +105 -54
- package/build/cjs/metrics.js.map +1 -1
- package/build/cjs/tracer.js +96 -7
- package/build/cjs/tracer.js.map +1 -1
- package/build/esm/logger.js +19 -2
- package/build/esm/logger.js.map +1 -1
- package/build/esm/metrics.js +106 -55
- package/build/esm/metrics.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/tracer.js +96 -7
- package/build/esm/tracer.js.map +1 -1
- package/build/types/logger.d.ts.map +1 -1
- package/build/types/metrics.d.ts +1 -10
- package/build/types/metrics.d.ts.map +1 -1
- package/build/types/tracer.d.ts.map +1 -1
- package/build/types-ts3.8/metrics.d.ts +0 -9
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -6,11 +6,16 @@
|
|
|
6
6
|
|
|
7
7
|
> NOTICE: This package is in alpha state and may be subject to breaking changes.
|
|
8
8
|
|
|
9
|
+
`@sentry/effect` supports both Effect v3 and Effect v4 (beta). The integration
|
|
10
|
+
auto-detects the installed Effect version at runtime, but the layer composition
|
|
11
|
+
APIs differ between the two major versions, so the setup code is slightly
|
|
12
|
+
different.
|
|
13
|
+
|
|
9
14
|
## Getting Started
|
|
10
15
|
|
|
11
16
|
This SDK does not have docs yet. Stay tuned.
|
|
12
17
|
|
|
13
|
-
## Usage
|
|
18
|
+
## Usage with Effect v3
|
|
14
19
|
|
|
15
20
|
```typescript
|
|
16
21
|
import * as Sentry from '@sentry/effect/server';
|
|
@@ -33,16 +38,45 @@ const MainLive = HttpLive.pipe(Layer.provide(SentryLive));
|
|
|
33
38
|
MainLive.pipe(Layer.launch, NodeRuntime.runMain);
|
|
34
39
|
```
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
## Usage with Effect v4
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
Effect v4 reorganized the `Tracer` and `Logger` layer APIs, so the wiring looks
|
|
44
|
+
slightly different. The `effectLayer`, `SentryEffectTracer`,
|
|
45
|
+
`SentryEffectLogger`, and `SentryEffectMetricsLayer` exports themselves are the
|
|
46
|
+
same.
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
```typescript
|
|
49
|
+
import * as Sentry from '@sentry/effect/server';
|
|
50
|
+
import { NodeHttpServer, NodeRuntime } from '@effect/platform-node';
|
|
51
|
+
import * as Layer from 'effect/Layer';
|
|
52
|
+
import * as Logger from 'effect/Logger';
|
|
53
|
+
import * as Tracer from 'effect/Tracer';
|
|
54
|
+
import { HttpRouter } from 'effect/unstable/http';
|
|
55
|
+
import { createServer } from 'http';
|
|
56
|
+
import { Routes } from './Routes.js';
|
|
57
|
+
|
|
58
|
+
const SentryLive = Layer.mergeAll(
|
|
59
|
+
Sentry.effectLayer({
|
|
60
|
+
dsn: '__DSN__',
|
|
61
|
+
tracesSampleRate: 1.0,
|
|
62
|
+
enableLogs: true,
|
|
63
|
+
}),
|
|
64
|
+
Layer.succeed(Tracer.Tracer, Sentry.SentryEffectTracer),
|
|
65
|
+
Logger.layer([Sentry.SentryEffectLogger]),
|
|
66
|
+
Sentry.SentryEffectMetricsLayer,
|
|
67
|
+
);
|
|
43
68
|
|
|
44
|
-
|
|
69
|
+
const HttpLive = HttpRouter.serve(Routes).pipe(
|
|
70
|
+
Layer.provide(NodeHttpServer.layer(() => createServer(), { port: 3030 })),
|
|
71
|
+
Layer.provide(SentryLive),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
NodeRuntime.runMain(Layer.launch(HttpLive));
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Links
|
|
45
78
|
|
|
79
|
+
- [Official SDK Docs](https://docs.sentry.io/platforms/javascript/guides/effect/)
|
|
46
80
|
- [Sentry.io](https://sentry.io/?utm_source=github&utm_medium=npm_effect)
|
|
47
81
|
- [Sentry Discord Server](https://discord.gg/Ww9hbqr)
|
|
48
82
|
- [Stack Overflow](https://stackoverflow.com/questions/tagged/sentry)
|
package/build/cjs/logger.js
CHANGED
|
@@ -3,6 +3,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
4
|
const Logger = require('effect/Logger');
|
|
5
5
|
|
|
6
|
+
function getLogLevelTag(logLevel) {
|
|
7
|
+
// Effect v4: logLevel is a string literal directly
|
|
8
|
+
if (typeof logLevel === 'string') {
|
|
9
|
+
return logLevel;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Effect v3: logLevel has _tag property
|
|
13
|
+
if (logLevel && typeof logLevel === 'object' && '_tag' in logLevel) {
|
|
14
|
+
return (logLevel )._tag;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return 'Info';
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
/**
|
|
7
21
|
* Effect Logger that sends logs to Sentry.
|
|
8
22
|
*/
|
|
@@ -17,14 +31,17 @@ const SentryEffectLogger = Logger.make(({ logLevel, message }) => {
|
|
|
17
31
|
msg = JSON.stringify(message);
|
|
18
32
|
}
|
|
19
33
|
|
|
20
|
-
|
|
34
|
+
const tag = getLogLevelTag(logLevel);
|
|
35
|
+
|
|
36
|
+
switch (tag) {
|
|
21
37
|
case 'Fatal':
|
|
22
38
|
core.logger.fatal(msg);
|
|
23
39
|
break;
|
|
24
40
|
case 'Error':
|
|
25
41
|
core.logger.error(msg);
|
|
26
42
|
break;
|
|
27
|
-
case 'Warning':
|
|
43
|
+
case 'Warning': // Effect v3
|
|
44
|
+
case 'Warn': // Effect v4
|
|
28
45
|
core.logger.warn(msg);
|
|
29
46
|
break;
|
|
30
47
|
case 'Info':
|
package/build/cjs/logger.js.map
CHANGED
|
@@ -1 +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
|
|
1
|
+
{"version":3,"file":"logger.js","sources":["../../src/logger.ts"],"sourcesContent":["import { logger as sentryLogger } from '@sentry/core';\nimport * as Logger from 'effect/Logger';\nimport type * as LogLevel from 'effect/LogLevel';\n\nfunction getLogLevelTag(logLevel: LogLevel.LogLevel): LogLevel.LogLevel | 'Warning' {\n // Effect v4: logLevel is a string literal directly\n if (typeof logLevel === 'string') {\n return logLevel;\n }\n\n // Effect v3: logLevel has _tag property\n if (logLevel && typeof logLevel === 'object' && '_tag' in logLevel) {\n return (logLevel as { _tag: LogLevel.LogLevel })._tag;\n }\n\n return 'Info';\n}\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 const tag = getLogLevelTag(logLevel);\n\n switch (tag) {\n case 'Fatal':\n sentryLogger.fatal(msg);\n break;\n case 'Error':\n sentryLogger.error(msg);\n break;\n case 'Warning': // Effect v3\n case 'Warn': // Effect v4\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 tag satisfies never;\n }\n});\n"],"names":["sentryLogger"],"mappings":";;;;;AAIA,SAAS,cAAc,CAAC,QAAQ,EAAoD;AACpF;AACA,EAAE,IAAI,OAAO,QAAA,KAAa,QAAQ,EAAE;AACpC,IAAI,OAAO,QAAQ;AACnB,EAAE;;AAEF;AACA,EAAE,IAAI,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,IAAY,MAAA,IAAU,QAAQ,EAAE;AACtE,IAAI,OAAO,CAAC,QAAA,GAAyC,IAAI;AACzD,EAAE;;AAEF,EAAE,OAAO,MAAM;AACf;;AAEA;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,MAAM,GAAA,GAAM,cAAc,CAAC,QAAQ,CAAC;;AAEtC,EAAE,QAAQ,GAAG;AACb,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,CAAA;AAClB,IAAI,KAAK,MAAM;AACf,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;;;;"}
|
package/build/cjs/metrics.js
CHANGED
|
@@ -1,39 +1,67 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
|
+
const Context = require('effect/Context');
|
|
4
5
|
const Effect = require('effect/Effect');
|
|
5
6
|
const Layer = require('effect/Layer');
|
|
6
7
|
const Metric = require('effect/Metric');
|
|
7
|
-
const MetricKeyType = require('effect/MetricKeyType');
|
|
8
|
-
const MetricState = require('effect/MetricState');
|
|
9
8
|
const Schedule = require('effect/Schedule');
|
|
10
9
|
|
|
10
|
+
// Effect v3 `MetricState` implementations brand themselves with a `Symbol.for(...)` TypeId
|
|
11
|
+
// rather than a string `_tag`. We use these globally-registered symbols to classify state
|
|
12
|
+
// instances returned by `Metric.unsafeSnapshot()` without importing `effect/MetricState`
|
|
13
|
+
// (the module does not exist in Effect v4).
|
|
14
|
+
const V3_COUNTER_STATE_TYPE_ID = Symbol.for('effect/MetricState/Counter');
|
|
15
|
+
const V3_GAUGE_STATE_TYPE_ID = Symbol.for('effect/MetricState/Gauge');
|
|
16
|
+
const V3_HISTOGRAM_STATE_TYPE_ID = Symbol.for('effect/MetricState/Histogram');
|
|
17
|
+
const V3_SUMMARY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Summary');
|
|
18
|
+
const V3_FREQUENCY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Frequency');
|
|
19
|
+
|
|
11
20
|
function labelsToAttributes(labels) {
|
|
12
21
|
return labels.reduce((acc, label) => ({ ...acc, [label.key]: label.value }), {});
|
|
13
22
|
}
|
|
14
23
|
|
|
15
|
-
function
|
|
24
|
+
function getMetricIdV3(pair) {
|
|
25
|
+
const tags = pair.metricKey.tags.map(t => `${t.key}=${t.value}`).join(',');
|
|
26
|
+
return `${pair.metricKey.name}:${tags}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getMetricIdV4(snapshot) {
|
|
30
|
+
const attrs = snapshot.attributes
|
|
31
|
+
? Object.entries(snapshot.attributes)
|
|
32
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
33
|
+
.join(',')
|
|
34
|
+
: '';
|
|
35
|
+
return `${snapshot.id}:${attrs}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function sendV3MetricToSentry(pair, previousCounterValues) {
|
|
16
39
|
const { metricKey, metricState } = pair;
|
|
17
40
|
const name = metricKey.name;
|
|
18
41
|
const attributes = labelsToAttributes(metricKey.tags);
|
|
42
|
+
const metricId = getMetricIdV3(pair);
|
|
43
|
+
|
|
44
|
+
const state = metricState ;
|
|
19
45
|
|
|
20
|
-
if (
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
46
|
+
if (state[V3_COUNTER_STATE_TYPE_ID] !== undefined) {
|
|
47
|
+
const currentValue = Number(metricState.count);
|
|
48
|
+
const previousValue = previousCounterValues.get(metricId) ?? 0;
|
|
49
|
+
const delta = currentValue - previousValue;
|
|
50
|
+
|
|
51
|
+
if (delta > 0) {
|
|
52
|
+
core.metrics.count(name, delta, { attributes });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
previousCounterValues.set(metricId, currentValue);
|
|
56
|
+
} else if (state[V3_GAUGE_STATE_TYPE_ID] !== undefined) {
|
|
24
57
|
const value = Number(metricState.value);
|
|
25
58
|
core.metrics.gauge(name, value, { attributes });
|
|
26
|
-
} else if (
|
|
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 (
|
|
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)) {
|
|
59
|
+
} else if (state[V3_HISTOGRAM_STATE_TYPE_ID] !== undefined || state[V3_SUMMARY_STATE_TYPE_ID] !== undefined) {
|
|
60
|
+
core.metrics.gauge(`${name}.sum`, metricState.sum ?? 0, { attributes });
|
|
61
|
+
core.metrics.gauge(`${name}.count`, Number(metricState.count ?? 0), { attributes });
|
|
62
|
+
core.metrics.gauge(`${name}.min`, metricState.min ?? 0, { attributes });
|
|
63
|
+
core.metrics.gauge(`${name}.max`, metricState.max ?? 0, { attributes });
|
|
64
|
+
} else if (state[V3_FREQUENCY_STATE_TYPE_ID] !== undefined && metricState.occurrences) {
|
|
37
65
|
for (const [word, count] of metricState.occurrences) {
|
|
38
66
|
core.metrics.count(name, count, {
|
|
39
67
|
attributes: { ...attributes, word },
|
|
@@ -42,50 +70,73 @@ function sendMetricToSentry(pair) {
|
|
|
42
70
|
}
|
|
43
71
|
}
|
|
44
72
|
|
|
45
|
-
function
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
73
|
+
function sendV4MetricToSentry(snapshot, previousCounterValues) {
|
|
74
|
+
const name = snapshot.id;
|
|
75
|
+
const attributes = snapshot.attributes ? { ...snapshot.attributes } : {};
|
|
76
|
+
const metricId = getMetricIdV4(snapshot);
|
|
49
77
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
const name = metricKey.name;
|
|
56
|
-
const attributes = labelsToAttributes(metricKey.tags);
|
|
57
|
-
const metricId = getMetricId(pair);
|
|
78
|
+
switch (snapshot.type) {
|
|
79
|
+
case 'Counter': {
|
|
80
|
+
const currentValue = Number(snapshot.state.count);
|
|
81
|
+
const previousValue = previousCounterValues.get(metricId) ?? 0;
|
|
82
|
+
const delta = currentValue - previousValue;
|
|
58
83
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const previousValue = previousCounterValues.get(metricId) ?? 0;
|
|
63
|
-
const delta = currentValue - previousValue;
|
|
84
|
+
if (delta > 0) {
|
|
85
|
+
core.metrics.count(name, delta, { attributes });
|
|
86
|
+
}
|
|
64
87
|
|
|
65
|
-
|
|
66
|
-
|
|
88
|
+
previousCounterValues.set(metricId, currentValue);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case 'Gauge': {
|
|
92
|
+
const value = Number(snapshot.state.value);
|
|
93
|
+
core.metrics.gauge(name, value, { attributes });
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case 'Histogram':
|
|
97
|
+
case 'Summary': {
|
|
98
|
+
core.metrics.gauge(`${name}.sum`, snapshot.state.sum ?? 0, { attributes });
|
|
99
|
+
core.metrics.gauge(`${name}.count`, snapshot.state.count ?? 0, { attributes });
|
|
100
|
+
core.metrics.gauge(`${name}.min`, snapshot.state.min ?? 0, { attributes });
|
|
101
|
+
core.metrics.gauge(`${name}.max`, snapshot.state.max ?? 0, { attributes });
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'Frequency': {
|
|
105
|
+
for (const [word, count] of snapshot.state.occurrences) {
|
|
106
|
+
core.metrics.count(name, count, {
|
|
107
|
+
attributes: { ...attributes, word },
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
67
111
|
}
|
|
68
|
-
|
|
69
|
-
previousCounterValues.set(metricId, currentValue);
|
|
70
|
-
} else {
|
|
71
|
-
sendMetricToSentry(pair);
|
|
72
112
|
}
|
|
73
113
|
}
|
|
74
114
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
115
|
+
// =============================================================================
|
|
116
|
+
// Effect v3 snapshot function type (vendored - not exported from effect@3.x)
|
|
117
|
+
// =============================================================================
|
|
118
|
+
|
|
119
|
+
// Use bracket notation to avoid Webpack static analysis flagging missing exports
|
|
120
|
+
// This is important for Effect v3 compatibility.
|
|
121
|
+
const MetricModule = Metric;
|
|
122
|
+
const snapshotUnsafe = MetricModule['snapshotUnsafe'] ;
|
|
123
|
+
// @ts-expect-error - unsafeSnapshot is not exported from effect@3.x
|
|
124
|
+
const unsafeSnapshot = MetricModule['unsafeSnapshot'] ;
|
|
81
125
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
126
|
+
function flushMetricsToSentry(previousCounterValues) {
|
|
127
|
+
if (snapshotUnsafe) {
|
|
128
|
+
// Effect v4
|
|
129
|
+
const snapshots = snapshotUnsafe(Context.empty());
|
|
130
|
+
for (const snapshot of snapshots) {
|
|
131
|
+
sendV4MetricToSentry(snapshot, previousCounterValues);
|
|
87
132
|
}
|
|
88
|
-
})
|
|
133
|
+
} else if (unsafeSnapshot) {
|
|
134
|
+
// Effect v3
|
|
135
|
+
const snapshots = unsafeSnapshot();
|
|
136
|
+
for (const pair of snapshots) {
|
|
137
|
+
sendV3MetricToSentry(pair, previousCounterValues);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
89
140
|
}
|
|
90
141
|
|
|
91
142
|
function createMetricsReporterEffect(previousCounterValues) {
|
|
@@ -102,7 +153,7 @@ function createMetricsReporterEffect(previousCounterValues) {
|
|
|
102
153
|
* The layer manages its own state for delta counter calculations,
|
|
103
154
|
* which is automatically cleaned up when the layer is finalized.
|
|
104
155
|
*/
|
|
105
|
-
const SentryEffectMetricsLayer = Layer.
|
|
156
|
+
const SentryEffectMetricsLayer = Layer.effectDiscard(
|
|
106
157
|
Effect.gen(function* () {
|
|
107
158
|
const previousCounterValues = new Map();
|
|
108
159
|
|
package/build/cjs/metrics.js.map
CHANGED
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"metrics.js","sources":["../../src/metrics.ts"],"sourcesContent":["import { metrics as sentryMetrics } from '@sentry/core';\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport * as Metric from 'effect/Metric';\nimport * as Schedule from 'effect/Schedule';\n\ntype MetricAttributes = Record<string, string>;\n\n// =============================================================================\n// Effect v3 Types (vendored - not exported from effect@3.x)\n// =============================================================================\n\ninterface V3MetricLabel {\n key: string;\n value: string;\n}\n\ninterface V3MetricPair {\n metricKey: {\n name: string;\n tags: ReadonlyArray<V3MetricLabel>;\n keyType: { _tag: string };\n };\n metricState: {\n count?: number | bigint;\n value?: number;\n sum?: number;\n min?: number;\n max?: number;\n occurrences?: Map<string, number>;\n };\n}\n\n// Effect v3 `MetricState` implementations brand themselves with a `Symbol.for(...)` TypeId\n// rather than a string `_tag`. We use these globally-registered symbols to classify state\n// instances returned by `Metric.unsafeSnapshot()` without importing `effect/MetricState`\n// (the module does not exist in Effect v4).\nconst V3_COUNTER_STATE_TYPE_ID = Symbol.for('effect/MetricState/Counter');\nconst V3_GAUGE_STATE_TYPE_ID = Symbol.for('effect/MetricState/Gauge');\nconst V3_HISTOGRAM_STATE_TYPE_ID = Symbol.for('effect/MetricState/Histogram');\nconst V3_SUMMARY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Summary');\nconst V3_FREQUENCY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Frequency');\n\nfunction labelsToAttributes(labels: ReadonlyArray<V3MetricLabel>): MetricAttributes {\n return labels.reduce((acc, label) => ({ ...acc, [label.key]: label.value }), {});\n}\n\nfunction getMetricIdV3(pair: V3MetricPair): string {\n const tags = pair.metricKey.tags.map(t => `${t.key}=${t.value}`).join(',');\n return `${pair.metricKey.name}:${tags}`;\n}\n\nfunction getMetricIdV4(snapshot: Metric.Metric.Snapshot): string {\n const attrs = snapshot.attributes\n ? Object.entries(snapshot.attributes)\n .map(([k, v]) => `${k}=${v}`)\n .join(',')\n : '';\n return `${snapshot.id}:${attrs}`;\n}\n\nfunction sendV3MetricToSentry(pair: V3MetricPair, previousCounterValues: Map<string, number>): void {\n const { metricKey, metricState } = pair;\n const name = metricKey.name;\n const attributes = labelsToAttributes(metricKey.tags);\n const metricId = getMetricIdV3(pair);\n\n const state = metricState as unknown as Record<symbol, unknown>;\n\n if (state[V3_COUNTER_STATE_TYPE_ID] !== undefined) {\n const currentValue = Number(metricState.count);\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 if (state[V3_GAUGE_STATE_TYPE_ID] !== undefined) {\n const value = Number(metricState.value);\n sentryMetrics.gauge(name, value, { attributes });\n } else if (state[V3_HISTOGRAM_STATE_TYPE_ID] !== undefined || state[V3_SUMMARY_STATE_TYPE_ID] !== undefined) {\n sentryMetrics.gauge(`${name}.sum`, metricState.sum ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.count`, Number(metricState.count ?? 0), { attributes });\n sentryMetrics.gauge(`${name}.min`, metricState.min ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.max`, metricState.max ?? 0, { attributes });\n } else if (state[V3_FREQUENCY_STATE_TYPE_ID] !== undefined && metricState.occurrences) {\n for (const [word, count] of metricState.occurrences) {\n sentryMetrics.count(name, count, {\n attributes: { ...attributes, word },\n });\n }\n }\n}\n\nfunction sendV4MetricToSentry(snapshot: Metric.Metric.Snapshot, previousCounterValues: Map<string, number>): void {\n const name = snapshot.id;\n const attributes: MetricAttributes = snapshot.attributes ? { ...snapshot.attributes } : {};\n const metricId = getMetricIdV4(snapshot);\n\n switch (snapshot.type) {\n case 'Counter': {\n const currentValue = Number(snapshot.state.count);\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 break;\n }\n case 'Gauge': {\n const value = Number(snapshot.state.value);\n sentryMetrics.gauge(name, value, { attributes });\n break;\n }\n case 'Histogram':\n case 'Summary': {\n sentryMetrics.gauge(`${name}.sum`, snapshot.state.sum ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.count`, snapshot.state.count ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.min`, snapshot.state.min ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.max`, snapshot.state.max ?? 0, { attributes });\n break;\n }\n case 'Frequency': {\n for (const [word, count] of snapshot.state.occurrences) {\n sentryMetrics.count(name, count, {\n attributes: { ...attributes, word },\n });\n }\n break;\n }\n }\n}\n\n// =============================================================================\n// Effect v3 snapshot function type (vendored - not exported from effect@3.x)\n// =============================================================================\n\ntype V3UnsafeSnapshotFn = () => ReadonlyArray<V3MetricPair>;\n\n// Use bracket notation to avoid Webpack static analysis flagging missing exports\n// This is important for Effect v3 compatibility.\nconst MetricModule = Metric;\nconst snapshotUnsafe = MetricModule['snapshotUnsafe'] as typeof Metric.snapshotUnsafe | undefined;\n// @ts-expect-error - unsafeSnapshot is not exported from effect@3.x\nconst unsafeSnapshot = MetricModule['unsafeSnapshot'] as V3UnsafeSnapshotFn | undefined;\n\nfunction flushMetricsToSentry(previousCounterValues: Map<string, number>): void {\n if (snapshotUnsafe) {\n // Effect v4\n const snapshots = snapshotUnsafe(Context.empty());\n for (const snapshot of snapshots) {\n sendV4MetricToSentry(snapshot, previousCounterValues);\n }\n } else if (unsafeSnapshot) {\n // Effect v3\n const snapshots = unsafeSnapshot();\n for (const pair of snapshots) {\n sendV3MetricToSentry(pair, previousCounterValues);\n }\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> = Layer.effectDiscard(\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"],"mappings":";;;;;;;;;AAkCA;AACA;AACA;AACA;AACA,MAAM,2BAA2B,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC;AACzE,MAAM,yBAAyB,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC;AACrE,MAAM,6BAA6B,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC;AAC7E,MAAM,2BAA2B,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC;AACzE,MAAM,6BAA6B,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC;;AAE7E,SAAS,kBAAkB,CAAC,MAAM,EAAkD;AACpF,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAA,EAAO,CAAC,EAAE,EAAE,CAAC;AAClF;;AAEA,SAAS,aAAa,CAAC,IAAI,EAAwB;AACnD,EAAE,MAAM,IAAA,GAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA,IAAK,CAAC,EAAA,CAAA,CAAA,GAAA,CAAA,CAAA,EAAA,CAAA,CAAA,KAAA,CAAA,CAAA,CAAA,CAAA,IAAA,CAAA,GAAA,CAAA;AACA,EAAA,OAAA,CAAA,EAAA,IAAA,CAAA,SAAA,CAAA,IAAA,CAAA,CAAA,EAAA,IAAA,CAAA,CAAA;AACA;;AAEA,SAAA,aAAA,CAAA,QAAA,EAAA;AACA,EAAA,MAAA,KAAA,GAAA,QAAA,CAAA;AACA,MAAA,MAAA,CAAA,OAAA,CAAA,QAAA,CAAA,UAAA;AACA,SAAA,GAAA,CAAA,CAAA,CAAA,CAAA,EAAA,CAAA,CAAA,KAAA,CAAA,EAAA,CAAA,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA;AACA,SAAA,IAAA,CAAA,GAAA;AACA,MAAA,EAAA;AACA,EAAA,OAAA,CAAA,EAAA,QAAA,CAAA,EAAA,CAAA,CAAA,EAAA,KAAA,CAAA,CAAA;AACA;;AAEA,SAAA,oBAAA,CAAA,IAAA,EAAA,qBAAA,EAAA;AACA,EAAA,MAAA,EAAA,SAAA,EAAA,WAAA,EAAA,GAAA,IAAA;AACA,EAAA,MAAA,IAAA,GAAA,SAAA,CAAA,IAAA;AACA,EAAA,MAAA,UAAA,GAAA,kBAAA,CAAA,SAAA,CAAA,IAAA,CAAA;AACA,EAAA,MAAA,QAAA,GAAA,aAAA,CAAA,IAAA,CAAA;;AAEA,EAAA,MAAA,KAAA,GAAA,WAAA;;AAEA,EAAA,IAAA,KAAA,CAAA,wBAAA,CAAA,KAAA,SAAA,EAAA;AACA,IAAA,MAAA,YAAA,GAAA,MAAA,CAAA,WAAA,CAAA,KAAA,CAAA;AACA,IAAA,MAAA,aAAA,GAAA,qBAAA,CAAA,GAAA,CAAA,QAAA,CAAA,IAAA,CAAA;AACA,IAAA,MAAA,KAAA,GAAA,YAAA,GAAA,aAAA;;AAEA,IAAA,IAAA,KAAA,GAAA,CAAA,EAAA;AACA,MAAAA,YAAA,CAAA,KAAA,CAAA,IAAA,EAAA,KAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,IAAA;;AAEA,IAAA,qBAAA,CAAA,GAAA,CAAA,QAAA,EAAA,YAAA,CAAA;AACA,EAAA,CAAA,MAAA,IAAA,KAAA,CAAA,sBAAA,CAAA,KAAA,SAAA,EAAA;AACA,IAAA,MAAA,KAAA,GAAA,MAAA,CAAA,WAAA,CAAA,KAAA,CAAA;AACA,IAAAA,YAAA,CAAA,KAAA,CAAA,IAAA,EAAA,KAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,EAAA,CAAA,MAAA,IAAA,KAAA,CAAA,0BAAA,CAAA,KAAA,SAAA,IAAA,KAAA,CAAA,wBAAA,CAAA,KAAA,SAAA,EAAA;AACA,IAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,IAAA,CAAA,EAAA,WAAA,CAAA,GAAA,IAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,IAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,MAAA,CAAA,EAAA,MAAA,CAAA,WAAA,CAAA,KAAA,IAAA,CAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,IAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,IAAA,CAAA,EAAA,WAAA,CAAA,GAAA,IAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,IAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,IAAA,CAAA,EAAA,WAAA,CAAA,GAAA,IAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,EAAA,CAAA,MAAA,IAAA,KAAA,CAAA,0BAAA,CAAA,KAAA,SAAA,IAAA,WAAA,CAAA,WAAA,EAAA;AACA,IAAA,KAAA,MAAA,CAAA,IAAA,EAAA,KAAA,CAAA,IAAA,WAAA,CAAA,WAAA,EAAA;AACA,MAAAA,YAAA,CAAA,KAAA,CAAA,IAAA,EAAA,KAAA,EAAA;AACA,QAAA,UAAA,EAAA,EAAA,GAAA,UAAA,EAAA,IAAA,EAAA;AACA,OAAA,CAAA;AACA,IAAA;AACA,EAAA;AACA;;AAEA,SAAA,oBAAA,CAAA,QAAA,EAAA,qBAAA,EAAA;AACA,EAAA,MAAA,IAAA,GAAA,QAAA,CAAA,EAAA;AACA,EAAA,MAAA,UAAA,GAAA,QAAA,CAAA,UAAA,GAAA,EAAA,GAAA,QAAA,CAAA,UAAA,EAAA,GAAA,EAAA;AACA,EAAA,MAAA,QAAA,GAAA,aAAA,CAAA,QAAA,CAAA;;AAEA,EAAA,QAAA,QAAA,CAAA,IAAA;AACA,IAAA,KAAA,SAAA,EAAA;AACA,MAAA,MAAA,YAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,KAAA,CAAA;AACA,MAAA,MAAA,aAAA,GAAA,qBAAA,CAAA,GAAA,CAAA,QAAA,CAAA,IAAA,CAAA;AACA,MAAA,MAAA,KAAA,GAAA,YAAA,GAAA,aAAA;;AAEA,MAAA,IAAA,KAAA,GAAA,CAAA,EAAA;AACA,QAAAA,YAAA,CAAA,KAAA,CAAA,IAAA,EAAA,KAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,MAAA;;AAEA,MAAA,qBAAA,CAAA,GAAA,CAAA,QAAA,EAAA,YAAA,CAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA,KAAA,OAAA,EAAA;AACA,MAAA,MAAA,KAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,KAAA,CAAA;AACA,MAAAA,YAAA,CAAA,KAAA,CAAA,IAAA,EAAA,KAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA,KAAA,WAAA;AACA,IAAA,KAAA,SAAA,EAAA;AACA,MAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,IAAA,CAAA,EAAA,QAAA,CAAA,KAAA,CAAA,GAAA,IAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,MAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,MAAA,CAAA,EAAA,QAAA,CAAA,KAAA,CAAA,KAAA,IAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,MAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,IAAA,CAAA,EAAA,QAAA,CAAA,KAAA,CAAA,GAAA,IAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,MAAAA,YAAA,CAAA,KAAA,CAAA,CAAA,EAAA,IAAA,CAAA,IAAA,CAAA,EAAA,QAAA,CAAA,KAAA,CAAA,GAAA,IAAA,CAAA,EAAA,EAAA,UAAA,EAAA,CAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA,KAAA,WAAA,EAAA;AACA,MAAA,KAAA,MAAA,CAAA,IAAA,EAAA,KAAA,CAAA,IAAA,QAAA,CAAA,KAAA,CAAA,WAAA,EAAA;AACA,QAAAA,YAAA,CAAA,KAAA,CAAA,IAAA,EAAA,KAAA,EAAA;AACA,UAAA,UAAA,EAAA,EAAA,GAAA,UAAA,EAAA,IAAA,EAAA;AACA,SAAA,CAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;;AAEA;AACA;AACA;;AAIA;AACA;AACA,MAAA,YAAA,GAAA,MAAA;AACA,MAAA,cAAA,GAAA,YAAA,CAAA,gBAAA,CAAA;AACA;AACA,MAAA,cAAA,GAAA,YAAA,CAAA,gBAAA,CAAA;;AAEA,SAAA,oBAAA,CAAA,qBAAA,EAAA;AACA,EAAA,IAAA,cAAA,EAAA;AACA;AACA,IAAA,MAAA,SAAA,GAAA,cAAA,CAAA,OAAA,CAAA,KAAA,EAAA,CAAA;AACA,IAAA,KAAA,MAAA,QAAA,IAAA,SAAA,EAAA;AACA,MAAA,oBAAA,CAAA,QAAA,EAAA,qBAAA,CAAA;AACA,IAAA;AACA,EAAA,CAAA,MAAA,IAAA,cAAA,EAAA;AACA;AACA,IAAA,MAAA,SAAA,GAAA,cAAA,EAAA;AACA,IAAA,KAAA,MAAA,IAAA,IAAA,SAAA,EAAA;AACA,MAAA,oBAAA,CAAA,IAAA,EAAA,qBAAA,CAAA;AACA,IAAA;AACA,EAAA;AACA;;AAEA,SAAA,2BAAA,CAAA,qBAAA,EAAA;AACA,EAAA,MAAA,QAAA,GAAA,QAAA,CAAA,MAAA,CAAA,YAAA,CAAA;;AAEA,EAAA,OAAA,MAAA,CAAA,MAAA;AACA,IAAA,MAAA,CAAA,IAAA,CAAA,MAAA,oBAAA,CAAA,qBAAA,CAAA,CAAA;AACA,IAAA,QAAA;AACA,GAAA,CAAA,IAAA,CAAA,MAAA,CAAA,MAAA,EAAA,MAAA,CAAA,aAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAA,wBAAA,GAAA,KAAA,CAAA,aAAA;AACA,EAAA,MAAA,CAAA,GAAA,CAAA,aAAA;AACA,IAAA,MAAA,qBAAA,GAAA,IAAA,GAAA,EAAA;;AAEA,IAAA,OAAA,MAAA,CAAA,cAAA,CAAA,MAAA,CAAA,IAAA,EAAA;AACA,MAAA,MAAA,CAAA,IAAA,CAAA,MAAA;AACA,QAAA,qBAAA,CAAA,KAAA,EAAA;AACA,MAAA,CAAA,CAAA;AACA,KAAA;;AAEA,IAAA,OAAA,MAAA,CAAA,UAAA,CAAA,2BAAA,CAAA,qBAAA,CAAA,CAAA;AACA,EAAA,CAAA,CAAA;AACA;;;;"}
|
package/build/cjs/tracer.js
CHANGED
|
@@ -25,6 +25,46 @@ function isSentrySpan(span) {
|
|
|
25
25
|
return SENTRY_SPAN_SYMBOL in span;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
function getErrorMessage(exit) {
|
|
29
|
+
if (!Exit.isFailure(exit)) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const cause = exit.cause ;
|
|
34
|
+
|
|
35
|
+
// Effect v4: cause.reasons is an array of Reason objects
|
|
36
|
+
if (
|
|
37
|
+
cause &&
|
|
38
|
+
typeof cause === 'object' &&
|
|
39
|
+
'reasons' in cause &&
|
|
40
|
+
Array.isArray((cause ).reasons)
|
|
41
|
+
) {
|
|
42
|
+
const reasons = (cause ).reasons;
|
|
43
|
+
for (const reason of reasons) {
|
|
44
|
+
if (reason._tag === 'Fail' && reason.error !== undefined) {
|
|
45
|
+
return String(reason.error);
|
|
46
|
+
}
|
|
47
|
+
if (reason._tag === 'Die' && reason.defect !== undefined) {
|
|
48
|
+
return String(reason.defect);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return 'internal_error';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Effect v3: cause has _tag directly
|
|
55
|
+
if (cause && typeof cause === 'object' && '_tag' in cause) {
|
|
56
|
+
const v3Cause = cause ;
|
|
57
|
+
if (v3Cause._tag === 'Fail') {
|
|
58
|
+
return String(v3Cause.error);
|
|
59
|
+
}
|
|
60
|
+
if (v3Cause._tag === 'Die') {
|
|
61
|
+
return String(v3Cause.defect);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return 'internal_error';
|
|
66
|
+
}
|
|
67
|
+
|
|
28
68
|
class SentrySpanWrapper {
|
|
29
69
|
|
|
30
70
|
constructor(
|
|
@@ -42,6 +82,7 @@ class SentrySpanWrapper {
|
|
|
42
82
|
this.parent = parent;
|
|
43
83
|
this.links = [...links];
|
|
44
84
|
this.sentrySpan = existingSpan;
|
|
85
|
+
this.annotations = context;
|
|
45
86
|
|
|
46
87
|
const spanContext = this.sentrySpan.spanContext();
|
|
47
88
|
this.spanId = spanContext.spanId;
|
|
@@ -79,9 +120,7 @@ class SentrySpanWrapper {
|
|
|
79
120
|
}
|
|
80
121
|
|
|
81
122
|
if (Exit.isFailure(exit)) {
|
|
82
|
-
const
|
|
83
|
-
const message =
|
|
84
|
-
cause._tag === 'Fail' ? String(cause.error) : cause._tag === 'Die' ? String(cause.defect) : 'internal_error';
|
|
123
|
+
const message = getErrorMessage(exit) ?? 'internal_error';
|
|
85
124
|
this.sentrySpan.setStatus({ code: 2, message });
|
|
86
125
|
} else {
|
|
87
126
|
this.sentrySpan.setStatus({ code: 1 });
|
|
@@ -122,9 +161,34 @@ function createSentrySpan(
|
|
|
122
161
|
return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);
|
|
123
162
|
}
|
|
124
163
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
164
|
+
// Check if we're running Effect v4 by checking the Exit/Cause structure
|
|
165
|
+
// In v4, causes have a 'reasons' array
|
|
166
|
+
// In v3, causes have '_tag' directly on the cause object
|
|
167
|
+
const isEffectV4 = (() => {
|
|
168
|
+
try {
|
|
169
|
+
const testExit = Exit.fail('test') ;
|
|
170
|
+
const cause = testExit.cause;
|
|
171
|
+
// v4 causes have 'reasons' array, v3 causes have '_tag' directly
|
|
172
|
+
if (cause && typeof cause === 'object' && 'reasons' in cause) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
176
|
+
} catch {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
})();
|
|
180
|
+
|
|
181
|
+
const makeSentryTracerV3 = () => {
|
|
182
|
+
// Effect v3 API: span(name, parent, context, links, startTime, kind)
|
|
183
|
+
return EffectTracer.make({
|
|
184
|
+
span(
|
|
185
|
+
name,
|
|
186
|
+
parent,
|
|
187
|
+
context,
|
|
188
|
+
links,
|
|
189
|
+
startTime,
|
|
190
|
+
kind,
|
|
191
|
+
) {
|
|
128
192
|
return createSentrySpan(name, parent, context, links, startTime, kind);
|
|
129
193
|
},
|
|
130
194
|
context(execution, fiber) {
|
|
@@ -134,12 +198,37 @@ const makeSentryTracer = () =>
|
|
|
134
198
|
}
|
|
135
199
|
return core.withActiveSpan(currentSpan.sentrySpan, execution);
|
|
136
200
|
},
|
|
201
|
+
} );
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const makeSentryTracerV4 = () => {
|
|
205
|
+
const EFFECT_EVALUATE = '~effect/Effect/evaluate' ;
|
|
206
|
+
|
|
207
|
+
return EffectTracer.make({
|
|
208
|
+
span(options) {
|
|
209
|
+
return createSentrySpan(
|
|
210
|
+
options.name,
|
|
211
|
+
options.parent,
|
|
212
|
+
options.annotations,
|
|
213
|
+
options.links,
|
|
214
|
+
options.startTime,
|
|
215
|
+
options.kind,
|
|
216
|
+
);
|
|
217
|
+
},
|
|
218
|
+
context(primitive, fiber) {
|
|
219
|
+
const currentSpan = fiber.currentSpan;
|
|
220
|
+
if (currentSpan === undefined || !isSentrySpan(currentSpan)) {
|
|
221
|
+
return primitive[EFFECT_EVALUATE](fiber);
|
|
222
|
+
}
|
|
223
|
+
return core.withActiveSpan(currentSpan.sentrySpan, () => primitive[EFFECT_EVALUATE](fiber));
|
|
224
|
+
},
|
|
137
225
|
});
|
|
226
|
+
};
|
|
138
227
|
|
|
139
228
|
/**
|
|
140
229
|
* Effect Layer that sets up the Sentry tracer for Effect spans.
|
|
141
230
|
*/
|
|
142
|
-
const SentryEffectTracer =
|
|
231
|
+
const SentryEffectTracer = isEffectV4 ? makeSentryTracerV4() : makeSentryTracerV3();
|
|
143
232
|
|
|
144
233
|
exports.SentryEffectTracer = SentryEffectTracer;
|
|
145
234
|
//# sourceMappingURL=tracer.js.map
|
package/build/cjs/tracer.js.map
CHANGED
|
@@ -1 +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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"}
|
|
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\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 (\n cause &&\n typeof cause === 'object' &&\n 'reasons' in cause &&\n Array.isArray((cause as { reasons: unknown }).reasons)\n ) {\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 (cause && typeof cause === 'object' && '_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\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\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 (cause && typeof cause === 'object' && 'reasons' in cause) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n})();\n\nconst makeSentryTracerV3 = (): 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(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 = (): EffectTracer.Tracer => {\n const EFFECT_EVALUATE = '~effect/Effect/evaluate' as const;\n\n return EffectTracer.make({\n span(options) {\n return createSentrySpan(\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 * Effect Layer that sets up the Sentry tracer for Effect spans.\n */\nexport const SentryEffectTracer = isEffectV4 ? makeSentryTracerV4() : makeSentryTracerV3();\n"],"names":["getActiveSpan","startInactiveSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","withActiveSpan"],"mappings":"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"}
|
package/build/esm/logger.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { logger } from '@sentry/core';
|
|
2
2
|
import * as Logger from 'effect/Logger';
|
|
3
3
|
|
|
4
|
+
function getLogLevelTag(logLevel) {
|
|
5
|
+
// Effect v4: logLevel is a string literal directly
|
|
6
|
+
if (typeof logLevel === 'string') {
|
|
7
|
+
return logLevel;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Effect v3: logLevel has _tag property
|
|
11
|
+
if (logLevel && typeof logLevel === 'object' && '_tag' in logLevel) {
|
|
12
|
+
return (logLevel )._tag;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return 'Info';
|
|
16
|
+
}
|
|
17
|
+
|
|
4
18
|
/**
|
|
5
19
|
* Effect Logger that sends logs to Sentry.
|
|
6
20
|
*/
|
|
@@ -15,14 +29,17 @@ const SentryEffectLogger = Logger.make(({ logLevel, message }) => {
|
|
|
15
29
|
msg = JSON.stringify(message);
|
|
16
30
|
}
|
|
17
31
|
|
|
18
|
-
|
|
32
|
+
const tag = getLogLevelTag(logLevel);
|
|
33
|
+
|
|
34
|
+
switch (tag) {
|
|
19
35
|
case 'Fatal':
|
|
20
36
|
logger.fatal(msg);
|
|
21
37
|
break;
|
|
22
38
|
case 'Error':
|
|
23
39
|
logger.error(msg);
|
|
24
40
|
break;
|
|
25
|
-
case 'Warning':
|
|
41
|
+
case 'Warning': // Effect v3
|
|
42
|
+
case 'Warn': // Effect v4
|
|
26
43
|
logger.warn(msg);
|
|
27
44
|
break;
|
|
28
45
|
case 'Info':
|
package/build/esm/logger.js.map
CHANGED
|
@@ -1 +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
|
|
1
|
+
{"version":3,"file":"logger.js","sources":["../../src/logger.ts"],"sourcesContent":["import { logger as sentryLogger } from '@sentry/core';\nimport * as Logger from 'effect/Logger';\nimport type * as LogLevel from 'effect/LogLevel';\n\nfunction getLogLevelTag(logLevel: LogLevel.LogLevel): LogLevel.LogLevel | 'Warning' {\n // Effect v4: logLevel is a string literal directly\n if (typeof logLevel === 'string') {\n return logLevel;\n }\n\n // Effect v3: logLevel has _tag property\n if (logLevel && typeof logLevel === 'object' && '_tag' in logLevel) {\n return (logLevel as { _tag: LogLevel.LogLevel })._tag;\n }\n\n return 'Info';\n}\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 const tag = getLogLevelTag(logLevel);\n\n switch (tag) {\n case 'Fatal':\n sentryLogger.fatal(msg);\n break;\n case 'Error':\n sentryLogger.error(msg);\n break;\n case 'Warning': // Effect v3\n case 'Warn': // Effect v4\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 tag satisfies never;\n }\n});\n"],"names":["sentryLogger"],"mappings":";;;AAIA,SAAS,cAAc,CAAC,QAAQ,EAAoD;AACpF;AACA,EAAE,IAAI,OAAO,QAAA,KAAa,QAAQ,EAAE;AACpC,IAAI,OAAO,QAAQ;AACnB,EAAE;;AAEF;AACA,EAAE,IAAI,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,IAAY,MAAA,IAAU,QAAQ,EAAE;AACtE,IAAI,OAAO,CAAC,QAAA,GAAyC,IAAI;AACzD,EAAE;;AAEF,EAAE,OAAO,MAAM;AACf;;AAEA;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,MAAM,GAAA,GAAM,cAAc,CAAC,QAAQ,CAAC;;AAEtC,EAAE,QAAQ,GAAG;AACb,IAAI,KAAK,OAAO;AAChB,MAAMA,MAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AACN,IAAI,KAAK,OAAO;AAChB,MAAMA,MAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AACN,IAAI,KAAK,SAAS,CAAA;AAClB,IAAI,KAAK,MAAM;AACf,MAAMA,MAAY,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5B,MAAM;AACN,IAAI,KAAK,MAAM;AACf,MAAMA,MAAY,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5B,MAAM;AACN,IAAI,KAAK,OAAO;AAChB,MAAMA,MAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AACN,IAAI,KAAK,OAAO;AAChB,MAAMA,MAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM;AAMN;AACA,CAAC;;;;"}
|
package/build/esm/metrics.js
CHANGED
|
@@ -1,37 +1,65 @@
|
|
|
1
1
|
import { metrics } from '@sentry/core';
|
|
2
|
+
import * as Context from 'effect/Context';
|
|
2
3
|
import * as Effect from 'effect/Effect';
|
|
3
|
-
import
|
|
4
|
+
import * as Layer from 'effect/Layer';
|
|
4
5
|
import * as Metric from 'effect/Metric';
|
|
5
|
-
import * as MetricKeyType from 'effect/MetricKeyType';
|
|
6
|
-
import * as MetricState from 'effect/MetricState';
|
|
7
6
|
import * as Schedule from 'effect/Schedule';
|
|
8
7
|
|
|
8
|
+
// Effect v3 `MetricState` implementations brand themselves with a `Symbol.for(...)` TypeId
|
|
9
|
+
// rather than a string `_tag`. We use these globally-registered symbols to classify state
|
|
10
|
+
// instances returned by `Metric.unsafeSnapshot()` without importing `effect/MetricState`
|
|
11
|
+
// (the module does not exist in Effect v4).
|
|
12
|
+
const V3_COUNTER_STATE_TYPE_ID = Symbol.for('effect/MetricState/Counter');
|
|
13
|
+
const V3_GAUGE_STATE_TYPE_ID = Symbol.for('effect/MetricState/Gauge');
|
|
14
|
+
const V3_HISTOGRAM_STATE_TYPE_ID = Symbol.for('effect/MetricState/Histogram');
|
|
15
|
+
const V3_SUMMARY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Summary');
|
|
16
|
+
const V3_FREQUENCY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Frequency');
|
|
17
|
+
|
|
9
18
|
function labelsToAttributes(labels) {
|
|
10
19
|
return labels.reduce((acc, label) => ({ ...acc, [label.key]: label.value }), {});
|
|
11
20
|
}
|
|
12
21
|
|
|
13
|
-
function
|
|
22
|
+
function getMetricIdV3(pair) {
|
|
23
|
+
const tags = pair.metricKey.tags.map(t => `${t.key}=${t.value}`).join(',');
|
|
24
|
+
return `${pair.metricKey.name}:${tags}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getMetricIdV4(snapshot) {
|
|
28
|
+
const attrs = snapshot.attributes
|
|
29
|
+
? Object.entries(snapshot.attributes)
|
|
30
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
31
|
+
.join(',')
|
|
32
|
+
: '';
|
|
33
|
+
return `${snapshot.id}:${attrs}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function sendV3MetricToSentry(pair, previousCounterValues) {
|
|
14
37
|
const { metricKey, metricState } = pair;
|
|
15
38
|
const name = metricKey.name;
|
|
16
39
|
const attributes = labelsToAttributes(metricKey.tags);
|
|
40
|
+
const metricId = getMetricIdV3(pair);
|
|
41
|
+
|
|
42
|
+
const state = metricState ;
|
|
17
43
|
|
|
18
|
-
if (
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
44
|
+
if (state[V3_COUNTER_STATE_TYPE_ID] !== undefined) {
|
|
45
|
+
const currentValue = Number(metricState.count);
|
|
46
|
+
const previousValue = previousCounterValues.get(metricId) ?? 0;
|
|
47
|
+
const delta = currentValue - previousValue;
|
|
48
|
+
|
|
49
|
+
if (delta > 0) {
|
|
50
|
+
metrics.count(name, delta, { attributes });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
previousCounterValues.set(metricId, currentValue);
|
|
54
|
+
} else if (state[V3_GAUGE_STATE_TYPE_ID] !== undefined) {
|
|
22
55
|
const value = Number(metricState.value);
|
|
23
56
|
metrics.gauge(name, value, { attributes });
|
|
24
|
-
} else if (
|
|
25
|
-
metrics.gauge(`${name}.sum`, metricState.sum, { attributes });
|
|
26
|
-
metrics.gauge(`${name}.count`, metricState.count, { attributes });
|
|
27
|
-
metrics.gauge(`${name}.min`, metricState.min, { attributes });
|
|
28
|
-
metrics.gauge(`${name}.max`, metricState.max, { attributes });
|
|
29
|
-
} else if (
|
|
30
|
-
metrics.gauge(`${name}.sum`, metricState.sum, { attributes });
|
|
31
|
-
metrics.gauge(`${name}.count`, metricState.count, { attributes });
|
|
32
|
-
metrics.gauge(`${name}.min`, metricState.min, { attributes });
|
|
33
|
-
metrics.gauge(`${name}.max`, metricState.max, { attributes });
|
|
34
|
-
} else if (MetricState.isFrequencyState(metricState)) {
|
|
57
|
+
} else if (state[V3_HISTOGRAM_STATE_TYPE_ID] !== undefined || state[V3_SUMMARY_STATE_TYPE_ID] !== undefined) {
|
|
58
|
+
metrics.gauge(`${name}.sum`, metricState.sum ?? 0, { attributes });
|
|
59
|
+
metrics.gauge(`${name}.count`, Number(metricState.count ?? 0), { attributes });
|
|
60
|
+
metrics.gauge(`${name}.min`, metricState.min ?? 0, { attributes });
|
|
61
|
+
metrics.gauge(`${name}.max`, metricState.max ?? 0, { attributes });
|
|
62
|
+
} else if (state[V3_FREQUENCY_STATE_TYPE_ID] !== undefined && metricState.occurrences) {
|
|
35
63
|
for (const [word, count] of metricState.occurrences) {
|
|
36
64
|
metrics.count(name, count, {
|
|
37
65
|
attributes: { ...attributes, word },
|
|
@@ -40,50 +68,73 @@ function sendMetricToSentry(pair) {
|
|
|
40
68
|
}
|
|
41
69
|
}
|
|
42
70
|
|
|
43
|
-
function
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
71
|
+
function sendV4MetricToSentry(snapshot, previousCounterValues) {
|
|
72
|
+
const name = snapshot.id;
|
|
73
|
+
const attributes = snapshot.attributes ? { ...snapshot.attributes } : {};
|
|
74
|
+
const metricId = getMetricIdV4(snapshot);
|
|
47
75
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
const name = metricKey.name;
|
|
54
|
-
const attributes = labelsToAttributes(metricKey.tags);
|
|
55
|
-
const metricId = getMetricId(pair);
|
|
76
|
+
switch (snapshot.type) {
|
|
77
|
+
case 'Counter': {
|
|
78
|
+
const currentValue = Number(snapshot.state.count);
|
|
79
|
+
const previousValue = previousCounterValues.get(metricId) ?? 0;
|
|
80
|
+
const delta = currentValue - previousValue;
|
|
56
81
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const previousValue = previousCounterValues.get(metricId) ?? 0;
|
|
61
|
-
const delta = currentValue - previousValue;
|
|
82
|
+
if (delta > 0) {
|
|
83
|
+
metrics.count(name, delta, { attributes });
|
|
84
|
+
}
|
|
62
85
|
|
|
63
|
-
|
|
64
|
-
|
|
86
|
+
previousCounterValues.set(metricId, currentValue);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
case 'Gauge': {
|
|
90
|
+
const value = Number(snapshot.state.value);
|
|
91
|
+
metrics.gauge(name, value, { attributes });
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case 'Histogram':
|
|
95
|
+
case 'Summary': {
|
|
96
|
+
metrics.gauge(`${name}.sum`, snapshot.state.sum ?? 0, { attributes });
|
|
97
|
+
metrics.gauge(`${name}.count`, snapshot.state.count ?? 0, { attributes });
|
|
98
|
+
metrics.gauge(`${name}.min`, snapshot.state.min ?? 0, { attributes });
|
|
99
|
+
metrics.gauge(`${name}.max`, snapshot.state.max ?? 0, { attributes });
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case 'Frequency': {
|
|
103
|
+
for (const [word, count] of snapshot.state.occurrences) {
|
|
104
|
+
metrics.count(name, count, {
|
|
105
|
+
attributes: { ...attributes, word },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
break;
|
|
65
109
|
}
|
|
66
|
-
|
|
67
|
-
previousCounterValues.set(metricId, currentValue);
|
|
68
|
-
} else {
|
|
69
|
-
sendMetricToSentry(pair);
|
|
70
110
|
}
|
|
71
111
|
}
|
|
72
112
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// Effect v3 snapshot function type (vendored - not exported from effect@3.x)
|
|
115
|
+
// =============================================================================
|
|
116
|
+
|
|
117
|
+
// Use bracket notation to avoid Webpack static analysis flagging missing exports
|
|
118
|
+
// This is important for Effect v3 compatibility.
|
|
119
|
+
const MetricModule = Metric;
|
|
120
|
+
const snapshotUnsafe = MetricModule['snapshotUnsafe'] ;
|
|
121
|
+
// @ts-expect-error - unsafeSnapshot is not exported from effect@3.x
|
|
122
|
+
const unsafeSnapshot = MetricModule['unsafeSnapshot'] ;
|
|
79
123
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
124
|
+
function flushMetricsToSentry(previousCounterValues) {
|
|
125
|
+
if (snapshotUnsafe) {
|
|
126
|
+
// Effect v4
|
|
127
|
+
const snapshots = snapshotUnsafe(Context.empty());
|
|
128
|
+
for (const snapshot of snapshots) {
|
|
129
|
+
sendV4MetricToSentry(snapshot, previousCounterValues);
|
|
85
130
|
}
|
|
86
|
-
})
|
|
131
|
+
} else if (unsafeSnapshot) {
|
|
132
|
+
// Effect v3
|
|
133
|
+
const snapshots = unsafeSnapshot();
|
|
134
|
+
for (const pair of snapshots) {
|
|
135
|
+
sendV3MetricToSentry(pair, previousCounterValues);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
87
138
|
}
|
|
88
139
|
|
|
89
140
|
function createMetricsReporterEffect(previousCounterValues) {
|
|
@@ -100,7 +151,7 @@ function createMetricsReporterEffect(previousCounterValues) {
|
|
|
100
151
|
* The layer manages its own state for delta counter calculations,
|
|
101
152
|
* which is automatically cleaned up when the layer is finalized.
|
|
102
153
|
*/
|
|
103
|
-
const SentryEffectMetricsLayer =
|
|
154
|
+
const SentryEffectMetricsLayer = Layer.effectDiscard(
|
|
104
155
|
Effect.gen(function* () {
|
|
105
156
|
const previousCounterValues = new Map();
|
|
106
157
|
|
package/build/esm/metrics.js.map
CHANGED
|
@@ -1 +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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"metrics.js","sources":["../../src/metrics.ts"],"sourcesContent":["import { metrics as sentryMetrics } from '@sentry/core';\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport * as Metric from 'effect/Metric';\nimport * as Schedule from 'effect/Schedule';\n\ntype MetricAttributes = Record<string, string>;\n\n// =============================================================================\n// Effect v3 Types (vendored - not exported from effect@3.x)\n// =============================================================================\n\ninterface V3MetricLabel {\n key: string;\n value: string;\n}\n\ninterface V3MetricPair {\n metricKey: {\n name: string;\n tags: ReadonlyArray<V3MetricLabel>;\n keyType: { _tag: string };\n };\n metricState: {\n count?: number | bigint;\n value?: number;\n sum?: number;\n min?: number;\n max?: number;\n occurrences?: Map<string, number>;\n };\n}\n\n// Effect v3 `MetricState` implementations brand themselves with a `Symbol.for(...)` TypeId\n// rather than a string `_tag`. We use these globally-registered symbols to classify state\n// instances returned by `Metric.unsafeSnapshot()` without importing `effect/MetricState`\n// (the module does not exist in Effect v4).\nconst V3_COUNTER_STATE_TYPE_ID = Symbol.for('effect/MetricState/Counter');\nconst V3_GAUGE_STATE_TYPE_ID = Symbol.for('effect/MetricState/Gauge');\nconst V3_HISTOGRAM_STATE_TYPE_ID = Symbol.for('effect/MetricState/Histogram');\nconst V3_SUMMARY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Summary');\nconst V3_FREQUENCY_STATE_TYPE_ID = Symbol.for('effect/MetricState/Frequency');\n\nfunction labelsToAttributes(labels: ReadonlyArray<V3MetricLabel>): MetricAttributes {\n return labels.reduce((acc, label) => ({ ...acc, [label.key]: label.value }), {});\n}\n\nfunction getMetricIdV3(pair: V3MetricPair): string {\n const tags = pair.metricKey.tags.map(t => `${t.key}=${t.value}`).join(',');\n return `${pair.metricKey.name}:${tags}`;\n}\n\nfunction getMetricIdV4(snapshot: Metric.Metric.Snapshot): string {\n const attrs = snapshot.attributes\n ? Object.entries(snapshot.attributes)\n .map(([k, v]) => `${k}=${v}`)\n .join(',')\n : '';\n return `${snapshot.id}:${attrs}`;\n}\n\nfunction sendV3MetricToSentry(pair: V3MetricPair, previousCounterValues: Map<string, number>): void {\n const { metricKey, metricState } = pair;\n const name = metricKey.name;\n const attributes = labelsToAttributes(metricKey.tags);\n const metricId = getMetricIdV3(pair);\n\n const state = metricState as unknown as Record<symbol, unknown>;\n\n if (state[V3_COUNTER_STATE_TYPE_ID] !== undefined) {\n const currentValue = Number(metricState.count);\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 if (state[V3_GAUGE_STATE_TYPE_ID] !== undefined) {\n const value = Number(metricState.value);\n sentryMetrics.gauge(name, value, { attributes });\n } else if (state[V3_HISTOGRAM_STATE_TYPE_ID] !== undefined || state[V3_SUMMARY_STATE_TYPE_ID] !== undefined) {\n sentryMetrics.gauge(`${name}.sum`, metricState.sum ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.count`, Number(metricState.count ?? 0), { attributes });\n sentryMetrics.gauge(`${name}.min`, metricState.min ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.max`, metricState.max ?? 0, { attributes });\n } else if (state[V3_FREQUENCY_STATE_TYPE_ID] !== undefined && metricState.occurrences) {\n for (const [word, count] of metricState.occurrences) {\n sentryMetrics.count(name, count, {\n attributes: { ...attributes, word },\n });\n }\n }\n}\n\nfunction sendV4MetricToSentry(snapshot: Metric.Metric.Snapshot, previousCounterValues: Map<string, number>): void {\n const name = snapshot.id;\n const attributes: MetricAttributes = snapshot.attributes ? { ...snapshot.attributes } : {};\n const metricId = getMetricIdV4(snapshot);\n\n switch (snapshot.type) {\n case 'Counter': {\n const currentValue = Number(snapshot.state.count);\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 break;\n }\n case 'Gauge': {\n const value = Number(snapshot.state.value);\n sentryMetrics.gauge(name, value, { attributes });\n break;\n }\n case 'Histogram':\n case 'Summary': {\n sentryMetrics.gauge(`${name}.sum`, snapshot.state.sum ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.count`, snapshot.state.count ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.min`, snapshot.state.min ?? 0, { attributes });\n sentryMetrics.gauge(`${name}.max`, snapshot.state.max ?? 0, { attributes });\n break;\n }\n case 'Frequency': {\n for (const [word, count] of snapshot.state.occurrences) {\n sentryMetrics.count(name, count, {\n attributes: { ...attributes, word },\n });\n }\n break;\n }\n }\n}\n\n// =============================================================================\n// Effect v3 snapshot function type (vendored - not exported from effect@3.x)\n// =============================================================================\n\ntype V3UnsafeSnapshotFn = () => ReadonlyArray<V3MetricPair>;\n\n// Use bracket notation to avoid Webpack static analysis flagging missing exports\n// This is important for Effect v3 compatibility.\nconst MetricModule = Metric;\nconst snapshotUnsafe = MetricModule['snapshotUnsafe'] as typeof Metric.snapshotUnsafe | undefined;\n// @ts-expect-error - unsafeSnapshot is not exported from effect@3.x\nconst unsafeSnapshot = MetricModule['unsafeSnapshot'] as V3UnsafeSnapshotFn | undefined;\n\nfunction flushMetricsToSentry(previousCounterValues: Map<string, number>): void {\n if (snapshotUnsafe) {\n // Effect v4\n const snapshots = snapshotUnsafe(Context.empty());\n for (const snapshot of snapshots) {\n sendV4MetricToSentry(snapshot, previousCounterValues);\n }\n } else if (unsafeSnapshot) {\n // Effect v3\n const snapshots = unsafeSnapshot();\n for (const pair of snapshots) {\n sendV3MetricToSentry(pair, previousCounterValues);\n }\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> = Layer.effectDiscard(\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"],"mappings":"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"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.50.0","sideEffects":false}
|
package/build/esm/tracer.js
CHANGED
|
@@ -23,6 +23,46 @@ function isSentrySpan(span) {
|
|
|
23
23
|
return SENTRY_SPAN_SYMBOL in span;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
function getErrorMessage(exit) {
|
|
27
|
+
if (!Exit.isFailure(exit)) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const cause = exit.cause ;
|
|
32
|
+
|
|
33
|
+
// Effect v4: cause.reasons is an array of Reason objects
|
|
34
|
+
if (
|
|
35
|
+
cause &&
|
|
36
|
+
typeof cause === 'object' &&
|
|
37
|
+
'reasons' in cause &&
|
|
38
|
+
Array.isArray((cause ).reasons)
|
|
39
|
+
) {
|
|
40
|
+
const reasons = (cause ).reasons;
|
|
41
|
+
for (const reason of reasons) {
|
|
42
|
+
if (reason._tag === 'Fail' && reason.error !== undefined) {
|
|
43
|
+
return String(reason.error);
|
|
44
|
+
}
|
|
45
|
+
if (reason._tag === 'Die' && reason.defect !== undefined) {
|
|
46
|
+
return String(reason.defect);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return 'internal_error';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Effect v3: cause has _tag directly
|
|
53
|
+
if (cause && typeof cause === 'object' && '_tag' in cause) {
|
|
54
|
+
const v3Cause = cause ;
|
|
55
|
+
if (v3Cause._tag === 'Fail') {
|
|
56
|
+
return String(v3Cause.error);
|
|
57
|
+
}
|
|
58
|
+
if (v3Cause._tag === 'Die') {
|
|
59
|
+
return String(v3Cause.defect);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return 'internal_error';
|
|
64
|
+
}
|
|
65
|
+
|
|
26
66
|
class SentrySpanWrapper {
|
|
27
67
|
|
|
28
68
|
constructor(
|
|
@@ -40,6 +80,7 @@ class SentrySpanWrapper {
|
|
|
40
80
|
this.parent = parent;
|
|
41
81
|
this.links = [...links];
|
|
42
82
|
this.sentrySpan = existingSpan;
|
|
83
|
+
this.annotations = context;
|
|
43
84
|
|
|
44
85
|
const spanContext = this.sentrySpan.spanContext();
|
|
45
86
|
this.spanId = spanContext.spanId;
|
|
@@ -77,9 +118,7 @@ class SentrySpanWrapper {
|
|
|
77
118
|
}
|
|
78
119
|
|
|
79
120
|
if (Exit.isFailure(exit)) {
|
|
80
|
-
const
|
|
81
|
-
const message =
|
|
82
|
-
cause._tag === 'Fail' ? String(cause.error) : cause._tag === 'Die' ? String(cause.defect) : 'internal_error';
|
|
121
|
+
const message = getErrorMessage(exit) ?? 'internal_error';
|
|
83
122
|
this.sentrySpan.setStatus({ code: 2, message });
|
|
84
123
|
} else {
|
|
85
124
|
this.sentrySpan.setStatus({ code: 1 });
|
|
@@ -120,9 +159,34 @@ function createSentrySpan(
|
|
|
120
159
|
return new SentrySpanWrapper(name, parent, context, links, startTime, kind, newSpan);
|
|
121
160
|
}
|
|
122
161
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
162
|
+
// Check if we're running Effect v4 by checking the Exit/Cause structure
|
|
163
|
+
// In v4, causes have a 'reasons' array
|
|
164
|
+
// In v3, causes have '_tag' directly on the cause object
|
|
165
|
+
const isEffectV4 = (() => {
|
|
166
|
+
try {
|
|
167
|
+
const testExit = Exit.fail('test') ;
|
|
168
|
+
const cause = testExit.cause;
|
|
169
|
+
// v4 causes have 'reasons' array, v3 causes have '_tag' directly
|
|
170
|
+
if (cause && typeof cause === 'object' && 'reasons' in cause) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
174
|
+
} catch {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
})();
|
|
178
|
+
|
|
179
|
+
const makeSentryTracerV3 = () => {
|
|
180
|
+
// Effect v3 API: span(name, parent, context, links, startTime, kind)
|
|
181
|
+
return EffectTracer.make({
|
|
182
|
+
span(
|
|
183
|
+
name,
|
|
184
|
+
parent,
|
|
185
|
+
context,
|
|
186
|
+
links,
|
|
187
|
+
startTime,
|
|
188
|
+
kind,
|
|
189
|
+
) {
|
|
126
190
|
return createSentrySpan(name, parent, context, links, startTime, kind);
|
|
127
191
|
},
|
|
128
192
|
context(execution, fiber) {
|
|
@@ -132,12 +196,37 @@ const makeSentryTracer = () =>
|
|
|
132
196
|
}
|
|
133
197
|
return withActiveSpan(currentSpan.sentrySpan, execution);
|
|
134
198
|
},
|
|
199
|
+
} );
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const makeSentryTracerV4 = () => {
|
|
203
|
+
const EFFECT_EVALUATE = '~effect/Effect/evaluate' ;
|
|
204
|
+
|
|
205
|
+
return EffectTracer.make({
|
|
206
|
+
span(options) {
|
|
207
|
+
return createSentrySpan(
|
|
208
|
+
options.name,
|
|
209
|
+
options.parent,
|
|
210
|
+
options.annotations,
|
|
211
|
+
options.links,
|
|
212
|
+
options.startTime,
|
|
213
|
+
options.kind,
|
|
214
|
+
);
|
|
215
|
+
},
|
|
216
|
+
context(primitive, fiber) {
|
|
217
|
+
const currentSpan = fiber.currentSpan;
|
|
218
|
+
if (currentSpan === undefined || !isSentrySpan(currentSpan)) {
|
|
219
|
+
return primitive[EFFECT_EVALUATE](fiber);
|
|
220
|
+
}
|
|
221
|
+
return withActiveSpan(currentSpan.sentrySpan, () => primitive[EFFECT_EVALUATE](fiber));
|
|
222
|
+
},
|
|
135
223
|
});
|
|
224
|
+
};
|
|
136
225
|
|
|
137
226
|
/**
|
|
138
227
|
* Effect Layer that sets up the Sentry tracer for Effect spans.
|
|
139
228
|
*/
|
|
140
|
-
const SentryEffectTracer =
|
|
229
|
+
const SentryEffectTracer = isEffectV4 ? makeSentryTracerV4() : makeSentryTracerV3();
|
|
141
230
|
|
|
142
231
|
export { SentryEffectTracer };
|
|
143
232
|
//# sourceMappingURL=tracer.js.map
|
package/build/esm/tracer.js.map
CHANGED
|
@@ -1 +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":[],"mappings":"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"}
|
|
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\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 (\n cause &&\n typeof cause === 'object' &&\n 'reasons' in cause &&\n Array.isArray((cause as { reasons: unknown }).reasons)\n ) {\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 (cause && typeof cause === 'object' && '_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\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\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 (cause && typeof cause === 'object' && 'reasons' in cause) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n})();\n\nconst makeSentryTracerV3 = (): 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(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 = (): EffectTracer.Tracer => {\n const EFFECT_EVALUATE = '~effect/Effect/evaluate' as const;\n\n return EffectTracer.make({\n span(options) {\n return createSentrySpan(\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 * Effect Layer that sets up the Sentry tracer for Effect spans.\n */\nexport const SentryEffectTracer = isEffectV4 ? makeSentryTracerV4() : makeSentryTracerV3();\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAiBxC;;GAEG;AACH,eAAO,MAAM,kBAAkB,8BAuC7B,CAAC"}
|
package/build/types/metrics.d.ts
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
/**
|
|
3
|
-
* Creates a metrics flusher with its own isolated state for delta tracking.
|
|
4
|
-
* Useful for testing scenarios where you need to control the lifecycle.
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export declare function createMetricsFlusher(): {
|
|
8
|
-
flush: () => void;
|
|
9
|
-
clear: () => void;
|
|
10
|
-
};
|
|
1
|
+
import * as Layer from 'effect/Layer';
|
|
11
2
|
/**
|
|
12
3
|
* Effect Layer that periodically flushes metrics to Sentry.
|
|
13
4
|
* The layer manages its own state for delta counter calculations,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AA8KtC;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAYrE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../src/tracer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../src/tracer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAgP9C;;GAEG;AACH,eAAO,MAAM,kBAAkB,qBAA2D,CAAC"}
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import * as Layer from 'effect/Layer';
|
|
2
|
-
/**
|
|
3
|
-
* Creates a metrics flusher with its own isolated state for delta tracking.
|
|
4
|
-
* Useful for testing scenarios where you need to control the lifecycle.
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export declare function createMetricsFlusher(): {
|
|
8
|
-
flush: () => void;
|
|
9
|
-
clear: () => void;
|
|
10
|
-
};
|
|
11
2
|
/**
|
|
12
3
|
* Effect Layer that periodically flushes metrics to Sentry.
|
|
13
4
|
* The layer manages its own state for delta counter calculations,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/effect",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.50.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",
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"access": "public"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@sentry/browser": "10.
|
|
61
|
-
"@sentry/core": "10.
|
|
62
|
-
"@sentry/node-core": "10.
|
|
60
|
+
"@sentry/browser": "10.50.0",
|
|
61
|
+
"@sentry/core": "10.50.0",
|
|
62
|
+
"@sentry/node-core": "10.50.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"effect": "^3.0.0"
|
|
65
|
+
"effect": "^3.0.0 || ^4.0.0-beta.50"
|
|
66
66
|
},
|
|
67
67
|
"peerDependenciesMeta": {
|
|
68
68
|
"effect": {
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@effect/vitest": "^0.
|
|
74
|
-
"effect": "^
|
|
73
|
+
"@effect/vitest": "^4.0.0-beta.50",
|
|
74
|
+
"effect": "^4.0.0-beta.50"
|
|
75
75
|
},
|
|
76
76
|
"scripts": {
|
|
77
77
|
"build": "run-p build:transpile build:types",
|