Skip to content

Uptrace for Python

uptrace-python

Introduction

Uptrace client is an OpenTelemery distribution configured to export traces to Uptrace. Uptrace client offers the following advantages over standard OpenTelemetry protocol (OTLP):

  • It is configured to work with Uptrace.
  • It uses MessagePack and HTTP 2 which offers the same performance as gRPC but is more lightweight.
  • It uses more efficient ZSTD compression.

But we also support OTLP over gRPC or HTTP in case you are already using OTLP or OpenTelemetry Collector.

Getting started

It only takes a few minutes to get started with Uptrace:

To get started with tracing you need to understand the following terms:

  • Span is an operation (unit of work) in a trace. For example, a database query or an RPC call.
  • Trace is a tree of spans that shows the path that a request makes through an app.
  • Tracer creates spans. You only need one tracer in your app or library.
  • Event is an entity within a span. Think of it as a span that does not have duration.
  • Attribute is a key-value pair carrying some information, for example, host.name = 'localhost'.

Installation

To install uptrace-python:

pip install uptrace

Configuration

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

import uptrace
from opentelemetry import trace

# Set dsn or UPTRACE_DSN env var.
uptrace.configure_opentelemetry(dsn="")
tracer = trace.get_tracer("app_or_package_name", "1.0.0")

The following configuration options are supported.

Option Description
dsn A data source that is used to connect to uptrace.dev. For example, https://<key>@api.uptrace.dev/<project_id>.
service_name service.name resource attribute. For example, myservice.
service_version service.version resource attribute. For example, 1.0.0.
resource_attributes Any other resource attributes.
resource Resource contains attributes representing an entity that produces telemetry. Resource attributes are copied to all spans and events.

Alternatively you use the following environment variables:

Env var Description
UPTRACE_DSN A data source that is used to connect to uptrace.dev. For example, https://<key>@api.uptrace.dev/<project_id>.
OTEL_RESOURCE_ATTRIBUTES Key-value pairs to be used as resource attributes. For example, service.name=myservice,service.version=1.0.0.
OTEL_PROPAGATORS Propagators to be used as a comma separated list. The default is tracecontext,baggage.

Quickstart

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

#!/usr/bin/env python3

import uptrace
from opentelemetry import trace

# Set dsn or UPTRACE_DSN env var.
uptrace.configure_opentelemetry(
    dsn="", service_name="myservice", service_version="1.0.0"
)
tracer = trace.get_tracer("app_or_package_name", "1.0.0")

with tracer.start_as_current_span("main") as span:
    with tracer.start_as_current_span("child1") as span:
        span.set_attribute("key1", "value1")
        span.record_exception(ValueError("error1"))

    with tracer.start_as_current_span("child2") as span:
        span.set_attribute("key2", "value2")
        span.set_attribute("key3", 123.456)

    print("trace:", uptrace.trace_url(span))

# Send buffered spans.
trace.get_tracer_provider().shutdown()

OpenTelemetry API

All the code below is also available as a runnable otel-api example.

Creating a tracer

To create a tracer you need a tracer name and a version (aka instrumentation library):

from opentelemetry import trace

tracer = trace.get_tracer("app_or_package_name", "1.0.0")

Creating a span

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

with tracer.start_as_current_span("operation-name", kind=trace.SpanKind.SERVER) as span:
    do_some_work()

Or you can use start_span:

# Create a span.
span = tracer.start_span("operation-name", kind=trace.SpanKind.SERVER)

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

Recording data

Once you have a span you can start adding attributes:

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

And events:

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

To record exceptions:

span.record_exception(ValueError("error1"))

To set the span status:

from opentelemetry.trace.status import StatusCode

span.set_status(trace.Status(StatusCode.ERROR, "error description"))

Current active span

To get the current span:

span = trace.get_current_span()

To activate the span:

with tracer.use_span(main, end_on_exit=True):
    print(trace.get_current_span() == main)

OTLP

Use the following example to configure OTLP to export data to Uptrace. You will need an Uptrace token which can be extracted from the project DSN:

resource = Resource(
    attributes={"service.name": "myservice", "service.version": "1.0.0"}
)
tracer_provider = TracerProvider(resource=resource)

# Load system TLS credentials.
credentials = grpc.ssl_channel_credentials()
otlp_exporter = OTLPSpanExporter(
    endpoint="otlp.uptrace.dev:4317",
    credentials=credentials,
    # Set the Uptrace dsn here or use UPTRACE_DSN env var.
    headers=(("uptrace-dsn", os.environ.get("UPTRACE_DSN")),),
)

span_processor = BatchSpanProcessor(
    otlp_exporter,
    max_queue_size=1000,
    max_export_batch_size=1000,
)
tracer_provider.add_span_processor(span_processor)

trace.set_tracer_provider(tracer_provider)