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

rails: fix broken 'airbrake:deploy' #1003

Merged
merged 1 commit into from Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,16 @@ Airbrake Changelog

### master

* Fixed broken `bundle exec rake airbrake:deploy`
([#1003](https://github.com/airbrake/airbrake/pull/1003))
* Introduced `Airbrake::Rails.logger`, which replaces the old way of configuring
Rails apps. The logging setup becomes as simple as
([#1003](https://github.com/airbrake/airbrake/pull/1003)):

```ruby
c.logger = Airbrake::Rails.logger
```

### [v9.4.3][v9.4.3] (August 8, 2019)

* Rails: report unauthorized requests properly. Instead of 0 HTTP code the
Expand Down
13 changes: 1 addition & 12 deletions README.md
Expand Up @@ -191,20 +191,9 @@ In new Rails apps, by default, all the Airbrake logs are written into
please configure your logger the following way:

```ruby
c.logger =
if ENV['RAILS_LOG_TO_STDOUT'].present?
Logger.new(STDOUT, level: Rails.logger.level)
else
Logger.new(
File.join(Rails.root, 'log', 'airbrake.log'), level: Rails.logger.level
)
end
c.logger = Airbrake::Rails.logger
```

Note the `RAILS_LOG_TO_STDOUT` environment variable. This variable is supported
by Rails 5+ only. When set, it would redirect all `Rails.logger` (and
`Airbrake.logger`) output to STDOUT, despite the configured logger.

### Sinatra

To use Airbrake with Sinatra, simply `require` the gem, [configure][config] it
Expand Down
149 changes: 14 additions & 135 deletions lib/airbrake/rails.rb
@@ -1,140 +1,19 @@
require 'airbrake/rails/railtie'

module Airbrake
# Rails namespace holds all Rails-related functionality.
module Rails
# This railtie works for any Rails application that supports railties (Rails
# 3.2+ apps). It makes Airbrake Ruby work with Rails and report errors
# occurring in the application automatically.
class Railtie < ::Rails::Railtie
initializer('airbrake.middleware') do |app|
# Since Rails 3.2 the ActionDispatch::DebugExceptions middleware is
# responsible for logging exceptions and showing a debugging page in
# case the request is local. We want to insert our middleware after
# DebugExceptions, so we don't notify Airbrake about local requests.

if ::Rails.version.to_i >= 5
# Avoid the warning about deprecated strings.
# Insert after DebugExceptions, since ConnectionManagement doesn't
# exist in Rails 5 anymore.
app.config.middleware.insert_after(
ActionDispatch::DebugExceptions,
Airbrake::Rack::Middleware
)
elsif defined?(::ActiveRecord::ConnectionAdapters::ConnectionManagement)
# Insert after ConnectionManagement to avoid DB connection leakage:
# https://github.com/airbrake/airbrake/pull/568
app.config.middleware.insert_after(
::ActiveRecord::ConnectionAdapters::ConnectionManagement,
'Airbrake::Rack::Middleware'
)
else
# Insert after DebugExceptions for apps without ActiveRecord.
app.config.middleware.insert_after(
ActionDispatch::DebugExceptions,
'Airbrake::Rack::Middleware'
)
end
end

rake_tasks do
# Report exceptions occurring in Rake tasks.
require 'airbrake/rake'

# Defines tasks such as `airbrake:test` & `airbrake:deploy`.
require 'airbrake/rake/tasks'
end

# rubocop:disable Metrics/BlockLength
initializer('airbrake.action_controller') do
ActiveSupport.on_load(:action_controller) do
# Patches ActionController with methods that allow us to retrieve
# interesting request data. Appends that information to notices.
require 'airbrake/rails/action_controller'
include Airbrake::Rails::ActionController

if Airbrake::Config.instance.performance_stats
# Cache route information for the duration of the request.
require 'airbrake/rails/action_controller_route_subscriber'
ActiveSupport::Notifications.subscribe(
'start_processing.action_controller',
Airbrake::Rails::ActionControllerRouteSubscriber.new
)

# Send route stats.
require 'airbrake/rails/action_controller_notify_subscriber'
ActiveSupport::Notifications.subscribe(
'process_action.action_controller',
Airbrake::Rails::ActionControllerNotifySubscriber.new
)

# Send performance breakdown: where a request spends its time.
require 'airbrake/rails/action_controller_performance_breakdown_subscriber'
ActiveSupport::Notifications.subscribe(
'process_action.action_controller',
Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new
)

require 'airbrake/rails/net_http' if defined?(Net) && defined?(Net::HTTP)

if defined?(Curl) && defined?(Curl::CURB_VERSION)
require 'airbrake/rails/curb'
end

require 'airbrake/rails/http' if defined?(HTTP) && defined?(HTTP::Client)
require 'airbrake/rails/http_client' if defined?(HTTPClient)
require 'airbrake/rails/typhoeus' if defined?(Typhoeus)

if defined?(Excon)
require 'airbrake/rails/excon_subscriber'
ActiveSupport::Notifications.subscribe(/excon/, Airbrake::Rails::Excon.new)
::Excon.defaults[:instrumentor] = ActiveSupport::Notifications
end
end
end
end
# rubocop:enable Metrics/BlockLength

initializer('airbrake.active_record') do
ActiveSupport.on_load(:active_record) do
# Reports exceptions occurring in some bugged ActiveRecord callbacks.
# Applicable only to the versions of Rails lower than 4.2.
require 'airbrake/rails/active_record'
include Airbrake::Rails::ActiveRecord

if defined?(ActiveRecord) && Airbrake::Config.instance.query_stats
# Send SQL queries.
require 'airbrake/rails/active_record_subscriber'
ActiveSupport::Notifications.subscribe(
'sql.active_record', Airbrake::Rails::ActiveRecordSubscriber.new
)

# Filter out parameters from SQL body.
Airbrake.add_performance_filter(
Airbrake::Filters::SqlFilter.new(
::ActiveRecord::Base.connection_config[:adapter]
)
)
end
end
end

initializer('airbrake.active_job') do
ActiveSupport.on_load(:active_job) do
# Reports exceptions occurring in ActiveJob jobs.
require 'airbrake/rails/active_job'
include Airbrake::Rails::ActiveJob
end
end

initializer('airbrake.action_cable') do
ActiveSupport.on_load(:action_cable) do
# Reports exceptions occurring in ActionCable connections.
require 'airbrake/rails/action_cable'
end
end

runner do
at_exit do
Airbrake.notify_sync($ERROR_INFO) if $ERROR_INFO
end
def self.logger
if ENV['RAILS_LOG_TO_STDOUT'].present?
Logger.new(STDOUT, level: ::Rails.logger.level)
else
Logger.new(
::Rails.root.join('log', 'airbrake.log'),

# Rails.logger is not set in some Rake tasks such as
# 'airbrake:deploy'. In this case we use a sensible fallback.
level: (::Rails.logger ? ::Rails.logger.level : Logger::ERROR)
)
end
end
end
Expand Down
141 changes: 141 additions & 0 deletions lib/airbrake/rails/railtie.rb
@@ -0,0 +1,141 @@
module Airbrake
module Rails
# This railtie works for any Rails application that supports railties (Rails
# 3.2+ apps). It makes Airbrake Ruby work with Rails and report errors
# occurring in the application automatically.
class Railtie < ::Rails::Railtie
initializer('airbrake.middleware') do |app|
# Since Rails 3.2 the ActionDispatch::DebugExceptions middleware is
# responsible for logging exceptions and showing a debugging page in
# case the request is local. We want to insert our middleware after
# DebugExceptions, so we don't notify Airbrake about local requests.

if ::Rails.version.to_i >= 5
# Avoid the warning about deprecated strings.
# Insert after DebugExceptions, since ConnectionManagement doesn't
# exist in Rails 5 anymore.
app.config.middleware.insert_after(
ActionDispatch::DebugExceptions,
Airbrake::Rack::Middleware
)
elsif defined?(::ActiveRecord::ConnectionAdapters::ConnectionManagement)
# Insert after ConnectionManagement to avoid DB connection leakage:
# https://github.com/airbrake/airbrake/pull/568
app.config.middleware.insert_after(
::ActiveRecord::ConnectionAdapters::ConnectionManagement,
'Airbrake::Rack::Middleware'
)
else
# Insert after DebugExceptions for apps without ActiveRecord.
app.config.middleware.insert_after(
ActionDispatch::DebugExceptions,
'Airbrake::Rack::Middleware'
)
end
end

rake_tasks do
# Report exceptions occurring in Rake tasks.
require 'airbrake/rake'

# Defines tasks such as `airbrake:test` & `airbrake:deploy`.
require 'airbrake/rake/tasks'
end

# rubocop:disable Metrics/BlockLength
initializer('airbrake.action_controller') do
ActiveSupport.on_load(:action_controller) do
# Patches ActionController with methods that allow us to retrieve
# interesting request data. Appends that information to notices.
require 'airbrake/rails/action_controller'
include Airbrake::Rails::ActionController

if Airbrake::Config.instance.performance_stats
# Cache route information for the duration of the request.
require 'airbrake/rails/action_controller_route_subscriber'
ActiveSupport::Notifications.subscribe(
'start_processing.action_controller',
Airbrake::Rails::ActionControllerRouteSubscriber.new
)

# Send route stats.
require 'airbrake/rails/action_controller_notify_subscriber'
ActiveSupport::Notifications.subscribe(
'process_action.action_controller',
Airbrake::Rails::ActionControllerNotifySubscriber.new
)

# Send performance breakdown: where a request spends its time.
require 'airbrake/rails/action_controller_performance_breakdown_subscriber'
ActiveSupport::Notifications.subscribe(
'process_action.action_controller',
Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new
)

require 'airbrake/rails/net_http' if defined?(Net) && defined?(Net::HTTP)

if defined?(Curl) && defined?(Curl::CURB_VERSION)
require 'airbrake/rails/curb'
end

require 'airbrake/rails/http' if defined?(HTTP) && defined?(HTTP::Client)
require 'airbrake/rails/http_client' if defined?(HTTPClient)
require 'airbrake/rails/typhoeus' if defined?(Typhoeus)

if defined?(Excon)
require 'airbrake/rails/excon_subscriber'
ActiveSupport::Notifications.subscribe(/excon/, Airbrake::Rails::Excon.new)
::Excon.defaults[:instrumentor] = ActiveSupport::Notifications
end
end
end
end
# rubocop:enable Metrics/BlockLength

initializer('airbrake.active_record') do
ActiveSupport.on_load(:active_record) do
# Reports exceptions occurring in some bugged ActiveRecord callbacks.
# Applicable only to the versions of Rails lower than 4.2.
require 'airbrake/rails/active_record'
include Airbrake::Rails::ActiveRecord

if defined?(ActiveRecord) && Airbrake::Config.instance.query_stats
# Send SQL queries.
require 'airbrake/rails/active_record_subscriber'
ActiveSupport::Notifications.subscribe(
'sql.active_record', Airbrake::Rails::ActiveRecordSubscriber.new
)

# Filter out parameters from SQL body.
Airbrake.add_performance_filter(
Airbrake::Filters::SqlFilter.new(
::ActiveRecord::Base.connection_config[:adapter]
)
)
end
end
end

initializer('airbrake.active_job') do
ActiveSupport.on_load(:active_job) do
# Reports exceptions occurring in ActiveJob jobs.
require 'airbrake/rails/active_job'
include Airbrake::Rails::ActiveJob
end
end

initializer('airbrake.action_cable') do
ActiveSupport.on_load(:action_cable) do
# Reports exceptions occurring in ActionCable connections.
require 'airbrake/rails/action_cable'
end
end

runner do
at_exit do
Airbrake.notify_sync($ERROR_INFO) if $ERROR_INFO
end
end
end
end
end
10 changes: 1 addition & 9 deletions lib/generators/airbrake_initializer.rb.erb
Expand Up @@ -33,15 +33,7 @@ Airbrake.configure do |c|
# By default, Airbrake Ruby outputs to STDOUT. In Rails apps it makes sense to
# use the Rails' logger.
# https://github.com/airbrake/airbrake-ruby#logger
c.logger =
if ENV['RAILS_LOG_TO_STDOUT'].present?
Logger.new(STDOUT, level: Rails.logger.level)
else
Logger.new(
Rails.root.join('log', 'airbrake.log'),
level: Rails.logger.level
)
end
c.logger = Airbrake::Rails.logger

# Configures the environment the application is running in. Helps the Airbrake
# dashboard to distinguish between exceptions occurring in different
Expand Down