Skip to main content

Span Profiles Support for OpenTelemetry in Python

This package links OpenTelemetry tracing data with Pyroscope continuous profiling data, enabling you to correlate traces with performance profiles.

Reference: https://grafana.com/docs/pyroscope/latest/configure-client/trace-span-profiles/

Prerequisites

Installation

pip install pyroscope-otel

Pyroscope Configuration (Required)

Pyroscope must be configured before creating any spans. This is mandatory for all setups:

from pyroscope import configure as pyroscope_configure

# Local setup (default)
pyroscope_configure(
    app_name="my-app",
    server_address="http://localhost:4040",
    sample_rate=100,
)

# Grafana Cloud setup (uncomment and update with your credentials)
# pyroscope_configure(
#     app_name="my-app",
#     server_address="https://pyroscope-blocks-prod-us-central-1.grafana-cloud.com/prom/push",
#     auth_token="<your-grafana-cloud-token>",
#     basic_auth_username="<your-username>",  # Optional: username for basic auth (Grafana Cloud)
#     basic_auth_password="<your-password>",  # Optional: password for basic auth (Grafana Cloud)
#     sample_rate=100,
# )

How It Works & Span Attributes

The PyroscopeSpanProcessor automatically attaches the profile identifier (pyroscope.profile.id) as an attribute to the root span of each trace. This creates a direct link between traces and their corresponding performance profiles in Grafana Tempo, allowing you to navigate from any trace to the exact performance profile data for that transaction.

On the profiling side, the processor adds these thread-level Pyroscope tags for the lifetime of the root span (child spans running on the same thread inherit them via the thread-local state):

  • span_id: the root span's ID (16 hex chars).
  • span_name: the root span's name.
  • trace_id: the trace ID (32 hex chars). Enables filtering profile samples by trace on the Pyroscope server.

Manual Instrumentation

Configure OpenTelemetry explicitly (after Pyroscope is already configured):

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from pyroscope.otel import PyroscopeSpanProcessor

# Configure OpenTelemetry
provider = TracerProvider()
provider.add_span_processor(PyroscopeSpanProcessor())

# TODO: Add your trace exporter configuration here
# (e.g., Grafana Tempo OTLP exporter, etc.)
# from opentelemetry.sdk.trace.export import BatchSpanProcessor
# provider.add_span_processor(BatchSpanProcessor(your_exporter))

trace.set_tracer_provider(provider)

# Use tracing in your application
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("my_operation"):
    # Your code here
    pass

Automatic Instrumentation

When using auto-instrumentation (e.g., opentelemetry-distro), you must still register PyroscopeSpanProcessor manually (after Pyroscope is already configured):

from opentelemetry import trace
from pyroscope.otel import PyroscopeSpanProcessor

# After auto-instrumentation is initialized
provider = trace.get_tracer_provider()
provider.add_span_processor(PyroscopeSpanProcessor())

Note: Auto-instrumentation only handles OpenTelemetry setup. Pyroscope configuration is still required.

Grafana Cloud OpenTelemetry Exporter (Optional)

# OpenTelemetry exporter for Grafana Cloud / Grafana Tempo
# from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
#
# otlp_exporter = OTLPSpanExporter(
#     endpoint="<your-tempo-instance>.grafana.net:443",
#     headers=(("Authorization", "Bearer <your-grafana-cloud-token>"),),
# )
# provider.add_span_processor(BatchSpanProcessor(otlp_exporter))

Integration Checklist

  • ✅ Pyroscope configured with pyroscope_configure()
  • ✅ OpenTelemetry TracerProvider created
  • ✅ PyroscopeSpanProcessor registered with add_span_processor()
  • ✅ Trace exporter configured (Grafana Tempo, etc.)
  • ✅ Application instrumented with OpenTelemetry
  • ✅ Verify pyroscope.profile.id appears in span attributes in Grafana Tempo

Troubleshooting

Issue Solution
pyroscope.profile.id not in spans Ensure PyroscopeSpanProcessor was registered with add_span_processor()
Profiles not appearing in Pyroscope Verify pyroscope_configure() is called before creating spans
Traces not exporting Check trace exporter configuration and credentials
Auto-instrumentation not working Manually add PyroscopeSpanProcessor() after initializing the provider

References

Metadata

Release files for pyroscope-otel 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyroscope-otel 1.1.0
File Size Uploaded
pyroscope_otel-1.1.0.tar.gz 14.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyroscope-otel 1.1.0
File Interpreter ABI Platform
pyroscope_otel-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 25.9 kB

Release files / pyroscope_otel-1.1.0.tar.gz

Download URL pyroscope_otel-1.1.0.tar.gz
Size 14.1 kB
Tags Source
SHA-256 checksum
How to use checksums
552e3401446d0406407f4c8c9487d36604949324cd240599af58a69d0d634175
BLAKE2b-256 checksum
How to use checksums
f38bd76727b27efed19b8893a9be56e3c62ecdbe2259268d69b16dcdb09444e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 30, 2026.

Transparency log

Release files / pyroscope_otel-1.1.0-py3-none-any.whl

Download URL pyroscope_otel-1.1.0-py3-none-any.whl
Size 11.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a10accd2a60fa00a18445f8e95df91500630f8f6b177133693792785f57637e5
BLAKE2b-256 checksum
How to use checksums
5aefd01ea5c880f478d1d91f7b7e4aa77837e7430fa6e3038ea7fbfe04f37e82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page