@edraj/sauron-browser 1.4.1 → 1.5.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/dist/index.d.cts CHANGED
@@ -144,6 +144,19 @@ interface TransactionItem {
144
144
  workflow_id?: string;
145
145
  workflow_name?: string;
146
146
  timestamp: string;
147
+ /**
148
+ * Developer-supplied flat string tags for THIS transaction.
149
+ *
150
+ * Unlike {@link EventItem} and the error item, this is NOT merged with the
151
+ * scope — see {@link TransactionInput.tags}. Omitted entirely when empty.
152
+ */
153
+ tags?: Record<string, string>;
154
+ /**
155
+ * Developer-supplied freeform JSON for THIS transaction — the request body,
156
+ * the response body, a retry count. Capped and replaced with a truncation
157
+ * marker past {@link MAX_TRANSACTION_EXTRA_BYTES}. Omitted when empty.
158
+ */
159
+ extra?: Record<string, unknown>;
147
160
  }
148
161
  /** An identity association (PostHog-style `identify`). */
149
162
  interface IdentifyItem {
@@ -330,6 +343,29 @@ interface TransactionInput {
330
343
  httpMethod?: string | null;
331
344
  httpStatus?: number | null;
332
345
  url?: string | null;
346
+ /**
347
+ * Flat string tags for this transaction.
348
+ *
349
+ * **Per-call only — the scope is NOT merged in**, which is the one place
350
+ * transactions differ from `track()` and `captureException()`. Those two
351
+ * merge `setTag`/`setExtra` defaults; a transaction carries only what its own
352
+ * call site attached. Transactions are the highest-volume signal (one per
353
+ * navigation and per HTTP call), so inheriting a global blob would write it
354
+ * onto every row.
355
+ */
356
+ tags?: Record<string, string>;
357
+ /**
358
+ * Freeform JSON for this transaction — the request body, the response body,
359
+ * an order id, a retry count.
360
+ *
361
+ * Per-call only, for the reason on {@link TransactionInput.tags}. Serialized
362
+ * and capped at {@link MAX_TRANSACTION_EXTRA_BYTES}; past that the whole map
363
+ * is replaced with `{ _truncated: true, _bytes: N }` so one large body cannot
364
+ * take a batched envelope over the ingest limit and drop every span in it.
365
+ *
366
+ * Nothing here is scrubbed. `beforeSend` is the redaction seam.
367
+ */
368
+ extra?: Record<string, unknown>;
333
369
  }
334
370
 
335
371
  /**
@@ -561,7 +597,34 @@ declare function parseError(err: unknown): Frame[];
561
597
  /** Small dependency-free helpers shared across the SDK. */
562
598
  /** SDK identity, embedded in every envelope header. */
563
599
  declare const SDK_NAME = "sauron.javascript";
564
- declare const SDK_VERSION = "1.4.1";
600
+ declare const SDK_VERSION = "1.5.0";
601
+ /**
602
+ * Largest serialized `extra` a single transaction may carry, in bytes.
603
+ *
604
+ * Transactions are the highest-volume signal and they ship in BATCHED
605
+ * envelopes, so one oversized payload does not fail alone — ingest rejects the
606
+ * whole envelope past `INGEST_MAX_BODY_BYTES` (1 MiB by default) and every
607
+ * unrelated span batched with it is lost. Since the motivating use of
608
+ * transaction `extra` is request and response bodies, that is not a remote
609
+ * hazard.
610
+ */
611
+ declare const MAX_TRANSACTION_EXTRA_BYTES: number;
612
+ /**
613
+ * Cap a transaction's `extra`, substituting a marker when it is too large.
614
+ *
615
+ * Replaces the WHOLE map rather than trimming keys: a half-written JSON value
616
+ * is worse than an honest marker, and per-key trimming would make the result
617
+ * depend on key iteration order, which differs across the five SDKs. The
618
+ * marker is deliberately readable on the dashboard — `_truncated` says data
619
+ * was dropped rather than silently serving a short object that looks complete.
620
+ *
621
+ * Returns the input unchanged when it fits. A value that cannot be serialized
622
+ * at all (a cycle, a BigInt) is replaced by the same marker with `_bytes: -1`,
623
+ * because the alternative is throwing from inside `trackTransaction` — and an
624
+ * SDK that crashes the app it is measuring is worse than one that drops a
625
+ * payload.
626
+ */
627
+ declare function capTransactionExtra(extra: Record<string, unknown>, maxBytes?: number): Record<string, unknown>;
565
628
 
566
629
  /**
567
630
  * `@edraj/sauron-browser` — public API surface.
@@ -673,4 +736,4 @@ declare const Sauron: {
673
736
  getClient: typeof getClient;
674
737
  };
675
738
 
676
- export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
739
+ export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, MAX_TRANSACTION_EXTRA_BYTES, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, capTransactionExtra, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
package/dist/index.d.ts CHANGED
@@ -144,6 +144,19 @@ interface TransactionItem {
144
144
  workflow_id?: string;
145
145
  workflow_name?: string;
146
146
  timestamp: string;
147
+ /**
148
+ * Developer-supplied flat string tags for THIS transaction.
149
+ *
150
+ * Unlike {@link EventItem} and the error item, this is NOT merged with the
151
+ * scope — see {@link TransactionInput.tags}. Omitted entirely when empty.
152
+ */
153
+ tags?: Record<string, string>;
154
+ /**
155
+ * Developer-supplied freeform JSON for THIS transaction — the request body,
156
+ * the response body, a retry count. Capped and replaced with a truncation
157
+ * marker past {@link MAX_TRANSACTION_EXTRA_BYTES}. Omitted when empty.
158
+ */
159
+ extra?: Record<string, unknown>;
147
160
  }
148
161
  /** An identity association (PostHog-style `identify`). */
149
162
  interface IdentifyItem {
@@ -330,6 +343,29 @@ interface TransactionInput {
330
343
  httpMethod?: string | null;
331
344
  httpStatus?: number | null;
332
345
  url?: string | null;
346
+ /**
347
+ * Flat string tags for this transaction.
348
+ *
349
+ * **Per-call only — the scope is NOT merged in**, which is the one place
350
+ * transactions differ from `track()` and `captureException()`. Those two
351
+ * merge `setTag`/`setExtra` defaults; a transaction carries only what its own
352
+ * call site attached. Transactions are the highest-volume signal (one per
353
+ * navigation and per HTTP call), so inheriting a global blob would write it
354
+ * onto every row.
355
+ */
356
+ tags?: Record<string, string>;
357
+ /**
358
+ * Freeform JSON for this transaction — the request body, the response body,
359
+ * an order id, a retry count.
360
+ *
361
+ * Per-call only, for the reason on {@link TransactionInput.tags}. Serialized
362
+ * and capped at {@link MAX_TRANSACTION_EXTRA_BYTES}; past that the whole map
363
+ * is replaced with `{ _truncated: true, _bytes: N }` so one large body cannot
364
+ * take a batched envelope over the ingest limit and drop every span in it.
365
+ *
366
+ * Nothing here is scrubbed. `beforeSend` is the redaction seam.
367
+ */
368
+ extra?: Record<string, unknown>;
333
369
  }
334
370
 
335
371
  /**
@@ -561,7 +597,34 @@ declare function parseError(err: unknown): Frame[];
561
597
  /** Small dependency-free helpers shared across the SDK. */
562
598
  /** SDK identity, embedded in every envelope header. */
563
599
  declare const SDK_NAME = "sauron.javascript";
564
- declare const SDK_VERSION = "1.4.1";
600
+ declare const SDK_VERSION = "1.5.0";
601
+ /**
602
+ * Largest serialized `extra` a single transaction may carry, in bytes.
603
+ *
604
+ * Transactions are the highest-volume signal and they ship in BATCHED
605
+ * envelopes, so one oversized payload does not fail alone — ingest rejects the
606
+ * whole envelope past `INGEST_MAX_BODY_BYTES` (1 MiB by default) and every
607
+ * unrelated span batched with it is lost. Since the motivating use of
608
+ * transaction `extra` is request and response bodies, that is not a remote
609
+ * hazard.
610
+ */
611
+ declare const MAX_TRANSACTION_EXTRA_BYTES: number;
612
+ /**
613
+ * Cap a transaction's `extra`, substituting a marker when it is too large.
614
+ *
615
+ * Replaces the WHOLE map rather than trimming keys: a half-written JSON value
616
+ * is worse than an honest marker, and per-key trimming would make the result
617
+ * depend on key iteration order, which differs across the five SDKs. The
618
+ * marker is deliberately readable on the dashboard — `_truncated` says data
619
+ * was dropped rather than silently serving a short object that looks complete.
620
+ *
621
+ * Returns the input unchanged when it fits. A value that cannot be serialized
622
+ * at all (a cycle, a BigInt) is replaced by the same marker with `_bytes: -1`,
623
+ * because the alternative is throwing from inside `trackTransaction` — and an
624
+ * SDK that crashes the app it is measuring is worse than one that drops a
625
+ * payload.
626
+ */
627
+ declare function capTransactionExtra(extra: Record<string, unknown>, maxBytes?: number): Record<string, unknown>;
565
628
 
566
629
  /**
567
630
  * `@edraj/sauron-browser` — public API surface.
@@ -673,4 +736,4 @@ declare const Sauron: {
673
736
  getClient: typeof getClient;
674
737
  };
675
738
 
676
- export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
739
+ export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, MAX_TRANSACTION_EXTRA_BYTES, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, capTransactionExtra, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
4
4
 
5
5
  // src/utils.ts
6
6
  var SDK_NAME = "sauron.javascript";
7
- var SDK_VERSION = "1.4.1";
7
+ var SDK_VERSION = "1.5.0";
8
8
  function getGlobal() {
9
9
  return globalThis;
10
10
  }
@@ -83,6 +83,32 @@ function makeLogger(debug) {
83
83
  warn: (...args) => console.warn("[sauron]", ...args)
84
84
  };
85
85
  }
86
+ var MAX_TRANSACTION_EXTRA_BYTES = 16 * 1024;
87
+ function capTransactionExtra(extra, maxBytes = MAX_TRANSACTION_EXTRA_BYTES) {
88
+ let bytes;
89
+ try {
90
+ const json = JSON.stringify(extra);
91
+ if (json === void 0) return { _truncated: true, _bytes: -1 };
92
+ bytes = utf8Length(json);
93
+ } catch {
94
+ return { _truncated: true, _bytes: -1 };
95
+ }
96
+ if (bytes <= maxBytes) return extra;
97
+ return { _truncated: true, _bytes: bytes };
98
+ }
99
+ function utf8Length(s) {
100
+ let n = 0;
101
+ for (let i = 0; i < s.length; i++) {
102
+ const c = s.charCodeAt(i);
103
+ if (c < 128) n += 1;
104
+ else if (c < 2048) n += 2;
105
+ else if (c >= 55296 && c <= 56319) {
106
+ n += 4;
107
+ i++;
108
+ } else n += 3;
109
+ }
110
+ return n;
111
+ }
86
112
 
87
113
  // src/identity.ts
88
114
  var DEVICE_ID_KEY = "sauron.device_id";
@@ -1022,7 +1048,7 @@ function normalizeOp(op) {
1022
1048
  return op && TRANSACTION_OPS.includes(op) ? op : "custom";
1023
1049
  }
1024
1050
  function buildTransactionItem(input, distinctId, sessionId2) {
1025
- return {
1051
+ const item = {
1026
1052
  type: "transaction",
1027
1053
  name: input.name,
1028
1054
  op: normalizeOp(input.op),
@@ -1035,6 +1061,11 @@ function buildTransactionItem(input, distinctId, sessionId2) {
1035
1061
  session_id: sessionId2,
1036
1062
  timestamp: nowIso()
1037
1063
  };
1064
+ if (input.tags && Object.keys(input.tags).length > 0) item.tags = { ...input.tags };
1065
+ if (input.extra && Object.keys(input.extra).length > 0) {
1066
+ item.extra = capTransactionExtra({ ...input.extra });
1067
+ }
1068
+ return item;
1038
1069
  }
1039
1070
  function trackTransaction(input) {
1040
1071
  const client = getClient();
@@ -2297,6 +2328,6 @@ var Sauron = {
2297
2328
  };
2298
2329
  var index_default = Sauron;
2299
2330
 
2300
- export { DsnError, SDK_NAME, SDK_VERSION, Sauron, SauronClient, addBreadcrumb2 as addBreadcrumb, buildEnvelope, cancelWorkflow2 as cancelWorkflow, captureException2 as captureException, captureMessage2 as captureMessage, close, index_default as default, endWorkflow2 as endWorkflow, flush, getClient, getScreen2 as getScreen, getWorkflow2 as getWorkflow, identify2 as identify, init2 as init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen2 as setScreen, setTag, setTags, setUser, startWorkflow2 as startWorkflow, track2 as track, trackTransaction2 as trackTransaction };
2331
+ export { DsnError, MAX_TRANSACTION_EXTRA_BYTES, SDK_NAME, SDK_VERSION, Sauron, SauronClient, addBreadcrumb2 as addBreadcrumb, buildEnvelope, cancelWorkflow2 as cancelWorkflow, capTransactionExtra, captureException2 as captureException, captureMessage2 as captureMessage, close, index_default as default, endWorkflow2 as endWorkflow, flush, getClient, getScreen2 as getScreen, getWorkflow2 as getWorkflow, identify2 as identify, init2 as init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen2 as setScreen, setTag, setTags, setUser, startWorkflow2 as startWorkflow, track2 as track, trackTransaction2 as trackTransaction };
2301
2332
  //# sourceMappingURL=index.js.map
2302
2333
  //# sourceMappingURL=index.js.map