Docs » µAPM Instrumentation Guide » Ruby Instrumentation

Ruby Instrumentation 🔗

Important

Before you start instrumenting your applications, review the information in Instrumentation Overview.

Auto-instrumentation 🔗

Supported libraries can be automatically instrumented with the SignalFx Tracing Library for Ruby.

In the application’s Gemfile, add the signalfx-tracing gem.

source 'https://rubygems.org'

gem 'signalfx-tracing'

Before using a library that needs to be traced, configure the instrumentation. If desired, this can be done automatically by trying to detect modules that are present.

SignalFx::Tracing::Instrumenter.configure(auto_instrument: true)

Libraries to auto-instrument can also be manually specified from the list of supported libraries below.

SignalFx::Tracing::Instrumenter.configure do |p|
    p.instrument(:LibName)
    ...
end

The tracer configuration is specified using environment variables, as shown below.

  • If these variables are not configured, a tracer will be initialized using the values shown.
  • If you are using our recommended implementation (Smart Agent and Smart Gateway), you do not need to provide a value for SIGNALFX_ACCESS_TOKEN.
export SIGNALFX_INGEST_URL="https://ingest.signalfx.com/v1/trace"
export SIGNALFX_SERVICE_NAME="signalfx-ruby-tracing"
export SIGNALFX_ACCESS_TOKEN=""

The following libraries are currently supported.

Library Supported Versions
Active Record > 3.2
Faraday > 0.9.2
MongoDB Driver > 2.1
Net::HTTP All
Rack > 2.0
Rails > 3.2
RestClient > 1.6
Sinatra > 1.0

When possible, span contexts will be injected into HTTP headers to allow remote service spans to be included in a trace.

For more information, see the documentation for the auto-instrumenter.

Manual instrumentation 🔗

When application code can be modified, it is possible to instrument the application to trace processes manually using the OpenTracing tracer for Jaeger.

source 'https://rubygems.org'

gem 'jaeger-client'

Use the following code to create and set the OpenTracing global tracer.

require 'jaeger/client'
require 'jaeger/client/http_sender'

headers = { "auth_token" => ENV['SIGNALFX_ACCESS_TOKEN'] }
encoder = Jaeger::Client::Encoders::ThriftEncoder.new(service_name: ENV['SIGNALFX_SERVICE_NAME'])
sender = Jaeger::Client::HttpSender.new(url: ENV['SIGNALFX_INGEST_URL'], headers: headers, encoder: encoder)

OpenTracing.global_tracer = Jaeger::Client.build(service_name: ENV['SIGNALFX_SERVICE_NAME'], sender: sender, flush_interval: 5)

Afterwards, the tracer can be used to instrument your code.

Span/scope management can be done automatically by putting your code in a span block:

OpenTracing.start_active_span('span_name') do |scope|
    # do something
    scope.span.set_tag("tag", data)
end

Spans can also be managed manually when the process it represents can’t be handled in a single block.

OpenTracing.start_span('span_name')

# do something

span.set_tag("tag", data)

span.finish()

Span contexts can also be propagated to remote services. To inject the context:

req = Net::HTTP::Post.new("/remote-service-path")

OpenTracing.start_span('span_name')

# inject the span context into the request
OpenTracing.inject(span.context, OpenTracing::FORMAT_RACK, req)

Net::HTTP.new("remote-service-address").request(req)

# finish the span

And then extract it from the remote service.

OpenTracing.extract(OpenTracing::FORMAT_RACK, req)

For more detailed usage info, see the documentation for jaeger-client-ruby and opentracing-ruby.