@groundcover/browser 2.1.1-rc.1 → 2.2.0-rc.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 +71 -8
- package/LICENSE +2 -0
- package/README.md +19 -3
- package/THIRD_PARTY_NOTICES.md +68 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +6 -13
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,72 @@ All notable changes to `@groundcover/browser` are documented here. This project
|
|
|
4
4
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the
|
|
5
5
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
|
|
6
6
|
|
|
7
|
-
## [2.
|
|
7
|
+
## [2.2.0-rc.0] — 2026-11-05
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
First release candidate of `2.2.0`. Issues for thrown or rejected values that aren't `Error`s start
|
|
10
|
+
new groups once; see Changed.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Third-party notices.** The package now ships `THIRD_PARTY_NOTICES.md` with the MIT notices of
|
|
15
|
+
fflate and `@rrweb/packer`, whose code its session-replay compression worker bundles.
|
|
16
|
+
- **Unhandled rejections of Bluebird promises are reported.** Bluebird announces an unhandled
|
|
17
|
+
rejection with its own `unhandledrejection` event, which the SDK ignored; it is now reported by
|
|
18
|
+
its reason, like a native one.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **`captureException` accepts any value, not only an `Error`.** A string, object or other value was
|
|
23
|
+
dropped without a word; it is now reported as an exception with `error_type` `Error`. A string or
|
|
24
|
+
number is its own message. An object is described by its shape, never its values, so captures of
|
|
25
|
+
the same kind group as one issue even when a field such as a request id changes:
|
|
26
|
+
`Object captured as exception with keys: code, requestId`, the class name for a class instance
|
|
27
|
+
(`Response captured as exception`), and an item count for an array. The value itself is sent in
|
|
28
|
+
`error_metadata.captured_value` as JSON, redacted field by field and cut at 10,000 characters. An
|
|
29
|
+
object with a string `message` keeps its own name, message and stack, and a DOM Event, such as an
|
|
30
|
+
image's `error` event, is described by its type and target
|
|
31
|
+
(`Event captured as exception (type=error, target=img)`).
|
|
32
|
+
- **`captureException` takes `unknown`.** Existing calls still compile, but a typed stand-in for it
|
|
33
|
+
written as `(error: Error) => …`, such as a test mock, no longer type-checks.
|
|
34
|
+
- **Thrown objects and rejection reasons that aren't `Error`s are described the same way.** A
|
|
35
|
+
rejection's reason was reported as its JSON, and a thrown object without a `message` as
|
|
36
|
+
`Unknown error`; both are now described by their shape
|
|
37
|
+
(`Object captured as promise rejection with keys: code`), with the value in
|
|
38
|
+
`error_metadata.captured_value`. Issues for such values start new groups once.
|
|
39
|
+
- **`error_message` is capped at 10,000 characters**, as log messages are. The fingerprint, made
|
|
40
|
+
from the first 400 characters, is unchanged.
|
|
41
|
+
- **The SDK no longer adds properties to your `Error` objects.** It defined read-only `fileName`,
|
|
42
|
+
`lineNumber` and `columnNumber` on every uncaught `Error` in Chromium and Safari, and nothing read
|
|
43
|
+
them.
|
|
44
|
+
- **`maskErrors` is documented as it works.** It redacts error messages and metadata; stack frames
|
|
45
|
+
are sent as they are.
|
|
46
|
+
- **The package `homepage` is the current documentation URL**, and the package's LICENSE carries its
|
|
47
|
+
copyright line.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- **An uncaught throw of a non-`Error` value is reported at its throw site.** `throw "boom"` or
|
|
52
|
+
`throw 0` outside a promise made the SDK's error listener fail, so the error was dropped. It is now
|
|
53
|
+
an exception with the message `boom` and one stack frame at the location the browser reported.
|
|
54
|
+
- **An uncaught error whose message contains "Script error" is reported.** The SDK dropped every
|
|
55
|
+
such error, such as RequireJS's `Script error for "<module>"`; it now drops only the browser's
|
|
56
|
+
muted cross-origin `Script error.`, which carries nothing to report.
|
|
57
|
+
- **An unhandled rejection whose reason can't be serialized is reported.** A rejection with a
|
|
58
|
+
circular object as its reason made the SDK fail, so it was dropped.
|
|
59
|
+
- **A rejection reason's nested secrets are redacted.** Its JSON was scrubbed as free text, which
|
|
60
|
+
masked only the first line under a sensitive key such as `token` or `credit_card`; the reason is
|
|
61
|
+
now redacted field by field.
|
|
62
|
+
- **An `Error` from another frame keeps its name and message as a rejection reason.** A same-origin
|
|
63
|
+
iframe's `Error` failed the SDK's `instanceof Error` check and was reported as `{}`.
|
|
64
|
+
|
|
65
|
+
## [2.1.1] — 2026-10-26
|
|
66
|
+
|
|
67
|
+
Stable release of `2.1.1-rc.1`. Session replay takes its periodic full snapshot every 5 minutes
|
|
68
|
+
instead of every 30 seconds. No configuration or API changes from `2.1.0`. `2.1.1-rc.0`, which tried
|
|
69
|
+
moving checkouts to idle time instead, was not pursued.
|
|
70
|
+
|
|
71
|
+
The type declarations are byte-for-byte those of `2.1.0` and rc.1. The shipped JavaScript differs
|
|
72
|
+
from rc.1 only in the text of the removed-option warnings below.
|
|
12
73
|
|
|
13
74
|
### Changed
|
|
14
75
|
|
|
@@ -20,6 +81,11 @@ every 5 minutes instead of every 30 seconds. No configuration or API changes. Su
|
|
|
20
81
|
send 10× fewer full snapshots. Every recording still starts with a full snapshot. A player that
|
|
21
82
|
seeks from the nearest earlier full snapshot may fetch more data to reach a point deep in a long
|
|
22
83
|
recording.
|
|
84
|
+
- **The warnings for removed options point to this package's README on npm.** The console warnings
|
|
85
|
+
for `enableMasking`, `maskFields` and `eventSampleRate` now name the README section to read
|
|
86
|
+
("Migrating to 1.0.0" or "Migrating from 1.x to 2.0.0") and link to the npm package page, instead
|
|
87
|
+
of a GitHub link.
|
|
88
|
+
- `package.json` no longer has `repository` and `bugs` fields.
|
|
23
89
|
|
|
24
90
|
## [2.1.0] — 2026-10-12
|
|
25
91
|
|
|
@@ -252,7 +318,7 @@ golden wire format, `attributes.location` intact, zero console errors).
|
|
|
252
318
|
|
|
253
319
|
### Fixed
|
|
254
320
|
|
|
255
|
-
- **Fetch response bodies are now hardened like request bodies
|
|
321
|
+
- **Fetch response bodies are now hardened like request bodies.** Responses are classified
|
|
256
322
|
by content-type (binary → placeholder, no mojibake) and their read is bounded by a timeout, so a
|
|
257
323
|
slow or never-ending response stream can no longer stall the network event. An over-cap response is
|
|
258
324
|
placeholdered instead of emitting an unredactable truncated slice.
|
|
@@ -325,6 +391,3 @@ These shipped ahead of 1.0.0 and are part of this major:
|
|
|
325
391
|
worker, with a transparent main-thread fallback under strict CSP / sandboxed iframes / SSR.
|
|
326
392
|
- **Configurable, lazily-enforced `sessionMaxDuration`** (default 4h, range 1 min–8h) plus 30-minute
|
|
327
393
|
inactivity-gap session rotation.
|
|
328
|
-
|
|
329
|
-
[1.0.1]: https://github.com/groundcover-com/rum/releases/tag/1.0.1
|
|
330
|
-
[1.0.0]: https://github.com/groundcover-com/rum/releases/tag/1.0.0
|
package/LICENSE
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
+
Copyright (c) 2025 groundcover
|
|
4
|
+
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
6
|
this software and associated documentation files (the "Software"), to deal in
|
|
5
7
|
the Software without restriction, including without limitation the rights to
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ application — with privacy masking **on by default**.
|
|
|
15
15
|
|
|
16
16
|
> Session replay is powered by [**rrweb**](https://github.com/rrweb-io/rrweb) under the hood.
|
|
17
17
|
|
|
18
|
-
See the [groundcover RUM documentation](https://docs.groundcover.com/
|
|
18
|
+
See the [groundcover RUM documentation](https://docs.groundcover.com/investigate/real-user-monitoring-rum)
|
|
19
19
|
for the full product guide.
|
|
20
20
|
|
|
21
21
|
---
|
|
@@ -351,7 +351,7 @@ and static page text stay visible; use `[data-private]` / `maskSelectors` to mas
|
|
|
351
351
|
| `maskNetworkBodies` | `boolean` | `true` | Redact network request/response bodies. |
|
|
352
352
|
| `maskNetworkQueryParams` | `boolean` | `true` | Redact URL query params. |
|
|
353
353
|
| `maskLogs` | `boolean` | `true` | Redact console/log messages and attributes. |
|
|
354
|
-
| `maskErrors` | `boolean` | `true` | Redact error messages
|
|
354
|
+
| `maskErrors` | `boolean` | `true` | Redact error messages and metadata. Stack frames are sent as they are. |
|
|
355
355
|
| `sensitiveKeys` | `string[]` | — | Extra case-insensitive key substrings treated as sensitive, merged with built-ins. |
|
|
356
356
|
| `redact` | `(field) => value \| undefined` | — | Per-leaf custom redactor for non-replay events. Return `undefined` to defer to the SDK default. |
|
|
357
357
|
| `replay.maskTextFn` | `(text, el) => string` | — | rrweb `maskTextFn` pass-through (replay only). |
|
|
@@ -545,7 +545,7 @@ All methods are available on the default export and on `window.groundcover`.
|
|
|
545
545
|
| `init(config)` | Initialize the SDK and install instrumentation once; calls after successful initialization are ignored. |
|
|
546
546
|
| `identifyUser(user)` | Attach user identity to subsequent events. |
|
|
547
547
|
| `sendCustomEvent({ event, attributes })` | Emit a custom business event. |
|
|
548
|
-
| `captureException(error, metadata?)` | Capture a handled error with optional context. |
|
|
548
|
+
| `captureException(error, metadata?)` | Capture a handled error (any value) with optional context. |
|
|
549
549
|
| `logger.{log,info,warn,error,debug,trace}(message, attributes?)` | Structured logging (see below). |
|
|
550
550
|
| `updateConfig({ options?, user?, … })` | Update config at runtime (merges nested groups one level deep). |
|
|
551
551
|
| `startNavigation(metadata)` / `endNavigation(metadata)` | Manual navigation spans (when `navigation` isn’t auto-tracked). |
|
|
@@ -587,6 +587,22 @@ groundcover.captureException(new Error("Payment failed"), {
|
|
|
587
587
|
});
|
|
588
588
|
```
|
|
589
589
|
|
|
590
|
+
`captureException` accepts any value, not only an `Error`. A string or number becomes the message.
|
|
591
|
+
An object is described by its shape, never its values, so captures of the same kind group as one
|
|
592
|
+
issue: `Object captured as exception with keys: code, reason`, the class name for a class instance
|
|
593
|
+
(`Response captured as exception`), or an item count for an array. The value itself is sent in
|
|
594
|
+
`error_metadata.captured_value` as JSON, redacted field by field and cut at 10,000 characters. An
|
|
595
|
+
object with a string `message` keeps its own name, message and stack, and a DOM Event is described
|
|
596
|
+
by its type and target (`Event captured as exception (type=error, target=img)`):
|
|
597
|
+
|
|
598
|
+
```ts
|
|
599
|
+
groundcover.captureException("Payment failed");
|
|
600
|
+
groundcover.captureException({ code: 500, reason: "timeout" });
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
Pass an `Error` when you can: a value that isn't one carries no stack trace of its own, so the
|
|
604
|
+
reported stack starts inside the SDK.
|
|
605
|
+
|
|
590
606
|
---
|
|
591
607
|
|
|
592
608
|
## Migrating from 1.x to 2.0.0
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
`@groundcover/browser` is licensed under the MIT License (see [LICENSE](LICENSE)).
|
|
4
|
+
|
|
5
|
+
The session-replay compression worker, which ships inlined in `dist/`, contains code from the
|
|
6
|
+
open-source projects below, whose notices follow.
|
|
7
|
+
|
|
8
|
+
The package's npm dependencies (`rrweb`, `@rrweb/packer`, `fflate`, `error-stack-parser` and
|
|
9
|
+
`web-vitals`) are installed alongside it under their own licenses and are not covered here.
|
|
10
|
+
|
|
11
|
+
## fflate
|
|
12
|
+
|
|
13
|
+
<https://github.com/101arrowz/fflate>. The worker calls it directly (0.8), and `@rrweb/packer`
|
|
14
|
+
carries its own copy (0.4). The two releases carry the same license, with copyright years 2023
|
|
15
|
+
and 2020 respectively.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
MIT License
|
|
19
|
+
|
|
20
|
+
Copyright (c) 2023 Arjun Barrett
|
|
21
|
+
Copyright (c) 2020 Arjun Barrett
|
|
22
|
+
|
|
23
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
24
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
25
|
+
in the Software without restriction, including without limitation the rights
|
|
26
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
27
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
28
|
+
furnished to do so, subject to the following conditions:
|
|
29
|
+
|
|
30
|
+
The above copyright notice and this permission notice shall be included in all
|
|
31
|
+
copies or substantial portions of the Software.
|
|
32
|
+
|
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
34
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
35
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
36
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
37
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
38
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
39
|
+
SOFTWARE.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## @rrweb/packer
|
|
43
|
+
|
|
44
|
+
<https://github.com/rrweb-io/rrweb>, the package the worker uses to pack session-replay events.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
MIT License
|
|
48
|
+
|
|
49
|
+
Copyright (c) 2018 Contributors (https://github.com/rrweb-io/rrweb/graphs/contributors)
|
|
50
|
+
|
|
51
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
52
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
53
|
+
in the Software without restriction, including without limitation the rights
|
|
54
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
55
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
56
|
+
furnished to do so, subject to the following conditions:
|
|
57
|
+
|
|
58
|
+
The above copyright notice and this permission notice shall be included in all
|
|
59
|
+
copies or substantial portions of the Software.
|
|
60
|
+
|
|
61
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
62
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
63
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
64
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
65
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
66
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
67
|
+
SOFTWARE.
|
|
68
|
+
```
|
package/dist/index.d.mts
CHANGED
|
@@ -134,7 +134,7 @@ interface PrivacyOptions$1 {
|
|
|
134
134
|
maskNetworkQueryParams?: boolean;
|
|
135
135
|
/** Redact console log messages and attributes. Default on unless `level` is `'allow'`. */
|
|
136
136
|
maskLogs?: boolean;
|
|
137
|
-
/** Redact error messages
|
|
137
|
+
/** Redact error messages and metadata (not stack frames). Default on unless `level` is `'allow'`. */
|
|
138
138
|
maskErrors?: boolean;
|
|
139
139
|
/** Extra case-insensitive key substrings treated as sensitive, merged with the built-in patterns. */
|
|
140
140
|
sensitiveKeys?: string[];
|
|
@@ -447,7 +447,7 @@ declare class SessionManager {
|
|
|
447
447
|
}): void;
|
|
448
448
|
startNavigation(metadata: Record<string, unknown>): void;
|
|
449
449
|
endNavigation(metadata: Record<string, unknown>): void;
|
|
450
|
-
captureException(error:
|
|
450
|
+
captureException(error: unknown, metadata?: Record<string, unknown>): void;
|
|
451
451
|
emitLog(message: string, level: LogLevel, attributes?: Record<string, unknown>): void;
|
|
452
452
|
getSessionId(): string;
|
|
453
453
|
setSessionId(newSessionId?: string): Promise<void>;
|
|
@@ -490,7 +490,7 @@ declare function sendCustomEvent(params: {
|
|
|
490
490
|
event: string;
|
|
491
491
|
attributes: Record<string, unknown>;
|
|
492
492
|
}): void;
|
|
493
|
-
declare function captureException(error:
|
|
493
|
+
declare function captureException(error: unknown, metadata?: Record<string, unknown>): void;
|
|
494
494
|
declare function updateConfig(params: SDKConfigUpdate): void;
|
|
495
495
|
declare function startNavigation(metadata: Record<string, unknown>): void;
|
|
496
496
|
declare function endNavigation(metadata: Record<string, unknown>): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -134,7 +134,7 @@ interface PrivacyOptions$1 {
|
|
|
134
134
|
maskNetworkQueryParams?: boolean;
|
|
135
135
|
/** Redact console log messages and attributes. Default on unless `level` is `'allow'`. */
|
|
136
136
|
maskLogs?: boolean;
|
|
137
|
-
/** Redact error messages
|
|
137
|
+
/** Redact error messages and metadata (not stack frames). Default on unless `level` is `'allow'`. */
|
|
138
138
|
maskErrors?: boolean;
|
|
139
139
|
/** Extra case-insensitive key substrings treated as sensitive, merged with the built-in patterns. */
|
|
140
140
|
sensitiveKeys?: string[];
|
|
@@ -447,7 +447,7 @@ declare class SessionManager {
|
|
|
447
447
|
}): void;
|
|
448
448
|
startNavigation(metadata: Record<string, unknown>): void;
|
|
449
449
|
endNavigation(metadata: Record<string, unknown>): void;
|
|
450
|
-
captureException(error:
|
|
450
|
+
captureException(error: unknown, metadata?: Record<string, unknown>): void;
|
|
451
451
|
emitLog(message: string, level: LogLevel, attributes?: Record<string, unknown>): void;
|
|
452
452
|
getSessionId(): string;
|
|
453
453
|
setSessionId(newSessionId?: string): Promise<void>;
|
|
@@ -490,7 +490,7 @@ declare function sendCustomEvent(params: {
|
|
|
490
490
|
event: string;
|
|
491
491
|
attributes: Record<string, unknown>;
|
|
492
492
|
}): void;
|
|
493
|
-
declare function captureException(error:
|
|
493
|
+
declare function captureException(error: unknown, metadata?: Record<string, unknown>): void;
|
|
494
494
|
declare function updateConfig(params: SDKConfigUpdate): void;
|
|
495
495
|
declare function startNavigation(metadata: Record<string, unknown>): void;
|
|
496
496
|
declare function endNavigation(metadata: Record<string, unknown>): void;
|