sentry-span-streaming-python について
Sentry のトランザクション単位のトレース送信から Span ストリーミングへ移行するための Python 向けスキルです。Span API、属性、伝播、サンプリング、フィルタリングの変更を案内します。
主な機能
- 01Sentry 初期化とトレース利用状況の検出
- 02ストリーミング Span ライフサイクルの設定
- 03Span 作成 API とデコレーターの移行
- 04データとタグを属性へ置き換え
- 05伝播とサンプリング規則の更新
活用シーン
- 01Python プロジェクトを Span ストリーミングへ移行
- 02従来の Span・トランザクション API の移行
- 03Span 属性、サンプリング、フィルターの変更
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ getsentry/ sentry-for-ai --skill sentry-span-streaming-pythonインストール後、Claude Code で/sentry-span-streaming-pythonを入力して読み込まれたか確認します。
詳細
Sentry スパンストリーミングへの移行(Python)
デフォルトのトランザクションベースのトレースライフサイクル(static)から、スパンストリーミング(stream)に移行します。スパンストリーミングでは、トランザクションの最後にまとめて送信するのではなく、スパンが完了するたびに個別に送信されます。
このスキルでは Python SDK を扱います。JavaScript については、スパンストリーミング(JavaScript)を参照してください。Dart/Flutter については、スパンストリーミング(Dart)を参照してください。
このスキルを使うタイミング
- ユーザーが Python プロジェクトで「スパンストリーミングを有効にする」または「スパンストリーミングに移行する」よう求めている
- ユーザーがトランザクションベースからスパンのストリーミング配信に切り替えたいと考えている
- ユーザーが
trace_lifecycle、sentry_sdk.traces、または新しいstart_spanAPI に言及している - ユーザーがスパン配信の低レイテンシ化や、スパンごとの処理を求めている
環境の検出
# Find sentry_sdk.init calls
grep -rn "sentry_sdk\.init\|sentry_sdk\.init(" --include="*.py" -l 2>/dev/null | head -20
# Find existing start_span / start_transaction / start_child usage
grep -rn "start_span\|start_transaction\|start_child" --include="*.py" -l 2>/dev/null | head -20
# Find trace decorator usage
grep -rn "@trace\|from sentry_sdk import trace\|from sentry_sdk.tracing import trace" --include="*.py" -l 2>/dev/null | head -20
# Find continue_trace usage
grep -rn "continue_trace" --include="*.py" -l 2>/dev/null | head -20
# Find before_send_transaction usage
grep -rn "before_send_transaction" --include="*.py" -l 2>/dev/null | head -20
# Find direct Span / Transaction class imports
grep -rn "from sentry_sdk.tracing import\|from sentry_sdk import.*Span\|from sentry_sdk import.*Transaction" --include="*.py" -l 2>/dev/null | head -20
# Find set_data / set_tag / set_context on spans
grep -rn "set_data\|set_tag\|set_context" --include="*.py" -l 2>/dev/null | head -20
# Find scope.span / scope.transaction / containing_transaction access
grep -rn "scope\.span\|scope\.transaction\|containing_transaction" --include="*.py" -l 2>/dev/null | head -20
# Find get_trace_context usage
grep -rn "get_trace_context" --include="*.py" -l 2>/dev/null | head -20
並列化
環境を検出した後、変更が必要なファイルの数を確認します。移行対象のファイルが多数ある場合(たとえば、start_span、start_transaction、set_data などを含むファイルが数十個ある場合)は、独立した移行タスクを並列で処理するサブエージェントを起動します。たとえば、移行カテゴリ(スパンの作成、スパンデータ、トレースの伝播)ごと、またはモジュール/パッケージごとにサブエージェントを割り当てます。各サブエージェントには、このスキルから該当する移行ルールを渡し、それぞれ異なるファイル群を担当させてください。
スパンストリーミングを有効にする
前提条件: トレースが有効な状態で(traces_sample_rate または traces_sampler を設定)、sentry-sdk >=2.66.0 を使用していること。
すべての sentry_sdk.init() に、トップレベルの trace_lifecycle オプションを追加します。
import sentry_sdk
# Before
sentry_sdk.init(
dsn="...",
traces_sample_rate=1.0,
)
# After
sentry_sdk.init(
dsn="...",
traces_sample_rate=1.0,
trace_lifecycle="stream",
)
スパンストリーミングを使用するには、新しい sentry_sdk.traces.start_span API を使う必要があります。従来の sentry_sdk.start_span および sentry_sdk.start_transaction API では、スパンはストリーミングされません。
スパンの作成を移行する
start_span
sentry_sdk.start_span() を sentry_sdk.traces.start_span() に置き換えます。
import sentry_sdk
# Before
with sentry_sdk.start_span(name="flow.checkout") as span:
...
# After
with sentry_sdk.traces.start_span(name="flow.checkout") as span:
...
または、インポートを変更します。
# Before
from sentry_sdk import start_span
# After
from sentry_sdk.traces import start_span
新しい API では、以下を指定できます。
name(必須)attributes— キーと値のペア(下記の「スパンデータを移行する」を参照)parent_span— 明示的な親スパン。デフォルトでは現在アクティブなスパンになりますactive— デフォルトはTrueです。Falseの場合、このスパンがほかのスパンの親に自動設定されることはありません
description 引数はなくなりました。代わりに name を使用してください。op 引数はサポートされなくなりました。代わりに sentry.op 属性を使用してください。
# Before
with sentry_sdk.start_span(op="http.client", description="GET /api/users") as span:
...
# After
with sentry_sdk.traces.start_span(
name="GET /api/users",
attributes={"sentry.op": "http.client"},
) as span:
...
start_transaction
sentry_sdk.start_transaction() を sentry_sdk.traces.start_span() に置き換えます。
import sentry_sdk
# Before
with sentry_sdk.start_transaction(name="flow.checkout") as transaction:
...
# After
with sentry_sdk.traces.start_span(name="flow.checkout", parent_span=None) as span:
...
parent_span=None を設定すると、このスパンはルートスパンになります。これは、従来の API でトランザクションを開始するのと同じです。
start_child
span.start_child() はなくなりました。親がアクティブな状態で新しいスパンを開始すると、自動的にその子になります。
import sentry_sdk
# Before
with sentry_sdk.start_span(name="outer") as parent:
with parent.start_child(op="db", description="SELECT") as child:
...
# After
with sentry_sdk.traces.start_span(name="outer") as parent:
with sentry_sdk.traces.start_span(
name="SELECT",
attributes={"sentry.op": "db"},
):
...
親子関係を明示的に制御する場合(たとえば、スパンを子ではなく兄弟にする場合)は、parent_span を使用します。
with sentry_sdk.traces.start_span(name="outer") as span:
with sentry_sdk.traces.start_span(name="child 1"):
with sentry_sdk.traces.start_span(name="child 2", parent_span=span):
# "child 2" is a sibling of "child 1", not its child
...
@trace デコレーター
sentry_sdk.trace を sentry_sdk.traces.trace に置き換えます。
# Before
from sentry_sdk import trace
@trace
def checkout():
...
# After — just change the import
from sentry_sdk.traces import trace
@trace
def checkout():
...
新しいデコレーターでは、オプションとして name(デフォルトは関数名)、attributes、および active も指定できます。
from sentry_sdk.traces import trace
@trace(name="checkout", attributes={"flow.pipeline": "legacy"})
def checkout():
...
get_current_span
sentry_sdk.get_current_span() を sentry_sdk.traces.get_current_span() に置き換えます。
# Before
from sentry_sdk import get_current_span
span = get_current_span()
# After
from sentry_sdk.traces import get_current_span
span = get_current_span()
scope.span と scope.transaction
scope オブジェクトを通じて現在のスパンまたはトランザクションにアクセスしている場合は、新しい API に移行します。
import sentry_sdk
# Before
scope = sentry_sdk.get_current_scope()
current_span = scope.span
# After
current_span = sentry_sdk.traces.get_current_span()
import sentry_sdk
# Before
scope = sentry_sdk.get_current_scope()
transaction = scope.transaction
# After
root_span = sentry_sdk.traces.get_current_span()._segment
_segment は、現在のトレースのルートスパン(従来のトランザクションに相当)を返します。これはプライベート API です。可能な限り、ルートスパンを必要としない形にコードを再構成してください。
span.containing_transaction
span.containing_transaction はなくなりました。ルートスパンを取得するには span._segment を使用します。
# Before
transaction = span.containing_transaction
# After
root_span = span._segment
Span クラスと Transaction クラス
コードで型注釈などのために Span または Transaction を直接インポートしている場合は、両方を StreamedSpan に置き換えます。
# Before
from sentry_sdk.tracing import Span, Transaction
def process(span: Span) -> None:
...
# After
from sentry_sdk.traces import StreamedSpan
def process(span: StreamedSpan) -> None:
...
get_trace_context
ストリーミングスパンでは span.get_trace_context() は使用できなくなりました。トレースコンテキストから実際に必要な情報に応じて移行してください。
trace_id、span_id、parent_span_id など、特定のフィールドだけを読み取る場合は、スパンのプロパティから直接アクセスします。
# Before
ctx = span.get_trace_context()
trace_id = ctx["trace_id"]
span_id = ctx["span_id"]
# After
trace_id = span.trace_id
span_id = span.span_id
外部システムに渡したりシリアライズしたりするために、トレースコンテキストの辞書全体が本当に必要な場合は、プライベートメソッド span._get_trace_context() を使用します。
# Before
ctx = span.get_trace_context()
# After
ctx = span._get_trace_context()
可能な場合は、プロパティに直接アクセスする方法を優先してください。_get_trace_context() はプライベート API であり、変更される可能性があります。
スパンデータの移行
スパンストリーミングモードでは、スパンにコンテキスト、データ、タグはありません。すべてスパン属性になります。属性キーは文字列で、値には int、bool、str、float、またはこれらの型の配列を指定する必要があります。None はサポートされていません。
重要: 従来の set_data/set_tag API とは異なり、set_attribute がサポートするのはプリミティブ型のみです。プリミティブ型以外の値は、文字列化するか、複数のプリミティブ型属性に分割する必要があります。
# Before — set_data accepted any type
span.set_data("request", {"method": "POST", "path": "/api/checkout"})
span.set_data("response_headers", response.headers)
# After — flatten dicts into separate attributes
span.set_attributes({
"request.method": "POST",
"request.path": "/api/checkout",
})
# After — stringify objects that can't be flattened
span.set_attribute("response_headers", str(response.headers))
set_data の置き換え
# Before
span.set_data("flow.step", "submit_payment")
# After
span.set_attribute("flow.step", "submit_payment")
set_tag の置き換え
# Before
span.set_tag("http.status_code", 201)
# After
span.set_attribute("http.response.status_code", 201)
連続する複数の set_data/set_tag 呼び出しを移行する場合は、1 つの set_attributes() 呼び出しにまとめます。
# Before
span.set_data("flow.step", "submit_payment")
span.set_data("flow.version", "0.35")
span.set_tag("http.status_code", 201)
# After
span.set_attributes({
"flow.step": "submit_payment",
"flow.version": "0.35",
"http.response.status_code": 201,
})
set_context の置き換え
辞書は属性値としてサポートされていません。個別の属性にフラット化してください。
# Before
span.set_context("flow", {"id": "123456789", "pipeline": "legacy"})
# After
span.set_attributes({"flow.id": "123456789", "flow.pipeline": "legacy"})
スコープレベルのタグ
スコープに設定されたタグは、sentry_sdk.set_tag() を使用してもストリーミングスパンには適用されません。スパンにデータを適用するには、sentry_sdk.set_attribute() を使用します。
import sentry_sdk
sentry_sdk.set_tag("region", "Europe") # applied to errors and other tag-supporting telemetry
sentry_sdk.set_attribute("region", "Europe") # applied to spans, logs, metrics
一括操作
with sentry_sdk.traces.start_span(name="flow.checkout") as span:
span.set_attribute("flow.version", "0.35")
span.set_attributes({"flow.conversion": 1.0, "flow.use_new_pipeline": True})
span.remove_attribute("flow.conversion")
スパンのステータス
ステータスには ok(デフォルト)または error のみを指定できます。
from sentry_sdk.traces import start_span
with start_span(name="process") as span:
try:
...
except Exception:
span.status = "error"
トレース伝播の移行
sentry_sdk.traces.continue_trace() は、従来の sentry_sdk.continue_trace() に代わるものです。コンテキストマネージャーではなくなりました。伝播コンテキストを設定し、次のスパンが自動的にそれを取得します。
import sentry_sdk
headers = {
"sentry-trace": "4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1",
"baggage": "sentry-trace_id=...",
}
# Before
with sentry_sdk.continue_trace(headers) as transaction:
...
# After
sentry_sdk.traces.continue_trace(headers)
with sentry_sdk.traces.start_span(name="handle request"):
...
まったく新しいトレースを開始するには、sentry_sdk.traces.new_trace() を使用します。
import sentry_sdk
with sentry_sdk.traces.start_span(name="span in trace 1"):
...
sentry_sdk.traces.new_trace()
with sentry_sdk.traces.start_span(name="span in trace 2"):
# This span is the root of a new, separate trace
...
サンプリングの移行
traces_sample_rate を使用している場合、変更は必要ありません。これまでと同じように動作します。
カスタムの traces_sampler を使用している場合、ストリーミングモードではサンプリングコンテキストの構造が異なります。
def traces_sampler(sampling_context):
# sampling_context["span_context"] contains:
# name, trace_id, parent_span_id, parent_sampled, attributes
if sampling_context["span_context"]["name"] in IGNORED_SPAN_NAMES:
return 0.0
return 1.0
sentry_sdk.init(
traces_sampler=traces_sampler,
trace_lifecycle="stream",
)
サンプリングの判定は start_span() の呼び出し時に行われます。ignore_spans によって除外されない限り、子スパンは親のサンプリング判定を引き継ぎます。
カスタムサンプリングコンテキスト
カスタムサンプリングコンテキストは、start_span の引数ではなくなりました。スパンを開始する前にスコープに設定してください。
import sentry_sdk
def traces_sampler(sampling_context):
if sampling_context["asgi_scope"].method not in ("GET", "POST"):
return 0.0
return 1.0
# Before
with sentry_sdk.start_span(
name="handle request",
custom_sampling_context={"asgi_scope": asgi_scope},
):
...
# After
sentry_sdk.Scope.set_custom_sampling_context({"asgi_scope": asgi_scope})
with sentry_sdk.traces.start_span(name="handle request"):
...
カスタムサンプリングコンテキストは、continue_trace(伝播コンテキストをリセットします)の後、かつ start_span(この時点でサンプリングが行われます)の前に設定する必要があります。
ignore_spans の設定(任意)
ignore_spans はスパンの作成時にスパンをフィルタリングします。ルールには文字列、コンパイル済みの正規表現、または name や attributes の条件を含む辞書を指定できます。
import re
import sentry_sdk
sentry_sdk.init(
trace_lifecycle="stream",
ignore_spans=[
# String match against span name
"/health",
# Regex match against span name
re.compile(r"/flow/.*"),
# Match by attributes (all must match)
{
"attributes": {
"service.id": "15def9a",
"flow.pipeline": "legacy",
}
},
# Match by name and attributes
{
"name": re.compile(r"/flow/.*"),
"attributes": {
"service.id": re.compile(r".*\.facade"),
},
},
],
)
ignore_spans が有効になるのは、trace_lifecycle="stream" が有効な場合のみです。スパンストリーミングを有効にせずに設定した場合、SDK は警告を出力し、このオプションを無視します。
照合に使用できるのは、スパン名と作成時に設定された属性のみです。スパンの存続期間中に後から追加された属性は考慮されません。
無視されたスパンがトップレベルのスパンの場合、そのサブツリー全体も無視されます。トップレベルではないスパンが無視された場合、その子スパンは、それぞれがルールに一致しない限り、自動的には無視されません。
before_send_transaction の移行
before_send_transaction はストリーミングモードでは効果がありません。スパンはトランザクションにまとめられず、完了するたびに個別に送信されます。
重要: 従来のトランザクションベースのモデルでは、before_send_transaction はトランザクション全体の完了後に実行されていたため、スパンの存続期間中に設定されたすべてのデータ(HTTP ステータスコード、レスポンスサイズ、最終結果など)にアクセスできました。ストリーミングモードでは、代替機能(ignore_spans と before_send_span)が使用できるのは、スパン開始時に設定された属性のみです。スパンの存続期間中に後から追加された属性(http.response.status_code、レスポンスボディのサイズ、その他の後から設定されるデータなど)は使用できません。
before_send_transaction のロジックがスパン開始時に設定されない属性に依存している場合、そのフィルタリングロジックはストリーミングモードでは再現できないため、削除する必要があります。代わりに、サーバーサイドの仕組み(Sentry の受信データフィルターや Relay ルールなど)にフィルタリングを移すことを検討してください。
| ユースケース | ストリーミングモードでの代替手段 |
|---|---|
| 名前/ルートでスパンを破棄する | ignore_spans を使用します |
| 後から設定される属性(HTTP ステータスコードなど)で破棄/フィルタリングする | 再現できません — ロジックを削除するか、サーバーサイドでフィルタリングします |
| 送信前にスパンデータを変更する | before_send_span を使用します |
| トランザクション名でフィルタリングする | 文字列/正規表現パターンを指定して ignore_spans を使用します |
ロジックの移行後、sentry_sdk.init() から before_send_transaction オプションを削除してください。
before_send_span の設定(任意)
before_send_span を使うと、機密情報の値のサニタイズなど、SDK から送信される前にスパンを変更できます。span と hint の引数を受け取り、スパンを返す必要があります。
import sentry_sdk
def postprocess_span(span, hint):
attributes_to_sanitize = [
"http.request.header.custom-auth",
"http.request.header.custom-user-id",
]
for attribute in attributes_to_sanitize:
if span["attributes"].get(attribute):
span["attributes"][attribute] = "[Sanitized]"
return span
sentry_sdk.init(
trace_lifecycle="stream",
_experiments={
"before_send_span": postprocess_span,
},
)
before_send_span でスパンを破棄することはできません。破棄する場合は ignore_spans を使用してください。コールバックがスパンの辞書以外を返した場合、その戻り値は無視されます。
動作確認
次の点を確認するようユーザーに案内してください。
- Sentry ダッシュボードを確認する:トランザクション全体の完了を待たず、スパンの完了後すぐに Traces ビューに表示されることを確認します
- ログを確認する:サポート対象外のスパン操作について、SDK の警告がないことを確認します
よくある問題
| 症状 | 原因 | 対処方法 |
|---|---|---|
| スパンがストリーミングされない | 従来の sentry_sdk.start_span を使用している | sentry_sdk.traces.start_span に切り替えます |
start_child で AttributeError が発生する | ストリーミングモードでは start_child が削除されている | 親スパンがアクティブな間に sentry_sdk.traces.start_span を使用します |
None の属性値が拒否される | 属性値として None はサポートされていない | 属性を削除するか、代替の文字列を使用します |
set_data/set_tag がスパンに反映されない | これらのメソッドはストリーミングスパンには適用されない | span.set_attribute() を使用します |
| スコープのタグがスパンにない | set_tag はストリーミングスパンに適用されない | sentry_sdk.set_attribute() を使用します |
カスタムサンプリングコンテキストを traces_sampler で使用できない | start_span の後、または continue_trace の前に設定している | continue_trace の後、start_span の前にスコープへ設定します |
scope.span が誤った型または None を返す | スコープを使ったスパンへのアクセスは、ストリーミングモードでは信頼できない | sentry_sdk.traces.get_current_span() を使用します |
containing_transaction で AttributeError が発生する | ストリーミングモードでは属性が削除されている | span._segment を使用します |
get_trace_context で AttributeError が発生する | ストリーミングモードではメソッドが削除されている | span.trace_id/span.span_id を直接使用するか、span._get_trace_context() を使用します |
before_send_transaction が呼び出されない | ストリーミングモードでは想定どおりの動作 | ロジックを before_send_span または ignore_spans に移行します |
警告:ignore_spans は trace_lifecycle が stream に設定されている場合のみ機能する | スパンストリーミングを有効にせずに ignore_spans を設定している | trace_lifecycle="stream" でストリーミングを有効にするか、ignore_spans を削除します |
before_send_transaction のロジックが後から設定される属性(ステータスコードなど)に依存している | これらの属性はスパン作成時には使用できない | ロジックを削除するか、サーバーサイドでフィルタリングします(Sentry の受信データフィルター/Relay ルール) |
クイックリファレンス
最小限のセットアップ
import sentry_sdk
sentry_sdk.init(
dsn="__DSN__",
traces_sample_rate=1.0,
trace_lifecycle="stream",
)
スパンの作成
from sentry_sdk.traces import start_span
with start_span(name="my operation", attributes={"sentry.op": "task"}) as span:
span.set_attribute("result.count", 42)
移行チェックリスト
- SDK のバージョンが
>=2.66.0である -
sentry_sdk.init()にトップレベルのtrace_lifecycle="stream"を追加した -
sentry_sdk.start_span()をsentry_sdk.traces.start_span()に移行した -
sentry_sdk.start_transaction()をsentry_sdk.traces.start_span()に移行した -
span.start_child()をsentry_sdk.traces.start_span()に移行した -
sentry_sdk.get_current_span()をsentry_sdk.traces.get_current_span()に移行した -
scope.spanをsentry_sdk.traces.get_current_span()に置き換えた -
scope.transactionをsentry_sdk.traces.get_current_span()._segmentに置き換えた -
span.containing_transactionをspan._segmentに置き換えた -
@sentry_sdk.traceを@sentry_sdk.traces.traceに移行した -
Span/TransactionクラスのインポートをStreamedSpanに置き換えた -
span.get_trace_context()を直接のプロパティ(span.trace_idなど)またはspan._get_trace_context()に置き換えた -
descriptionをnameに置き換えた -
opをsentry.op属性に置き換えた -
set_data()/set_tag()/set_context()をset_attribute()に置き換えた - 必要に応じて、スコープレベルの
set_tag()にset_attribute()を追加した -
continue_traceを、コンテキストマネージャーを使わないsentry_sdk.traces.continue_trace()に移行した -
custom_sampling_contextをScope.set_custom_sampling_context()に移行した - (
traces_samplerを使用している場合)新しいsampling_contextの形式に対応するよう更新した -
before_send_transactionのロジックをbefore_send_spanまたはignore_spansに移行した - 後から設定される属性(HTTP ステータスコードなど)に依存する
before_send_transactionのロジックを削除するか、サーバー側のフィルタリングに移行した - 設定から
before_send_transactionを削除した - Sentry ダッシュボードにスパンが表示される