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 |
Method 1: Use an agent to configure automatic instrumentation for an application
Download and install the required packages.
pip install django
pip install requests
pip install opentelemetry-distro \
opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
Create an AutoAndManualDemo project and create a HelloWorld application.
Create an AutoAndManualDemo project.
django-admin startproject AutoAndManualDemo
Create a HelloWorld application in the project.
cd AutoAndManualDemo
# Create a HelloWorld application in the project.
python manage.py startapp helloworld
Modify the code of the HelloWorld application.
Add the following code to the AutoAndManualDemo/helloworld/views.py file:
from django.http import HttpResponse
from datetime import datetime
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")
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')
]
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')),
]
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.
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
Download and install the required packages.
pip install opentelemetry-api
pip install opentelemetry-sdk
pip install opentelemetry-exporter-otlp
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():
resource = Resource(attributes={
SERVICE_NAME: "<service-name>",
HOST_NAME: "<host-name>"
})
span_processor = BatchSpanProcessor(OTLPSpanGrpcExporter(
endpoint="<endpoint>",
headers=("Authentication=<token>")
))
trace_provider = TracerProvider(resource=resource, active_span_processor=span_processor)
trace.set_tracer_provider(trace_provider)
Create a span.
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("child_span") as child_span:
print("hello world")
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)
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")
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))
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")
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():
resource = Resource(attributes={
SERVICE_NAME: "<service-name>",
HOST_NAME: "<host-name>"
})
span_processor = BatchSpanProcessor(OTLPSpanGrpcExporter(
endpoint="<endpoint>",
headers=("Authentication=<token>")
))
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()
Run the application.
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:
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
Create an AutoAndManualDemo project and create a HelloWorld application.
Create an AutoAndManualDemo project.
django-admin startproject AutoAndManualDemo
Create a HelloWorld application in the project.
cd AutoAndManualDemo
# Create a HelloWorld application in the project.
python manage.py startapp helloworld
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
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__)
with tracer.start_as_current_span("time_span") as time_span:
return now.strftime("%H:%M:%S")
Modify the urls.py file.
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')
]
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')),
]
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
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>"
)))
trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
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.
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:
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 . On the Applications page, click the name of the application. On the page that appears, view the trace data.
Note
If the
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.