すべてのプロダクト
Search
ドキュメントセンター

Simple Log Service:OpenTelemetry SDK for Pythonを使用してPythonアプリケーションからSimple Log Serviceにトレースデータをインポートする

最終更新日:Sep 03, 2024

このトピックでは、OpenTelemetry SDK for Pythonを使用してPythonアプリケーションからSimple Log Serviceにトレースデータをインポートする方法について説明します。

前提条件

  • トレースインスタンスが作成されます。 詳細については、「トレースインスタンスの作成」をご参照ください。

  • Python開発環境がセットアップされました。 Pythonのバージョンは3.7以降です。

  • Python開発環境には、OpenTelemetry SDK for Pythonがインストールされています。

    OpenTelemetry SDK for Pythonがインストールされていない場合は、次のコマンドを実行してSDKをインストールできます。

    pip install opentelemetry-api==1.12.0
    pip install opentelemetry-sdk==1.12.0
    pip install opentelemetry-exporter-otlp==1.12.0

手順

  1. OpenTelemetryプロバイダーを初期化します。

  2. 半自動モードでデータをインポートする条件が満たされているかどうかを確認します。

    • 条件が満たされている場合、トレースデータを半自動モードでインポートできます。

      トレースデータを半自動モードでインポートできないシナリオでは、手動モードでデータをインポートする必要があります。

    • 条件が満たされていない場合は、手動モードでトレースデータをインポートできます。

手順1: OpenTelemetryプロバイダーの初期化

次のコードを使用して、OpenTelemetryプロバイダーを初期化できます。 コード内の変数を実際の値に置き換える必要があります。 変数の詳細については、「変数」をご参照ください。

# For Opentelemetry
import socket
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.export import ConsoleSpanExporter
from opentelemetry.sdk.trace.export import SimpleSpanProcessor


class OpenTelemetrySLSProvider(object):

    def __init__(self, namespace="", service="", version="", endpoint='stdout',
                 project=None, instance=None, access_key_id=None, access_key_secret=None):
        '''
        :param namespace: Your service namespace
        :param service: Your Application Service Name
        :param version: Your Application Version
        :param endpoint: console or https://sls_endpoint:10010
        :param project: SLS project
        :param instance: SLS OTEL InstanceId
        :param access_key_id: Aliyun AccesskeyId
        :param access_key_secret:  Aliyun AccesskeySecret
        '''
        self.sls_otel_endpoint = endpoint
        self.sls_otel_project = project
        self.sls_otel_akid = access_key_id
        self.sls_otel_aksecret = access_key_secret
        self.sls_otel_instanceid = instance
        self.local_mode = False
        if endpoint == "stdout":
            self.local_mode = True
            self.resource = Resource(attributes={
                "host.name": socket.gethostname(),
                "service.name": service,
                "service.namespace": namespace,
                "service.version": version})
        else:
            self.resource = Resource(attributes={
                "host.name": socket.gethostname(),
                "service.namespace": namespace,
                "service.name": service,
                "service.version": version,
                "sls.otel.project": self.sls_otel_project,
                "sls.otel.akid": self.sls_otel_akid,
                "sls.otel.aksecret": self.sls_otel_aksecret,
                "sls.otel.instanceid": self.sls_otel_instanceid
            })

    def initTracer(self):
        trace.set_tracer_provider(TracerProvider(resource=self.resource))
        if self.local_mode:
            trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
        else:
            otlp_exporter = OTLPSpanExporter(endpoint=self.sls_otel_endpoint)
            trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(otlp_exporter))

# debug mode
#sls_ot_provider = OpenTelemetrySLSProvider(service="example", version="v0.1.0")

# write to sls
sls_ot_provider = OpenTelemetrySLSProvider(namespace="${service.namespace}", service="${service}", version="${version}",
                                         endpoint='${endpoint}',
                                         project="${project}",
                                         instance="${instance}",
                                         access_key_id="${access-key-id}",
                                         access_key_secret="${access-key-secret}"
                                         )

表 1. 変数

変数

説明

${service.nameスペース}

サービスが属する名前空間。

order

${service}

サービスの名前です。 ビジネス要件に基づいて値を指定します。

payment

${version}

サービスのバージョンです。 va.b.c形式でバージョンを指定することを推奨します。

v0.1.2

${endpoint}

Simple Log Serviceプロジェクトのエンドポイント。 形式: https://${project}.${region-endpoint}:Port

  • ${project}: Simple Log Serviceプロジェクトの名前。

  • ${region-endpoint}: プロジェクトが存在するリージョンのSimple Log Serviceエンドポイント。 Simple Log Serviceには、内部エンドポイントまたはパブリックエンドポイントを使用してアクセスできます。 内部エンドポイントは、クラシックネットワークまたは仮想プライベートクラウド (VPC) 経由でアクセスできます。 インターネット経由でパブリックエンドポイントにアクセスできます。 詳細については、「エンドポイント」をご参照ください。

  • Port: ポート番号。 値は10010のように固定されます。

説明
  • 変数をstdout (endpoint='stdout') に設定した場合、データは標準出力に表示されます。

  • 変数を空のままにすると、トレースデータはSimple Log Serviceにアップロードされません。

https://test-project.cn-hangzhou.log.aliyuncs.com:10010

${project}

Simple Log Serviceプロジェクトの名前。

test-project

${instance}

トレースインスタンスのID。 詳細については、「トレースインスタンスの作成」をご参照ください。

テストトレース

${access-key-id}

Alibaba CloudアカウントのAccessKey ID。

Simple Log Serviceプロジェクトに対する書き込み権限のみを持つRAMユーザーのAccessKeyペアを使用することを推奨します。 AccessKey ペアは、AccessKey ID と AccessKey Secret で構成されます。 指定したプロジェクトの書き込み権限をRAMユーザーに付与する方法の詳細については、「カスタムポリシーを使用してRAMユーザーに権限を付与する」をご参照ください。 AccessKeyペアを取得する方法の詳細については、「AccessKeyペア」をご参照ください。

なし

${access-key-secret}

Alibaba CloudアカウントのAccessKeyシークレット。

Simple Log Serviceプロジェクトに対する書き込み権限のみを持つRAMユーザーのAccessKeyペアを使用することを推奨します。

なし

ステップ2: データのインポート

トレースデータは、半自動または手動モードでSimple Log Serviceにインポートできます。 OpenTelemetry SDK for Pythonは、さまざまなタイプのインストルメンテーションパッケージを提供し、共通フレームワークの半自動インストルメンテーションをサポートします。 いずれかのインストルメンテーションパッケージを使用する場合は、半自動モードでデータをインポートする必要があります。 詳細については、Instrumentationパッケージをご参照ください。

  • 半自動計測

    この例では、フラスコおよび要求計装パッケージが使用される。

    1. インストルメンテーションパッケージをインストールします。

      pip install requests
      pip install flask
      
      pip install opentelemetry-instrumentation-flask
      
      pip install opentelemetry-instrumentation-requests
    2. コードを実行します。

      次のコードの変数を実際の値に置き換えます。 詳細については、「変数」をご参照ください。

      フラスコのための

      # for flask
      import flask
      import requests
      
      # for Opentelemetry instrumentation
      import socket
      from opentelemetry.instrumentation.flask import FlaskInstrumentor
      from opentelemetry.instrumentation.requests import RequestsInstrumentor
      
      # For Opentelemetry pip install opentelemetry-instrumentation-requests
      from opentelemetry import trace
      from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
          OTLPSpanExporter,
      )
      from opentelemetry.sdk.resources import Resource
      from opentelemetry.sdk.trace import TracerProvider
      from opentelemetry.sdk.trace.export import BatchSpanProcessor
      from opentelemetry.sdk.trace.export import ConsoleSpanExporter
      from opentelemetry.sdk.trace.export import SimpleSpanProcessor
      
      
      class OpenTelemetrySLSProvider(object):
      
          def __init__(self, namespace="", service="", version="", endpoint='stdout',
                       project=None, instance=None, access_key_id=None, access_key_secret=None):
              '''
              :param namespace: Your service namespace
              :param service: Your Application Service Name
              :param version: Your Application Version
              :param endpoint: console or https://sls_endpoint:10010
              :param project: SLS project
              :param instance: SLS OTEL InstanceId
              :param access_key_id: Aliyun AccesskeyId
              :param access_key_secret:  Aliyun AccesskeySecret
              '''
              self.sls_otel_endpoint = endpoint
              self.sls_otel_project = project
              self.sls_otel_akid = access_key_id
              self.sls_otel_aksecret = access_key_secret
              self.sls_otel_instanceid = instance
              self.local_mode = False
              if endpoint == "stdout":
                  self.local_mode = True
                  self.resource = Resource(attributes={
                      "host.name": socket.gethostname(),
                      "service.name": service,
                      "service.namespace": namespace,
                      "service.version": version})
              else:
                  self.resource = Resource(attributes={
                      "host.name": socket.gethostname(),
                      "service.name": service,
                      "service.version": version,
                      "service.namespace": namespace,
                      "sls.otel.project": self.sls_otel_project,
                      "sls.otel.akid": self.sls_otel_akid,
                      "sls.otel.aksecret": self.sls_otel_aksecret,
                      "sls.otel.instanceid": self.sls_otel_instanceid
                  })
      
          def initTracer(self):
              trace.set_tracer_provider(TracerProvider(resource=self.resource))
              if self.local_mode:
                  trace.get_tracer_provider().add_span_processor(
                      SimpleSpanProcessor(ConsoleSpanExporter()))
              else:
                  otlp_exporter = OTLPSpanExporter(endpoint=self.sls_otel_endpoint)
                  trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(otlp_exporter))
      
      
      # write to sls
      sls_ot_provider = OpenTelemetrySLSProvider(namespace="${service.namespace}", service="${service}", version="${version}",
                                                 endpoint='${endpoint}',
                                                 project="${project}",
                                                 instance="${instance}",
                                                 access_key_id="${access-key-id}",
                                                 access_key_secret="${access-key-secret}"
                                                 )
      # for console debug
      #sls_ot_provider = OpenTelemetrySLSProvider(service="example", version="v0.1.0")
      
      sls_ot_provider.initTracer()
      
      # flask init
      app = flask.Flask(__name__)
      
      # instrumentation init
      FlaskInstrumentor().instrument_app(app)
      RequestsInstrumentor().instrument()
      
      
      @app.route("/")
      def hello():
          tracer = trace.get_tracer(__name__)
          with tracer.start_as_current_span("request_server"):
              requests.get("http://www.taobao.com")
          return "hello"
      
      
      app.run(debug=True, port=5000)
    3. サービスにアクセスしてトレースデータの生成をトリガーし、トレースデータをSimple Log serviceに送信します。

      127.0.0.1:5000/hello
  • マニュアル

    次のコードを実行します。 コード内の変数を実際の値に置き換えます。 コードの詳細については、「変数」をご参照ください。

    # ot-manual-example.py
    import time
    
    # For Opentelemetry
    import socket
    from opentelemetry import trace
    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
    from opentelemetry.sdk.resources import Resource
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    from opentelemetry.sdk.trace.export import ConsoleSpanExporter
    from opentelemetry.sdk.trace.export import SimpleSpanProcessor
    
    
    class OpenTelemetrySLSProvider(object):
    
        def __init__(self, namespace="", service="", version="", endpoint='stdout',
                     project=None, instance=None, access_key_id=None, access_key_secret=None):
            '''
            :param service: Your service namespace
            :param service: Your Application Service Name
            :param version: Your Application Version
            :param endpoint: console or https://sls_endpoint:10010
            :param project: SLS project
            :param instance: SLS OTEL InstanceId
            :param access_key_id: Aliyun AccesskeyId
            :param access_key_secret:  Aliyun AccesskeySecret
            '''
            self.sls_otel_endpoint = endpoint
            self.sls_otel_project = project
            self.sls_otel_akid = access_key_id
            self.sls_otel_aksecret = access_key_secret
            self.sls_otel_instanceid = instance
            self.local_mode = False
            if endpoint == "stdout":
                self.local_mode = True
                self.resource = Resource(attributes={
                    "host.name": socket.gethostname(),
                    "service.name": service,
                    "service.namespace": namespace,
                    "service.version": version})
            else:
                self.resource = Resource(attributes={
                    "host.name": socket.gethostname(),
                    "service.name": service,
                    "service.version": version,
                    "service.namespace": namespace,
                    "sls.otel.project": self.sls_otel_project,
                    "sls.otel.akid": self.sls_otel_akid,
                    "sls.otel.aksecret": self.sls_otel_aksecret,
                    "sls.otel.instanceid": self.sls_otel_instanceid
                })
    
        def initTracer(self):
            trace.set_tracer_provider(TracerProvider(resource=self.resource))
            if self.local_mode:
                trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
            else:
                otlp_exporter = OTLPSpanExporter(endpoint=self.sls_otel_endpoint)
                trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(otlp_exporter))
    
    # write to sls
    sls_ot_provider = OpenTelemetrySLSProvider(namespace="${service.namespace}", service="${service}", version="${version}",
                                               endpoint='${endpoint}',
                                               project="${project}",
                                               instance="${instance}",
                                               access_key_id="${access-key-id}",
                                               access_key_secret="${access-key-secret}"
                                               )
    
    # for console debug
    #sls_ot_provider = OpenTelemetrySLSProvider(service="example", version="v0.1.0")
    
    # Trace Example
    sls_ot_provider.initTracer()
    tracer = trace.get_tracer(__name__)
    
    with tracer.start_as_current_span("foo"):
        print("Hello world!")
    
    
    labels = {"environment": "staging"}
    
    time.sleep(60)

よくある質問

OpenTelemetry SDK for Pythonが期待どおりにインストールされているかどうかを確認するにはどうすればよいですか?

次のサンプルコードを使用して、SDKが期待どおりにインストールされているかどうかを確認できます。 コードをtracing.pyファイルとして保存します。 次に、tracing.pyコマンドを実行します。 コマンド出力が期待どおりに返されると、OpenTelemetry SDK for Pythonの関連する依存関係がインストールされます。

# tracing-example-1.py
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleSpanProcessor,
)

trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
    SimpleSpanProcessor(ConsoleSpanExporter())
)

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("foo"):
    print("Hello world!")

python trace

次のステップ