
sentry-span-streaming-dart
Migrate Dart/Flutter SDK to Sentry span streaming (span-first trace lifecycle). Use when asked to "enable span streaming", "migrate to span streaming", "use traceLifecycle stream", "use Sentry.startSpan", or switch from transaction-based to streamed span delivery in a Dart or Flutter project.
- Installs
- 211
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/getsentry/sentry-for-ai --skill sentry-span-streaming-dart- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads sentry-span-streaming-dart automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
All Skills > Feature Setup > Span Streaming (Dart)
Sentry Span Streaming Migration (Dart/Flutter)
Migrate from the default transaction-based trace lifecycle (SentryTraceLifecycle.static) to span streaming (SentryTraceLifecycle.stream), where spans are sent individually as they complete instead of being batched into a transaction at the end.
This skill covers the Dart and Flutter SDKs (sentry, sentry_flutter, and integration packages such as sentry_dio, sentry_sqflite, sentry_drift). For JavaScript, see Span Streaming (JavaScript). For Python, see Span Streaming (Python).
Invoke This Skill When
- User asks to "enable span streaming" or "migrate to span streaming" in a Dart or Flutter project
- User wants to switch from transaction-based to streamed span delivery
- User mentions
traceLifecycle,SentryTraceLifecycle.stream,Sentry.startSpan, orSentrySpanV2 - User wants lower latency span delivery or per-span processing
Phase 1: Detect
1.1 Detect SDK and Version
# Which Sentry packages does the project use?
grep -n "sentry" pubspec.yaml 2>/dev/null
# Resolved versions — span streaming requires >= 9.19.0
grep -A8 '^ sentry:' pubspec.lock 2>/dev/null | grep -m1 version
grep -A8 '^ sentry_flutter:' pubspec.lock 2>/dev/null | grep -m1 version
Span streaming requires sentry / sentry_flutter >=9.19.0.
1.2 Find Existing Sentry Config and Tracing Usage
# Find init calls
grep -rn "SentryFlutter\.init\|Sentry\.init" lib/ bin/ test/ --include="*.dart" 2>/dev/null | head -10
# Find old transaction API usage (these become no-ops in streaming mode)
grep -rn "startTransaction\|\.startChild(" lib/ bin/ test/ --include="*.dart" 2>/dev/null | head -20
# Find callbacks affected by the migration
grep -rn "beforeSendTransaction\|beforeSendSpan\|ignoreSpans" lib/ bin/ test/ --include="*.dart" 2>/dev/null
# Find untyped span data/tag usage on transactions
grep -rn "\.setData(\|\.setTag(" lib/ bin/ test/ --include="*.dart" 2>/dev/null | head -20
1.3 Classify the Migration Work
| Finding | Migration Work |
|---|---|
Sentry.startTransaction(...) calls | Replace with Sentry.startSpan / Sentry.startSpanSync / Sentry.startInactiveSpan |
span.startChild(...) calls | Replace with nested Sentry.startSpan calls — parenting is automatic via zones |
setData / setTag on spans | Replace with typed span.setAttribute(...) / SentryAttribute |
beforeSendTransaction callback | Never called in streaming mode — migrate logic to beforeSendSpan or ignoreSpans |
Existing beforeSendSpan / ignoreSpans usage | Review against streaming semantics — beforeSendSpan is mutation-only, ignoreSpans matches names only (see 2.5/2.6) |
| Only auto-instrumentation (no manual spans) | Just enable the option — integrations switch automatically |
Phase 2: Migrate
Prerequisites: sentry / sentry_flutter >=9.19.0 with tracing enabled (tracesSampleRate or tracesSampler configured).
2.1 Enable Span Streaming
Set traceLifecycle in the init options. This is the only required config change.
// Flutter
await SentryFlutter.init((options) {
options.dsn = '__DSN__';
options.tracesSampleRate = 1.0;
options.traceLifecycle = SentryTraceLifecycle.stream;
}, appRunner: () => runApp(const MyApp()));
// Plain Dart
await Sentry.init((options) {
options.dsn = '__DSN__';
options.tracesSampleRate = 1.0;
options.traceLifecycle = SentryTraceLifecycle.stream;
});
You can only use one tracing system at a time:
- In
streammode, the transaction APIs (Sentry.startTransaction,ISentrySpan.startChild) do nothing and log a warning. - In
staticmode (the default), the new span APIs (Sentry.startSpan) do nothing. - Auto-instrumentations automatically switch to the correct API based on this setting.
2.2 Replace Transactions with Spans
Sentry.startSpan runs an async callback and ends the span when the returned future completes. Nested calls auto-parent through zones — there is no startChild equivalent to migrate to; just nest.
// Before (static mode)
final transaction = Sentry.startTransaction('checkout', 'task');
try {
final child = transaction.startChild('db.query', description: 'load cart');
final cart = await loadCart();
await child.finish();
transaction.setData('cart.item_count', cart.items.length);
transaction.status = const SpanStatus.ok();
} catch (exception) {
transaction.status = const SpanStatus.internalError(); // -> span.status (see below)
rethrow;
} finally {
await transaction.finish();
}
// After (streaming mode)
await Sentry.startSpan('checkout', (span) async {
final cart = await Sentry.startSpan('load cart', (_) => loadCart());
span.setAttribute('cart.item_count', SentryAttribute.int(cart.items.length));
});
Error handling is automatic: if the callback throws (or the future errors), the span status is set to SentrySpanStatusV2.error before the span ends, and the error is rethrown. Otherwise the status defaults to ok.
You can also set the status manually via the status setter:
span.status = SentrySpanStatusV2.error;
There is no untyped SpanStatus string equivalent. Explicit statuses from the old API (e.g. transaction.status = const SpanStatus.internalError()) migrate to span.status = SentrySpanStatusV2.error — though error is set automatically on throw and ok automatically otherwise, so manual assignment is only needed to override the default.
For synchronous work, use Sentry.startSpanSync:
final config = Sentry.startSpanSync('parse-config', (_) {
return Config.parse(raw);
});
Both variants can be freely nested — parent-child relationships resolve correctly across sync/async boundaries. If a span is not sampled, the callback still runs and receives a no-op span, so all span operations are safe.
2.3 Spans That Outlive a Callback
Use Sentry.startInactiveSpan when the work cannot be wrapped in a single callback — widget lifecycles, stream subscriptions, platform channel round-trips. You must call end() manually, and other spans do not automatically become its children.
final paymentSpan = Sentry.startInactiveSpan('payment',
attributes: {'payment.provider': SentryAttribute.string('stripe')});
// ...later, from a different entry point
void onDeepLink(Uri uri) {
paymentSpan.end();
}
Parenting. parentSpan defaults to an internal unset sentinel (const UnsetSentrySpanV2()), which means "inherit the currently active span." This is explicitly distinct from passing parentSpan: null, which forces a root span with no parent. Pass an explicit SentrySpanV2 to parent under a specific span. (The same default applies to startSpan / startSpanSync.)
Retroactive timing. startSpan and startSpanSync accept an optional startTimestamp, and span.end(endTimestamp: ...) accepts an explicit end time. Use these when the real start or end of the work happened before you could create or end the span — for example, a duration measured by a platform channel:
final paymentSpan = Sentry.startInactiveSpan('payment');
// ...native reports it started at `nativeStart` and ended at `nativeEnd`
paymentSpan.end(endTimestamp: nativeEnd);
// startTimestamp is available on the callback variants:
Sentry.startSpanSync('replay-import', (_) => importRows(),
startTimestamp: measuredStart);
2.4 Migrate setData / setTag to Typed Attributes
Streamed spans use typed attributes instead of untyped data and tags:
// Before
transaction.setData('retry_count', 3);
transaction.setTag('payment.provider', 'stripe');
// After
span.setAttribute('retry_count', SentryAttribute.int(3));
span.setAttributes({
'payment.provider': SentryAttribute.string('stripe'),
'cache.hit': SentryAttribute.bool(true),
'response_time_ms': SentryAttribute.double(12.5),
});
span.removeAttribute('old_key');
| Factory | Dart Type |
|---|---|
SentryAttribute.string(v) | String |
SentryAttribute.int(v) | int |
SentryAttribute.bool(v) | bool |
SentryAttribute.double(v) | double |
2.5 Migrate beforeSendTransaction
beforeSendTransaction has no effect in streaming mode — transactions are never created, so the callback is never invoked. Migrate its logic:
| Use Case | Streaming Replacement |
|---|---|
| Drop spans by name | ignoreSpans with IgnoreSpanRule |
| Scrub sensitive data / PII | beforeSendSpan |
| Modify span data before send | beforeSendSpan |
beforeSendSpan receives each SentrySpanV2 before it is sent. Unlike other beforeSend callbacks, it cannot drop spans — it is mutation-only (FutureOr<void> return). Use ignoreSpans to drop.
await Sentry.init((options) {
options.traceLifecycle = SentryTraceLifecycle.stream;
options.beforeSendSpan = (span) {
span.removeAttribute('http.request.body');
};
});
Remove the beforeSendTransaction option after migrating its logic.
2.6 Configure ignoreSpans (Optional)
ignoreSpans drops spans by name before sampling. Matching is name-only (attribute matching is not yet supported in the Dart SDK).
options.ignoreSpans = [
IgnoreSpanRule.nameEquals('health-check'),
IgnoreSpanRule.nameStartsWith('internal.'),
IgnoreSpanRule.nameContains('metrics'),
IgnoreSpanRule.nameEndsWith('.bg'),
];
| Factory | Matches |
|---|---|
IgnoreSpanRule.nameEquals(String) | Exact span name |
IgnoreSpanRule.nameStartsWith(Pattern) | Name prefix (String or RegExp) |
IgnoreSpanRule.nameContains(Pattern) | Name substring (String or RegExp) |
IgnoreSpanRule.nameEndsWith(String) | Name suffix |
When an ignored span has children, the children are re-parented to the nearest recording ancestor rather than dropped.
2.7 Flutter Auto-Instrumentation
No code changes needed: frames tracking, app start, TTID/TTFD, navigation, user interaction, HTTP, database, and GraphQL instrumentations all switch to the streaming API automatically when traceLifecycle is stream.
2.8 Sampling
tracesSampleRate and tracesSampler work unchanged. Only root spans are sampled; child spans inherit the root's decision. When a root span is not sampled, the callback still executes with a no-op span.
Phase 3: Verify
3.1 Static Check
dart analyze 2>&1 | head -30
# or for Flutter projects
flutter analyze 2>&1 | head -30
Expect no new analyzer errors from the migration.
3.2 Runtime Verification
Instruct the user to verify with options.debug = true or network inspection:
- Envelope content type: span envelopes are sent with content type
application/vnd.sentry.items.span.v2+jsoninstead of transaction envelopes. Spans are buffered briefly and flushed in batches, so expect a short delay before envelopes appear. - Sentry dashboard: spans appear in the Traces view shortly after each span completes, without waiting for a whole transaction to finish.
- No-op warnings: a log line
startTransaction is not supported when traceLifecycle is 'stream'means old transaction API calls remain — find and migrate them.
3.3 Common Issues
| Symptom | Cause | Fix |
|---|---|---|
Log: startTransaction is not supported when traceLifecycle is 'stream' | Old transaction API still called in streaming mode | Replace with Sentry.startSpan / startSpanSync |
Sentry.startSpan produces no spans | traceLifecycle still static (the default), or tracing disabled | Set options.traceLifecycle = SentryTraceLifecycle.stream and a tracesSampleRate |
beforeSendTransaction never called | Expected in streaming mode | Migrate logic to beforeSendSpan or ignoreSpans, then remove it |
Returning a value from beforeSendSpan to drop a span does nothing | beforeSendSpan is mutation-only (FutureOr<void> return) | Use ignoreSpans to drop spans |
Compile error: startSpan callback type mismatch | Callback must return Future<T> for startSpan | Use startSpanSync for synchronous work |
Quick Reference
Minimal Flutter Setup
import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
Future<void> main() async {
await SentryFlutter.init((options) {
options.dsn = '__DSN__';
options.tracesSampleRate = 1.0;
options.traceLifecycle = SentryTraceLifecycle.stream;
}, appRunner: () => runApp(const MyApp()));
await Sentry.startSpan('load-config', (span) async {
span.setAttribute('source', SentryAttribute.string('remote'));
await loadConfig();
});
}
Minimal Dart Setup
import 'package:sentry/sentry.dart';
Future<void> main() async {
await Sentry.init((options) {
options.dsn = '__DSN__';
options.tracesSampleRate = 1.0;
options.traceLifecycle = SentryTraceLifecycle.stream;
});
await Sentry.startSpan('main-task', (span) async {
span.setAttribute('job.id', SentryAttribute.string('42'));
await doWork();
});
}
Span Control Reference
// Status (auto-set to error on throw, ok otherwise)
span.status = SentrySpanStatusV2.error; // error | ok
// Retroactive timing
Sentry.startSpanSync('task', (_) => work(), startTimestamp: start); // also on startSpan
span.end(endTimestamp: end); // on any span
// Parenting (startSpan / startSpanSync / startInactiveSpan)
// default: inherit active span | parentSpan: someSpan -> explicit parent | parentSpan: null -> root
Full Migration Checklist
- SDK version is
>=9.19.0(sentry/sentry_flutter) -
options.traceLifecycle = SentryTraceLifecycle.streamset in every init call - All
Sentry.startTransactioncalls replaced withSentry.startSpan/startSpanSync/startInactiveSpan - All
startChildcalls replaced with nestedSentry.startSpancalls -
setData/setTagon spans replaced with typedsetAttribute/SentryAttribute -
beforeSendTransactionlogic migrated tobeforeSendSpanorignoreSpans, option removed -
startInactiveSpanspans have a guaranteedend()call path -
dart analyze/flutter analyzepasses - Spans visible in Sentry Traces view
FAQ
What does the sentry-span-streaming-dart skill do?
Migrate Dart/Flutter SDK to Sentry span streaming (span-first trace lifecycle). Use when asked to "enable span streaming", "migrate to span streaming", "use traceLifecycle stream", "use Sentry.startSpan", or switch from transaction-based to streamed span delivery in a Dart or Flutter project.
How do I install sentry-span-streaming-dart?
Run npx skills add https://github.com/getsentry/sentry-for-ai --skill sentry-span-streaming-dart in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/sentry-span-streaming-dart/ (personal) or .claude/skills/sentry-span-streaming-dart/ (project).
Which AI agents can use sentry-span-streaming-dart?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is sentry-span-streaming-dart safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains sentry-span-streaming-dart?
It is published by getsentry in getsentry/sentry-for-ai. It has 211 recorded installs.
More from getsentry/sentry-for-ai
sentry-fix-issues
getsentry/sentry-for-ai
Find and fix issues from Sentry using MCP. Use when asked to fix Sentry errors, debug production issues, investigate exceptions, or resolve bugs reported in Sentry. Methodically analyzes stack traces, breadcrumbs, traces, and context to identify root causes.
sentry-react-native-sdk
getsentry/sentry-for-ai
Full Sentry SDK setup for React Native and Expo. Use when asked to "add Sentry to React Native", "install @sentry/react-native", "setup Sentry in Expo", or configure error monitoring, tracing, profiling, session replay, or logging for React Native applications. Supports Expo managed, Expo bare, and vanilla React Native.
sentry-create-alert
getsentry/sentry-for-ai
Create 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.
sentry-nextjs-sdk
getsentry/sentry-for-ai
Full Sentry SDK setup for Next.js. Use when asked to "add Sentry to Next.js", "install @sentry/nextjs", or configure error monitoring, tracing, session replay, logging, profiling, AI monitoring, or crons for Next.js applications. Supports Next.js 13+ with App Router and Pages Router.
sentry-sdk-setup
getsentry/sentry-for-ai
Set up Sentry in any language or framework. Detects the user's platform and loads the right SDK skill. Use when asked to add Sentry, install an SDK, or set up error monitoring in a project.
sentry-workflow
getsentry/sentry-for-ai
Keep Sentry SDKs up to date. Use when asked to upgrade the Sentry SDK across major versions, migrate SDK versions, or fix deprecated APIs.
Popular devops & cloud skills
microsoft-foundry
microsoft/azure-skills
Build, deploy, evaluate, optimize, fine-tune, and manage Microsoft Foundry agents, models, and resources end to end. USE FOR: foundry, azd ai agent, azd provision/deploy, hosted agent scaffold/develop/run/deploy/troubleshoot, prompt agent create, managed harness agent create, GitHub Copilot harness agent, create agent, update agent, add tool to agent, invoke agent, agent insights, evaluate agent, batch eval, continuous eval, continuous monitoring, agent CI/CD, optimize prompt, improve prompt, optimize agent instructions, Agent Optimizer scaffold, dataset curation from traces, deploy model, model fine-tuning (SFT/DPO/RFT), Foundry project, RBAC, role assignment, permissions, quota, capacity, region, deployment failure, AI Services, create Foundry resource, knowledge index, customize deployment, onboard, availability, training-data, grader, distillation, large file upload. DO NOT USE FOR: Azure Functions, App Service, general Azure deploy (use azure-deploy), general Azure prep (use azure
azure-diagnostics
microsoft/azure-skills
Debug Azure production issues on Azure using AppLens, Azure Monitor, resource health, and safe triage. WHEN: debug production issues, troubleshoot app service, app service high CPU, app service deployment failure, troubleshoot container apps, container app 503 or target port mismatch, troubleshoot functions, function telemetry missing or stopped after a config/connection-string change, troubleshoot AKS, VM RDP, Linux SSH, VM black screen, can't connect to VM, reset VM password, NSG or firewall blocking, kubectl cannot connect, kube-system/CoreDNS failures, pod pending, crashloop, node not ready, upgrade failures, analyze logs, KQL, insights, image pull failures, cold start issues, health probe failures, resource health, root cause of errors, troubleshoot event hubs, troubleshoot service bus, messaging SDK error, AMQP connection failure, message lock lost, lock renewal during long-running processing, service bus dead letter.
azure-prepare
microsoft/azure-skills
Prepare azd-based Azure projects for deployment: generates azure.yaml, infrastructure (Bicep/Terraform), and Dockerfiles for the Azure Developer CLI (azd) workflow. USE ONLY when the user explicitly wants to use azd as the deployment tool, or the project already has an azure.yaml file. DO NOT USE FOR: non-azd deployments, Python App Service code-only deploys (use python-appservice-deploy), or cross-cloud migration (use azure-cloud-migrate). WHEN: prepare app for azd, create azure.yaml, set up azd infrastructure, modernize app for Azure with azd, deploy with azd, function app, timer trigger, service bus trigger, event-driven function, managed identity, generate Bicep, generate Terraform, create and deploy to Azure.
azure-ai
microsoft/azure-skills
Use for Azure AI: Search, Speech, OpenAI, Document Intelligence. Helps with search, vector/hybrid search, speech-to-text, text-to-speech, transcription, OCR. WHEN: AI Search, query search, vector search, hybrid search, semantic search, speech-to-text, text-to-speech, transcribe, OCR, convert text to speech.
azure-deploy
microsoft/azure-skills
Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/deployment-plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/deployment-plan.md from azure-prepare and validated status from azure-validate. WHEN: "run azd up", "run azd deploy", "execute deployment", "push to production", "push to cloud", "go live", "ship it", "bicep deploy", "terraform apply", "publish to Azure", "launch on Azure". DO NOT USE WHEN: "create and deploy", "build and deploy", "create a new app", "set up infrastructure", "create and deploy to Azure using Terraform" — use azure-prepare for these.
azure-validate
microsoft/azure-skills
Pre-deployment validation for Azure readiness. Run deep checks on configuration, infrastructure (Bicep or Terraform), RBAC role assignments, managed identity permissions, and prerequisites before deploying. WHEN: validate my app, check deployment readiness, run preflight checks, verify configuration, check if ready to deploy, validate azure.yaml, validate Bicep, test before deploying, troubleshoot deployment errors, validate Azure Functions, validate function app, validate serverless deployment, verify RBAC roles, check role assignments, review managed identity permissions, what-if analysis, validate Container Apps deployment.