Skip to content

Uptrace for Python

Installation

pip install uptrace

Introduction

uptrace-python is the official Uptrace client for Python that sends your traces/spans to Uptrace.

To learn about tracing, please see Introduction to distributed tracing.

Configuring Uptrace client

You configure Uptrace client using a DSN (Data Source Name, e.g. https://<token>@api.uptrace.dev/<project_id>) from the project settings page. Add following code to the app main file (manage.py for Django):

import uptrace

# Set dsn or UPTRACE_DSN env var.
upclient = uptrace.Client(dsn="")

tracer = upclient.get_tracer(__name__)

The following example shows how to create a tracer, start spans and add events:

import uptrace

# Set dsn or UPTRACE_DSN env var.
upclient = uptrace.Client(dsn="")

upclient.report_exception(ValueError("Hello from uptrace-python"))

tracer = upclient.get_tracer(__name__)

with tracer.start_as_current_span("main span"):
    with tracer.start_as_current_span("child1") as span:
        span.set_attribute("key1", "value1")
        span.add_event("event-name", {"foo": "bar"})

    with tracer.start_as_current_span("child2") as span:
        span.set_attribute("key2", "value2")
        span.add_event("event-name", {"foo": "baz"})

# Flush and close the client.
upclient.close()

Instrumenting your code

To create a tracer:

# Create a named tracer using module name as an identifier.
tracer = upclient.get_tracer(__name__, __version__)

To create a span and activate it in the current context:

with tracer.start_as_current_span("operation-name") as span:
    do_some_work()

Or you can use start_span:

# Create a span.
span = tracer.start_span(name)

# Activate the span in the current context.
with tracer.use_span(span, end_on_exit=True):
    do_some_work()

To get the active span from the tracer context:

span = upclient.get_current_span()

Or using OpenTelemetry API:

from opentelemetry import trace

span = trace.get_current_span()

Once you have a span you can start adding attributes:

span.set_attribute("enduser.id", "123")
span.set_attribute("enduser.role", "admin")

And more complex events:

span.add_event("log", {
    "log.severity": "error",
    "log.message": "User not found",
    "enduser.id": "123",
})

Instrumenting Django

Install Django instrumentation extension:

pip install opentelemetry-instrumentation-django

Edit manage.py:

from opentelemetry.instrumentation.django import DjangoInstrumentor

if __name__ == "__main__":
    # Make sure sure that settings module is defined. It is used by DjangoInstrumentor.
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app_name.settings")

    # Instrument Django by adding middleware etc.
    DjangoInstrumentor().instrument()

    ...

Run the server:

# Enable instrumentation.
export OTEL_DJANGO_INSTRUMENT=True

./manage.py runserver

You can also check already instrumented django-realworld-example-app.

Instrumenting PostgreSQL psycopg2

Install psycopg instrumentation extension:

pip install opentelemetry-instrumentation-psycopg2

Update your main file (manage.py for Django):

from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor

if __name__ == "__main__":
    Psycopg2Instrumentor().instrument()

    ...

Instrumenting MySQL

Using pymysql

pymysql is a Python3 compatible replacement for mysql-python.

pip install PyMySQL

To use it with libraries that expect mysql-python, add the following to your main file (manage.py for Django):

import pymysql

pymysql.install_as_MySQLdb()

Install opentelemetry-instrumentation-pymysql that instruments mysql-connector-python:

pip install opentelemetry-instrumentation-pymysql

Update your main file (manage.py for Django):

from opentelemetry.instrumentation.pymysql import PyMySQLInstrumentor

if __name__ == "__main__":
    PyMySQLInstrumentor().instrument()

    ...

Using mysql-connector-python

Install opentelemetry-instrumentation-mysql that instruments mysql-connector-python:

pip install mysql-connector-python
pip install opentelemetry-instrumentation-mysql

Update your main file (manage.py for Django):

from opentelemetry.instrumentation.mysql import MySQLInstrumentor

if __name__ == "__main__":
    MySQLInstrumentor().instrument()

    ...