Svelte
Context Setup

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:

  1. setupTraceway() initializes the SDK and sets context
  2. getTraceway() 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

OptionTypeRequiredDescription
connectionStringstringYesYour Traceway connection string
optionsobjectNoSDK configuration

SDK Options

OptionTypeDefaultDescription
debugbooleanfalseLog filtered-out exceptions and failed uploads to the console
debounceMsnumber1500Batch delay in milliseconds
retryDelayMsnumber10000Retry delay for failed uploads
versionstringundefinedYour application version
ignoreErrorsArray<string | RegExp>DEFAULT_IGNORE_PATTERNSError patterns to ignore. Pass [] to capture all errors. See Error Filtering
beforeCapture(exception) => booleanundefinedReturn false to suppress an error. See Error Filtering
sessionRecordingbooleantrueEnable the rrweb session recorder
sessionRecordingSegmentDurationnumber30000rrweb segment length in ms
recordAllSessionsbooleanfalseAlways-on session recording. See Sessions
captureLogsbooleantrueMirror console.* calls into the rolling log buffer
captureNetworkbooleantrueRecord fetch / XHR calls as network actions
captureNavigationbooleantrueRecord 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

FunctionDescription
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 logout

Layering 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

  1. Initialize early: Call setupTraceway in your root layout
  2. Skip the browser guard: setupTraceway must also run during SSR, or getTraceway() throws in child components
  3. Use attributes: Add context with captureExceptionWithAttributes
  4. 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}