sentry-span-streaming
Migrate to Sentry span streaming (span-first trace lifecycle). Use when asked to "enable span streaming", "migrate to span streaming", "use traceLifecycle stream", "add spanStreamingIntegration", or switch from transaction-based to streamed span delivery.
What this skill does
> [All Skills](../../SKILL_TREE.md) > [Feature Setup](../sentry-feature-setup/SKILL.md) > Span Streaming
# Sentry Span Streaming Migration
Migrate from the default transaction-based trace lifecycle (`static`) to span streaming (`stream`), where spans are sent in multiple batches as they complete instead of being batched into one transaction at the end.
## Invoke This Skill When
- User asks to "enable span streaming" or "migrate to span streaming"
- User wants to switch from transaction-based to streamed span delivery
- User mentions `traceLifecycle`, `spanStreamingIntegration`, or `withStreamedSpan`
- User wants lower latency span delivery or per-span processing
## Supported Platforms
| Platform | Status |
|---|---|
| JavaScript (Browser, Node.js, Bun, Deno, Cloudflare) | Supported |
| Python | Not yet available |
| Ruby | Not yet available |
| Go | Not yet available |
| Other SDKs | Not yet available |
If the user's project does not use a supported SDK, inform them that span streaming is currently only available for JavaScript SDKs and stop here.
---
## Phase 1: Detect
Identify the user's platform, SDK version, and current tracing configuration.
### 1.1 Detect Platform and SDK
```bash
# Check for JavaScript Sentry packages
cat package.json 2>/dev/null | grep -E '"@sentry/'
# Check for Python Sentry
cat requirements.txt setup.py pyproject.toml 2>/dev/null | grep -i sentry
# Check for Ruby Sentry
cat Gemfile 2>/dev/null | grep sentry
# Check for Go Sentry
cat go.mod 2>/dev/null | grep sentry
```
If an unsupported Sentry SDK is detected, inform the user that span streaming is not yet available for their platform.
### 1.2 Detect JavaScript Environment
```bash
# Detect if browser, server, or both
grep -rn "from '@sentry/browser'\|from '@sentry/react'\|from '@sentry/vue'\|from '@sentry/angular'\|from '@sentry/svelte'\|from '@sentry/nextjs'\|from '@sentry/nuxt'\|from '@sentry/sveltekit'\|from '@sentry/remix'\|from '@sentry/solidstart'\|from '@sentry/astro'\|from '@sentry/react-router'" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null | head -20
grep -rn "from '@sentry/node'\|from '@sentry/bun'\|from '@sentry/deno'\|from '@sentry/cloudflare'" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null | head -20
```
### 1.3 Find Existing Sentry Config
```bash
# Find Sentry.init calls
grep -rn "Sentry\.init\|init({" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null | head -20
# Find beforeSendSpan usage
grep -rn "beforeSendSpan" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null
# Find beforeSendTransaction usage
grep -rn "beforeSendTransaction" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null
# Find ignoreSpans usage
grep -rn "ignoreSpans" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" -l 2>/dev/null
```
### 1.4 Classify Environment
Based on detection results, classify each `Sentry.init` call as:
| Environment | Packages | Migration Path |
|---|---|---|
| **Browser** | `@sentry/browser`, `@sentry/react`, `@sentry/vue`, `@sentry/angular`, `@sentry/svelte` | Add `spanStreamingIntegration()` |
| **Server** | `@sentry/node`, `@sentry/bun`, `@sentry/deno`, `@sentry/cloudflare` | Add `traceLifecycle: 'stream'` |
| **Framework (both)** | `@sentry/nextjs`, `@sentry/nuxt`, `@sentry/sveltekit`, `@sentry/remix`, `@sentry/astro`, `@sentry/solidstart`, `@sentry/react-router` | Migrate both client and server configs separately |
---
## Phase 2: Migrate (JavaScript)
**Prerequisites:** Sentry JavaScript SDK `>=10.53.1` with tracing enabled (`tracesSampleRate` or `tracesSampler` configured).
Apply changes to each `Sentry.init` call. Work through each file identified in Phase 1.
### 2.1 Enable Span Streaming
#### Server-Side SDKs
Add `traceLifecycle: 'stream'` to `Sentry.init()`:
```js
// Before
Sentry.init({
dsn: '...',
tracesSampleRate: 1.0,
});
// After
Sentry.init({
dsn: '...',
tracesSampleRate: 1.0,
traceLifecycle: 'stream',
});
```
#### Browser-Side SDKs
Add `Sentry.spanStreamingIntegration()` to the `integrations` array. The integration automatically enables `traceLifecycle: 'stream'` — you do not need to set it manually.
```js
// Before
Sentry.init({
dsn: '...',
integrations: [
Sentry.browserTracingIntegration(),
],
tracesSampleRate: 1.0,
});
// After
Sentry.init({
dsn: '...',
integrations: [
Sentry.spanStreamingIntegration(),
Sentry.browserTracingIntegration(),
],
tracesSampleRate: 1.0,
});
```
The order of `spanStreamingIntegration()` relative to other integrations does not matter.
#### Framework SDKs (Client + Server)
Apply the browser migration to client config files and the server migration to server config files. Common patterns:
| Framework | Client Config | Server Config |
|---|---|---|
| Next.js | `sentry.client.config.ts` | `sentry.server.config.ts`, `sentry.edge.config.ts` |
| Nuxt | Client-side `Sentry.init` in module | Server-side `Sentry.init` in module |
| SvelteKit | `src/hooks.client.ts` | `src/hooks.server.ts` |
| Remix | `entry.client.tsx` | `entry.server.tsx` |
| Astro | Client-side init | Server-side init |
### 2.2 Migrate `beforeSendSpan`
If the user has a `beforeSendSpan` callback, it **must** be wrapped with `Sentry.withStreamedSpan()` to work in streaming mode. Without this wrapper, the SDK falls back to static mode.
The callback shape also changes:
- `description` is now `name`
- `data` is now `attributes`
- The span object is `StreamedSpanJSON` instead of `SpanJSON`
```js
// Before (static mode)
Sentry.init({
beforeSendSpan: (span) => {
if (span.description?.includes('/health')) {
span.description = '[filtered]';
}
// 'data' contains span attributes
delete span.data?.['http.request.body'];
return span;
},
});
// After (streaming mode)
Sentry.init({
beforeSendSpan: Sentry.withStreamedSpan((span) => {
if (span.name?.includes('/health')) {
span.name = '[filtered]';
}
// 'attributes' replaces 'data'
if (span.attributes) {
delete span.attributes['http.request.body'];
}
return span;
}),
});
```
**Key differences in the callback:**
| Static (`SpanJSON`) | Streaming (`StreamedSpanJSON`) |
|---|---|
| `span.description` | `span.name` |
| `span.data` (processed attributes) | `span.attributes` (raw attributes) |
| `span.timestamp` (end time) | `span.end_timestamp` |
| `span.status` (optional string) | `span.status` (`'ok'` or `'error'`) |
| `span.op` | `span.attributes['sentry.op']` |
Returning `null` from `beforeSendSpan` does **not** drop the span — it is ignored and a warning is logged.
### 2.3 Remove or Replace `beforeSendTransaction`
`beforeSendTransaction` has **no effect** in streaming mode. Spans are sent individually, not batched into transactions.
```js
// Before
Sentry.init({
beforeSendTransaction: (event) => {
// This entire callback is ignored in streaming mode
if (event.transaction === '/health') {
return null;
}
return event;
},
});
```
**Migration paths depending on what `beforeSendTransaction` was used for:**
| Use Case | Streaming Replacement |
|---|---|
| Drop spans by name/route | Use `ignoreSpans` option |
| Modify span data before send | Use `beforeSendSpan` with `withStreamedSpan` |
| Filter by transaction name | Use `ignoreSpans` with string/RegExp pattern |
| Add tags/context to transaction | Use `beforeSendSpan` with `withStreamedSpan` |
Remove the `beforeSendTransaction` option from `Sentry.init()` after migrating its logic.
### 2.4 Configure `ignoreSpans` (Optional)
`ignoreSpans` works in both static and streaming modes, but the filter is evaluated at different points in the span lifecycle:
- **Streaming mode:** evaluated when the span **Related in feature-setup
sentry-instrumentation-guide
IncludedDecide which Sentry signal to reach for when instrumenting code — error, span, span attribute, log, or metric. Use when adding instrumentation and unsure whether something should be a log vs a span vs a metric, when deciding "what to instrument where", when reviewing instrumentation for gaps, or when a coding agent needs a rule for choosing between errors, traces, logs, and metrics. This skill decides WHAT to emit; the sentry-*-sdk skills handle HOW to set each pillar up.
sentry-setup-ai-monitoring
IncludedSetup Sentry AI Agent Monitoring in any project. Use when asked to monitor LLM calls, track AI agents, track conversations, or instrument OpenAI/Anthropic/Vercel AI/LangChain/Google GenAI/Pydantic AI. Detects installed AI SDKs and configures appropriate integrations.
sentry-otel-exporter-setup
IncludedConfigure the OpenTelemetry Collector with Sentry Exporter for multi-project routing and automatic project creation. Use when setting up OTel with Sentry, configuring collector pipelines for traces and logs, or routing telemetry from multiple services to Sentry projects.
sentry-create-alert
IncludedCreate Sentry alerts using the workflow engine API. Use when asked to create alerts, set up notifications, configure issue priority alerts, or build workflow automations. Supports email, Slack, PagerDuty, Discord, and other notification actions.