getsentry / sentry-ruby

Sentry SDK for Ruby
https://sentry.io/for/ruby
MIT License
926 stars 493 forks source link

rack integration silently fails unless you use rackup #2167

Closed jd-bus closed 9 months ago

jd-bus commented 10 months ago

Issue Description

In Sinatra, most everything including middleware works fine when you have an app that you just launch with bundle exec ruby app.rb.

But for Sentry, the rack integration didn't work (exceptions silently not reported) unless you use a config.ru and use rackup.

Reproduction Steps

app.rb:

require 'sinatra'
require 'sentry-ruby'

Sentry.init do |config|
  config.dsn = 'your dsn'
end
use Sentry::Rack::CaptureExceptions

post '/test500' do
  raise 'test message'
end

Expected Behavior

bundle exec ruby app.rb and post to test500, expect it will report to sentry

Actual Behavior

it does not report to sentry. actually the backtrace doesn't include sentry almost all:

    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1156:in `invoke'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1180:in `dispatch!'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:996:in `block in call!'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1156:in `catch'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1156:in `invoke'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:996:in `call!'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:985:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry/rack/capture_exceptions.rb:13:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/xss_header.rb:20:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/path_traversal.rb:18:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/json_csrf.rb:28:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/base.rb:53:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/base.rb:53:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/frame_options.rb:33:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/logger.rb:17:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/common_logger.rb:38:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:261:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:254:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/head.rb:12:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/method_override.rb:24:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:219:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:2074:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1633:in `block in call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1849:in `synchronize'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1633:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/handler/webrick.rb:95:in `service'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/2.7.0/webrick/httpserver.rb:140:in `service'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/2.7.0/webrick/httpserver.rb:96:in `run'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/2.7.0/webrick/server.rb:307:in `block in start_thread'

compare if you make a config.ru and use bundle exec rackup, the excepton reporting DOES work and the stack trace is totally different:

    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1180:in `dispatch!'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:996:in `block in call!'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1156:in `catch'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1156:in `invoke'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:996:in `call!'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:985:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/xss_header.rb:20:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/path_traversal.rb:18:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/json_csrf.rb:28:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/base.rb:53:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/base.rb:53:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-protection-3.1.0/lib/rack/protection/frame_options.rb:33:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/logger.rb:17:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/common_logger.rb:38:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:261:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:254:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/head.rb:12:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/method_override.rb:24:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:219:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:2074:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1633:in `block in call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1849:in `synchronize'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sinatra-3.1.0/lib/sinatra/base.rb:1633:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry/rack/capture_exceptions.rb:28:in `block (2 levels) in call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry/hub.rb:251:in `with_session_tracking'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry-ruby.rb:387:in `with_session_tracking'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry/rack/capture_exceptions.rb:19:in `block in call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry/hub.rb:59:in `with_scope'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry-ruby.rb:367:in `with_scope'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/sentry-ruby-5.13.0/lib/sentry/rack/capture_exceptions.rb:18:in `call'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rack-2.2.8/lib/rack/handler/webrick.rb:95:in `service'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/2.7.0/webrick/httpserver.rb:140:in `service'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/2.7.0/webrick/httpserver.rb:96:in `run'
    /Users/jdb/.rbenv/versions/2.7.5/lib/ruby/2.7.0/webrick/server.rb:307:in `block in start_thread'

as you can see, protection and other middleware are loaded fine ine bundle exec ruby app.rb case but Sentry doesn't work at all. if it's going to be like this, at least it should be documented :(

Ruby Version

2.7.5

SDK Version

5.13.0

Integration and Its Version

No response

Sentry Config

No response

sl0thentr0py commented 10 months ago

@jd-bus you need to do the sentry stuff before requiring sinatra, see here. Unfortunately this is about the at_exit order that sinatra also hooks into, so no clean way to do this.

natikgadzhi commented 10 months ago

Would that be worth putting in docs, since that came up a couple of times? Perhaps here? https://docs.sentry.io/platforms/ruby/guides/rack/

natikgadzhi commented 10 months ago

Alright! I know this is not an optimal solution, but hope this helps folks for now ⬆️

natikgadzhi commented 10 months ago

@jd-bus, cool if we close this issue? Did the example above solve the problem for you?

jd-bus commented 9 months ago

This looks great, thank you! Amazing to get an actual response here 😄