All Products
Search
Document Center

Application Real-Time Monitoring Service:Use OpenTelemetry to report the trace data of a Python application

Last Updated:Oct 18, 2024

After you use OpenTelemetry to instrument an application and report the trace data to Managed Service for OpenTelemetry, Managed Service for OpenTelemetry starts to monitor the application. You can view the monitoring data of the application such as application topology, traces, abnormal transactions, slow transactions, and SQL analysis. This topic describes how to use an agent or OpenTelemetry SDK for Python to automatically or manually instrument a Python application and report trace data.

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, visit GitHub.

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-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 configure automatic instrumentation for 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 AutoAndManualDemo/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 AutoAndManualDemo/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/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 --noreload
    Note
    • The --noreload parameter is used to prevent the manage.main method from running twice.

    • 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 trace data.
        span_processor = BatchSpanProcessor(OTLPSpanGrpcExporter(
            endpoint="<endpoint>",
            headers=("Authentication=<token>")
        ))
        # Use the HTTP protocol to report trace 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. Get the trace ID and span ID.

    ctx = trace.get_current_span().get_span_context()
    trace_id = '{trace:032x}'.format(trace=ctx.trace_id)
    span_id = '{span:016x}'.format(span=ctx.span_id)
    print(trace_id)
    print(span_id)
  5. 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))
        

    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 trace data.
        span_processor = BatchSpanProcessor(OTLPSpanGrpcExporter(
            endpoint="<endpoint>",
            headers=("Authentication=<token>")
        ))
        # Use the HTTP protocol to report trace 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()
  6. 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/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 trace data.
    # from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter # Use the HTTP protocol to report trace 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 trace data over HTTP or gRPC.

    • <token>: the authentication token that is used to report trace 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

Log on to the ARMS console. In the left-side navigation pane, choose Application Monitoring > Applications. On the Applications page, click the name of the application. On the page that appears, view the trace data.

Note

If the image icon is displayed in the Language column, the application is connected to Application Monitoring. If a hyphen (-) is displayed, the application is connected to Managed Service for OpenTelemetry.