sentry-span-streaming-js について
JavaScriptのSentry SDKをトランザクション単位のトレースからspanストリーミングへ移行するスキルです。ブラウザー、サーバー、フレームワークの設定に加え、コールバックや属性の変更、ビルドと実行時の確認を扱います。
主な機能
- 01JavaScript SDK環境と設定の検出
- 02ブラウザーおよびサーバーSDKでのストリーミング有効化
- 03spanコールバックとタグ属性の調整
- 04トランザクション用コールバックとフィルターの置換
- 05ビルドとspan配信の確認
活用シーン
- 01JavaScriptアプリを個別span送信へ移行
- 02beforeSendSpanとbeforeSendTransactionの動作を更新
- 03spanの表示とフォールバック警告を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ getsentry/ sentry-for-ai --skill sentry-span-streaming-jsインストール後、Claude Code で/sentry-span-streaming-jsを入力して読み込まれたか確認します。
詳細
Sentry Span Streaming への移行(JavaScript)
デフォルトのトランザクションベースのトレースライフサイクル(static)から、スパンが完了するたびに個別に送信し、最後にトランザクションとしてまとめて送信しない Span Streaming(stream)へ移行します。
このスキルでは、JavaScript SDK(Browser、Node.js、Bun、Deno、Cloudflare)を扱います。Python については、Span Streaming(Python)を参照してください。Dart/Flutter については、Span Streaming(Dart)を参照してください。
このスキルを使用するタイミング
- JavaScript プロジェクトで「span streaming を有効にする」または「span streaming に移行する」ようユーザーから依頼された場合
- トランザクションベースからストリーミングによるスパン配信に切り替えたい場合
traceLifecycle、spanStreamingIntegration、withStreamedSpanに言及された場合- スパン配信のレイテンシを下げたい場合、またはスパンごとに処理したい場合
フェーズ 1:検出
1.1 環境を検出する
# 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.2. 既存の Sentry 設定を見つける
# 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.3 環境を分類する
検出結果に基づいて、各 Sentry.init 呼び出しを次のように分類します。
| 環境 | パッケージ | 移行方法 |
|---|---|---|
| ブラウザー | @sentry/browser、@sentry/react、@sentry/vue、@sentry/angular、@sentry/svelte | spanStreamingIntegration() を追加 |
| サーバー | @sentry/node、@sentry/bun、@sentry/deno、@sentry/cloudflare | traceLifecycle: 'stream' を追加 |
| フレームワーク(両方) | @sentry/nextjs、@sentry/nuxt、@sentry/sveltekit、@sentry/remix、@sentry/astro、@sentry/solidstart、@sentry/react-router | クライアントとサーバーの設定を個別に移行 |
フェーズ 2:移行
前提条件: Sentry JavaScript SDK >=10.66.0 を使用し、トレーシングを有効にしている(tracesSampleRate または tracesSampler が設定されている)こと。
各 Sentry.init 呼び出しに変更を適用します。上記で特定したファイルをすべて確認してください。
2.1 Span Streaming を有効にする
サーバーサイド SDK
Sentry.init() に traceLifecycle: 'stream' を追加します。
// Before
Sentry.init({
dsn: '...',
tracesSampleRate: 1.0,
});
// After
Sentry.init({
dsn: '...',
tracesSampleRate: 1.0,
traceLifecycle: 'stream',
});
ブラウザーサイド SDK
Sentry.spanStreamingIntegration() を integrations 配列に追加します。このインテグレーションによって traceLifecycle: 'stream' が自動的に有効になるため、手動で設定する必要はありません。
// Before
Sentry.init({
dsn: '...',
integrations: [
Sentry.browserTracingIntegration(),
],
tracesSampleRate: 1.0,
});
// After
Sentry.init({
dsn: '...',
integrations: [
Sentry.spanStreamingIntegration(),
Sentry.browserTracingIntegration(),
],
tracesSampleRate: 1.0,
});
spanStreamingIntegration() と他のインテグレーションの順序は問いません。
フレームワーク SDK(クライアント+サーバー)
クライアント設定ファイルにはブラウザー向けの移行を、サーバー設定ファイルにはサーバー向けの移行を適用します。一般的なパターンは次のとおりです。
| フレームワーク | クライアント設定 | サーバー設定 |
|---|---|---|
| Next.js | sentry.client.config.ts | sentry.server.config.ts、sentry.edge.config.ts |
| Nuxt | モジュール内のクライアント側 Sentry.init | モジュール内のサーバー側 Sentry.init |
| SvelteKit | src/hooks.client.ts | src/hooks.server.ts |
| Remix | entry.client.tsx | entry.server.tsx |
| Astro | クライアント側の初期化 | サーバー側の初期化 |
2.2 beforeSendSpan を移行する
ユーザーが beforeSendSpan コールバックを使用している場合、ストリーミングモードで動作させるには、必ず Sentry.withStreamedSpan() でラップする必要があります。このラッパーがない場合、SDK は static モードにフォールバックします。
コールバックの形式も変わります。
descriptionはnameになりますdataはattributesになります- スパンオブジェクトは
SpanJSONではなくStreamedSpanJSONになります
// 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;
}),
});
コールバックの主な違い:
Static(SpanJSON) | Streaming(StreamedSpanJSON) |
|---|---|
span.description | span.name |
span.data(処理済みの属性) | span.attributes(生の属性) |
span.timestamp(終了時刻) | span.end_timestamp |
span.status(省略可能な文字列) | span.status('ok' または 'error') |
span.op | span.attributes['sentry.op'] |
beforeSendSpan から null を返しても、スパンは破棄されません。返された値は無視され、警告が記録されます。
2.3 setTag(s) を setAttribute(s) に移行する
ストリーミングモードでは、タグはストリーミングされるスパンには適用されなくなり、適用されるのは属性のみです。ユーザーが Sentry.setTag / Sentry.setTags または scope.setTag / scope.setTags(例:withScope()、getCurrentScope()、getGlobalScope() を使用)でタグを設定している箇所では、同じキーと値の組み合わせで setAttribute / setAttributes も呼び出し、データが引き続きスパンに届くようにしてください。
タグは引き続きエラーで機能するため、既存の setTag(s) 呼び出しは残し、それと並べて属性を設定する呼び出しを追加してください。一方を他方に置き換えないでください。
既存の使用箇所を検索します。
grep -rn "\.setTag\b\|\.setTags\b\|setTag(\|setTags(" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.mjs" 2>/dev/null
移行を適用します。ほとんどの setTag(s) 呼び出しはスパンも生成するコードパスで実行されるため、その呼び出しがエラー報告専用であることが明らかな場合を除き、属性を設定する呼び出しも追加してください。
// Before
Sentry.setTag('feature', 'checkout');
Sentry.setTags({ tier: 'premium', region: 'eu' });
// After — keep the tags, add matching attributes
Sentry.setTag('feature', 'checkout');
Sentry.setAttribute('feature', 'checkout');
Sentry.setTags({ tier: 'premium', region: 'eu' });
Sentry.setAttributes({ tier: 'premium', region: 'eu' });
スコープベースの呼び出しにも同様に適用します。
// Before
Sentry.withScope((scope) => {
scope.setTag('job', 'sync-orders');
// ...
});
Sentry.getCurrentScope().setTag('job', 'sync-orders')
// After
Sentry.withScope((scope) => {
scope.setTag('job', 'sync-orders');
scope.setAttribute('job', 'sync-orders');
// ...
});
Sentry.getCurrentScope().setTag('job', 'sync-orders')
Sentry.getCurrentScope().setAttribute('job', 'sync-orders')
setAttribute(s) は SDK >=10.66.0 から利用できます。この手順を適用する前に、前提となるバージョンを確認してください。
2.4 beforeSendTransaction を削除または置き換える
beforeSendTransaction はストリーミングモードでは効果がありません。スパンはトランザクションにまとめられず、個別に送信されます。
// Before
Sentry.init({
beforeSendTransaction: (event) => {
// This entire callback is ignored in streaming mode
if (event.transaction === '/health') {
return null;
}
return event;
},
});
beforeSendTransaction の用途に応じた移行方法:
| 用途 | ストリーミングでの置き換え |
|---|---|
| 名前/ルートでスパンを破棄する | ignoreSpans オプションを使用する |
| 送信前にスパンデータを変更する | withStreamedSpan と beforeSendSpan を使用する |
| トランザクション名でフィルタリングする | 文字列/RegExp パターンを指定して ignoreSpans を使用する |
| トランザクションにタグ/コンテキストを追加する | withStreamedSpan と beforeSendSpan を使用する |
ロジックを移行した後、Sentry.init() から beforeSendTransaction オプションを削除してください。
2.5 ignoreSpans を設定する(任意)
ignoreSpans は静的モードとストリーミングモードの両方で機能しますが、フィルターの評価タイミングはスパンのライフサイクル内で異なります。
- ストリーミングモード: スパンの開始時に評価されます。スパン開始時点で利用可能なデータ、つまりスパン名と作成時に設定された属性のみが考慮されます。
- 静的モード: ルートスパンの終了時に評価されます。その時点で利用可能なデータ、つまりスパン名と属性のみが考慮されます。
どちらのモードでも、一致するとスパンは記録も送信もされません。ストリーミングではスパン開始時に一致判定が行われることがあるため、スパン名とスパン開始時に設定された属性のみが確実に利用できます。スパンのライフサイクル中に後から追加される属性には依存しないでください。
Sentry.init({
traceLifecycle: 'stream',
ignoreSpans: [
// String match against span name
'/health',
'/ready',
// RegExp match against span name
/^OPTIONS /,
// Object filter — all conditions must match
{
op: 'middleware.handle',
name: /^corsMiddleware/,
},
// Filter by attributes (string = substring match, RegExp for patterns)
{
op: 'http.server',
attributes: {
'http.route': /^\/internal\//,
},
},
],
});
フィルターオブジェクトのプロパティ:
| プロパティ | 型 | 一致対象 |
|---|---|---|
name | string | RegExp | スパン名(説明) |
op | string | RegExp | スパンの操作 |
attributes | Record<string, string | RegExp | number | boolean | Array> | スパン属性 |
フィルターオブジェクトで複数のプロパティを指定した場合、スパンを無視するにはすべてが一致する必要があります。
2.6 ブラウザのプロファイリングを設定する(任意)
ブラウザでスパンストリーミングを使用する場合は、レガシーな profilesSampleRate ではなく、v2 のプロファイリングオプションを使用してください。レガシーオプションは非推奨であり、スパンストリーミングのライフサイクルと連携しません。
browserProfilingIntegration() を追加し、次の 2 つの v2 オプションを設定します。
// Before (legacy profiling — do NOT use with span streaming)
Sentry.init({
integrations: [
Sentry.browserTracingIntegration(),
],
tracesSampleRate: 1.0,
profilesSampleRate: 0.5, // deprecated
});
// After (v2 profiling with span streaming)
Sentry.init({
integrations: [
Sentry.spanStreamingIntegration(),
Sentry.browserTracingIntegration(),
Sentry.browserProfilingIntegration(),
],
tracesSampleRate: 1.0,
profileSessionSampleRate: 1.0,
profileLifecycle: 'trace',
});
v2 のプロファイリングオプション:
| オプション | 型 | 説明 |
|---|---|---|
profileSessionSampleRate | number (0–1) | プロファイリングを有効にするユーザーセッションの割合です。デフォルト:0(無効)。 |
profileLifecycle | 'trace' | 'manual' | 'trace':サンプリングされたルートスパンが存在する間、プロファイラーが自動的に実行されます。'manual':Sentry.uiProfiler.startProfiler() / stopProfiler() でプロファイラーを明示的に開始・停止します。デフォルト:'manual'。 |
profileLifecycle: 'trace' を使用するには、トレーシングを有効にする必要があります(tracesSampleRate または tracesSampler)。ルートスパンが開始するとプロファイラーが起動し、サンプリングされたルートスパンがなくなると停止します。プロファイルチャンクは 60 秒ごと、または最後のルートスパンが終了したときに、個別に送信されます。
レガシーオプションと v2 オプションを混在させないでください。profilesSampleRate が設定されている場合、profileSessionSampleRate は効果がなく、SDK は警告をログに出力します。
フェーズ 3:検証
変更を適用した後、移行が正しく機能することを確認します。
3.1 ビルドチェック
# TypeScript check
npx tsc --noEmit 2>&1 | head -30
# Build
npm run build 2>&1 | tail -20
3.2 実行時の検証
ユーザーに、ブラウザーの開発者ツールまたはサーバーログで次の点を確認するよう案内してください。
- ネットワークタブを確認する:スパンのエンベロープがトランザクションエンベロープではなく、コンテンツタイプ
application/vnd.sentry.items.span.v2+jsonの個別のリクエストとして表示されること - Sentry ダッシュボードを確認する:トランザクション全体の完了を待たず、スパンの完了後すぐに Traces ビューに表示されること
- フォールバック警告を確認する:SDK が静的モードへのフォールバックに関する警告をログに出力する場合、
beforeSendSpanコールバックにwithStreamedSpanラッパーがない可能性があります
3.3 よくある問題
| 症状 | 原因 | 対処方法 |
|---|---|---|
| SDK が静的モードにフォールバックする | beforeSendSpan が withStreamedSpan でラップされていない | コールバックをラップします:Sentry.withStreamedSpan(callback) |
beforeSendTransaction が呼び出されない | ストリーミングモードでは想定される動作 | ロジックを beforeSendSpan または ignoreSpans に移行します |
| スパンが引き続きトランザクションとして届く | traceLifecycle が設定されていないか、インテグレーションがない | サーバー:traceLifecycle: 'stream' を追加します。ブラウザー:spanStreamingIntegration() を追加します |
span.description の型エラー | StreamedSpanJSON では description ではなく name を使用する | コールバック内の span.description を span.name に変更します |
span.data の型エラー | StreamedSpanJSON では data ではなく attributes を使用する | コールバック内の span.data を span.attributes に変更します |
profileSessionSampleRate が効果を発揮しない | レガシーな profilesSampleRate も設定されている | profilesSampleRate を削除し、profileSessionSampleRate と profileLifecycle のみを使用します |
| スパンにタグがない | タグはストリーミングされたスパンには適用されない | 既存の setTag(s) 呼び出しと併せて、対応する setAttribute(s) 呼び出しを追加します |
クイックリファレンス
最小限のサーバー設定
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
traceLifecycle: 'stream',
});
最小限のブラウザー設定
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: '__DSN__',
integrations: [
Sentry.spanStreamingIntegration(),
Sentry.browserTracingIntegration(),
],
tracesSampleRate: 1.0,
});
プロファイリングを含むブラウザー設定
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: '__DSN__',
integrations: [
Sentry.spanStreamingIntegration(),
Sentry.browserTracingIntegration(),
Sentry.browserProfilingIntegration(),
],
tracesSampleRate: 1.0,
profileSessionSampleRate: 1.0,
profileLifecycle: 'trace',
});
移行チェックリスト全体
- SDK のバージョンが
>=10.66.0 - サーバー設定:
traceLifecycle: 'stream'を追加済み - ブラウザー設定:
spanStreamingIntegration()を追加済み -
beforeSendSpanコールバックをSentry.withStreamedSpan()でラップ済み -
beforeSendSpanコールバックを更新済み:description->name、data->attributes -
setTag(s)/scope.setTag(s)の呼び出しに、対応するsetAttribute(s)の呼び出しを追加済み -
beforeSendTransactionのロジックをbeforeSendSpanまたはignoreSpansに移行済み - 設定から
beforeSendTransactionを削除済み - (プロファイリングを使用する場合)
profilesSampleRateをprofileSessionSampleRateとprofileLifecycleに置き換え済み - (プロファイリングを使用する場合)インテグレーションに
browserProfilingIntegration()を追加済み - 型エラーなしでビルドが成功する
- Sentry ダッシュボードにスパンが表示される