Docs » Ruby Instrumentation (APM PG)

Ruby Instrumentation (APM PG) 🔗

Back to Instrumentation Guide contents

Important

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

Auto-instrumentation 🔗

Supported libraries can be automatically instrumented with the SignalFx Tracing Library for Ruby by its configuration of a tracer instance and OpenTracing community-contributed instrumentations. To minimize dependencies, specify the target library instrumentations you’d like installed on your system. You can either use the sfx-rb-trace-bootstrap command-line utility or install from the gem dependencies file.

$ gem install signalfx-tracing -v '~>1.0'
$ # use the now available sfx-rb-trace-bootstrap's --list option to see all available instrumentations
$ sfx-rb-trace-bootstrap --list
Available target libraries:
{"activerecord"=>["activerecord-opentracing", "~> 0.2.1"],
 < ... >
 "sinatra"=>["sinatra-instrumentation", "~> 0.1.2"]}

$ # Use the --install-deps option to specify the desired instrumentations to be installed
$ sfx-rb-trace-bootstrap --install-deps rack,rails,activerecord,restclient

You can specify the SignalFx Tracing Library for Ruby as a dependency in your in your application’s Gemfile by adding the signalfx-tracing gem.

source 'https://rubygems.org'

gem 'signalfx-tracing', '~> 1.0'

Please note that you must still install the desired instrumentations manually via sfx-rb-trace-bootstrap or the gem dependencies file when adding signalfx-tracing as a dependency.

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.

require 'signalfx/tracing'

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.
# These are the default values
$ export SIGNALFX_ENDPOINT_URL="http://localhost:9080/v1/trace"
$ export SIGNALFX_SERVICE_NAME="signalfx-ruby-tracing"
$ export SIGNALFX_ACCESS_TOKEN=""

The following libraries are currently supported.

Library Supported Versions
Active Record ~> 5.0
Elasticsearch >= 6.0.2
Faraday >= 0.9.0
Grape >= 0.13.0
MongoDB Driver >= 2.1.0
Mysql2 >= 0.4.0
Net::HTTP Ruby >= 2.0
Pg >= 0.18.0
Rack >= 0.1
Rails >= 3.0.0
Redis >= 4.0.0
RestClient >= 1.5.0
Sequel >= 3.47.0
Sidekiq >= 0.7.0
Sinatra >= 1.0.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.

Back to Instrumentation Guide contents