Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Make Rack install optional for sinatra #1019

Merged
merged 12 commits into from
Jun 21, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,25 @@ module Extensions
# Sinatra extension that installs TracerMiddleware and provides
# tracing for template rendering
module TracerExtension
# Sinatra hook after extension is registered
def self.registered(app)
# Create tracing `render` method
::Sinatra::Base.module_eval do
def render(_engine, data, *)
template_name = data.is_a?(Symbol) ? data : :literal
# Contants patches for `render` method
module RenderPatches
def render(_engine, data, *)
template_name = data.is_a?(Symbol) ? data : :literal

Sinatra::Instrumentation.instance.tracer.in_span(
'sinatra.render_template',
attributes: { 'sinatra.template_name' => template_name.to_s }
) do
super
end
Sinatra::Instrumentation.instance.tracer.in_span(
'sinatra.render_template',
attributes: { 'sinatra.template_name' => template_name.to_s }
) do
super
end
end
app.use(*OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.middleware_args)
app.use(Middlewares::TracerMiddleware)
end

# Sinatra hook after extension is registered
def self.registered(app)
# Create tracing `render` method
::Sinatra::Base.prepend(RenderPatches)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate the use of a module we can prepend rather than module_eval. The later always causes me a little anxiety, and to go re-read the docs; probably trauma from over-use and being overly-clever back in the Ruby meta-programming heydays. 😆

Sinatra::Instrumentation.instance.install_middleware(app)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@ module Sinatra
# The Instrumentation class contains logic to detect and install the Sinatra
# instrumentation
class Instrumentation < OpenTelemetry::Instrumentation::Base
install do |_|
OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.install({})
install do |config|
OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.install({}) if config[:install_rack]

::Sinatra::Base.register Extensions::TracerExtension
end

option :install_rack, default: true, validate: :boolean

present do
defined?(::Sinatra)
end

def install_middleware(app)
app.use(*OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.middleware_args) if config[:install_rack]
app.use(Middlewares::TracerMiddleware)
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

let(:instrumentation) { OpenTelemetry::Instrumentation::Sinatra::Instrumentation.instance }
let(:exporter) { EXPORTER }
let(:config) { {} }

class CustomError < StandardError; end

Expand Down Expand Up @@ -66,7 +67,14 @@ class CustomError < StandardError; end
end

before do
instrumentation.install
Sinatra::Base.reset!

OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.instance_variable_set(:@installed, false)
OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.config.clear

instrumentation.instance_variable_set(:@installed, false)
instrumentation.config.clear
instrumentation.install(config)
exporter.reset
end

Expand Down Expand Up @@ -169,4 +177,48 @@ class CustomError < StandardError; end
_(exporter.finished_spans.first.events[0].attributes['exception.message']).must_equal('custom message')
end
end

describe 'when install_rack is set to false' do
let(:config) { { install_rack: false } }

describe 'missing rack installation' do
it 'disables tracing' do
get '/one/endpoint'

_(exporter.finished_spans).must_be_empty
end
end

describe 'when rack is manully installed' do
arielvalentin marked this conversation as resolved.
Show resolved Hide resolved
let(:app) do
apps_to_build = apps
Rack::Builder.new do
use(*OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.middleware_args)

apps_to_build.each do |root, app|
map root do
run app
end
end
end.to_app
end

before do
OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.install
end

it 'creates a span' do
get '/one/endpoint'

_(exporter.finished_spans.first.attributes).must_equal(
'http.method' => 'GET',
'http.host' => 'example.org',
'http.scheme' => 'http',
'http.target' => '/one/endpoint',
'http.route' => '/endpoint',
'http.status_code' => 200
)
end
end
end
end
Loading