This guide demonstrates how to use OpenTelemetry SDK to instrument Python code and send traces to TrueFoundry’s OtelCollector.

In this example, we’ll show how to instrument a simple Python application with nested function calls using OpenTelemetry’s context managers.

1

Install Dependencies

First, you need to install the following packages:

pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http python-dotenv
2

Setup environment variables

To enable tracing, you’ll need to configure a few environment variables in your application.

Before proceeding, make sure you’ve, Created a tracing project and Generated an API token. If you haven’t done this yet, follow the instructions in Getting Started.

# Tracing configs
OTEL_EXPORTER_OTLP_ENDPOINT=<<control-plane-url>>/api/otel
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20<<api-key>>,tfy-tracing-project=<<tracing-project-fqn>>"

Replace the placeholders above:

  • <<control-plane-url>>: Your actual TrueFoundry control plane URL
  • <<api-key>>: The API key associated with your tracing project
  • <<tracing-project-fqn>>: The fully qualified name of your tracing project
3

Initialize OpenTelemetry

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Setup tracer provider
provider = TracerProvider()
trace.set_tracer_provider(provider)

# OTLP exporter (HTTP)
otlp_exporter = OTLPSpanExporter()

# Span processor using batch (recommended for production)
span_processor = BatchSpanProcessor(otlp_exporter)
provider.add_span_processor(span_processor)

# Get tracer
tracer = trace.get_tracer(__name__)
4

Instrument your Python code

This section shows how to instrument your Python code using OpenTelemetry’s context managers. The example demonstrates nested function calls with proper tracing.

Tracing related code has been highlighted in the below code block.

# Child function — will create its own span
def greet_user(name):
    with tracer.start_as_current_span("greet_user_task") as span:
        # Add attributes to the span
        span.set_attribute("user.name", name)
        span.set_attribute("greeting.type", "welcome")

        print(f"Hello, {name}!")

# Parent function — also creates a span and calls the child
def main():
    with tracer.start_as_current_span("main_task"):
        user_name = "Sateesh"
        greet_user(user_name)
        print("Main task finished.")

# Run the main function
main()
5

Run your application and view logged trace