lukeredpath / hoptoad_notifier forked from thoughtbot/hoptoad_notifier

Reports exceptions to Hoptoad

This URL has Read+Write access

hoptoad_notifier / lib / hoptoad / notice.rb
100644 108 lines (94 sloc) 3.149 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
module Hoptoad
  class Notice
    
    # Parameters:
    # :request (hash or ActionController::CgiRequest)
    # :session (hash or CGI::Session)
    # :environment (hash)
    # :error_class (string)
    # :error_message (string)
    # :backtrace (array)
    def initialize(params={})
      @params = default_params.merge(params.delete_if { |k,v| v.nil? })
    end
    
    def default_params
      {
        :api_key => Hoptoad.api_key,
        :request => {},
        :session => {},
        :environment => {},
        :error_message => "Notification",
        :backtrace => self.class.default_backtrace
      }
    end
    
    def environment_data
      environment_data = @params[:environment]
      if @params[:request].respond_to?(:env)
        environment_data.merge!(@params[:request].env.to_hash)
      end
      environment_data
    end
    
    def request_data
      return @params[:request] if @params[:request].is_a?(Hash)
      cgi_request = @params[:request]
      {
        :params => filtered_parameters(cgi_request.parameters.to_hash),
        :rails_root => File.expand_path(RAILS_ROOT),
        :url => "#{cgi_request.protocol}#{cgi_request.host}#{cgi_request.request_uri}"
      }
    end
    
    def session_data
      return @params[:session] if @params[:session].is_a?(Hash)
      cgi_session = @params[:session]
      {
        :key => cgi_session.instance_variable_get("@session_id"),
        :data => cgi_session.instance_variable_get("@data")
      }
    end
    
    def to_hash
      {
        :api_key => @params[:api_key],
        :error_class => @params[:error_class],
        :error_message => @params[:error_message],
        :backtrace => filtered_backtrace(@params[:backtrace]),
        :environment => environment_data,
        :request => request_data,
        :session => session_data
      }.delete_if { |key, value| value.nil? }
    end
    
    class << self
      
      def build(hash_or_exception, request = {}, session = {}, environment = {})
        error_message = "#{hash_or_exception.class.name}: #{hash_or_exception.message}"
        new(
          :error_class => hash_or_exception.class.name,
          :error_message => error_message,
          :backtrace => (hash_or_exception.backtrace || []),
          :request => request,
          :session => session,
          :environment => environment
        )
      end
      
      # TODO: yuck!
      def default_backtrace
        caller
      end
      
    end
    
    private
      def filtered_backtrace(backtrace)
        if backtrace.to_a.size == 1
          backtrace = backtrace.to_a.first.split(/\n\s*/)
        end
 
        backtrace.to_a.map do |line|
          Hoptoad.backtrace_filters.inject(line) do |line, proc|
            proc.call(line)
          end
        end
      end
 
      def filtered_parameters(parameters)
        parameters.each do |k, v|
          parameters[k] = "<filtered>" if Hoptoad.params_filters.any? do |filter|
            k.to_s.match(/#{filter}/)
          end
        end
      end
    
  end
end