class Racknga::ExceptionMailNotifier

Ruby 1.9 only. 1.8 isn’t supported.

Constants

DEFAULT_LIMIT_DURATION
DEFAULT_MAX_MAIL_COUNT_IN_LIMIT_DURATION

Public Class Methods

new(options) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 29
def initialize(options)
  @options = Utils.normalize_options(options || {})
  reset_limitation
end

Public Instance Methods

notify(exception, environment) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 34
def notify(exception, environment)
  return if to.empty?

  if limitation_expired?
    send_summaries unless @summaries.empty?
    reset_limitation
  end

  if @mail_count < max_mail_count_in_limit_duration
    send_notification(exception, environment)
  else
    @summaries << summarize(exception, environment)
  end

  @mail_count += 1
end

Private Instance Methods

charset() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 174
def charset
  @options[:charset] || 'utf-8'
end
create_mail(options) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 69
def create_mail(options)
  subject = [@options[:subject_label], options[:subject]].compact.join(' ')
  header = header(:subject => subject)

  body = options[:body]

  mail = "#{header}\r\n#{body}"
  mail.force_encoding("utf-8")
  begin
    mail = mail.encode(charset)
  rescue EncodingError
  end
  mail.force_encoding("ASCII-8BIT")
end
encode_subject(subject) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 197
def encode_subject(subject)
  case charset
  when /\Aiso-2022-jp\z/i
    NKF.nkf('-Wj -M', subject)
  else
    NKF.nkf('-Ww -M', subject)
  end
end
ensure_array(maybe_array) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 159
def ensure_array(maybe_array)
  maybe_array = [maybe_array] if maybe_array.is_a?(String)
  maybe_array
end
from() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 164
def from
  @from ||= @options[:from] || guess_from
end
guess_from() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 168
def guess_from
  name = Etc.getpwuid(Process.uid).name
  host = Socket.gethostname
  "#{name}@#{host}"
end
header(options) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 84
    def header(options)
      <<-EOH
MIME-Version: 1.0
Content-Type: Text/Plain; charset=#{charset}
Content-Transfer-Encoding: #{transfer_encoding}
From: #{from}
To: #{to.join(', ')}
Subject: #{encode_subject(options[:subject])}
Date: #{Time.now.rfc2822}
EOH
    end
limit_duration() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 184
def limit_duration
  @options[:limit_duration] || DEFAULT_LIMIT_DURATION
end
limitation_expired?() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 58
def limitation_expired?
  (Time.now - @count_start_time) > limit_duration
end
max_mail_count_in_limit_duration() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 179
def max_mail_count_in_limit_duration
  @options[:max_mail_count_in_limit_duration] || DEFAULT_MAX_MAIL_COUNT_IN_LIMIT_DURATION
end
notification_body(exception, environment) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 102
    def notification_body(exception, environment)
      request = Rack::Request.new(environment)
      body = <<-EOB
#{summarize(exception, environment)}
--
#{exception.backtrace.join("\n")}
EOB
      params = request.params
      max_key_size = (environment.keys.collect(&:size) +
                      params.keys.collect(&:size)).max
      body << <<-EOE
--
Environments:
EOE
      environment.sort_by {|key, value| key}.each do |key, value|
        body << "  %*s: <%s>\n" % [max_key_size, key, value]
      end

      unless params.empty?
        body << <<-EOE
--
Parameters:
EOE
        params.sort_by {|key, value| key}.each do |key, value|
          body << "  %#{max_key_size}s: <%s>\n" % [key, value]
        end
      end

      body
    end
report_body() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 140
def report_body
  @summaries[0..10].join("\n\n")
end
reset_limitation() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 52
def reset_limitation
  @mail_count = 0
  @count_start_time = Time.now
  @summaries = []
end
send(mail) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 62
def send(mail)
  host = @options[:host] || "localhost"
  Net::SMTP.start(host, @options[:port]) do |smtp|
    smtp.send_message(mail, from, *to)
  end
end
send_notification(exception, environment) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 96
def send_notification(exception, environment)
  mail = create_mail(:subject => exception.to_s,
                     :body => notification_body(exception, environment))
  send(mail)
end
send_summaries() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 133
def send_summaries
    subject = "summaries of #{@summaries.size} notifications"
    mail = create_mail(:subject => subject,
                       :body => report_body)
    send(mail)
end
summarize(exception, environment) click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 144
    def summarize(exception, environment)
      request = Rack::Request.new(environment)
      <<-EOB
Timestamp: #{Time.now.rfc2822}
--
URL: #{request.url}
--
#{exception.class}: #{exception.message}
EOB
    end
to() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 155
def to
  @to ||= ensure_array(@options[:to]) || []
end
transfer_encoding() click to toggle source
# File lib/racknga/exception_mail_notifier.rb, line 188
def transfer_encoding
  case charset
  when /\Autf-8\z/i
    "8bit"
  else
    "7bit"
  end
end