rollbar 2.19.1 → 2.27.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/.github/pull_request_template.md +25 -0
  3. data/.rubocop.yml +168 -0
  4. data/.travis.yml +63 -34
  5. data/Appraisals +10 -10
  6. data/Gemfile +35 -14
  7. data/README.md +5 -2
  8. data/Rakefile +0 -0
  9. data/data/rollbar.snippet.js +1 -1
  10. data/docs/configuration.md +17 -0
  11. data/gemfiles/rails30.gemfile +10 -10
  12. data/gemfiles/rails31.gemfile +10 -9
  13. data/gemfiles/rails32.gemfile +10 -9
  14. data/gemfiles/rails40.gemfile +10 -9
  15. data/gemfiles/rails41.gemfile +10 -9
  16. data/gemfiles/rails42.gemfile +12 -9
  17. data/gemfiles/rails50.gemfile +21 -14
  18. data/gemfiles/rails51.gemfile +21 -14
  19. data/gemfiles/rails52.gemfile +15 -12
  20. data/gemfiles/rails60.gemfile +67 -0
  21. data/lib/generators/rollbar/rollbar_generator.rb +1 -1
  22. data/lib/rails/rollbar_runner.rb +4 -2
  23. data/lib/rollbar/capistrano.rb +1 -1
  24. data/lib/rollbar/capistrano3.rb +6 -3
  25. data/lib/rollbar/capistrano_tasks.rb +29 -21
  26. data/lib/rollbar/configuration.rb +86 -16
  27. data/lib/rollbar/delay/girl_friday.rb +4 -8
  28. data/lib/rollbar/delay/resque.rb +3 -6
  29. data/lib/rollbar/delay/sidekiq.rb +4 -10
  30. data/lib/rollbar/delay/sucker_punch.rb +16 -19
  31. data/lib/rollbar/delay/thread.rb +16 -2
  32. data/lib/rollbar/deploy.rb +52 -29
  33. data/lib/rollbar/encoding/encoder.rb +17 -10
  34. data/lib/rollbar/exception_reporter.rb +19 -5
  35. data/lib/rollbar/item/backtrace.rb +13 -3
  36. data/lib/rollbar/item/frame.rb +9 -1
  37. data/lib/rollbar/item/locals.rb +100 -0
  38. data/lib/rollbar/item.rb +56 -17
  39. data/lib/rollbar/json.rb +6 -51
  40. data/lib/rollbar/language_support.rb +4 -20
  41. data/lib/rollbar/lazy_store.rb +5 -5
  42. data/lib/rollbar/logger.rb +1 -0
  43. data/lib/rollbar/logger_proxy.rb +6 -2
  44. data/lib/rollbar/middleware/js.rb +28 -18
  45. data/lib/rollbar/middleware/rack.rb +4 -1
  46. data/lib/rollbar/middleware/rails/rollbar.rb +10 -1
  47. data/lib/rollbar/notifier/trace_with_bindings.rb +65 -0
  48. data/lib/rollbar/notifier.rb +225 -89
  49. data/lib/rollbar/plugin.rb +54 -6
  50. data/lib/rollbar/plugins/active_job.rb +6 -2
  51. data/lib/rollbar/plugins/basic_socket.rb +21 -6
  52. data/lib/rollbar/plugins/delayed_job/job_data.rb +3 -3
  53. data/lib/rollbar/plugins/delayed_job/plugin.rb +13 -3
  54. data/lib/rollbar/plugins/error_context.rb +11 -0
  55. data/lib/rollbar/plugins/goalie.rb +11 -3
  56. data/lib/rollbar/plugins/rails/controller_methods.rb +15 -3
  57. data/lib/rollbar/plugins/rake.rb +2 -2
  58. data/lib/rollbar/plugins/sidekiq/plugin.rb +5 -4
  59. data/lib/rollbar/plugins.rb +7 -1
  60. data/lib/rollbar/rake_tasks.rb +4 -148
  61. data/lib/rollbar/request_data_extractor.rb +31 -21
  62. data/lib/rollbar/rollbar_test.rb +36 -0
  63. data/lib/rollbar/scrubbers/params.rb +19 -18
  64. data/lib/rollbar/scrubbers/url.rb +18 -9
  65. data/lib/rollbar/scrubbers.rb +3 -3
  66. data/lib/rollbar/truncation/frames_strategy.rb +1 -1
  67. data/lib/rollbar/truncation/min_body_strategy.rb +2 -3
  68. data/lib/rollbar/truncation/mixin.rb +1 -1
  69. data/lib/rollbar/truncation/remove_any_key_strategy.rb +123 -0
  70. data/lib/rollbar/truncation/remove_extra_strategy.rb +35 -0
  71. data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
  72. data/lib/rollbar/truncation/strings_strategy.rb +6 -5
  73. data/lib/rollbar/truncation.rb +9 -2
  74. data/lib/rollbar/util/hash.rb +15 -0
  75. data/lib/rollbar/util/ip_anonymizer.rb +8 -7
  76. data/lib/rollbar/util/ip_obfuscator.rb +1 -1
  77. data/lib/rollbar/util.rb +6 -2
  78. data/lib/rollbar/version.rb +1 -1
  79. data/lib/rollbar.rb +2 -3
  80. data/lib/tasks/benchmark.rake +103 -0
  81. data/rollbar.gemspec +13 -5
  82. data/spec/support/rollbar_api.rb +67 -0
  83. metadata +21 -23
  84. data/gemfiles/ruby_1_8_and_1_9_2.gemfile +0 -49
  85. data/lib/rollbar/json/default.rb +0 -11
  86. data/lib/rollbar/json/oj.rb +0 -16
@@ -1,5 +1,3 @@
1
- require 'capistrano'
2
- require 'capistrano/version'
3
1
  require 'rollbar/deploy'
4
2
 
5
3
  module Rollbar
@@ -10,15 +8,15 @@ module Rollbar
10
8
  deploy_task(logger, :desc => 'Notifying Rollbar of deployment start') do
11
9
  result = report_deploy_started(capistrano, dry_run)
12
10
 
13
- info_request_response(logger, result)
11
+ debug_request_response(logger, result)
14
12
 
15
13
  capistrano.set(:rollbar_deploy_id, 123) if dry_run
16
14
 
17
15
  skip_in_dry_run(logger, dry_run) do
18
- if (deploy_id = result[:data][:deploy_id])
16
+ if result[:success] && (deploy_id = result[:data] && result[:data][:deploy_id])
19
17
  capistrano.set :rollbar_deploy_id, deploy_id
20
18
  else
21
- logger.error 'Unable to report deploy to Rollbar'
19
+ logger.error 'Unable to report deploy to Rollbar' + (result[:message] ? ': ' + result[:message] : '')
22
20
  end
23
21
  end
24
22
  end
@@ -42,6 +40,9 @@ module Rollbar
42
40
  capistrano_300_warning(logger)
43
41
  logger.info opts[:desc] if opts[:desc]
44
42
  yield
43
+
44
+ rescue StandardError => e
45
+ logger.error "Error reporting to Rollbar: #{e.inspect}"
45
46
  end
46
47
 
47
48
  def deploy_update(capistrano, logger, dry_run, opts = {})
@@ -49,13 +50,13 @@ module Rollbar
49
50
  depend_on_deploy_id(capistrano, logger) do
50
51
  result = yield
51
52
 
52
- info_request_response(logger, result)
53
+ debug_request_response(logger, result)
53
54
 
54
55
  skip_in_dry_run(logger, dry_run) do
55
- if result[:response].is_a?(Net::HTTPSuccess)
56
+ if result[:success]
56
57
  logger.info 'Updated deploy status in Rollbar'
57
58
  else
58
- logger.error 'Unable to update deploy status in Rollbar'
59
+ logger.error 'Unable to update deploy status in Rollbar' + (result[:message] ? ': ' + result[:message] : '')
59
60
  end
60
61
  end
61
62
  end
@@ -63,7 +64,11 @@ module Rollbar
63
64
  end
64
65
 
65
66
  def capistrano_300_warning(logger)
66
- logger.warn("You need to upgrade capistrano to '>= 3.1' version in order to correctly report deploys to Rollbar. (On 3.0, the reported revision will be incorrect.)") if ::Capistrano::VERSION =~ /^3\.0/
67
+ return unless ::Capistrano.const_defined?('VERSION') && ::Capistrano::VERSION =~ /^3\.0/
68
+
69
+ logger.warn('You need to upgrade capistrano to >= 3.1 version in order'\
70
+ 'to correctly report deploys to Rollbar. (On 3.0, the reported revision'\
71
+ 'will be incorrect.)')
67
72
  end
68
73
 
69
74
  def report_deploy_started(capistrano, dry_run)
@@ -76,33 +81,35 @@ module Rollbar
76
81
  :proxy => :ENV,
77
82
  :dry_run => dry_run
78
83
  },
79
- :access_token => capistrano.fetch(:rollbar_token),
80
- :environment => capistrano.fetch(:rollbar_env),
81
- :revision => capistrano.fetch(:rollbar_revision)
84
+ capistrano.fetch(:rollbar_token),
85
+ capistrano.fetch(:rollbar_env),
86
+ capistrano.fetch(:rollbar_revision)
82
87
  )
83
88
  end
84
89
 
85
90
  def report_deploy_succeeded(capistrano, dry_run)
86
91
  ::Rollbar::Deploy.update(
87
92
  {
93
+ :comment => capistrano.fetch(:rollbar_comment),
88
94
  :proxy => :ENV,
89
95
  :dry_run => dry_run
90
96
  },
91
- :access_token => capistrano.fetch(:rollbar_token),
92
- :deploy_id => capistrano.fetch(:rollbar_deploy_id),
93
- :status => :succeeded
97
+ capistrano.fetch(:rollbar_token),
98
+ capistrano.fetch(:rollbar_deploy_id),
99
+ :succeeded
94
100
  )
95
101
  end
96
102
 
97
103
  def report_deploy_failed(capistrano, dry_run)
98
104
  ::Rollbar::Deploy.update(
99
105
  {
106
+ :comment => capistrano.fetch(:rollbar_comment),
100
107
  :proxy => :ENV,
101
108
  :dry_run => dry_run
102
109
  },
103
- :access_token => capistrano.fetch(:rollbar_token),
104
- :deploy_id => capistrano.fetch(:rollbar_deploy_id),
105
- :status => :failed
110
+ capistrano.fetch(:rollbar_token),
111
+ capistrano.fetch(:rollbar_deploy_id),
112
+ :failed
106
113
  )
107
114
  end
108
115
 
@@ -122,9 +129,10 @@ module Rollbar
122
129
  end
123
130
  end
124
131
 
125
- def info_request_response(logger, result)
126
- logger.info result[:request_info]
127
- logger.info result[:response_info] if result[:response_info]
132
+ def debug_request_response(logger, result)
133
+ # NOTE: in Capistrano debug messages go to log/capistrano.log but not to stdout even if log_level == :debug
134
+ logger.debug result[:request_info]
135
+ logger.debug result[:response_info] if result[:response_info]
128
136
  end
129
137
  end
130
138
  end
@@ -8,6 +8,7 @@ module Rollbar
8
8
  attr_accessor :async_handler
9
9
  attr_accessor :branch
10
10
  attr_reader :before_process
11
+ attr_accessor :capture_uncaught
11
12
  attr_accessor :code_version
12
13
  attr_accessor :custom_data_method
13
14
  attr_accessor :delayed_job_enabled
@@ -16,16 +17,18 @@ module Rollbar
16
17
  attr_accessor :disable_monkey_patch
17
18
  attr_accessor :disable_rack_monkey_patch
18
19
  attr_accessor :disable_core_monkey_patch
20
+ attr_accessor :enable_error_context
19
21
  attr_accessor :dj_threshold
22
+ attr_accessor :async_skip_report_handler
20
23
  attr_accessor :enabled
21
24
  attr_accessor :endpoint
22
25
  attr_accessor :environment
23
26
  attr_accessor :exception_level_filters
24
27
  attr_accessor :failover_handlers
25
- attr_accessor :filepath
26
28
  attr_accessor :framework
27
29
  attr_accessor :ignored_person_ids
28
30
  attr_accessor :host
31
+ attr_accessor :locals
29
32
  attr_writer :logger
30
33
  attr_accessor :payload_options
31
34
  attr_accessor :person_method
@@ -55,23 +58,36 @@ module Rollbar
55
58
  attr_reader :transform
56
59
  attr_accessor :verify_ssl_peer
57
60
  attr_accessor :use_async
61
+ attr_accessor :async_json_payload
58
62
  attr_reader :use_eventmachine
59
63
  attr_accessor :web_base
60
- attr_accessor :write_to_file
61
64
  attr_reader :send_extra_frame_data
62
65
  attr_accessor :use_exception_level_filters_default
63
66
  attr_accessor :proxy
67
+ attr_accessor :raise_on_error
68
+ attr_accessor :transmit
69
+ attr_accessor :log_payload
70
+ attr_accessor :backtrace_cleaner
71
+
72
+ attr_accessor :write_to_file
73
+ attr_accessor :filepath
74
+ attr_accessor :files_with_pid_name_enabled
75
+ attr_accessor :files_processed_enabled
76
+ attr_accessor :files_processed_duration # seconds
77
+ attr_accessor :files_processed_size # bytes
64
78
 
65
79
  attr_reader :project_gem_paths
80
+ attr_accessor :configured_options
66
81
 
67
- alias_method :safely?, :safely
82
+ alias safely? safely
68
83
 
69
- DEFAULT_ENDPOINT = 'https://api.rollbar.com/api/1/item/'
70
- DEFAULT_WEB_BASE = 'https://rollbar.com'
84
+ DEFAULT_ENDPOINT = 'https://api.rollbar.com/api/1/item/'.freeze
85
+ DEFAULT_WEB_BASE = 'https://rollbar.com'.freeze
71
86
 
72
87
  def initialize
73
88
  @async_handler = nil
74
89
  @before_process = []
90
+ @capture_uncaught = nil
75
91
  @code_version = nil
76
92
  @custom_data_method = nil
77
93
  @default_logger = lambda { ::Logger.new(STDERR) }
@@ -80,7 +96,9 @@ module Rollbar
80
96
  @disable_monkey_patch = false
81
97
  @disable_core_monkey_patch = false
82
98
  @disable_rack_monkey_patch = false
99
+ @enable_error_context = true
83
100
  @dj_threshold = 0
101
+ @async_skip_report_handler = nil
84
102
  @enabled = nil # set to true when configure is called
85
103
  @endpoint = DEFAULT_ENDPOINT
86
104
  @environment = nil
@@ -105,12 +123,13 @@ module Rollbar
105
123
  @net_retries = 3
106
124
  @js_enabled = false
107
125
  @js_options = {}
126
+ @locals = {}
108
127
  @scrub_fields = [:passwd, :password, :password_confirmation, :secret,
109
128
  :confirm_password, :password_confirmation, :secret_token,
110
- :api_key, :access_token, :session_id]
129
+ :api_key, :access_token, :accessToken, :session_id]
111
130
  @scrub_user = true
112
131
  @scrub_password = true
113
- @randomize_scrub_length = true
132
+ @randomize_scrub_length = false
114
133
  @scrub_whitelist = []
115
134
  @uncaught_exception_level = 'error'
116
135
  @scrub_headers = ['Authorization']
@@ -118,20 +137,32 @@ module Rollbar
118
137
  @safely = false
119
138
  @transform = []
120
139
  @use_async = false
140
+ @async_json_payload = false
121
141
  @use_eventmachine = false
122
142
  @verify_ssl_peer = true
123
143
  @web_base = DEFAULT_WEB_BASE
124
- @write_to_file = false
125
144
  @send_extra_frame_data = :none
126
145
  @project_gem_paths = []
127
146
  @use_exception_level_filters_default = false
128
147
  @proxy = nil
148
+ @raise_on_error = false
149
+ @transmit = true
150
+ @log_payload = false
129
151
  @collect_user_ip = true
130
152
  @anonymize_user_ip = false
153
+ @backtrace_cleaner = nil
131
154
  @hooks = {
132
155
  :on_error_response => nil, # params: response
133
- :on_report_internal_error => nil, # params: exception
156
+ :on_report_internal_error => nil # params: exception
134
157
  }
158
+
159
+ @write_to_file = false
160
+ @files_with_pid_name_enabled = false
161
+ @files_processed_enabled = false
162
+ @files_processed_duration = 60
163
+ @files_processed_size = 5 * 1000 * 1000
164
+
165
+ @configured_options = ConfiguredOptions.new(self)
135
166
  end
136
167
 
137
168
  def initialize_copy(orig)
@@ -139,9 +170,18 @@ module Rollbar
139
170
 
140
171
  instance_variables.each do |var|
141
172
  instance_var = instance_variable_get(var)
142
- instance_variable_set(var, Rollbar::Util::deep_copy(instance_var))
173
+ instance_variable_set(var, Rollbar::Util.deep_copy(instance_var))
174
+ end
175
+ end
176
+
177
+ def wrapped_clone
178
+ original_clone.tap do |new_config|
179
+ new_config.configured_options = ConfiguredOptions.new(new_config)
180
+ new_config.configured_options.configured = configured_options.configured
143
181
  end
144
182
  end
183
+ alias original_clone clone
184
+ alias clone wrapped_clone
145
185
 
146
186
  def merge(options)
147
187
  new_configuration = clone
@@ -210,9 +250,10 @@ module Rollbar
210
250
  value.is_a?(Hash) ? use_sidekiq(value) : use_sidekiq
211
251
  end
212
252
 
213
- def use_thread
253
+ def use_thread(options = {})
214
254
  require 'rollbar/delay/thread'
215
255
  @use_async = true
256
+ Rollbar::Delay::Thread.options = options
216
257
  @async_handler = Rollbar::Delay::Thread
217
258
  end
218
259
 
@@ -222,7 +263,7 @@ module Rollbar
222
263
  @async_handler = Rollbar::Delay::SuckerPunch
223
264
  end
224
265
 
225
- def use_sucker_punch=(value)
266
+ def use_sucker_punch=(_value)
226
267
  deprecation_message = '#use_sucker_punch=(value) has been deprecated in favor of #use_sucker_punch. Please update your rollbar configuration.'
227
268
  defined?(ActiveSupport) ? ActiveSupport::Deprecation.warn(deprecation_message) : puts(deprecation_message)
228
269
 
@@ -239,7 +280,10 @@ module Rollbar
239
280
  found = Gem::Specification.each.select { |spec| name === spec.name }
240
281
  puts "[Rollbar] No gems found matching #{name.inspect}" if found.empty?
241
282
  found
242
- end.flatten.uniq.map(&:gem_dir)
283
+ end
284
+ @project_gem_paths.flatten!
285
+ @project_gem_paths.uniq!
286
+ @project_gem_paths.map!(&:gem_dir)
243
287
  end
244
288
 
245
289
  def before_process=(*handler)
@@ -266,7 +310,11 @@ module Rollbar
266
310
  end
267
311
 
268
312
  def logger_level=(level)
269
- @logger_level = level.to_sym
313
+ @logger_level = if level
314
+ level.to_sym
315
+ else
316
+ level
317
+ end
270
318
  end
271
319
 
272
320
  def logger
@@ -274,14 +322,14 @@ module Rollbar
274
322
  end
275
323
 
276
324
  def hook(symbol, &block)
277
- if @hooks.has_key?(symbol)
325
+ if @hooks.key?(symbol)
278
326
  if block_given?
279
327
  @hooks[symbol] = block
280
328
  else
281
329
  @hooks[symbol]
282
330
  end
283
331
  else
284
- raise StandardError.new "Hook :" + symbol.to_s + " is not supported by Rollbar SDK."
332
+ raise StandardError, 'Hook :' + symbol.to_s + ' is not supported by Rollbar SDK.'
285
333
  end
286
334
  end
287
335
 
@@ -289,4 +337,26 @@ module Rollbar
289
337
  hook(symbol).call(*args) if hook(symbol).is_a?(Proc)
290
338
  end
291
339
  end
340
+
341
+ class ConfiguredOptions
342
+ attr_accessor :configuration, :configured
343
+
344
+ def initialize(configuration)
345
+ @configuration = configuration
346
+ @configured = {}
347
+ end
348
+
349
+ def method_missing(method, *args, &block)
350
+ return super unless configuration.respond_to?(method)
351
+
352
+ method_string = method.to_s
353
+ configured[method_string.chomp('=').to_sym] = args.first if method_string.end_with?('=')
354
+
355
+ configuration.send(method, *args, &block)
356
+ end
357
+
358
+ def respond_to_missing?(method)
359
+ configuration.respond_to?(method) || super
360
+ end
361
+ end
292
362
  end
@@ -11,14 +11,10 @@ module Rollbar
11
11
  end
12
12
 
13
13
  def queue
14
- @queue ||= self.queue_class.new(nil, :size => 5) do |payload|
15
- begin
16
- Rollbar.process_from_async_handler(payload)
17
- rescue
18
- # According to https://github.com/mperham/girl_friday/wiki#error-handling
19
- # we reraise the exception so it can be handled some way
20
- raise
21
- end
14
+ @queue ||= queue_class.new(nil, :size => 5) do |payload|
15
+ Rollbar.process_from_async_handler(payload)
16
+
17
+ # Do not rescue. GirlFriday will call the error handler.
22
18
  end
23
19
  end
24
20
  end
@@ -23,12 +23,9 @@ module Rollbar
23
23
  end
24
24
 
25
25
  def perform(payload)
26
- begin
27
- Rollbar.process_from_async_handler(payload)
28
- rescue
29
- # Raise the exception so Resque can track the errored job
30
- raise
31
- end
26
+ Rollbar.process_from_async_handler(payload)
27
+
28
+ # Do not rescue. Resque will call the error handler.
32
29
  end
33
30
  end
34
31
  end
@@ -10,21 +10,15 @@ module Rollbar
10
10
  end
11
11
 
12
12
  def call(payload)
13
- if ::Sidekiq::Client.push(@options.merge('args' => [payload])) == nil
14
- raise StandardError.new "Unable to push the job to Sidekiq"
15
- end
13
+ raise StandardError, 'Unable to push the job to Sidekiq' if ::Sidekiq::Client.push(@options.merge('args' => [payload])).nil?
16
14
  end
17
15
 
18
16
  include ::Sidekiq::Worker
19
17
 
20
18
  def perform(*args)
21
- begin
22
- Rollbar.process_from_async_handler(*args)
23
- rescue
24
- # Raise the exception so Sidekiq can track the errored job
25
- # and retry it
26
- raise
27
- end
19
+ Rollbar.process_from_async_handler(*args)
20
+
21
+ # Do not rescue. Sidekiq will call the error handler.
28
22
  end
29
23
  end
30
24
  end
@@ -16,11 +16,11 @@ module Rollbar
16
16
  def self.setup
17
17
  major_version = ::SuckerPunch::VERSION.split.first.to_i
18
18
 
19
- if major_version > 1
20
- self.perform_proc = proc { |payload| perform_async(payload) }
21
- else
22
- self.perform_proc = proc { |payload| new.async.perform(payload) }
23
- end
19
+ self.perform_proc = if major_version > 1
20
+ proc { |payload| perform_async(payload) }
21
+ else
22
+ proc { |payload| new.async.perform(payload) }
23
+ end
24
24
 
25
25
  self.ready = true
26
26
  end
@@ -32,20 +32,17 @@ module Rollbar
32
32
  end
33
33
 
34
34
  def perform(*args)
35
- begin
36
- Rollbar.process_from_async_handler(*args)
37
- rescue
38
- # SuckerPunch can configure an exception handler with:
39
- #
40
- # SuckerPunch.exception_handler { # do something here }
41
- #
42
- # This is just passed to Celluloid.exception_handler which will
43
- # push the reiceved block to an array of handlers, by default empty, [].
44
- #
45
- # We reraise the exception here casue it's safe and users could have defined
46
- # their own exception handler for SuckerPunch
47
- raise
48
- end
35
+ Rollbar.process_from_async_handler(*args)
36
+
37
+ # SuckerPunch can configure an exception handler with:
38
+ #
39
+ # SuckerPunch.exception_handler { # do something here }
40
+ #
41
+ # This is just passed to Celluloid.exception_handler which will
42
+ # push the reiceved block to an array of handlers, by default empty, [].
43
+ #
44
+
45
+ # Do not rescue. SuckerPunch will call the error handler.
49
46
  end
50
47
  end
51
48
  end
@@ -1,4 +1,3 @@
1
- require 'thread'
2
1
  require 'timeout'
3
2
 
4
3
  module Rollbar
@@ -10,7 +9,10 @@ module Rollbar
10
9
  Error = Class.new(StandardError)
11
10
  TimeoutError = Class.new(Error)
12
11
 
12
+ DEFAULT_PRIORITY = 1
13
+
13
14
  class << self
15
+ attr_writer :options
14
16
  attr_reader :reaper
15
17
 
16
18
  def call(payload)
@@ -21,6 +23,10 @@ module Rollbar
21
23
  thread
22
24
  end
23
25
 
26
+ def options
27
+ @options || {}
28
+ end
29
+
24
30
  private
25
31
 
26
32
  def threads
@@ -29,6 +35,7 @@ module Rollbar
29
35
 
30
36
  def spawn_threads_reaper
31
37
  return if @spawned
38
+
32
39
  @spawned = true
33
40
 
34
41
  @reaper ||= build_reaper_thread
@@ -61,11 +68,18 @@ module Rollbar
61
68
  end
62
69
  end # class << self
63
70
 
71
+ def priority
72
+ self.class.options[:priority] || DEFAULT_PRIORITY
73
+ end
74
+
64
75
  def call(payload)
76
+ priority = self.priority
77
+
65
78
  ::Thread.new do
66
79
  begin
80
+ ::Thread.current.priority = priority
67
81
  Rollbar.process_from_async_handler(payload)
68
- rescue
82
+ rescue StandardError
69
83
  # Here we swallow the exception:
70
84
  # 1. The original report wasn't sent.
71
85
  # 2. An internal error was sent and logged
@@ -1,68 +1,91 @@
1
- require 'capistrano'
1
+ require 'json'
2
2
 
3
3
  module Rollbar
4
4
  # Deploy Tracking API wrapper module
5
5
  module Deploy
6
6
  ENDPOINT = 'https://api.rollbar.com/api/1/deploy/'.freeze
7
7
 
8
- def self.report(opts = {}, access_token:, environment:, revision:)
8
+ def self.report(opts, access_token, environment, revision)
9
+ return {} unless access_token && !access_token.empty?
10
+
9
11
  opts[:status] ||= :started
10
12
 
11
- uri = URI.parse(::Rollbar::Deploy::ENDPOINT)
13
+ uri = ::URI.parse(::Rollbar::Deploy::ENDPOINT)
12
14
 
13
- request = Net::HTTP::Post.new(uri.request_uri)
14
- request.body = ::JSON.dump({
15
+ request_data = {
15
16
  :access_token => access_token,
16
17
  :environment => environment,
17
18
  :revision => revision
18
- }.merge(opts))
19
+ }.merge(opts)
20
+ request_data.delete(:proxy)
21
+ request_data.delete(:dry_run)
22
+
23
+ request = ::Net::HTTP::Post.new(uri.request_uri)
24
+ request.body = ::JSON.dump(request_data)
19
25
 
20
- send_request(opts, :uri => uri, :request => request)
26
+ send_request(opts, uri, request)
21
27
  end
22
28
 
23
- def self.update(opts = {}, deploy_id:, access_token:, status:)
24
- uri = URI.parse(
29
+ def self.update(opts, access_token, deploy_id, status)
30
+ return {} unless access_token && !access_token.empty?
31
+
32
+ uri = ::URI.parse(
25
33
  ::Rollbar::Deploy::ENDPOINT +
26
34
  deploy_id.to_s +
27
35
  '?access_token=' + access_token
28
36
  )
29
37
 
30
- request = Net::HTTP::Patch.new(uri.request_uri)
38
+ request = ::Net::HTTP::Patch.new(uri.request_uri)
31
39
  request.body = ::JSON.dump(:status => status.to_s, :comment => opts[:comment])
32
40
 
33
- send_request(opts, :uri => uri, :request => request)
41
+ send_request(opts, uri, request)
34
42
  end
35
43
 
36
44
  class << self
37
45
  private
38
46
 
39
- def send_request(opts = {}, uri:, request:)
40
- Net::HTTP.start(uri.host, uri.port, opts[:proxy], :use_ssl => true) do |http|
47
+ def send_request(opts, uri, request)
48
+ ::Net::HTTP.start(uri.host, uri.port, opts[:proxy], :use_ssl => true) do |http|
41
49
  build_result(
42
- :uri => uri,
43
- :request => request,
44
- :response => opts[:dry_run] ? nil : http.request(request)
50
+ uri,
51
+ request,
52
+ opts[:dry_run] ? nil : http.request(request),
53
+ opts[:dry_run]
45
54
  )
46
55
  end
47
56
  end
48
57
 
49
- def build_result(uri:, request:, response: nil)
50
- result = {
51
- :request_info => uri.inspect + ': ' + request.body,
52
- :request => request,
53
- :response => response
54
- }
58
+ def build_result(uri, request, response = nil, dry_run = false)
59
+ result = {}
60
+ result.merge!(request_result(uri, request))
61
+ result.merge!(response_result(response)) unless response.nil?
62
+ result[:success] = success?(result, dry_run)
63
+ result
64
+ end
55
65
 
56
- unless result[:response].nil?
57
- result.merge!(JSON.parse(result[:response].body, :symbolize_names => true))
58
- result[:response_info] = build_response_info(result[:response])
59
- end
66
+ def success?(result, dry_run = false)
67
+ return true if dry_run
60
68
 
61
- result
69
+ result[:response] &&
70
+ result[:response].is_a?(::Net::HTTPSuccess) &&
71
+ result[:response].code == '200' &&
72
+ (result.key?('err') ? result['err'].to_i.zero? : true)
73
+ end
74
+
75
+ def request_result(uri, request)
76
+ {
77
+ :request_info => uri.inspect + ': ' + request.body,
78
+ :request => request
79
+ }
62
80
  end
63
81
 
64
- def build_response_info(response)
65
- response.code + '; ' + response.message + '; ' + response.body.delete!("\n")
82
+ def response_result(response)
83
+ {
84
+ :response => response,
85
+ :response_info => response.code + '; ' +
86
+ response.message + '; ' +
87
+ response.body.delete("\n")
88
+ }.merge(::JSON.parse(response.body, :symbolize_names => true))
66
89
  end
67
90
  end
68
91
  end