class Utopia::Exceptions::Mailer
A middleware which catches all exceptions raised from the app it wraps and sends a useful email with the exception, stacktrace, and contents of the environment.
Constants
- DEFAULT_FROM
- DEFAULT_SUBJECT
- LOCAL_SMTP
A basic local non-authenticated SMTP server.
- REQUEST_KEYS
Public Class Methods
new(app, to: "postmaster", from: DEFAULT_FROM, subject: DEFAULT_SUBJECT, delivery_method: LOCAL_SMTP, dump_environment: false)
click to toggle source
@param to [String] The address to email error reports to. @param from [String] The from address for error reports. @param subject [String] The subject template which can access attributes defined by `#attributes_for`. @param delivery_method [Object] The delivery method as required by the mail gem. @param dump_environment [Boolean] Attach `env` as `environment.yaml` to the error report.
# File lib/utopia/exceptions/mailer.rb, line 45 def initialize(app, to: "postmaster", from: DEFAULT_FROM, subject: DEFAULT_SUBJECT, delivery_method: LOCAL_SMTP, dump_environment: false) @app = app @to = to @from = from @subject = subject @delivery_method = delivery_method @dump_environment = dump_environment end
Public Instance Methods
call(env)
click to toggle source
# File lib/utopia/exceptions/mailer.rb, line 67 def call(env) begin return @app.call(env) rescue => exception send_notification exception, env raise end end
freeze()
click to toggle source
Calls superclass method
# File lib/utopia/exceptions/mailer.rb, line 55 def freeze return self if frozen? @to.freeze @from.freeze @subject.freeze @delivery_method.freeze @dump_environment.freeze super end
Private Instance Methods
attributes_for(exception, env)
click to toggle source
# File lib/utopia/exceptions/mailer.rb, line 135 def attributes_for(exception, env) { exception: exception.class.name, pid: $$, cwd: Dir.getwd, } end
extract_body(env)
click to toggle source
# File lib/utopia/exceptions/mailer.rb, line 175 def extract_body(env) if io = env['rack.input'] io.rewind if io.respond_to?(:rewind) io.read end end
generate_backtrace(io, exception, prefix: "Exception")
click to toggle source
# File lib/utopia/exceptions/mailer.rb, line 86 def generate_backtrace(io, exception, prefix: "Exception") io.puts "#{prefix} #{exception.class.name}: #{exception.to_s}" if exception.respond_to?(:backtrace) io.puts exception.backtrace else io.puts exception.to_s end if cause = exception.cause generate_backtrace(io, cause, prefix: "Caused by") end end
generate_body(exception, env)
click to toggle source
# File lib/utopia/exceptions/mailer.rb, line 100 def generate_body(exception, env) io = StringIO.new # Dump out useful rack environment variables: request = Rack::Request.new(env) io.puts "#{request.request_method} #{request.url}" # TODO embed `rack.input` if it's textual? # TODO dump and embed `utopia.variables`? io.puts REQUEST_KEYS.each do |key| value = request.send(key) io.puts "request.#{key}: #{value.inspect}" end request.params.each do |key, value| io.puts "request.params.#{key}: #{value.inspect}" end io.puts env.select{|key,_| key.start_with? 'HTTP_'}.each do |key, value| io.puts "#{key}: #{value.inspect}" end io.puts generate_backtrace(io, exception) return io.string end
generate_mail(exception, env)
click to toggle source
# File lib/utopia/exceptions/mailer.rb, line 143 def generate_mail(exception, env) mail = Mail.new( :from => @from, :to => @to, :subject => @subject % attributes_for(exception, env) ) mail.text_part = Mail::Part.new mail.text_part.body = generate_body(exception, env) if body = extract_body(env) and body.size > 0 mail.attachments['body.bin'] = body end if @dump_environment mail.attachments['environment.yaml'] = YAML.dump(env) end return mail end
send_notification(exception, env)
click to toggle source
# File lib/utopia/exceptions/mailer.rb, line 164 def send_notification(exception, env) mail = generate_mail(exception, env) mail.delivery_method(*@delivery_method) if @delivery_method mail.deliver rescue => mail_exception $stderr.puts mail_exception.to_s $stderr.puts mail_exception.backtrace end