# Python tracing installation - Docs

1.  1

    ## Install OpenTelemetry packages

    Required

    For the complete SDK reference, see the [OpenTelemetry Python docs](https://opentelemetry.io/docs/languages/python/).

    Terminal

    PostHog AI

    ```bash
    pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
    ```

    `opentelemetry-exporter-otlp-proto-http` is the OTLP HTTP/protobuf trace exporter. The `-proto-grpc` variant sends gRPC, so pick `-proto-http` to match this guide.

2.  2

    ## Get your project token

    Required

    You'll need your PostHog project token to authenticate trace requests. This is the same token you use for capturing events with the PostHog SDK.

    > **Important:** Use your **project token** which starts with `phc_`. Do **not** use a personal API key (which starts with `phx_`).

    You can find your project token in [Project settings](https://app.posthog.com/settings).

3.  3

    ## Configure the SDK

    Required

    Set up the OpenTelemetry SDK to export spans to PostHog over OTLP HTTP.

    Python

    PostHog AI

    ```python
    from opentelemetry import trace
    from opentelemetry.sdk.resources import Resource, SERVICE_NAME
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
    resource = Resource.create({SERVICE_NAME: "my-service"})
    provider = TracerProvider(resource=resource)
    exporter = OTLPSpanExporter(
        endpoint="https://us.i.posthog.com/i/v1/traces",
        headers={"Authorization": "Bearer <ph_project_token>"},
    )
    provider.add_span_processor(BatchSpanProcessor(exporter))
    trace.set_tracer_provider(provider)
    ```

    The `.http.` segment in the import path is what selects the HTTP/protobuf exporter.

    Alternatively, configure the exporter with environment variables:

    Terminal

    PostHog AI

    ```bash
    OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://us.i.posthog.com/i/v1/traces"
    OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Bearer <ph_project_token>"
    OTEL_SERVICE_NAME="my-service"
    ```

    > **Note:** Pass the full `/i/v1/traces` path to the traces endpoint. Don't use the base `OTEL_EXPORTER_OTLP_ENDPOINT` variable, which appends its own `/v1/traces`.

4.  4

    ## Create spans

    Required

    Wrap the operations you want to measure in spans, and attach attributes for context.

    Python

    PostHog AI

    ```python
    tracer = trace.get_tracer("my-service")
    def checkout(order_id, amount):
        with tracer.start_as_current_span("checkout") as span:
            span.set_attribute("order.id", order_id)
            span.set_attribute("order.amount", amount)
            # ... do work ...
            return "confirmed"
    ```

5.  5

    ## Test your setup

    Recommended

    Once everything is configured, confirm spans are reaching PostHog:

    1.  Run your application and trigger the instrumented code
    2.  Open the PostHog Tracing interface
    3.  Confirm your spans and traces appear

    [View your traces in PostHog](https://app.posthog.com/traces)

7.  ## Next steps

    Checkpoint

    *What you can do with your traces*

    | Action | Description |
    | --- | --- |
    | [Why you need distributed tracing](/docs/distributed-tracing/basics.md) | What a trace shows you that nothing else does |
    | Explore traces | Read a trace as a waterfall to see where time goes |
    | Filter spans | Narrow down by service, status, duration, and attributes |
    | Propagate context | Pass trace context across services so spans join the same trace |

    [View your traces in PostHog](https://app.posthog.com/traces)

### Community questions

Ask a question

### Was this page useful?

HelpfulCould be better