rollbar 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,7 +5,7 @@ module Rollbar
5
5
  def report_validation_errors_to_rollbar
6
6
  self.errors.full_messages.each do |error|
7
7
  Rollbar.log_info "[Rollbar] Reporting form validation error: #{error} for #{self.to_s}"
8
- Rollbar.report_message("Form Validation Error: #{error} for #{self.to_s}")
8
+ Rollbar.warning("Form Validation Error: #{error} for #{self.to_s}")
9
9
  end
10
10
  end
11
11
  end
@@ -20,6 +20,7 @@ module Rollbar
20
20
  attr_accessor :framework
21
21
  attr_accessor :ignored_person_ids
22
22
  attr_accessor :logger
23
+ attr_accessor :payload_options
23
24
  attr_accessor :person_method
24
25
  attr_accessor :person_id_method
25
26
  attr_accessor :person_username_method
@@ -28,6 +29,7 @@ module Rollbar
28
29
  attr_accessor :request_timeout
29
30
  attr_accessor :root
30
31
  attr_accessor :scrub_fields
32
+ attr_accessor :uncaught_exception_level
31
33
  attr_accessor :scrub_headers
32
34
  attr_accessor :use_async
33
35
  attr_accessor :use_eventmachine
@@ -57,6 +59,7 @@ module Rollbar
57
59
  @failover_handlers = []
58
60
  @framework = 'Plain'
59
61
  @ignored_person_ids = []
62
+ @payload_options = {}
60
63
  @person_method = 'current_user'
61
64
  @person_id_method = 'id'
62
65
  @person_username_method = 'username'
@@ -66,6 +69,7 @@ module Rollbar
66
69
  @request_timeout = 3
67
70
  @scrub_fields = [:passwd, :password, :password_confirmation, :secret,
68
71
  :confirm_password, :password_confirmation, :secret_token]
72
+ @uncaught_exception_level = 'error'
69
73
  @scrub_headers = ['Authorization']
70
74
  @use_async = false
71
75
  @use_eventmachine = false
@@ -73,6 +77,15 @@ module Rollbar
73
77
  @write_to_file = false
74
78
  end
75
79
 
80
+ def initialize_copy(orig)
81
+ super
82
+
83
+ instance_variables.each do |var|
84
+ instance_var = instance_variable_get(var)
85
+ instance_variable_set(var, Rollbar::Util::deep_copy(instance_var))
86
+ end
87
+ end
88
+
76
89
  def use_sidekiq(options = {})
77
90
  require 'rollbar/delay/sidekiq' if defined?(Sidekiq)
78
91
  @use_async = true
@@ -133,5 +146,9 @@ module Rollbar
133
146
  def [](option)
134
147
  send(option)
135
148
  end
149
+
150
+ def logger
151
+ @logger ||= default_logger.call
152
+ end
136
153
  end
137
154
  end
@@ -0,0 +1,9 @@
1
+ class Thread
2
+ def initialize_with_rollbar(*args, &block)
3
+ self[:_rollbar_notifier] ||= Rollbar.notifier.scope
4
+ initialize_without_rollbar(*args, &block)
5
+ end
6
+
7
+ alias_method :initialize_without_rollbar, :initialize
8
+ alias_method :initialize, :initialize_with_rollbar
9
+ end
@@ -3,10 +3,9 @@ module Rollbar
3
3
  include RequestDataExtractor
4
4
 
5
5
  def report_exception_to_rollbar(env, exception)
6
- Rollbar.log_error "Reporting exception: #{exception.message}"
7
- request_data = extract_request_data_from_rack(env)
8
- person_data = extract_person_data_from_controller(env)
9
- exception_data = Rollbar.report_exception(exception, request_data, person_data)
6
+ Rollbar.log_debug "[Rollbar] Reporting exception: #{exception.try(:message)}"
7
+
8
+ exception_data = Rollbar.log(Rollbar.configuration.uncaught_exception_level, exception)
10
9
 
11
10
  if exception_data.is_a?(Hash)
12
11
  env['rollbar.exception_uuid'] = exception_data[:uuid]
@@ -17,7 +16,7 @@ module Rollbar
17
16
  Rollbar.log_debug "[Rollbar] Exception not reported because it was ignored"
18
17
  end
19
18
  rescue => e
20
- Rollbar.log_debug "[Rollbar] Exception while reporting exception to Rollbar: #{e.message}"
19
+ Rollbar.log_warning "[Rollbar] Exception while reporting exception to Rollbar: #{e.message}"
21
20
  end
22
21
  end
23
22
  end
@@ -0,0 +1,32 @@
1
+ module Rollbar
2
+ class LoggerProxy
3
+ attr_reader :object
4
+
5
+ def initialize(object)
6
+ @object = object
7
+ end
8
+
9
+ def debug(message)
10
+ log('debug', message)
11
+ end
12
+
13
+ def info(message)
14
+ log('info', message)
15
+ end
16
+
17
+ def warn(message)
18
+ log('warn', message)
19
+ end
20
+
21
+ def error(message)
22
+ log('error', message)
23
+ end
24
+
25
+ def log(level, message)
26
+ @object.send(level, message)
27
+ rescue
28
+ puts "[Rollbar] Error logging #{level}:"
29
+ puts "[Rollbar] #{message}"
30
+ end
31
+ end
32
+ end
@@ -1,14 +1,32 @@
1
+ require 'rollbar/exception_reporter'
2
+ require 'rollbar/request_data_extractor'
3
+
1
4
  module Rollbar
2
5
  module Middleware
3
6
  module Rack
4
7
  module Builder
5
8
  include ExceptionReporter
9
+ include RequestDataExtractor
6
10
 
7
11
  def call_with_rollbar(env)
8
- call_without_rollbar(env)
9
- rescue Exception => exception
10
- report_exception_to_rollbar(env, exception)
11
- raise exception
12
+ Rollbar.reset_notifier!
13
+
14
+ Rollbar.scoped(fetch_scope(env)) do
15
+ begin
16
+ call_without_rollbar(env)
17
+ rescue ::Exception => exception
18
+ report_exception_to_rollbar(env, exception)
19
+ raise
20
+ end
21
+ end
22
+ end
23
+
24
+ def fetch_scope(env)
25
+ request_data = extract_request_data_from_rack(env)
26
+ { :request => request_data }
27
+ rescue Exception => e
28
+ report_exception_to_rollbar(env, e)
29
+ raise
12
30
  end
13
31
 
14
32
  def self.included(base)
@@ -0,0 +1,62 @@
1
+ module Rollbar
2
+ module Middleware
3
+ module Rails
4
+ class RollbarMiddleware
5
+ include RequestDataExtractor
6
+ include ExceptionReporter
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ Rollbar.reset_notifier!
14
+
15
+ Rollbar.scoped(fetch_scope(env)) do
16
+ begin
17
+ response = @app.call(env)
18
+
19
+ if (framework_exception = env['action_dispatch.exception'])
20
+ report_exception_to_rollbar(env, framework_exception)
21
+ end
22
+
23
+ response
24
+ rescue Exception => exception
25
+ report_exception_to_rollbar(env, exception)
26
+ raise
27
+ end
28
+ end
29
+ end
30
+
31
+ def fetch_scope(env)
32
+ request_data = extract_request_data_from_rack(env)
33
+
34
+ # Scope a new notifier with request data and a Proc for person data
35
+ # for any reports that happen while a controller is handling a request
36
+ {
37
+ :request => request_data,
38
+ :person => person_data_proc(env),
39
+ :context => context(request_data)
40
+ }
41
+ end
42
+
43
+ def person_data_proc(env)
44
+ block = proc { extract_person_data_from_controller(env) }
45
+ return block unless defined?(ActiveRecord::Base)
46
+
47
+ proc do
48
+ ActiveRecord::Base.connection_pool.with_connection(&block)
49
+ end
50
+ end
51
+
52
+ def context(request_data)
53
+ return unless request_data[:route]
54
+
55
+ route = request_data[:route]
56
+ # make sure route is a hash built by RequestDataExtractor
57
+ return "#{route[:controller]}" + '#' + "#{route[:action]}" if route.is_a?(Hash) && !route.empty?
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -6,18 +6,16 @@ module Rollbar
6
6
 
7
7
  def render_exception_with_rollbar(env, exception)
8
8
  key = 'action_dispatch.show_detailed_exceptions'
9
-
10
- # don't report production exceptions here as it is done below
11
- # in call_with_rollbar() when show_detailed_exception is false
12
- if not env.has_key?(key) or env[key]
9
+ if exception.is_a? ActionController::RoutingError and env[key]
13
10
  report_exception_to_rollbar(env, exception)
14
11
  end
12
+
15
13
  render_exception_without_rollbar(env, exception)
16
14
  end
17
15
 
18
16
  def call_with_rollbar(env)
19
17
  call_without_rollbar(env)
20
- rescue Exception => exception
18
+ rescue ActionController::RoutingError => exception
21
19
  # won't reach here if show_detailed_exceptions is true
22
20
  report_exception_to_rollbar(env, exception)
23
21
  raise exception
@@ -1,21 +1,37 @@
1
1
  require 'rollbar'
2
2
  require 'rollbar/exception_reporter'
3
+ require 'rollbar/request_data_extractor'
3
4
 
4
5
  module Rollbar
5
6
  module Middleware
6
7
  class Sinatra
7
8
  include ::Rollbar::ExceptionReporter
9
+ include RequestDataExtractor
8
10
 
9
11
  def initialize(app)
10
12
  @app = app
11
13
  end
12
14
 
13
15
  def call(env)
14
- response = @app.call(env)
15
- report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
16
- response
17
- rescue ::Exception => exception
18
- report_exception_to_rollbar(env, exception)
16
+ Rollbar.reset_notifier!
17
+
18
+ Rollbar.scoped(fetch_scope(env)) do
19
+ begin
20
+ response = @app.call(env)
21
+ report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
22
+ response
23
+ rescue Exception => e
24
+ report_exception_to_rollbar(env, e)
25
+ raise
26
+ end
27
+ end
28
+ end
29
+
30
+ def fetch_scope(env)
31
+ request_data = extract_request_data_from_rack(env)
32
+ { :request => request_data }
33
+ rescue Exception => e
34
+ report_exception_to_rollbar(env, e)
19
35
  raise
20
36
  end
21
37
 
@@ -6,11 +6,24 @@ module Rollbar
6
6
  rake_tasks do
7
7
  require 'rollbar/rake_tasks'
8
8
  end
9
-
10
- if defined? ActiveRecord
11
- initializer 'rollbar.middleware.rails' do |app|
12
- require 'rollbar/middleware/rails/rollbar_request_store'
13
- app.config.middleware.use Rollbar::Middleware::Rails::RollbarRequestStore
9
+
10
+ initializer 'rollbar.middleware.rails' do |app|
11
+ if defined?(ActionDispatch::DebugExceptions)
12
+ # Rails 3.2.x+
13
+ require 'rollbar/middleware/rails/rollbar'
14
+ require 'rollbar/middleware/rails/show_exceptions'
15
+
16
+ app.config.middleware.insert_after ActionDispatch::DebugExceptions,
17
+ Rollbar::Middleware::Rails::RollbarMiddleware
18
+ ActionDispatch::DebugExceptions.send(:include, Rollbar::Middleware::Rails::ShowExceptions)
19
+ elsif defined?(ActionDispatch::ShowExceptions)
20
+ # Rails 3.0.x and 3.1.x
21
+ require 'rollbar/middleware/rails/rollbar'
22
+ require 'rollbar/middleware/rails/show_exceptions'
23
+
24
+ app.config.middleware.insert_after ActionDispatch::ShowExceptions,
25
+ Rollbar::Middleware::Rails::RollbarMiddleware
26
+ ActionDispatch::ShowExceptions.send(:include, Rollbar::Middleware::Rails::ShowExceptions)
14
27
  end
15
28
  end
16
29
 
@@ -28,16 +41,6 @@ module Rollbar
28
41
  require 'rollbar/rails/controller_methods'
29
42
  include Rollbar::Rails::ControllerMethods
30
43
  end
31
-
32
- if defined?(ActionDispatch::DebugExceptions)
33
- # Rails 3.2.x
34
- require 'rollbar/middleware/rails/show_exceptions'
35
- ActionDispatch::DebugExceptions.send(:include, Rollbar::Middleware::Rails::ShowExceptions)
36
- elsif defined?(ActionDispatch::ShowExceptions)
37
- # Rails 3.0.x and 3.1.x
38
- require 'rollbar/middleware/rails/show_exceptions'
39
- ActionDispatch::ShowExceptions.send(:include, Rollbar::Middleware::Rails::ShowExceptions)
40
- end
41
44
  end
42
45
  end
43
46
  end
@@ -1,10 +1,7 @@
1
+ require 'multi_json'
2
+
1
3
  module Rollbar
2
4
  module RequestDataExtractor
3
- ATTACHMENT_CLASSES = %w[
4
- ActionDispatch::Http::UploadedFile
5
- Rack::Multipart::UploadedFile
6
- ].freeze
7
-
8
5
  def extract_person_data_from_controller(env)
9
6
  if env.has_key? 'rollbar.person_data'
10
7
  person_data = env['rollbar.person_data'] || {}
@@ -23,11 +20,12 @@ module Rollbar
23
20
  request_params = rollbar_filtered_params(sensitive_params, rollbar_request_params(env))
24
21
  get_params = rollbar_filtered_params(sensitive_params, rollbar_get_params(rack_req))
25
22
  post_params = rollbar_filtered_params(sensitive_params, rollbar_post_params(rack_req))
23
+ raw_post_params = rollbar_filtered_params(sensitive_params, rollbar_raw_post_params(rack_req))
26
24
  cookies = rollbar_filtered_params(sensitive_params, rollbar_request_cookies(rack_req))
27
25
  session = rollbar_filtered_params(sensitive_params, env['rack.session.options'])
28
26
  route_params = rollbar_filtered_params(sensitive_params, rollbar_route_params(env))
29
27
 
30
- params = request_params.merge(get_params).merge(post_params)
28
+ params = request_params.merge(get_params).merge(post_params).merge(raw_post_params)
31
29
 
32
30
  data = {
33
31
  :params => params,
@@ -101,6 +99,15 @@ module Rollbar
101
99
  {}
102
100
  end
103
101
 
102
+ def rollbar_raw_post_params(rack_req)
103
+ return {} unless rack_req.env['CONTENT_TYPE'] =~ %r{application/json}i
104
+
105
+ params = MultiJson.decode(rack_req.body.read)
106
+ rack_req.body.rewind
107
+
108
+ params
109
+ end
110
+
104
111
  def rollbar_request_params(env)
105
112
  env['action_dispatch.request.parameters'] || {}
106
113
  end
@@ -125,18 +132,20 @@ module Rollbar
125
132
  end
126
133
 
127
134
  def rollbar_filtered_params(sensitive_params, params)
128
- @sensitive_params_regexp ||= Regexp.new(sensitive_params.map{ |val| Regexp.escape(val.to_s).to_s }.join('|'), true)
135
+ sensitive_params_regexp = Regexp.new(sensitive_params.map{ |val| Regexp.escape(val.to_s).to_s }.join('|'), true)
129
136
 
130
137
  if params.nil?
131
138
  {}
132
139
  else
133
140
  params.to_hash.inject({}) do |result, (key, value)|
134
- if @sensitive_params_regexp =~ key.to_s
141
+ if sensitive_params_regexp =~ key.to_s
135
142
  result[key] = rollbar_scrubbed(value)
136
143
  elsif value.is_a?(Hash)
137
144
  result[key] = rollbar_filtered_params(sensitive_params, value)
138
145
  elsif value.is_a?(Array)
139
- result[key] = value.map {|v| v.is_a?(Hash) ? rollbar_filtered_params(sensitive_params, v) : v}
146
+ result[key] = value.map do |v|
147
+ v.is_a?(Hash) ? rollbar_filtered_params(sensitive_params, v) : v
148
+ end
140
149
  elsif ATTACHMENT_CLASSES.include?(value.class.name)
141
150
  result[key] = {
142
151
  :content_type => value.content_type,
@@ -146,6 +155,7 @@ module Rollbar
146
155
  else
147
156
  result[key] = value
148
157
  end
158
+
149
159
  result
150
160
  end
151
161
  end
@@ -37,6 +37,45 @@ module Rollbar
37
37
  end
38
38
  end
39
39
 
40
+ def self.iterate_and_update_hash(hash, block)
41
+ hash.each do |k, v|
42
+ if v.is_a?(Hash)
43
+ self.iterate_and_update_hash(v, block)
44
+ else
45
+ hash[k] = block.call(k, v)
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.deep_copy(obj)
51
+ if obj.is_a?(Hash)
52
+ result = obj.clone
53
+ obj.each {|k, v| result[k] = deep_copy(v)}
54
+ result
55
+ elsif obj.is_a?(Array)
56
+ result = obj.clone
57
+ result.clear
58
+ obj.each {|v| result << deep_copy(v)}
59
+ result
60
+ else
61
+ obj
62
+ end
63
+ end
64
+
65
+ def self.deep_merge(hash1, hash2)
66
+ hash2.each_key do |k|
67
+ if hash1[k].is_a? Hash and hash2[k].is_a? Hash
68
+ hash1[k] = deep_merge(hash1[k], hash2[k])
69
+ elsif hash1[k].is_a? Array and hash2[k].is_a? Array
70
+ hash1[k] += deep_copy(hash2[k])
71
+ elsif hash2[k]
72
+ hash1[k] = deep_copy(hash2[k])
73
+ end
74
+ end
75
+
76
+ hash1
77
+ end
78
+
40
79
  def self.truncate(str, length)
41
80
  ellipsis = '...'
42
81