mcpField
S
sentry-span-streaming-python

sentry-span-streaming-python

github.com/getsentry開発272472 回インストール今日更新
リポジトリ

sentry-span-streaming-python について

Sentry のトランザクション単位のトレース送信から Span ストリーミングへ移行するための Python 向けスキルです。Span API、属性、伝播、サンプリング、フィルタリングの変更を案内します。

主な機能

  1. 01Sentry 初期化とトレース利用状況の検出
  2. 02ストリーミング Span ライフサイクルの設定
  3. 03Span 作成 API とデコレーターの移行
  4. 04データとタグを属性へ置き換え
  5. 05伝播とサンプリング規則の更新

活用シーン

  1. 01Python プロジェクトを Span ストリーミングへ移行
  2. 02従来の Span・トランザクション API の移行
  3. 03Span 属性、サンプリング、フィルターの変更

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/getsentry/sentry-for-ai --skill sentry-span-streaming-python

インストール後、Claude Code で/sentry-span-streaming-pythonを入力して読み込まれたか確認します。

詳細

すべてのスキル > 機能のセットアップ > スパンストリーミング(Python)

Sentry スパンストリーミングへの移行(Python)

デフォルトのトランザクションベースのトレースライフサイクル(static)から、スパンストリーミング(stream)に移行します。スパンストリーミングでは、トランザクションの最後にまとめて送信するのではなく、スパンが完了するたびに個別に送信されます。

このスキルでは Python SDK を扱います。JavaScript については、スパンストリーミング(JavaScript)を参照してください。Dart/Flutter については、スパンストリーミング(Dart)を参照してください。

このスキルを使うタイミング

  • ユーザーが Python プロジェクトで「スパンストリーミングを有効にする」または「スパンストリーミングに移行する」よう求めている
  • ユーザーがトランザクションベースからスパンのストリーミング配信に切り替えたいと考えている
  • ユーザーが trace_lifecycle、sentry_sdk.traces、または新しい start_span API に言及している
  • ユーザーがスパン配信の低レイテンシ化や、スパンごとの処理を求めている

環境の検出
# 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 を使用してください。コールバックがスパンの辞書以外を返した場合、その戻り値は無視されます。

動作確認

次の点を確認するようユーザーに案内してください。

  1. Sentry ダッシュボードを確認する:トランザクション全体の完了を待たず、スパンの完了後すぐに Traces ビューに表示されることを確認します
  2. ログを確認する:サポート対象外のスパン操作について、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 ダッシュボードにスパンが表示される

コメント