Skip to main content
info

In March 2023, Grafana Labs acquired Pyroscope, the company behind the eponymous open source continuous profiling project. In September 2023, Grafana Pyroscope v1.0.0 was released.

This documentation covers Pyroscope versions preceding v1.0.0. We're keeping it for the time being, but we recommend that you upgrade to Grafana Pyroscope v1.0.0 or higher and switch to the new Grafana Pyroscope Docs for most up-to-date documentation.

Ruby Tracing Integration

note

This feature is currently undergoing a rewrite and will be updated as soon as we have re-enabled it. For any questions or updates feel free to reach out on github or slack!

OpenTelemetry support#

Pyroscope can integrate with distributed tracing systems supporting OpenTelemetry standard which allows you to link traces with the profiling data, and find specific lines of code related to a performance issue.

note
  • Because of how sampling profilers work, spans shorter than the sample interval may not be captured. By default pyroscope CPU profiler probes stack traces 100 times per second, meaning that spans shorter than 10ms may not be captured.

Ruby code can be easily instrumented with otel-profiling-ruby package package - a Pyroscope::Otel::SpanProcessor implementation, that annotates profiling data with span IDs which makes it possible to filter out profile of a particular trace span in Pyroscope.

Installation#

Add this line to your application's Gemfile:

gem 'pyroscope-otel'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install pyroscope-otel

Usage#

Configure pyroscope and then configure OpenTelemetry with Pyroscope::Otel::SpanProcessor

Pyroscope.configure do |config|  # Configure pyroscope as described https://pyroscope.io/docs/ruby/end
OpenTelemetry::SDK.configure do |config|  config.add_span_processor Pyroscope::Otel::SpanProcessor.new(    "#{app_name}.cpu", # your app name with ".cpu" suffix, for example rideshare-ruby.cpu    pyroscope_endpoint # link to your pyroscope server, for example "http://localhost:4040"  )  # Configure the rest of opentelemetry as described  https://github.com/open-telemetry/opentelemetry-rubyend

Configuration options#

You can control some processor options with the following flags:

Pyroscope::Otel::SpanProcessor.new("#{app_name}.cpu", pyroscope_endpoint).tap do |proc|    # boolean flag option to annotate spans with profile attributes only on root spans.    proc.root_span_only = true    # boolean flag option to annotate pyroscope profiles with parent name    proc.add_span_name = true    # boolean flag option to add profiler url to parent attributes    proc.add_url = true  end

Profiles#

Collected profiles can be viewed in Pyroscope UI using FlameQL:

  • simple.ruby.cpu{profile_id="<spanID>"} - Shows flamegraph for a particular span.
  • simple.ruby.cpu{span_name="ExampleSpan"} - Shows aggregated profile for all spans named ExampleSpan.

For convenience, the tracer annotates profiled spans with extra attributes:

  • pyroscope.profile.id - is set to span ID to indicate that profile was captured for a span.
  • pyroscope.profile.url - contains the URL to the flamegraph in Pyroscope UI.

Examples#

Check out the examples directory in our repository to find a complete example application that demonstrates tracing integration features (using a custom jaeger ui) and learn more!

jaeger example