Python トレース SDK

Instana によるトレースは自動的に行われますが、カスタムコード、特定のアプリケーション領域、または社内コンポーネントについてさらに詳細な可視性を確保したい場合は、 Instana Python のトレース SDK をご利用いただけます。

注:Instana Python Tracing SDK 3.0.0 以降のバージョンでは、 OpenTelemetry API がサポートされています。 非推奨となった OpenTracing API をサポートする Instana Python トレース SDK を使用する場合は、 Python OpenTracing (非推奨) を参照してください。

Instana Python Tracing SDK

Instana ( Python )モジュールは、 OpenTelemetry ( API )をベースにした API を提供し、アプリケーションの任意の部分を追跡することができます。

API を使用して、コードの一部にトレース用のインストルメンテーションを適用するには、次のようにします

from instana.singletons import tracer


try:
    span = tracer.start_span("span_name")
    # The code to be instrumented
    id = user.find_by_name("john.smith")
    span.set_attribute("user_id", id)
except Exception as e:
    span.record_exception(e)
finally:
    if span and span.is_recording():
        span.end()
 

あるいは、 with-as ステートメントでコンテキスト・マネージャーを使用することもできます。これにより、以下のように、発生したすべての例外が自動的にキャプチャーされ、ログに記録されます。

from instana.singletons import tracer


with tracer.start_as_current_span("span_name") as span:
    # The code to be instrumented.
    id = user.find_by_name("john.smith")
    span.set_attribute("user_id", id)
 

非同期トレース

トレースしたい操作の中には、非同期のものがあるかもしれません。つまり、即座に処理を返しますが、メインの命令シーケンスとは別個に処理が継続されるということです。 たとえば、asyncio ライブラリを使用してこれらの操作を追跡するには、以下のトレースメソッドを使用できます:

import asyncio
from instana.singletons import tracer


async def do_work(parent_span):
    parent_context = parent_span.get_span_context() if parent_span else None
    with tracer.start_as_current_span(
        "launch_async_work",
        span_context=parent_context
    ):
        print("Work stared")
        await asyncio.sleep(1)
        print("Work finished!")

with tracer.start_as_current_span("launch_uvloop") as sync_span:
    asyncio.run(do_work(sync_span))
 

分岐したプロセスにおけるスパンを追跡する

フォークされたプロセス内のスパンを追跡したい場合は、の後に time.sleep() を追加してください span.end()。 以下の例を参照してください。

from instana.singletons import tracer


 def forked_process(num):
    print(f"in forked process {num}")
    try:
        span = tracer.start_span(f"forked process {num}")
        print(f"sleep 10 for forked process {num}")
        time.sleep(10)
    except Exception as e:
        span.record_exception(e)
    finally:
        if span and span.is_recording():
            span.end()

    logger.warning(f"sleep 2 for forked process {num}")
    time.sleep(2)   ##  < -- with a sleep after span.finish(), the span can be collected
 

新規スレッドへのコンテキストの伝達

トレースはスレッドに対してローカルです。 新規スレッドを作成する場合は、コンテキストをその新規スレッドに持ち込んでから、取得する必要があります。 以下のように、コンテキストを新しいスレッドに持ち込めるようにコードをインスツルメントできます。

from instana.singletons import tracer
from threading import Thread


def child_thread_function(parent_span):
    parent_context = parent_span.get_span_context() if parent_span else None
    with tracer.start_as_current_span(
        "child_thread_span",
        span_context=parent_context
    ) as child_span:
        print("Thread offloaded work goes here")

with tracer.start_as_current_span("parent_thread_span") as parent_span:
    thread = Thread(
        target = child_thread_function,
        args = (parent_span,)
    )
    thread.start()
    thread.join()
 

後で実行されるジョブの追跡

以下のようにして、後で実行するためにキューに入れられたジョブをインスツルメンテーションすることができます。

# Python 3.8
import asyncio
import datetime
import uvloop
import aiohttp

from instana.singletons import tracer
from opentelemetry.trace import SpanKind


uvloop.install()


async def launch_async_calls(parent_span):
    parent_context = parent_span.get_span_context() if parent_span else None
    with tracer.start_as_current_span(
        "launch_async_calls",
        span_context=parent_context
    ):
        async with aiohttp.ClientSession() as session:
            async with session.get("https://wikipedia.org") as resp:
               print(resp.status)
               print(await resp.text())


async def run_at(dt, coro):
    await asyncio.sleep((dt - datetime.datetime.now()).total_seconds())
    return await coro


with tracer.start_as_current_span("launch_uvloop") as sync_span:
    sync_span.set_attribute("span.kind", SpanKind.SERVER)
    asyncio.run(
        run_at(
            datetime.datetime.now() + datetime.timedelta(seconds=5),
            launch_async_calls(sync_scope.span)
        )
    )
 

Instana のスパンにカスタムタグを追加する

Instana のspan要素にカスタム属性を追加するには、` set_attribute() method` を使用して以下のコードを実装してください:

from instana.singletons import tracer


with tracer.start_as_current_span("span_name") as span:
    span.set_attribute("custom_attribute", "custom_value")
 

カスタムタグを使用したスパン種別の設定

Instana のspan要素の型を明示的に定義するには、カスタム属性を span.kind 次のように設定します:

from instana.singletons import tracer
from opentelemetry.trace import SpanKind


with tracer.start_as_current_span("span_name") as span:
    span.set_attribute("span.kind", <value>)

を、以下の有効な値のいずれかに <value> 置き換えてください:

スパンの種類 許容値
エントリの範囲 "entry""server""consumer"SpanKind.SERVER、または SpanKind.CONSUMER
出口のスパン "exit""client""producer"SpanKind.CLIENT、または SpanKind.PRODUCER
内部スパン(デフォルト) "intermediate"またはSpanKind.INTERNAL