grafana/otel-profiling-go

Open Telemetry integration for Grafana Pyroscope and tracing solutions such as Grafana Tempo, Honeycomb, or Jaeger

Go

101

54 commits

updated Oct 9, 2026

See the code

README

Profiling Instrumentation for OpenTelemetry Go SDK

The package provides means to integrate tracing with profiling. More specifically, a TracerProvider implementation that annotates profiling data with trace_id and span_id pprof tags, making it possible to filter the profile of a particular trace or span in Pyroscope.

Note that the module does not control pprof profiler itself – it still needs to be started for profiles to be collected. This can be done either via runtime/pprof package, or using the Pyroscope client.

By default:

  • The trace_id label is added on the local root span and inherited by every descendant span through pprof's context label propagation.
  • The span_id label and pyroscope.profile.id span attribute are set on the local root span only (the first span created locally) — this is the join key Grafana's "Traces to profiles" UI uses today. Presence of the attribute does not necessarily indicate that the span has a profile: stack trace samples might not be collected if the utilized CPU time is less than the sample interval (10ms).

Limitations:

  • Only CPU profiling is fully supported at the moment.

Options

  • WithSpanIDLabelScope(Scope) — control whether the span_id label is emitted: ScopeNone (off), ScopeRootSpan (default — local root only, descendants inherit the root's value), or ScopeAllSpans (every span emits its own). ScopeAllSpans significantly increases label cardinality.
  • WithSpanNameLabelScope(Scope) — same, for the span_name label.

Trace spans profiles

To start profiling trace spans, you need to include our go module in your app:

go get github.com/grafana/otel-profiling-go

Then add the pyroscope tracer provider:

package main

import (
	otelpyroscope "github.com/grafana/otel-profiling-go"
	"github.com/grafana/pyroscope-go"
)

func main() {
	// Initialize your tracer provider as usual.
	tp := initTracer()

	// Wrap it with otelpyroscope tracer provider.
	otel.SetTracerProvider(otelpyroscope.NewTracerProvider(tp))

	// If you're using Pyroscope Go SDK, initialize pyroscope profiler.
	_, _ = pyroscope.Start(pyroscope.Config{
		ApplicationName: "my-service",
		ServerAddress:   "http://localhost:4040",
	})

	// Your code goes here.
}

Tracing integration is supported in pull mode as well: if you scrape profiles using Grafana Agent, you should make sure that the pyroscope service_name label matches service.name attribute specified in the OTel SDK configuration. Please refer to the Grafana Agent documentation to learn more.

Example

You can find a complete example setup with Grafana Tempo in the Pyroscope repository.

image

go
honeycomb
honeycombio
jaeger
opentelemetry
opentracing
optimization
performance
pprof
profiler
profiling
trace
tracing

grafana/otel-profiling-go

Open Telemetry integration for Grafana Pyroscope and tracing solutions such as Grafana Tempo, Honeycomb, or Jaeger

Go

101

54 commits

updated Oct 9, 2026

See the code

README

Profiling Instrumentation for OpenTelemetry Go SDK

The package provides means to integrate tracing with profiling. More specifically, a TracerProvider implementation that annotates profiling data with trace_id and span_id pprof tags, making it possible to filter the profile of a particular trace or span in Pyroscope.

Note that the module does not control pprof profiler itself – it still needs to be started for profiles to be collected. This can be done either via runtime/pprof package, or using the Pyroscope client.

By default:

  • The trace_id label is added on the local root span and inherited by every descendant span through pprof's context label propagation.
  • The span_id label and pyroscope.profile.id span attribute are set on the local root span only (the first span created locally) — this is the join key Grafana's "Traces to profiles" UI uses today. Presence of the attribute does not necessarily indicate that the span has a profile: stack trace samples might not be collected if the utilized CPU time is less than the sample interval (10ms).

Limitations:

  • Only CPU profiling is fully supported at the moment.

Options

  • WithSpanIDLabelScope(Scope) — control whether the span_id label is emitted: ScopeNone (off), ScopeRootSpan (default — local root only, descendants inherit the root's value), or ScopeAllSpans (every span emits its own). ScopeAllSpans significantly increases label cardinality.
  • WithSpanNameLabelScope(Scope) — same, for the span_name label.

Trace spans profiles

To start profiling trace spans, you need to include our go module in your app:

go get github.com/grafana/otel-profiling-go

Then add the pyroscope tracer provider:

package main

import (
	otelpyroscope "github.com/grafana/otel-profiling-go"
	"github.com/grafana/pyroscope-go"
)

func main() {
	// Initialize your tracer provider as usual.
	tp := initTracer()

	// Wrap it with otelpyroscope tracer provider.
	otel.SetTracerProvider(otelpyroscope.NewTracerProvider(tp))

	// If you're using Pyroscope Go SDK, initialize pyroscope profiler.
	_, _ = pyroscope.Start(pyroscope.Config{
		ApplicationName: "my-service",
		ServerAddress:   "http://localhost:4040",
	})

	// Your code goes here.
}

Tracing integration is supported in pull mode as well: if you scrape profiles using Grafana Agent, you should make sure that the pyroscope service_name label matches service.name attribute specified in the OTel SDK configuration. Please refer to the Grafana Agent documentation to learn more.

Example

You can find a complete example setup with Grafana Tempo in the Pyroscope repository.

image

go
honeycomb
honeycombio
jaeger
opentelemetry
opentracing
optimization
performance
pprof
profiler
profiling
trace
tracing

Project health

Overall

6.5/10

Maintained

4/10

Code review

9/10
OpenSSF Scorecard

Latest release

v0.7.0 · Oct 6, 2026

Releases this year

4

Significant stargazers

Aleksandr Razumov

404 followers · starred Jan 2025

Chance Zibolski

263 followers · starred Nov 2022

rrreeezzz

19 followers · starred Feb 2024