Configuration
The agent takes a single config object through Faultsense.init(config). This page documents every option.
Faultsense.init({
releaseLabel: '2.4.1',
collectorURL: 'https://collector.example.com/events',
apiKey: 'fs_secret_...',
userContext: { plan: 'pro' },
userCohorts: { plan: 'pro', region: 'us-east' },
debug: false,
});
Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
releaseLabel |
string | yes | — | App version or commit hash. Used to bucket assertion stats per release. |
collectorURL |
string or function | yes | — | Backend endpoint URL or custom collector function. |
apiKey |
string | if URL | — | API key for authentication. Required when collectorURL is a URL, not required for function collectors or named collectors (panel, console). |
userContext |
Record<string, any> |
no | — | Arbitrary context attached to every assertion payload. |
userCohorts |
Record<string, string> |
no | — | Low-cardinality cohort dimensions for per-cohort assertion health (e.g., plan tier, region). |
debug |
boolean | no | false |
Enable verbose console logging. |
gcInterval |
number (ms) | no | 5000 |
Background sweep interval for stale assertions. Matches Playwright's default assertion timeout. |
unloadGracePeriod |
number (ms) | no | 2000 |
On page unload, assertions older than this are reported as failed. Fresh assertions are silently dropped (user navigated, not a failure). |
spec |
SpecEntry[] |
no | — | JSON-spec instrumentation — the peer of fs-* HTML attributes. See JSON-spec instrumentation. |
ignoreHtmlAttrs |
boolean | no | false |
When true, the agent ignores any fs-* HTML attributes in the DOM and operates purely from the JSON spec. Useful for validating an existing HTML-instrumented page through the JSON path without removing its attributes. |
releaseLabel
Required. A version string that identifies the deploy the assertion was created under. Common shapes:
- Semver tag:
2.4.1 - Git SHA:
a1b2c3d - Environment + build:
prod-2043
The collector compares pass rates across release labels to surface regressions. The label is embedded in every payload; there's no separate "release" API call.
collectorURL
Required. Where events are POSTed. Two valid shapes:
String URL. HTTPS endpoint that accepts the payload format. Requires apiKey.
collectorURL: 'https://collector.example.com/events',
apiKey: 'fs_secret_...',
Function. A custom collector that receives the payload directly. Use for client-side side-panels, in-memory collectors in tests, or routing through a proxy. apiKey is not required.
collectorURL: (payload) => {
console.log('[faultsense]', payload);
// or push into your own queue / logger / analytics pipe
},
The function signature matches the payload shape documented in payload-spec.md. The agent does not serialize or batch before handing off — the function receives one call per event.
apiKey
Authenticates the write path. Required only when collectorURL is an HTTPS URL. Validation is skipped for function collectors and for named collectors like panel or console.
Keep the key in a server-rendered template, an environment variable injected at build time, or a runtime bootstrap endpoint. Do not hardcode production keys in client-side source.
userContext
Arbitrary record attached to every assertion payload. Use it for anything you want to slice assertion health by:
Faultsense.init({
...,
userContext: {
userId: 'u_123',
plan: 'pro',
experiment: 'checkout-v2',
region: 'us-east',
},
});
All fields are attached as strings in the payload. The collector's user-context correlation engine reads these fields and surfaces the ones that predict failures (for example, "pass rate drops from 99% to 72% for plan=free").
Updating at runtime
After login or context change, call setUserContext with the complete new context:
Faultsense.setUserContext({ userId: 'u_123', plan: 'pro' });
setUserContext replaces — it does not merge. Pass every field you want attached to subsequent events.
userCohorts
Low-cardinality dimensions used to segment assertion health by user cohort. Unlike userContext (which is free-form metadata), userCohorts is designed for aggregation — the collector groups assertion pass/fail rates by these dimensions to surface cohort-specific regressions.
Faultsense.init({
...,
userCohorts: {
plan: 'pro',
region: 'us-east',
experiment: 'checkout-v2',
},
});
Values must be strings. All values are treated as cohort dimension values for aggregation.
Cardinality limits
The collector enforces strict cardinality limits on userCohorts:
- Maximum 10 keys per workspace. Keys beyond the limit are silently dropped during aggregation.
- Maximum 50 unique values per key per workspace. Values beyond the limit are silently dropped.
- Maximum 200 bytes total payload size. Payloads exceeding this are rejected at ingestion.
Use cohorts for dimensions with a small, bounded set of values — plan tiers, regions, A/B experiment groups, device classes. Do not use cohorts for high-cardinality identifiers like user IDs, session IDs, or email addresses — those belong in userContext.
Updating at runtime
Faultsense.setUserCohorts({ plan: 'enterprise', region: 'eu-west' });
setUserCohorts replaces — it does not merge. Pass the complete cohort set each time.
debug
Enables verbose logging to the browser console. Use during initial instrumentation to confirm triggers are firing and assertions are resolving. Turn off in production.
Faultsense.init({ ..., debug: true });
Debug output covers trigger registration, assertion creation, mutation observer records, resolution paths, and payload dispatch.
gcInterval
How often (in milliseconds) the background sweep runs to clean up stale assertions. An assertion that never resolves and doesn't have an explicit fs-assert-timeout gets cleaned up by the next GC pass.
Default is 5000 (5 seconds), chosen to match Playwright's default assertion timeout so the semantics feel familiar to engineers coming from E2E test suites.
unloadGracePeriod
On pagehide, pending assertions older than this (milliseconds) are reported as failed via sendBeacon. Fresh assertions (younger than unloadGracePeriod) are silently dropped — the user navigated before the expected outcome had a realistic chance to happen, which is not a failure signal.
Default is 2000 (2 seconds).
Timeout model
There is no default per-assertion timeout. Assertions resolve naturally when the DOM changes, or get cleaned up by the GC sweep, or get finalized on page unload. See assertions/timeout.md for the full lifecycle and when to use fs-assert-timeout.
spec
JSON-spec instrumentation — declare assertions as a config array instead of fs-* HTML attributes. Use when you can't edit HTML (third-party widgets, generated output) or when you want to ship instrumentation independently of the application code. Both sources coexist on the same page.
Faultsense.init({
...,
spec: [
{
'fs-target': '#submit-btn',
'fs-trigger': 'click',
'fs-assert': 'checkout/submit-order',
'fs-assert-added': '.confirmation',
},
],
});
See JSON-spec instrumentation for the full authoring reference — SpecEntry shape, runtime API (setSpec / addSpec / getSpec), selector stability, JSON string escape rules, and co-existence behaviour.
ignoreHtmlAttrs
Boolean opt-in flag that disables HTML attribute discovery so the agent runs purely off the JSON spec. The page can still carry fs-* attributes — they're just ignored.
Faultsense.init({
...,
ignoreHtmlAttrs: true,
spec: [/* ... */],
});
Useful for two scenarios:
- Validation. Run an existing HTML-instrumented app through the JSON path end-to-end to prove parity, without stripping its attributes from production templates.
- Lockdown. A SaaS-hosted page that you can't control may carry stray
fs-*attributes from a third-party widget. SettingignoreHtmlAttrs: truekeeps those out of your assertion stream so only the entries you authored fire.
Caveat: connectivity triggers (online / offline) discover targets via document.querySelectorAll('[fs-trigger=online/offline]'). When ignoreHtmlAttrs is true, that scan finds nothing and the per-target JSON discovery path doesn't fire. If you need JSON-only connectivity triggers, file an issue — the fix is plumbing, not architecture.
Named collectors
Two named collectors are built in for development:
collectorURL: 'panel'— routes events to the Faultsense dev panel overlay if one is loaded on the pagecollectorURL: 'console'— logs events toconsole.loginstead of sending them
Neither requires an apiKey.
API methods
| Method | Purpose |
|---|---|
Faultsense.init(config) |
Initialize the agent. Idempotent — calling twice does nothing on the second call. |
Faultsense.cleanup() |
Remove every listener and observer. Use in SPAs that hot-reload or in tests. |
Faultsense.setUserContext(ctx) |
Replace the current user context. Does not merge. |
Faultsense.setUserCohorts(cohorts) |
Replace the current user cohorts. Does not merge. |
Faultsense.setSpec(entries) |
Replace the active JSON spec. Diffs custom-event listeners against the previous spec. See JSON-spec instrumentation. |
Faultsense.addSpec(entries) |
Append entries to the active JSON spec. Never removes. |
Faultsense.getSpec() |
Return a readonly snapshot of the active JSON spec. |
Faultsense.registerCleanupHook(fn) |
Register a function to run during cleanup. Useful for custom state. |
Reading the agent version
The bundle exposes its semver as a string on the global so you can identify which agent version is loaded on a page without inspecting the bundle bytes:
Faultsense.version // e.g. "0.4.1"
The same version is also stamped into the bundle as a banner comment (/*! Faultsense agent v0.4.1 | … */), so you can curl the served file and read it from the first line. Both values come from package.json at build time — they cannot drift from the published release.
Use Faultsense.version when filing bug reports, when correlating production behavior to a specific release, or when feature-gating client code on agent capabilities.