Context Setup
Understanding Traceway's Svelte context integration.
How It Works
Traceway uses Svelte's context API to provide error capture functions to your component tree:
setupTraceway()initializes the SDK and sets contextgetTraceway()retrieves the context in child components
setupTraceway
Must be called during component initialization (not in an event handler):
<script>
import { setupTraceway } from "@tracewayapp/svelte";
// Correct: called at component initialization
setupTraceway({
connectionString: "your-token@https://traceway.example.com/api/report",
});
</script>Initialization is synchronous: setupTraceway calls the SDK's init() immediately, during component setup, not in onMount. Everything captured after that point is recorded, including captures in a child component's setup code that runs before onMount. There is no pre-init buffer, so a capture made before setupTraceway runs is dropped.
Options
| Option | Type | Required | Description |
|---|---|---|---|
connectionString | string | Yes | Your Traceway connection string |
options | object | No | SDK configuration |
SDK Options
| Option | Type | Default | Description |
|---|---|---|---|
debug | boolean | false | Log filtered-out exceptions and failed uploads to the console |
debounceMs | number | 1500 | Batch delay in milliseconds |
retryDelayMs | number | 10000 | Retry delay for failed uploads |
version | string | undefined | Your application version |
ignoreErrors | Array<string | RegExp> | DEFAULT_IGNORE_PATTERNS | Error patterns to ignore. Pass [] to capture all errors. See Error Filtering |
beforeCapture | (exception) => boolean | undefined | Return false to suppress an error. See Error Filtering |
sessionRecording | boolean | true | Enable the rrweb session recorder |
sessionRecordingSegmentDuration | number | 30000 | rrweb segment length in ms |
recordAllSessions | boolean | false | Always-on session recording. See Sessions |
captureLogs | boolean | true | Mirror console.* calls into the rolling log buffer |
captureNetwork | boolean | true | Record fetch / XHR calls as network actions |
captureNavigation | boolean | true | Record History API push / replace / pop transitions |
getTraceway
Retrieve capture functions in any child component:
<script>
import { getTraceway } from "@tracewayapp/svelte";
const { captureException, captureExceptionWithAttributes, captureMessage } = getTraceway();
</script>Return Value
| Function | Description |
|---|---|
captureException(error) | Capture an error with stack trace |
captureExceptionWithAttributes(error, attributes) | Capture error with metadata |
captureMessage(message) | Send a custom message |
recordAction(category, name, data) | Record an action into the rolling buffer that ships with the next exception |
Complete Example
Root layout:
<!-- src/routes/+layout.svelte -->
<script>
import { setupTraceway } from "@tracewayapp/svelte";
import { PUBLIC_TRACEWAY_CONNECTION } from "$env/static/public";
setupTraceway({
connectionString: PUBLIC_TRACEWAY_CONNECTION,
options: {
debug: import.meta.env.DEV,
},
});
</script>
<slot />Child component:
<!-- src/lib/components/Form.svelte -->
<script>
import { getTraceway } from "@tracewayapp/svelte";
const { captureException, captureExceptionWithAttributes } = getTraceway();
let formData = { email: "", name: "" };
async function handleSubmit() {
try {
const response = await fetch("/api/submit", {
method: "POST",
body: JSON.stringify(formData),
});
if (!response.ok) throw new Error("Submission failed");
} catch (error) {
captureExceptionWithAttributes(error, {
email: formData.email,
action: "form_submit",
});
}
}
</script>
<form on:submit|preventDefault={handleSubmit}>
<input bind:value={formData.name} placeholder="Name" />
<input bind:value={formData.email} placeholder="Email" />
<button type="submit">Submit</button>
</form>Custom Attributes
Use useTracewayAttributes to bind a reactive map of attributes (userId, tenant, feature flags, etc.) to the SDK's global scope. It's a factory: call it once during component setup, then invoke the returned setter from $effect (Svelte 5) or $: (Svelte 4). The setter diffs against the last map and pushes only the deltas; onDestroy removes every key it currently owns.
<!-- 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 setter accepts null / undefined as "empty map", which is useful while user data loads or after logout.
For imperative use (load functions, hooks), the same primitives are exported as plain functions:
import { setAttribute, setAttributes, removeAttribute, clearAttributes } from "@tracewayapp/svelte";
setAttribute("build_channel", "canary");
setAttributes({ tenant: "acme", plan: "pro" });
clearAttributes(); // on logoutLayering on each event: defaults < global scope < per-call. See Sessions for the full attribute model.
TRACEWAY_KEY
For advanced use cases, you can access the context key directly:
<script>
import { getContext } from "svelte";
import { TRACEWAY_KEY } from "@tracewayapp/svelte";
const traceway = getContext(TRACEWAY_KEY);
</script>SvelteKit Error Handling
handleError in src/hooks.client.js is where SvelteKit hands you the real error from a failed load or a render crash during client-side navigation. Svelte context is not available in a hook, so import the capture function directly. It is the same function getTraceway() returns.
// src/hooks.client.js
import { captureExceptionWithAttributes } from "@tracewayapp/svelte";
export function handleError({ error, event }) {
captureExceptionWithAttributes(error, {
route: event.route?.id ?? event.url.pathname,
});
return { message: "Something went wrong" };
}Do not capture from +error.svelte. That page only receives $page.error, which SvelteKit has already reduced to a plain { message } object. Passing it to captureException produces an issue titled Object: Internal Error with no stack trace and no original message. Use the page for display and let handleError do the reporting.
<!-- src/routes/+error.svelte -->
<script>
import { page } from "$app/stores";
</script>
<h1>Error: {$page.status}</h1>
<p>{$page.error?.message}</p>Render Errors (Svelte 5)
Svelte 5's <svelte:boundary> catches errors thrown while its children render. Pass captureSvelteError as onerror to report them:
<script>
import { captureSvelteError } from "@tracewayapp/svelte";
import Widget from "$lib/components/Widget.svelte";
</script>
<svelte:boundary onerror={captureSvelteError}>
<Widget />
{#snippet failed(error)}
<p>Something went wrong: {error.message}</p>
{/snippet}
</svelte:boundary>Environment Variables
For SvelteKit, use public environment variables:
# .env
PUBLIC_TRACEWAY_CONNECTION=your-token@https://traceway.example.com/api/report<script>
import { PUBLIC_TRACEWAY_CONNECTION } from "$env/static/public";
setupTraceway({
connectionString: PUBLIC_TRACEWAY_CONNECTION,
});
</script>Best Practices
- Initialize early: Call
setupTracewayin your root layout - Skip the browser guard:
setupTracewaymust also run during SSR, orgetTraceway()throws in child components - Use attributes: Add context with
captureExceptionWithAttributes - Handle gracefully: Show user-friendly errors while capturing details
<script>
import { getTraceway } from "@tracewayapp/svelte";
const { captureException } = getTraceway();
let error = null;
async function loadData() {
try {
const data = await fetchData();
// use data
} catch (e) {
captureException(e);
error = "Failed to load data. Please try again.";
}
}
</script>
{#if error}
<p class="error">{error}</p>
{/if}