4

I recently discovered that I get memory bloats when I experience an error code 500 in my Rails apps (I run several and experience the same in all). I found out using Scout and could see a pattern of memory leaks (almost) every time I had a 500-error. Below is the most recent example:

enter image description here

Although it seems in the graph that exception_notification does not have much memory allocation, but rather "Middleware" has. The only middleware I use (as far as I know) is the Exception Notification (gem '[exception_notification][2]' v. 4.2.1) so I assume it must be it and it is only my interpretation that is wrong.

Edit after comment by Alexis - I ran:

Rails.configuration.middleware.each do |m|
puts "use #{m.inspect}"
end;0

which gave the following output about middleware:

use UTF8Cleaner::Middleware
use Rack::Sendfile
use ActionDispatch::Static
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x0055f8e1dd5a60>
use Rack::Timeout
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use Airbrake::Rack::Middleware
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use ExceptionNotification::Rack
use Rakismet::Middleware
use ScoutApm::Middleware

where Airbrake and ScoutApm would be the only one related to errors.

My production.rb contains this information:

  config.middleware.use ExceptionNotification::Rack, :email => {
      :email_prefix => "[MyApp.se Exception] ",
      :sender_address => %{"Exception Notifier" <support@myapp.se>},
      :exception_recipients => %w{me@myapp.se}
    }

  # Taken from mailer.rb
  config.action_mailer.delivery_method = :smtp

  config.action_mailer.smtp_settings = {
    :enable_starttls_auto => false,
    :return_response => true,
    :raise_delivery_errors => true,
    :address => 'smtp.myapp.se',
    :port => 587,
    :domain => "myapp.se",
    :user_name => 'mailer@myapp.se',
    :password => ENV['MAILER_PWD'],
    :authentication => 'plain'
  } 

As I have been on a Great Memory Bloat Hunt for the last week I have read that mail at least used to be a cause for concern so there may be something about this.

Why does this happen? How can I solve it, or at least troubleshoot it further? Could it be any other Rails default middleware?

Christoffer
  • 2,271
  • 3
  • 26
  • 57
  • When you disable exception_notification, is the middleware line still showing 50% of allocations? To check if there are other middlewares use: `Rails.configuration.middleware` – Alexis Jan 17 '18 at 13:19
  • Thanks! I added the output in the question. I will test disabling it as well. – Christoffer Jan 18 '18 at 08:24

2 Answers2

1

You can use ExceptionMailer(whatever).deliver_later to defer this task to a background job which will free up some memory.

  • Thanks. There is an option within ExceptionNotification that says :deliver_with but I can't see any options for this, but I assume there is a :deliver_later option. I will test this. Still, I haven't really worked with background jobs before so I am not sure how to execute/use them afterwards. Will they not use memory when it is executed? Or will that be in a worker dyno? – Christoffer Jan 18 '18 at 08:43
1

IMO a better way to send notifications in rails is via the airbrake gem. You could run an instance of errbit to save some money or sign up to use airbrake itself. This also has the benefit of giving you a lot more flexibility in how you receive the notifications too, e.g. pushover, and you'll receive full stack traces that you can act upon vs having to hunt through the logs.

engineerDave
  • 3,887
  • 26
  • 28