All Products
Search
Document Center

Managed Service for OpenTelemetry:Use OpenTelemetry to report the trace data of Python applications

Last Updated:Jan 29, 2024

Before you can view the trace data of your application, you must use a client to report the trace data to Managed Service for OpenTelemetry. This topic describes how to use OpenTelemetry SDK for Python to report the trace data of a Python application.

Prerequisites

To obtain an endpoint of OpenTelemetry, perform the following steps:

  1. Log on to the Managed Service for OpenTelemetry console.

  2. In the left-side navigation pane, click Cluster Configurations. Then, click the Access point information tab.

  3. In the top navigation bar, select a region. In the Cluster Information section, turn on Show Token.

  4. In the Client section, click OpenTelemetry.

    Obtain an endpoint of OpenTelemetry in the Related Information column of the table in the lower part. OT接入点信息

    Note

    If your application is deployed in an Alibaba Cloud production environment, use a Virtual Private Cloud (VPC) endpoint. Otherwise, use a public endpoint.

Background information

OpenTelemetry provides multiple automatic instrumentation plug-ins that can be used to automatically create spans for common frameworks. The following table describes the supported frameworks. For more information, see OpenTelemetry official documentation.

Note

In the following table, Version number ~= V.N indicates Version number ≥ V.N and Version number == V.*. For example, aiohttp ~= 3.0 indicates that the version of aiohttp must meet the following requirements: Version number ≥ 3.0 and Version number == 3.*.

Supported Python frameworks

OpenTelemetry plug-in

Supported package and version

opentelemetry-instrumentation-aio-pika

aio_pika - [7.2.0, 10.0.0)

opentelemetry-instrumentation-aiohttp-client

aiohttp ~= 3.0

opentelemetry-instrumentation-aiohttp-server

aiohttp ~= 3.0

opentelemetry-instrumentation-aiopg

aiopg - [0.13.0, 2.0.0)

opentelemetry-instrumentation-asgi

asgiref ~= 3.0

opentelemetry-instrumentation-asyncpg

asyncpg ≥ 0.12.0

opentelemetry-instrumentation-aws-lambda

aws_lambda

opentelemetry-instrumentation-boto

boto ~= 2.0

opentelemetry-instrumentation-boto3sqs

boto3 ~= 1.0

opentelemetry-instrumentation-botocore

botocore ~= 1.0

opentelemetry-instrumentation-cassandra

  • cassandra-driver ~= 3.25

  • scylla-driver ~= 3.25

opentelemetry-instrumentation-celery

celery - [4.0, 6.0)

opentelemetry-instrumentation-confluent-kafka

confluent-kafka - [1.8.2, 2.2.0]

opentelemetry-instrumentation-dbapi

dbapi

opentelemetry-instrumentation-django

django ≥ 1.10

opentelemetry-instrumentation-elasticsearch

elasticsearch ≥ 2.0

opentelemetry-instrumentation-falcon

falcon - [1.4.1, 4.0.0)

opentelemetry-instrumentation-fastapi

fastapi ~= 0.58

opentelemetry-instrumentation-flask

flask - [1.0, 3.0)

opentelemetry-instrumentation-grpc

grpcio ~= 1.27

opentelemetry-instrumentation-httpx

httpx ≥ 0.18.0

opentelemetry-instrumentation-jinja2

jinja2 - [2.7, 4.0)

opentelemetry-instrumentation-kafka-python

kafka-python ≥ 2.0

opentelemetry-instrumentation-logging

logging

opentelemetry-instrumentation-mysql

mysql-connector-python ~= 8.0

opentelemetry-instrumentation-mysqlclient

mysqlclient < 3

opentelemetry-instrumentation-pika

pika ≥ 0.12.0

opentelemetry-instrumentation-psycopg2

psycopg2 ≥ 2.7.3.1

opentelemetry-instrumentation-pymemcache

pymemcache - [1.3.5, 5)

opentelemetry-instrumentation-pymongo

pymongo - [3.1, 5.0)

opentelemetry-instrumentation-pymysql

PyMySQL < 2

opentelemetry-instrumentation-pyramid

pyramid ≥ 1.7

opentelemetry-instrumentation-redis

redis ≥ 2.6

opentelemetry-instrumentation-remoulade

remoulade ≥ 0.50

opentelemetry-instrumentation-requests

requests ~= 2.0

opentelemetry-instrumentation-sklearn

scikit-learn ~= 0.24.0

opentelemetry-instrumentation-sqlalchemy

sqlalchemy

opentelemetry-instrumentation-sqlite3

sqlite3

opentelemetry-instrumentation-starlette

starlette ~= 0.13.0

opentelemetry-instrumentation-system-metrics

psutil ≥ 5

opentelemetry-instrumentation-tornado

tornado ≥ 5.1.1

opentelemetry-instrumentation-tortoiseorm

tortoise-orm ≥ 0.17.0

opentelemetry-instrumentation-urllib

urllib

opentelemetry-instrumentation-urllib3

urllib3 - [1.0.0, 3.0.0)

opentelemetry-instrumentation-wsgi

wsgi

Sample code

Download the sample code from python-opentelemetry-demo.

Method 1: Use an agent to automatically instrument an application

  1. Download and install the required packages.

    pip install django
    pip install requests
    pip install opentelemetry-distro \
    	opentelemetry-exporter-otlp
     
    opentelemetry-bootstrap -a install
  2. Create an AutoAndManualDemo project and create a HelloWorld application.

    1. Create an AutoAndManualDemo project.

      django-admin startproject AutoAndManualDemo
    2. Create a HelloWorld application in the project.

      cd AutoAndManualDemo
      
      # Create a HelloWorld application in the project.
      python manage.py startapp helloworld
  3. Modify the code of the HelloWorld application.

    1. Add the following code to the helloworld/views.py file:

      from django.http import HttpResponse
      from datetime import datetime
      
      # Create your views here.
      def hello_world_view(request):
          result = "Hello World! Current Time =" + str(get_time())
          return HttpResponse(result)
      
      def get_time():
          now = datetime.now()
          return now.strftime("%H:%M:%S")
    2. Create a helloworld/urls.py file and add the following code to the file:

      from django.urls import path
      
      from . import views
      
      urlpatterns = [
          path('', views.hello_world_view, name='helloworld')
      ]
    3. Add the URL pattern to the AutoAndManualDemo/urls.py file.

      from django.contrib import admin
      from django.urls import path, include
      
      urlpatterns = [
       path('admin/', admin.site.urls),
       path('helloworld/', include('helloworld.urls')),
      ]
  4. Run the project.

    To report trace data over HTTP, replace <your-service-name> with your application name and <http-endpoint> with the HTTP endpoint.

    opentelemetry-instrument \
        --traces_exporter console,otlp_proto_http \
        --metrics_exporter none \
        --service_name <your-service-name> \
        --exporter_otlp_traces_endpoint <http-endpoint> \
        python manage.py runserver
    Note

    A CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False error may occur even though both DEBUG and ALLOWED_HOSTS in the AutoAndManualDemo/AutoAndManualDemo/settings.py file are correctly specified. This is because the default configuration file django/conf/global_settings.py of Django is used when you start the project by using opentelemetry-instrument. In this case, you must add the export DJANGO_SETTINGS_MODULE=AutoAndManualDemo.settings environment variable.

  5. Visit http://127.0.0.1:8000/helloworld/ in a browser. The console displays the trace data and reports the trace data to Managed Service for OpenTelemetry.

    If you do not want the console to display the trace data, set the --traces_exporter parameter to --traces_exporter otlp_proto_http.

Method 2: Manually instrument an application

  1. Download and install the required packages.

    pip install opentelemetry-api
    pip install opentelemetry-sdk
    pip install opentelemetry-exporter-otlp
  2. Specify the OpenTelemetry initialization code in the manual.py file.

    • Replace <endpoint> in the <token> section of the code with the endpoint of OpenTelemetry that you obtained.

    • Replace <service-name> and <host-name> in the code with the actual application name and hostname.

    from opentelemetry import trace, baggage
    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter as OTLPSpanGrpcExporter
    from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter as OTLPSpanHttpExporter
    from opentelemetry.sdk.resources import SERVICE_NAME, Resource, HOST_NAME
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    
    def init_opentelemetry():
        # Specify the application name and hostname.
        resource = Resource(attributes={
            SERVICE_NAME: "<service-name>",
            HOST_NAME: "<host-name>"
        })
        # Use the gRPC protocol to report data.
        span_processor = BatchSpanProcessor(OTLPSpanGrpcExporter(
            endpoint="<endpoint>",
            headers=("Authentication=<token>")
        ))
        # Use the HTTP protocol to report data.
        # span_processor = BatchSpanProcessor(OTLPSpanHttpExporter(
        #     endpoint="<endpoint>",
        # ))
        trace_provider = TracerProvider(resource=resource, active_span_processor=span_processor)
        trace.set_tracer_provider(trace_provider)
                            
  3. Create a span.

    tracer = trace.get_tracer(__name__)  # Obtain a tracer.
    with tracer.start_as_current_span("child_span") as child_span:  # Create a span named child_span.
        print("hello world")
  4. Use the OpenTelemetry Baggage API to pass custom tags.

    When you create the baggage_parent_span span, specify the attributes parameter to configure attributes.

    def baggage_and_attribute_usage():
        tracer = trace.get_tracer(__name__)
        global_ctx = baggage.set_baggage("key", "value_from_global_ctx")  # Use the OpenTelemetry Baggage API to transfer data between different spans.
        with tracer.start_as_current_span(name='baggage_parent_span', attributes={'attribute_key': 'value'}) as baggage_parent_span:
            parent_ctx = baggage.set_baggage("key", "value_from_parent_ctx")
            with tracer.start_as_current_span(name='baggage_child_span', context=parent_ctx) as baggage_child_span:
                child_ctx = baggage.set_baggage("key", "value_from_child_ctx")
    
        # Obtain the values of keys in different contexts.
        print(baggage.get_baggage("key", global_ctx))
        print(baggage.get_baggage("key", parent_ctx))
        print(baggage.get_baggage("key", child_ctx))
        

    View the complete sample code

    from opentelemetry import trace, baggage
    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter as OTLPSpanGrpcExporter
    from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter as OTLPSpanHttpExporter
    from opentelemetry.sdk.resources import SERVICE_NAME, Resource, HOST_NAME
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    
    def inner_method():
        tracer = trace.get_tracer(__name__)
        with tracer.start_as_current_span("child_span") as child_span:
            print("hello world")
    
    
    def outer_method():
        tracer = trace.get_tracer(__name__)
        with tracer.start_as_current_span("parent_span") as parent_span:
            inner_method()
    
    def baggage_and_attribute_usage():
        tracer = trace.get_tracer(__name__)
        global_ctx = baggage.set_baggage("key", "value_from_global_ctx")  # Use the OpenTelemetry Baggage API to transfer data between different spans.
        with tracer.start_as_current_span(name='baggage_parent_span', attributes={'attribute_key': 'value'}) as baggage_parent_span:
            parent_ctx = baggage.set_baggage("key", "value_from_parent_ctx")
            with tracer.start_as_current_span(name='baggage_child_span', context=parent_ctx) as baggage_child_span:
                child_ctx = baggage.set_baggage("key", "value_from_child_ctx")
    
        print(baggage.get_baggage("key", global_ctx))
        print(baggage.get_baggage("key", parent_ctx))
        print(baggage.get_baggage("key", child_ctx))
    
    
    
    def init_opentelemetry():
        # Specify the application name and hostname.
        resource = Resource(attributes={
            SERVICE_NAME: "<service-name>",
            HOST_NAME: "<host-name>"
        })
        # Use the gRPC protocol to report data.
        span_processor = BatchSpanProcessor(OTLPSpanGrpcExporter(
            endpoint="<endpoint>",
            headers=("Authentication=<token>")
        ))
        # Use the HTTP protocol to report data.
        # span_processor = BatchSpanProcessor(OTLPSpanHttpExporter(
        #     endpoint="<endpoint>",
        # ))
        trace_provider = TracerProvider(resource=resource, active_span_processor=span_processor)
        trace.set_tracer_provider(trace_provider)
    
    
    if __name__ == '__main__':
        init_opentelemetry()
        outer_method()
        baggage_and_attribute_usage()
  5. Run the application.

    python manual.py

Method 3: Combine automatic instrumentation with manual instrumentation

If you want to manually add instrumentation based on your business requirements after you use OpenTelemetry to automatically instrument an application, perform the following steps after you use Method 1:

  1. Download and install the required packages.

    pip install django
    pip install requests
    pip install opentelemetry-sdk
    pip install opentelemetry-instrumentation-django
    pip install opentelemetry-exporter-otlp 
  2. Create an AutoAndManualDemo project and create a HelloWorld application.

    1. Create an AutoAndManualDemo project.

      django-admin startproject AutoAndManualDemo
    2. Create a HelloWorld application in the project.

      cd AutoAndManualDemo
      
      # Create a HelloWorld application in the project.
      python manage.py startapp helloworld
  3. Modify the code of the helloworld/views.py file.

    Obtain a tracer. Create a span and set the span name.

    from django.http import HttpResponse
    from opentelemetry import trace
    from datetime import datetime
    
    
    # Create your views here.
    def hello_world_view(request):
        tracer = trace.get_tracer(__name__)
    
        with tracer.start_as_current_span("hello_world_span") as hello_world_span:
            result = "Hello World! Current Time =" + str(get_time())
            return HttpResponse(result)
    
    
    def get_time():
        now = datetime.now()
        tracer = trace.get_tracer(__name__)
        # Create a span.
        with tracer.start_as_current_span("time_span") as time_span:
            return now.strftime("%H:%M:%S")
  4. Modify the urls.py file.

    1. Create a helloworld/urls.py file and add the following code to the file:

      from django.urls import path
      
      from . import views
      
      urlpatterns = [
          path('', views.hello_world_view, name='helloworld')
      ]
    2. Add the URL pattern to the AutoAndManualDemo/urls.py file.

      from django.contrib import admin
      from django.urls import path, include
      
      urlpatterns = [
       path('admin/', admin.site.urls),
       path('helloworld/', include('helloworld.urls')),
      ]
  5. Add the following code to the OpenTelemetry initialization code in the manual.py file:

    from opentelemetry import trace
    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter  # Use the gRPC protocol to report data.
    # from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter # Use the HTTP protocol to report data.
    from opentelemetry.sdk.resources import SERVICE_NAME, Resource, HOST_NAME
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
    
    
    
    resource = Resource(attributes={
            SERVICE_NAME: "<service-name>",
            HOST_NAME: "<host-name>"
    })
    trace.set_tracer_provider(TracerProvider(resource=resource))
    trace.get_tracer_provider().add_span_processor(
        BatchSpanProcessor(OTLPSpanExporter(
            endpoint="<endpoint>",
            headers="Authentication=<token>" # The headers parameter is required only for the gRPC protocol.
    )))  # Use OTLPSpanExporter to report trace data.
    trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))  # Obtain trace data in the Managed Service for OpenTelemetry console.

    Replace the following content with actual values and modify the code based on the protocol that you use:

    • <service-name>: the name of your application.

    • <host-name>: the hostname.

    • <endpoint>: the endpoint that is used to report data over HTTP or gRPC.

    • <token>: the authentication token that is used to report data over gRPC.

  6. Run the project.

    python manage.py runserver --noreload
    • The --noreload parameter is used to prevent the manage.main method from running twice.

    • If an ImportError(symbol not found in flat namespace '_CFRelease') error occurs, run the following command to download and install the Grpcio package:

      pip install grpcio
  7. Visit 127.0.0.1:8000/helloworld in a browser. The trace data is reported to the Managed Service for OpenTelemetry console.

View the monitoring data

On the Applications page of the Managed Service for OpenTelemetry console, click the name of the application. On the page that appears, view the trace data.