rollbar 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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