@tracewayapp/svelte
v1.1.0
Published
Traceway Svelte integration with context and helper functions
Readme
Traceway Svelte SDK
Error tracking and session replay for Svelte and SvelteKit apps. Provides setupTraceway() / getTraceway() context helpers on top of @tracewayapp/frontend.
Traceway is a completely open-source error tracking platform. You can self-host it or use Traceway Cloud.
Features
- Context-based setup that initializes Traceway exactly once during component init
getTraceway()helper for capturing exceptions and messages from any descendant component- Inherits everything from
@tracewayapp/frontend: rrweb session replay, console logs, network/navigation actions, gzip transport - SvelteKit's client-side routing flows through the History API and is captured automatically
- Simple one-line setup
Installation
npm install @tracewayapp/svelteQuick Start
Call setupTraceway in your root component:
<script>
import { setupTraceway } from "@tracewayapp/svelte";
setupTraceway({
connectionString: "your-token@https://traceway.example.com/api/report",
});
</script>
<slot />That's it. setupTraceway runs init(...) synchronously, which installs window.onerror, unhandledrejection, the console.* mirror, the fetch / XHR instrumentation, the History API instrumentation, and the rrweb recorder.
Render-time errors
Svelte does not have a global error-boundary primitive like React or Vue. The global window.onerror and unhandledrejection handlers catch runtime errors (event handlers, async work, network failures), but a component that throws during render does not automatically reach those handlers.
Svelte 5+ ships
<svelte:boundary>. Pipe itsonerrorprop into Traceway via the exportedcaptureSvelteErrorhelper:<script> import { captureSvelteError } from "@tracewayapp/svelte"; </script> <svelte:boundary onerror={(error) => captureSvelteError(error)}> <YourApp /> {#snippet failed(error, reset)} <p>Something went wrong.</p> {/snippet} </svelte:boundary>Svelte 4 has no boundary primitive at all. Wrap risky code in
try/catchand callcaptureSvelteError(err)manually, or upgrade to Svelte 5 for<svelte:boundary>.
SvelteKit
In SvelteKit, set up Traceway in the root layout — and gate it on the browser import so it doesn't run during SSR:
<!-- src/routes/+layout.svelte -->
<script>
import { setupTraceway } from "@tracewayapp/svelte";
import { browser } from "$app/environment";
if (browser) {
setupTraceway({
connectionString: "your-token@https://traceway.example.com/api/report",
});
}
</script>
<slot />Manual Capture
Use getTraceway in child components:
<script>
import { getTraceway } from "@tracewayapp/svelte";
const { captureException } = getTraceway();
async function handleSubmit() {
try {
await submitForm();
} catch (error) {
captureException(error);
}
}
</script>
<button on:click={handleSubmit}>Submit</button>To record a custom action breadcrumb, import recordAction directly from @tracewayapp/frontend (it's not on the context surface):
import { recordAction } from "@tracewayapp/frontend";
recordAction("checkout", "payment_submitted", { amount: 42 });Custom Attributes (global scope)
Two ways to attach app-level identifiers (userId, tenant, feature flags, …) to every session and exception.
Declarative — useTracewayAttributes, a factory that returns a sync function. Call once during component setup; invoke the returned function from $effect (Svelte 5) or $: (Svelte 4). The hook diffs the new map against the previous one and pushes only the deltas; on onDestroy every key it currently owns is removed.
<!-- Svelte 5 -->
<script>
import { useTracewayAttributes } from "@tracewayapp/svelte";
let { user, org } = $props();
const sync = useTracewayAttributes();
$effect(() => sync({ userId: user.id, tenant: org.id }));
</script><!-- Svelte 4 -->
<script>
import { useTracewayAttributes } from "@tracewayapp/svelte";
export let user; export let org;
const sync = useTracewayAttributes();
$: sync({ userId: user.id, tenant: org.id });
</script>The sync function accepts null / undefined as "empty map" — useful while user data loads or after logout. The factory must run during component init so onDestroy can register cleanup.
Imperative — setAttribute / setAttributes / removeAttribute / clearAttributes. Use these outside component trees (+layout.ts load functions, server hooks that run client-side after hydration):
import {
setAttribute,
setAttributes,
clearAttributes,
} from "@tracewayapp/svelte";
setAttribute("build_channel", "canary");
setAttributes({ tenant: "acme", plan: "pro" });
// ...later, on logout:
clearAttributes();Layering order on each event: auto-collected defaults < global scope < per-call attributes. See the @tracewayapp/frontend README for the full mechanics.
Always-on Session Recording
Pass recordAllSessions: true to upload full sessions continuously (not just exception-bound clips):
<script>
setupTraceway({
connectionString: "your-token@https://traceway.example.com/api/report",
options: { recordAllSessions: true },
});
</script>See the @tracewayapp/frontend README for the full description.
Options
The options field forwards directly to @tracewayapp/frontend. The most-used flags:
| Option | Default | Description |
|--------|---------|-------------|
| version | "" | App version string, attached to every report |
| debug | false | Print debug info to the console |
| captureLogs | true | Mirror console.* into the rolling log buffer |
| captureNetwork | true | Record fetch / XHR as network actions |
| captureNavigation | true | Record History API push / replace / pop as navigation actions |
| sessionRecording | true | Enable the rrweb session recorder |
| recordAllSessions | false | Always-on session recording (every ~30 s segment uploaded continuously) |
| eventsWindowMs | 10000 | Rolling window kept in the log/action buffers (ms) |
| eventsMaxCount | 200 | Hard cap applied independently to logs and actions |
See the @tracewayapp/frontend README for the full options reference.
Logs & Actions
Each captured exception ships with the buffered logs, actions, and replay frames:
- Logs —
console.{debug, log, info, warn, error}mirrored into a rolling buffer. - Actions —
fetch/XHRand History API navigations recorded as breadcrumbs. SvelteKit's client-side routing is captured automatically. - Session recordings — rrweb-based replay of the seconds leading up to each exception.
API
setupTraceway(config)
Initializes Traceway and stores the API in Svelte context. Must be called during component initialization.
| Field | Type | Description |
|-------|------|-------------|
| connectionString | string | Traceway connection string (token@url) |
| options | TracewayFrontendOptions | Forwarded to init() from @tracewayapp/frontend |
Returns { captureException, captureExceptionWithAttributes, captureMessage }.
getTraceway()
Returns { captureException, captureExceptionWithAttributes, captureMessage }.
Throws if used outside a component tree where setupTraceway has been called.
useTracewayAttributes()
Returns a (attrs: Record<string, string> | null | undefined) => void setter. Call once during component init, then invoke the setter from $effect (Svelte 5) or a $: reactive statement (Svelte 4). Diffs against the last map; removes every owned key on onDestroy.
Platform Support
| Environment | Error Tracking | Session Replay |
|---|---|---|
| Svelte 4+ in any modern browser | Yes | Yes |
| SvelteKit (browser) | Yes | Yes |
| SvelteKit SSR | Skip — gate on $app/environment.browser | No |
Links
License
MIT
