@edraj/sauron-browser 1.4.1 → 1.6.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/CHANGELOG.md +64 -0
- package/README.md +140 -3
- package/dist/index.cjs +42 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -2
- package/dist/index.d.ts +65 -2
- package/dist/index.js +41 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,70 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@edraj/sauron-browser` are documented here.
|
|
4
4
|
|
|
5
|
+
## 1.6.0
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Navigation direction on history breadcrumbs.** SPA navigation breadcrumbs
|
|
10
|
+
now carry `operation` alongside `from` and `to`: `push` for
|
|
11
|
+
`history.pushState`, `replace` for `history.replaceState`, and `pop` for
|
|
12
|
+
`popstate`. A breadcrumb trail no longer reads the same whether the user
|
|
13
|
+
advanced through a flow or backed out of it.
|
|
14
|
+
|
|
15
|
+
The vocabulary is shared with the Flutter SDK's `SauronNavigatorObserver`
|
|
16
|
+
(`push` / `pop` / `replace` / `remove`), so a trail reads the same whichever
|
|
17
|
+
SDK sent it. `remove` has no web equivalent and is never emitted here.
|
|
18
|
+
|
|
19
|
+
**A forward navigation is recorded as `pop`.** `history.forward()` fires the
|
|
20
|
+
same `popstate` event as `history.back()` and carries nothing to separate
|
|
21
|
+
them, so `pop` means "moved through history" rather than specifically "went
|
|
22
|
+
back". Telling them apart would mean writing a counter into `history.state`,
|
|
23
|
+
which the host app's router also owns — not a trade this SDK makes to
|
|
24
|
+
improve a breadcrumb.
|
|
25
|
+
|
|
26
|
+
No API change: `operation` is added to `data` on breadcrumbs the SDK already
|
|
27
|
+
emitted, and the same-path guard still suppresses a `replaceState` to the
|
|
28
|
+
current URL before any direction is recorded.
|
|
29
|
+
|
|
30
|
+
## 1.5.0
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **`tags` and `extra` on transactions.** `trackTransaction` now accepts two
|
|
35
|
+
developer-supplied maps: `tags` (flat string→string, indexed) and `extra`
|
|
36
|
+
(freeform JSON). `extra` is where a request body, a response body, an order
|
|
37
|
+
id or a retry count goes — the span that times an HTTP call can now carry
|
|
38
|
+
what the call actually sent and received.
|
|
39
|
+
|
|
40
|
+
Both are visible on the new **Transactions** page and in the session
|
|
41
|
+
timeline, and both are searchable: `@tag.tier:premium`,
|
|
42
|
+
`extra.order_id:9001`, or `extra.response:~9001` to match a substring
|
|
43
|
+
*inside* a stored response body.
|
|
44
|
+
|
|
45
|
+
**They are per-call only.** Unlike `captureException` and `track`, a
|
|
46
|
+
transaction does not inherit the scope — `setTag()` / `setExtra()` defaults
|
|
47
|
+
are not merged in. Transactions are the highest-volume signal an app emits,
|
|
48
|
+
one per navigation and per request, so inheriting a global blob would write
|
|
49
|
+
it onto every row. This asymmetry is deliberate and is documented on the
|
|
50
|
+
method.
|
|
51
|
+
|
|
52
|
+
`extra` is serialized and capped at **16 KB**. Past that the whole map is
|
|
53
|
+
replaced with a `{"_truncated": true, "_bytes": N}` marker, and the
|
|
54
|
+
dashboard says so on the row rather than showing a short object that looks
|
|
55
|
+
complete. The cap is not cosmetic: envelopes are batched, and one oversized
|
|
56
|
+
body would push the whole envelope past the ingest limit and take every
|
|
57
|
+
unrelated span sent with it — a silent loss of data nobody asked about.
|
|
58
|
+
Size is measured in UTF-8 bytes, so non-ASCII payloads are counted at what
|
|
59
|
+
they actually cost on the wire.
|
|
60
|
+
|
|
61
|
+
Nothing in `extra` is scrubbed. `beforeSend` remains the redaction seam;
|
|
62
|
+
think twice before attaching a body that can carry tokens or personal data.
|
|
63
|
+
|
|
64
|
+
An app that sets neither field serializes byte-identically to before: both
|
|
65
|
+
keys are omitted when empty, never sent as `null`.
|
|
66
|
+
|
|
67
|
+
Signature: `trackTransaction({ …, tags?: Record<string, string>, extra?: Record<string, unknown> })`. `MAX_TRANSACTION_EXTRA_BYTES` and `capTransactionExtra` are now exported from the package entrypoint, so a caller can size a payload before attaching it.
|
|
68
|
+
|
|
5
69
|
## 1.4.1
|
|
6
70
|
|
|
7
71
|
### Added
|
package/README.md
CHANGED
|
@@ -358,10 +358,28 @@ function trackTransaction(input: TransactionInput): void
|
|
|
358
358
|
| `httpMethod` | `string \| null` | `null` | For `http` ops. |
|
|
359
359
|
| `httpStatus` | `number \| null` | `null` | For `http` ops. |
|
|
360
360
|
| `url` | `string \| null` | `null` | For `http` ops. |
|
|
361
|
+
| `tags` | `Record<string, string>` | omitted | Indexed string→string labels. Filter with `@tag.key:value` on the Transactions page. |
|
|
362
|
+
| `extra` | `Record<string, unknown>` | omitted | Freeform JSON — request body, response body, SQL text, row counts. Searchable with `extra.key:value`. |
|
|
361
363
|
|
|
362
364
|
The item is stamped with the current distinct id, session id and timestamp.
|
|
363
365
|
Never sampled. Returns `void`.
|
|
364
366
|
|
|
367
|
+
**`tags` and `extra` are per-call only.** Unlike `track()` and
|
|
368
|
+
`captureException()`, a transaction does **not** inherit the scope:
|
|
369
|
+
`setTag()` / `setExtra()` defaults are not merged in. Transactions are the
|
|
370
|
+
highest-volume signal a page emits — one per navigation and per fetch — so
|
|
371
|
+
inheriting a global blob would write it onto every row.
|
|
372
|
+
|
|
373
|
+
`extra` is serialized and capped at **16 KB** (`MAX_TRANSACTION_EXTRA_BYTES`).
|
|
374
|
+
Past that the whole map is replaced with `{ _truncated: true, _bytes: N }` and
|
|
375
|
+
the dashboard says so on the row. The cap is not cosmetic: envelopes are
|
|
376
|
+
batched, and one oversized body would push the whole envelope past the ingest
|
|
377
|
+
limit and drop every unrelated span sent with it. Size is measured in **UTF-8
|
|
378
|
+
bytes**, so a body of non-ASCII text counts what it will actually cost.
|
|
379
|
+
|
|
380
|
+
Nothing in `extra` is scrubbed. Use `beforeSend` for redaction, and think twice
|
|
381
|
+
before attaching a body that can carry tokens or personal data.
|
|
382
|
+
|
|
365
383
|
```ts
|
|
366
384
|
const started = performance.now();
|
|
367
385
|
const res = await fetch('/api/orders');
|
|
@@ -376,6 +394,115 @@ Sauron.trackTransaction({
|
|
|
376
394
|
});
|
|
377
395
|
```
|
|
378
396
|
|
|
397
|
+
#### Example: a `fetch` wrapper that records both bodies
|
|
398
|
+
|
|
399
|
+
Drop-in replacement for `fetch` on the calls you care about. Note the
|
|
400
|
+
`res.clone()` — reading the body consumes the stream, so the caller would get an
|
|
401
|
+
empty response otherwise.
|
|
402
|
+
|
|
403
|
+
```ts
|
|
404
|
+
import * as Sauron from '@edraj/sauron-browser';
|
|
405
|
+
|
|
406
|
+
export async function tracedFetch(
|
|
407
|
+
input: string,
|
|
408
|
+
init: RequestInit = {},
|
|
409
|
+
): Promise<Response> {
|
|
410
|
+
const method = (init.method ?? 'GET').toUpperCase();
|
|
411
|
+
const path = new URL(input, location.origin).pathname;
|
|
412
|
+
const started = performance.now();
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const res = await fetch(input, init);
|
|
416
|
+
// Clone BEFORE reading: a Response body is a one-shot stream, and
|
|
417
|
+
// consuming it here would hand the caller an empty one.
|
|
418
|
+
const responseBody = await res.clone().text();
|
|
419
|
+
|
|
420
|
+
Sauron.trackTransaction({
|
|
421
|
+
name: `${method} ${path}`, // grouping key — keep it low cardinality
|
|
422
|
+
op: 'http',
|
|
423
|
+
durationMs: performance.now() - started,
|
|
424
|
+
httpMethod: method,
|
|
425
|
+
httpStatus: res.status,
|
|
426
|
+
url: input,
|
|
427
|
+
status: res.ok ? 'ok' : 'error',
|
|
428
|
+
tags: { api: path.split('/')[2] ?? 'root' },
|
|
429
|
+
extra: {
|
|
430
|
+
request: typeof init.body === 'string' ? init.body : undefined,
|
|
431
|
+
response: responseBody,
|
|
432
|
+
response_bytes: responseBody.length,
|
|
433
|
+
},
|
|
434
|
+
});
|
|
435
|
+
return res;
|
|
436
|
+
} catch (err) {
|
|
437
|
+
Sauron.trackTransaction({
|
|
438
|
+
name: `${method} ${path}`,
|
|
439
|
+
op: 'http',
|
|
440
|
+
durationMs: performance.now() - started,
|
|
441
|
+
httpMethod: method,
|
|
442
|
+
url: input,
|
|
443
|
+
status: 'error',
|
|
444
|
+
extra: { request: init.body, error: String(err) },
|
|
445
|
+
});
|
|
446
|
+
throw err;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
On the dashboard: **Transactions → the row → expand**. Both bodies render as a
|
|
452
|
+
JSON tree, and every one of these finds it:
|
|
453
|
+
|
|
454
|
+
```text
|
|
455
|
+
extra.response:~9001 # substring, inside the stored response body
|
|
456
|
+
@tag.api:orders # indexed tag
|
|
457
|
+
op:http http.status:>=500 # the failures
|
|
458
|
+
duration:>2s # the slow ones
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### Example: a client-side SQL query (`sql.js` / `wa-sqlite`)
|
|
462
|
+
|
|
463
|
+
If your app runs SQLite in the browser, spans work the same way. Put the
|
|
464
|
+
**statement** in `extra` and keep `name` a stable label — a query with literals
|
|
465
|
+
baked in would mint a new dashboard row per execution.
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
function tracedQuery(db: Database, sql: string, params: unknown[] = []) {
|
|
469
|
+
const started = performance.now();
|
|
470
|
+
try {
|
|
471
|
+
const rows = db.exec(sql, params);
|
|
472
|
+
Sauron.trackTransaction({
|
|
473
|
+
// The LABEL, not the statement. `op` accepts only
|
|
474
|
+
// navigation|http|resource|screen_load|custom — anything else, `'db'`
|
|
475
|
+
// included, is coerced to 'custom', so pass 'custom' and say it with a tag.
|
|
476
|
+
name: 'SELECT orders',
|
|
477
|
+
op: 'custom',
|
|
478
|
+
durationMs: performance.now() - started,
|
|
479
|
+
status: 'ok',
|
|
480
|
+
tags: { db: 'sqlite', table: 'orders' },
|
|
481
|
+
extra: {
|
|
482
|
+
statement: sql,
|
|
483
|
+
row_count: rows[0]?.values.length ?? 0,
|
|
484
|
+
// Bind PARAMETERS are user data. Log them only if you have decided
|
|
485
|
+
// that is acceptable, or log their shape instead.
|
|
486
|
+
params,
|
|
487
|
+
},
|
|
488
|
+
});
|
|
489
|
+
return rows;
|
|
490
|
+
} catch (err) {
|
|
491
|
+
Sauron.trackTransaction({
|
|
492
|
+
name: 'SELECT orders',
|
|
493
|
+
op: 'custom',
|
|
494
|
+
durationMs: performance.now() - started,
|
|
495
|
+
status: 'error',
|
|
496
|
+
tags: { db: 'sqlite', table: 'orders' },
|
|
497
|
+
extra: { statement: sql, error: String(err) },
|
|
498
|
+
});
|
|
499
|
+
throw err;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Then `@tag.table:orders duration:>500ms` is your slow-query list.
|
|
505
|
+
|
|
379
506
|
### `setScreen(name)`
|
|
380
507
|
|
|
381
508
|
```ts
|
|
@@ -858,7 +985,7 @@ const appFrames = frames.filter((f) => isInAppFrame(f.filename));
|
|
|
858
985
|
|
|
859
986
|
```ts
|
|
860
987
|
const SDK_NAME: string // 'sauron.javascript'
|
|
861
|
-
const SDK_VERSION: string // '1.
|
|
988
|
+
const SDK_VERSION: string // '1.6.0'
|
|
862
989
|
```
|
|
863
990
|
|
|
864
991
|
The SDK identity embedded in `header.sdk` of every envelope.
|
|
@@ -900,7 +1027,7 @@ On by default:
|
|
|
900
1027
|
| `window.onunhandledrejection` | Error item from `event.reason`, mechanism `{ type: 'onunhandledrejection', handled: false }`, level `error`. |
|
|
901
1028
|
| `console.log/info/warn/error/debug` | Breadcrumb, category `console`, level mapped (`warn`→`warning`, `error`→`error`, `debug`→`debug`, else `info`), message = arguments joined and truncated to 512 chars, `data: { arguments: n }`. Output is untouched. |
|
|
902
1029
|
| `document` click listener (capture, passive) | Breadcrumb, category `ui.click`, message = a `tag#id.class` selector (up to 3 classes). Element text and attribute values are never serialized. |
|
|
903
|
-
| `history.pushState` / `replaceState` / `popstate` | Breadcrumb, type `navigation`, category `history`, `data: { from, to }`
|
|
1030
|
+
| `history.pushState` / `replaceState` / `popstate` | Breadcrumb, type `navigation`, category `history`, `data: { from, to, operation }` — paths plus the direction: `push`, `replace` or `pop`. Same-path transitions are skipped. |
|
|
904
1031
|
| `fetch` | Breadcrumb, category `fetch`, message `METHOD url`, `data: { method, url, status_code }`, level `warning` for status >= 400. |
|
|
905
1032
|
| `XMLHttpRequest.prototype.open` / `send` | Breadcrumb, category `xhr`, same shape as `fetch`. |
|
|
906
1033
|
| `document` `visibilitychange` + window `pagehide` | Beacon flush of the pending batch on unload. |
|
|
@@ -913,6 +1040,16 @@ Opt-in:
|
|
|
913
1040
|
| `performance: true` | A `navigation` transaction for the initial page load (Navigation Timing, captured on `load`), an `http` transaction per instrumented `fetch` (`name` = `METHOD /path`, `status` `ok`/`error`), and a `navigation` transaction per SPA route change measured over one animation frame. No-op when `document` is undefined. |
|
|
914
1041
|
| `screenTracking: true` | Sets the screen to the new path on each SPA History navigation, which emits a `$screen` event on change. |
|
|
915
1042
|
|
|
1043
|
+
`operation` uses the same vocabulary as the Flutter SDK's
|
|
1044
|
+
`SauronNavigatorObserver` (`push` / `pop` / `replace` / `remove`), so a trail
|
|
1045
|
+
reads the same whichever SDK sent it. `remove` has no web equivalent and is
|
|
1046
|
+
never emitted here. One limit worth knowing: **a forward navigation is recorded
|
|
1047
|
+
as `pop`.** `history.forward()` fires the same `popstate` event as
|
|
1048
|
+
`history.back()` and carries nothing to separate them, so `pop` means "moved
|
|
1049
|
+
through history", not specifically "went back". Distinguishing them would mean
|
|
1050
|
+
writing to `history.state`, which the host app's router also owns — not a
|
|
1051
|
+
trade the SDK makes.
|
|
1052
|
+
|
|
916
1053
|
Two guards keep the SDK from observing itself: a reentrancy flag held while SDK
|
|
917
1054
|
code runs, and a denylist on the DSN host. Requests the transport makes are
|
|
918
1055
|
therefore never turned into breadcrumbs or transactions. Wrappers are tagged, so
|
|
@@ -989,7 +1126,7 @@ Sauron.track('upgraded', {}, { tags: { tier: 'trial' } });
|
|
|
989
1126
|
|
|
990
1127
|
```html
|
|
991
1128
|
<script type="module">
|
|
992
|
-
import { Sauron } from 'https://esm.sh/@edraj/sauron-browser@1.
|
|
1129
|
+
import { Sauron } from 'https://esm.sh/@edraj/sauron-browser@1.6.0';
|
|
993
1130
|
Sauron.init({ dsn: 'https://pk_test@ingest.example.com/42' });
|
|
994
1131
|
</script>
|
|
995
1132
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -8,7 +8,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
8
8
|
|
|
9
9
|
// src/utils.ts
|
|
10
10
|
var SDK_NAME = "sauron.javascript";
|
|
11
|
-
var SDK_VERSION = "1.
|
|
11
|
+
var SDK_VERSION = "1.6.0";
|
|
12
12
|
function getGlobal() {
|
|
13
13
|
return globalThis;
|
|
14
14
|
}
|
|
@@ -87,6 +87,32 @@ function makeLogger(debug) {
|
|
|
87
87
|
warn: (...args) => console.warn("[sauron]", ...args)
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
+
var MAX_TRANSACTION_EXTRA_BYTES = 16 * 1024;
|
|
91
|
+
function capTransactionExtra(extra, maxBytes = MAX_TRANSACTION_EXTRA_BYTES) {
|
|
92
|
+
let bytes;
|
|
93
|
+
try {
|
|
94
|
+
const json = JSON.stringify(extra);
|
|
95
|
+
if (json === void 0) return { _truncated: true, _bytes: -1 };
|
|
96
|
+
bytes = utf8Length(json);
|
|
97
|
+
} catch {
|
|
98
|
+
return { _truncated: true, _bytes: -1 };
|
|
99
|
+
}
|
|
100
|
+
if (bytes <= maxBytes) return extra;
|
|
101
|
+
return { _truncated: true, _bytes: bytes };
|
|
102
|
+
}
|
|
103
|
+
function utf8Length(s) {
|
|
104
|
+
let n = 0;
|
|
105
|
+
for (let i = 0; i < s.length; i++) {
|
|
106
|
+
const c = s.charCodeAt(i);
|
|
107
|
+
if (c < 128) n += 1;
|
|
108
|
+
else if (c < 2048) n += 2;
|
|
109
|
+
else if (c >= 55296 && c <= 56319) {
|
|
110
|
+
n += 4;
|
|
111
|
+
i++;
|
|
112
|
+
} else n += 3;
|
|
113
|
+
}
|
|
114
|
+
return n;
|
|
115
|
+
}
|
|
90
116
|
|
|
91
117
|
// src/identity.ts
|
|
92
118
|
var DEVICE_ID_KEY = "sauron.device_id";
|
|
@@ -817,12 +843,12 @@ function installHistory() {
|
|
|
817
843
|
const loc = g2.location;
|
|
818
844
|
if (!hist) return;
|
|
819
845
|
let lastPath = toPath(loc?.href ?? null, loc?.href);
|
|
820
|
-
const emit = (toHref) => {
|
|
846
|
+
const emit = (toHref, operation) => {
|
|
821
847
|
const to = toPath(toHref, loc?.href);
|
|
822
848
|
const from = lastPath;
|
|
823
849
|
lastPath = to;
|
|
824
850
|
if (from === to) return;
|
|
825
|
-
withInternal(() => addNavigationBreadcrumb(from, to));
|
|
851
|
+
withInternal(() => addNavigationBreadcrumb(from, to, operation));
|
|
826
852
|
if (to && navHandler) {
|
|
827
853
|
try {
|
|
828
854
|
navHandler(to);
|
|
@@ -833,11 +859,12 @@ function installHistory() {
|
|
|
833
859
|
const wrap = (name) => {
|
|
834
860
|
const original = hist[name];
|
|
835
861
|
if (typeof original !== "function" || isWrapped(original)) return;
|
|
862
|
+
const operation = name === "pushState" ? "push" : "replace";
|
|
836
863
|
hist[name] = markWrapped(function sauronHistory(...args) {
|
|
837
864
|
const result = original.apply(this, args);
|
|
838
865
|
if (!isInternal()) {
|
|
839
866
|
const urlArg = args[2];
|
|
840
|
-
emit(urlArg != null ? String(urlArg) : loc?.href ?? null);
|
|
867
|
+
emit(urlArg != null ? String(urlArg) : loc?.href ?? null, operation);
|
|
841
868
|
}
|
|
842
869
|
return result;
|
|
843
870
|
});
|
|
@@ -849,7 +876,7 @@ function installHistory() {
|
|
|
849
876
|
wrap("replaceState");
|
|
850
877
|
if (typeof g2.addEventListener === "function") {
|
|
851
878
|
const onPopState = () => {
|
|
852
|
-
if (!isInternal()) emit(loc?.href ?? null);
|
|
879
|
+
if (!isInternal()) emit(loc?.href ?? null, "pop");
|
|
853
880
|
};
|
|
854
881
|
g2.addEventListener("popstate", onPopState);
|
|
855
882
|
registerPatch("popstate", () => {
|
|
@@ -1026,7 +1053,7 @@ function normalizeOp(op) {
|
|
|
1026
1053
|
return op && TRANSACTION_OPS.includes(op) ? op : "custom";
|
|
1027
1054
|
}
|
|
1028
1055
|
function buildTransactionItem(input, distinctId, sessionId2) {
|
|
1029
|
-
|
|
1056
|
+
const item = {
|
|
1030
1057
|
type: "transaction",
|
|
1031
1058
|
name: input.name,
|
|
1032
1059
|
op: normalizeOp(input.op),
|
|
@@ -1039,6 +1066,11 @@ function buildTransactionItem(input, distinctId, sessionId2) {
|
|
|
1039
1066
|
session_id: sessionId2,
|
|
1040
1067
|
timestamp: nowIso()
|
|
1041
1068
|
};
|
|
1069
|
+
if (input.tags && Object.keys(input.tags).length > 0) item.tags = { ...input.tags };
|
|
1070
|
+
if (input.extra && Object.keys(input.extra).length > 0) {
|
|
1071
|
+
item.extra = capTransactionExtra({ ...input.extra });
|
|
1072
|
+
}
|
|
1073
|
+
return item;
|
|
1042
1074
|
}
|
|
1043
1075
|
function trackTransaction(input) {
|
|
1044
1076
|
const client = getClient();
|
|
@@ -2195,13 +2227,13 @@ function addBreadcrumb(input, hint) {
|
|
|
2195
2227
|
if (!client) return;
|
|
2196
2228
|
client.addBreadcrumb(normalizeBreadcrumb(input), hint);
|
|
2197
2229
|
}
|
|
2198
|
-
function addNavigationBreadcrumb(from, to) {
|
|
2230
|
+
function addNavigationBreadcrumb(from, to, operation = "push") {
|
|
2199
2231
|
addBreadcrumb({
|
|
2200
2232
|
type: "navigation",
|
|
2201
2233
|
category: "history",
|
|
2202
2234
|
level: "info",
|
|
2203
2235
|
message: null,
|
|
2204
|
-
data: { from, to }
|
|
2236
|
+
data: { from, to, operation }
|
|
2205
2237
|
});
|
|
2206
2238
|
}
|
|
2207
2239
|
|
|
@@ -2302,6 +2334,7 @@ var Sauron = {
|
|
|
2302
2334
|
var index_default = Sauron;
|
|
2303
2335
|
|
|
2304
2336
|
exports.DsnError = DsnError;
|
|
2337
|
+
exports.MAX_TRANSACTION_EXTRA_BYTES = MAX_TRANSACTION_EXTRA_BYTES;
|
|
2305
2338
|
exports.SDK_NAME = SDK_NAME;
|
|
2306
2339
|
exports.SDK_VERSION = SDK_VERSION;
|
|
2307
2340
|
exports.Sauron = Sauron;
|
|
@@ -2309,6 +2342,7 @@ exports.SauronClient = SauronClient;
|
|
|
2309
2342
|
exports.addBreadcrumb = addBreadcrumb2;
|
|
2310
2343
|
exports.buildEnvelope = buildEnvelope;
|
|
2311
2344
|
exports.cancelWorkflow = cancelWorkflow2;
|
|
2345
|
+
exports.capTransactionExtra = capTransactionExtra;
|
|
2312
2346
|
exports.captureException = captureException2;
|
|
2313
2347
|
exports.captureMessage = captureMessage2;
|
|
2314
2348
|
exports.close = close;
|