right_agent 2.6.3 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16d90487a104c3df9bda429bb53e65aea08986c3
4
- data.tar.gz: 01b33304e25eb7399946c2a08db53a493dcfeb22
3
+ metadata.gz: 74c2e07823dff52a0a487855918d9fe020f4509b
4
+ data.tar.gz: b9fc140fd85dc787e63a04880e3b195024ca0f42
5
5
  SHA512:
6
- metadata.gz: 740c5fc4895b8b39b36196908548b22f614af3bd1b69bcdd1784703c9363816b513e07c88c9ba01ce2c89c6ee2bf3041a9b02e262fc0e44baaa8a6a05bc8d570
7
- data.tar.gz: cf41ede79b081d7db299440e0e4753751088bb093c2ce85b7dc3f615e510aba2d5c501ee082687b6a18ae1915825ec611b08cf832bd2ef4db19197a78cc1c135
6
+ metadata.gz: a17751f1a016b2e81cdebb0281449c90db0be2cf4e8c17062d54ce36ee29d1517c4d2c1686debf81f75c34f4ae054d109ff9b3f45453b9db27070affb3df7f9b
7
+ data.tar.gz: f5720ae5a981c8b54a6d3d811fc8f35e8c0ea8c02d573c29fc78e9011c28fbf33aa7d9d089c0337f2a653f250f120cc94fa0403337a23b98681f6728f3037a70
data/Rakefile CHANGED
@@ -48,7 +48,6 @@ task :default => :spec
48
48
 
49
49
  desc 'Run unit tests'
50
50
  RSpec::Core::RakeTask.new do |t|
51
- t.rspec_opts = RSPEC_OPTS
52
51
  t.pattern = Dir['**/*_spec.rb']
53
52
  end
54
53
 
@@ -273,40 +273,57 @@ module RightScale
273
273
  end
274
274
  end
275
275
 
276
- # Reconnect with server by periodically checking health
277
- # Randomize when initially start checking to reduce server spiking
276
+ # If EventMachine reactor is running, begin attempting to periodically
277
+ # reconnect with server by checking health. Randomize initial attempt to
278
+ # reduce server spiking.
279
+ #
280
+ # If EventMachine reactor is NOT running, attempt to reconnect once
281
+ # and raise any exception that is encountered.
278
282
  #
279
283
  # @return [TrueClass] always true
280
284
  def reconnect
281
285
  unless @reconnecting
282
286
  @reconnecting = true
283
- @stats["reconnects"].update("initiate")
284
- @reconnect_timer = EM_S::PeriodicTimer.new(rand(@options[:reconnect_interval])) do
285
- begin
286
- create_http_client
287
- if check_health == :connected
288
- enable_use
289
- # Check state again since may have disconnected during enable_use
290
- if self.state == :connected
291
- @stats["reconnects"].update("success")
292
- @reconnect_timer.cancel if @reconnect_timer # only need 'if' for test purposes
293
- @reconnect_timer = @reconnecting = nil
294
- end
287
+
288
+ if EM.reactor_running?
289
+ @stats["reconnects"].update("initiate")
290
+ @reconnect_timer = EM_S::PeriodicTimer.new(rand(@options[:reconnect_interval])) do
291
+ begin
292
+ reconnect_once
293
+ rescue Exception => e
294
+ ErrorTracker.log(self, "Failed #{@options[:server_name]} reconnect", e, nil, :caller)
295
+ @stats["reconnects"].update("failure")
296
+ self.state = :disconnected
295
297
  end
296
- rescue Exception => e
297
- ErrorTracker.log(self, "Failed #{@options[:server_name]} reconnect", e, nil, :caller)
298
- @stats["reconnects"].update("failure")
299
- self.state = :disconnected
298
+ @reconnect_timer.interval = @options[:reconnect_interval] if @reconnect_timer
300
299
  end
301
- @reconnect_timer.interval = @options[:reconnect_interval] if @reconnect_timer
300
+ else
301
+ reconnect_once
302
302
  end
303
303
  end
304
+
304
305
  true
305
306
  end
306
307
 
307
- # Make request via HTTP
308
- # Rely on underlying HTTP client to log request and response
309
- # Retry request if response indicates to or if there are connectivity failures
308
+ # Attempt to reconnect exactly once. Perform no exception handling,
309
+ # state management, or scheduling of future reconnects, but cancel the
310
+ # reconnect timer if it exists and set @reconnecting, et al to nil.
311
+ def reconnect_once
312
+ create_http_client
313
+ if check_health == :connected
314
+ enable_use
315
+ # Check state again since may have disconnected during enable_use
316
+ if self.state == :connected
317
+ @stats["reconnects"].update("success")
318
+ @reconnect_timer.cancel if @reconnect_timer
319
+ @reconnect_timer = @reconnecting = nil
320
+ end
321
+ end
322
+ end
323
+
324
+ # Make request via HTTP. Attempt to reconnect first if disconnected and EM reactor is not running.
325
+ # Rely on underlying HTTP client to log request and response.
326
+ # Retry request if response indicates to or if there are connectivity failures.
310
327
  #
311
328
  # There are also several timeouts involved:
312
329
  # - Underlying BalancedHttpClient connection open timeout (:open_timeout)
@@ -364,6 +381,7 @@ module RightScale
364
381
  :request_timeout => @options[:request_timeout],
365
382
  :request_uuid => request_uuid,
366
383
  :headers => headers }
384
+ reconnect_once if (:disconnected == state) && !EM.reactor_running?
367
385
  raise Exceptions::ConnectivityFailure, "#{@type} client not connected" unless [:connected, :closing].include?(state)
368
386
  result = @http_client.send(verb, path, params, http_options.merge(options))
369
387
  rescue StandardError => e
@@ -40,7 +40,7 @@ module RightScale
40
40
  @public_key = args[2]
41
41
  @common_name = args[3] || ''
42
42
  @superuser = args[4] || false
43
- @expires_at = Time.at(args[5]) if args[5] && (args[5] != 0) # nil -> 0 because of expires_at.to_i below
43
+ @expires_at = Time.at(args[5].to_i) if args[5] && (args[5] != 0) # nil -> 0 because of expires_at.to_i below
44
44
  @public_keys = args[6]
45
45
  @profile_data = args[7]
46
46
  @public_key_fingerprints = args[8]
@@ -14,7 +14,7 @@ module RightScale
14
14
  # Tracker for unexpected errors
15
15
  # Logs them with appropriate trace information
16
16
  # Accumulates statistics about exceptions
17
- # Reports exceptions to external Errbit service via HydraulicBrake
17
+ # Reports exceptions to external Errbit service via Airbrake
18
18
  class ErrorTracker
19
19
 
20
20
  include RightSupport::Ruby::EasySingleton
@@ -104,36 +104,38 @@ module RightScale
104
104
  # @return [TrueClass] always true
105
105
  def notify(exception, packet = nil, agent = nil, component = nil)
106
106
  if @notify_enabled
107
- data = {
108
- :error_message => exception.respond_to?(:message) ? exception.message : exception.to_s,
109
- :backtrace => exception.respond_to?(:backtrace) ? exception.backtrace : caller,
110
- :environment_name => ENV["RAILS_ENV"],
111
- }
112
- if agent
113
- data[:cgi_data] = (@cgi_data || {}).merge(:agent_class => agent.class.name)
114
- elsif @cgi_data
115
- data[:cgi_data] = @cgi_data
116
- end
117
- data[:error_class] = exception.class.name if exception.is_a?(Exception)
118
- data[:component] = component if component
119
107
  if packet && packet.is_a?(Packet)
120
- data[:action] = packet.type.split("/").last if packet.respond_to?(:type)
108
+ action = packet.type.split("/").last if packet.respond_to?(:type)
121
109
  params = packet.respond_to?(:payload) && packet.payload
122
110
  uuid = packet.respond_to?(:token) && packet.token
123
111
  elsif packet.is_a?(Hash)
124
- action = packet[:path] || packet["path"]
125
- data[:action] = action.split("/").last if action
112
+ action_path = packet[:path] || packet["path"]
113
+ action = action_path.split("/").last if action_path
126
114
  params = packet[:data] || packet["data"]
127
115
  uuid = packet[:uuid] || packet["uuid"]
128
116
  else
129
117
  params = uuid = nil
130
118
  end
131
- data[:parameters] = params.is_a?(Hash) ? filter(params) : {:param => params} if params
132
- data[:session_data] = {:uuid => uuid} if uuid
133
- HydraulicBrake.notify(data)
119
+
120
+ n = Airbrake.build_notice(
121
+ exception,
122
+ { component: component, action: action },
123
+ :right_agent )
124
+
125
+ n[:params] = params.is_a?(Hash) ? filter(params) : {:param => params} if params
126
+ n[:session] = { :uuid => uuid } if uuid
127
+
128
+ if agent
129
+ n[:environment] = (@cgi_data || {}).merge(:agent_class => agent.class.name)
130
+ elsif @cgi_data
131
+ n[:environment] = @cgi_data || {}
132
+ end
133
+
134
+ Airbrake.notify(n, {}, :right_agent)
134
135
  end
135
136
  true
136
137
  rescue Exception => e
138
+ raise if e.class.name =~ /^RSpec/ # keep us from going insane while running tests
137
139
  Log.error("Failed to notify Errbit", e, :trace)
138
140
  end
139
141
 
@@ -168,7 +170,7 @@ module RightScale
168
170
  @exception_stats.reset
169
171
  end
170
172
 
171
- # Configure HydraulicBreak for exception notification
173
+ # Configure Airbrake for exception notification
172
174
  #
173
175
  # @param [String] agent_name uniquely identifying agent process on given server
174
176
  #
@@ -181,11 +183,11 @@ module RightScale
181
183
  #
182
184
  # @return [TrueClass] always true
183
185
  #
184
- # @raise [RuntimeError] hydraulic_brake gem missing
186
+ # @raise [RuntimeError] airbrake gem missing
185
187
  def notify_init(agent_name, options)
186
188
  if options[:airbrake_endpoint] && options[:airbrake_api_key]
187
- unless require_succeeds?("hydraulic_brake")
188
- raise RuntimeError, "hydraulic_brake gem missing - required if airbrake options used in ErrorTracker"
189
+ unless require_succeeds?("airbrake-ruby")
190
+ raise RuntimeError, "airbrake-ruby gem missing - required if airbrake options used in ErrorTracker"
189
191
  end
190
192
 
191
193
  @cgi_data = {
@@ -194,21 +196,23 @@ module RightScale
194
196
  :agent_name => agent_name
195
197
  }
196
198
  @cgi_data[:shard_id] = options[:shard_id] if options[:shard_id]
197
- @cgi_data[:sha] = CURRENT_SOURCE_SHA if defined?(CURRENT_SOURCE_SHA)
198
-
199
- uri = URI.parse(options[:airbrake_endpoint])
200
- HydraulicBrake.configure do |config|
201
- config.secure = (uri.scheme == "https")
202
- config.host = uri.host
203
- config.port = uri.port
204
- config.api_key = options[:airbrake_api_key]
205
- config.project_root = AgentConfig.root_dir
206
- end
207
199
  @filter_params = (options[:filter_params] || []).map { |p| p.to_s }
208
200
  @notify_enabled = true
201
+
202
+ return true if Airbrake.send(:configured?, :right_agent)
203
+
204
+ Airbrake.configure(:right_agent) do |config|
205
+ config.host = options[:airbrake_endpoint]
206
+ config.project_id = options[:airbrake_api_key]
207
+ config.project_key = options[:airbrake_api_key]
208
+ config.root_directory = AgentConfig.root_dir
209
+ config.environment = ENV['RAILS_ENV']
210
+ config.app_version = CURRENT_SOURCE_SHA if defined?(CURRENT_SOURCE_SHA)
211
+ end
209
212
  else
210
213
  @notify_enabled = false
211
214
  end
215
+
212
216
  true
213
217
  end
214
218
 
@@ -416,22 +416,21 @@ module RightScale
416
416
 
417
417
  # Initialize logger
418
418
  #
419
- # === Parameters
420
- # identity(String):: Log identity
421
- # path(String):: Log directory path
422
- # opts[:force](TrueClass|FalseClass):: Whether to re-initialize if logger
423
- # is already initialized
424
- # opts[:print](TrueClass|FalseClass):: Whether to print to STDOUT log destination
419
+ # @param [String] identity RightNet identity (for log file name or syslog program name)
420
+ # @param [String] path directory to create log files in
421
+ # @option opts [Boolean] :force whether to re-initialize if logger is already initialized
422
+ # @option opts [Boolean] :print whether to print log-location info to STDOUT
425
423
  #
426
- # === Return
427
- # logger(RightScale::Multiplexer):: logger instance
424
+ # @return [RightScale::Multiplexer] logger instance
428
425
  def init(identity=nil, path=nil, opts={})
429
426
  if opts[:force] || !@initialized
430
427
  @initialized = true
431
428
  @level_frozen = false
432
- logger = nil
429
+ logger = opts[:logger]
433
430
 
434
- if @log_to_file_only || Platform.windows?
431
+ if !logger.nil?
432
+ $stderr.puts "Logging to already-initialized #{logger.class.name}" if opts[:print]
433
+ elsif @log_to_file_only || Platform.windows?
435
434
  if path
436
435
  file = File.join(path, "#{identity}.log")
437
436
  else
@@ -25,8 +25,8 @@ require 'rbconfig'
25
25
 
26
26
  Gem::Specification.new do |spec|
27
27
  spec.name = 'right_agent'
28
- spec.version = '2.6.3'
29
- spec.date = '2015-09-16'
28
+ spec.version = '2.7.0'
29
+ spec.date = '2016-05-20'
30
30
  spec.authors = ['Lee Kirchhoff', 'Raphael Simon', 'Tony Spataro', 'Scott Messier']
31
31
  spec.email = 'lee@rightscale.com'
32
32
  spec.homepage = 'https://github.com/rightscale/right_agent'
@@ -44,7 +44,7 @@ Gem::Specification.new do |spec|
44
44
  spec.add_dependency('faye-websocket', '~> 0.7.0')
45
45
  spec.add_dependency('eventmachine', ['>= 0.12.10', '< 2.0'])
46
46
  spec.add_dependency('net-ssh', '~> 2.0')
47
- spec.add_dependency('addressable', '~> 2.3', '< 2.4')
47
+ spec.add_dependency('addressable', '~> 2.3')
48
48
 
49
49
  # TEAL HACK: rake gem may override current RUBY_PLATFORM to allow building
50
50
  # gems for all supported platforms from any platform. rubygems 1.8.x makes it
@@ -34,6 +34,7 @@ describe RightScale::BaseRetryClient do
34
34
  @log.should_receive(:warning).by_default.and_return { |m| raise RightScale::Log.format(*m) }
35
35
  @url = "http://test.com"
36
36
  @timer = flexmock("timer", :cancel => true, :interval= => 0).by_default
37
+ flexmock(EM).should_receive(:reactor_running?).and_return(true).by_default
37
38
  flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).by_default
38
39
  @http_client = flexmock("http client", :get => true, :check_health => true, :close => true).by_default
39
40
  flexmock(RightScale::BalancedHttpClient).should_receive(:new).and_return(@http_client).by_default
@@ -338,82 +339,102 @@ describe RightScale::BaseRetryClient do
338
339
  @client.instance_variable_set(:@reconnecting, nil)
339
340
  end
340
341
 
341
- it "waits random interval for initial reconnect attempt" do
342
- flexmock(@client).should_receive(:rand).with(15).and_return(10).once
343
- flexmock(EM::PeriodicTimer).should_receive(:new).with(10, Proc).and_return(@timer).once
344
- @client.send(:reconnect).should be_true
345
- end
346
-
347
- it "attempts to connect even if currently connected" do
348
- flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
349
- @client.send(:create_http_client)
350
- @client.send(:check_health).should == :connected
351
- flexmock(@client).should_receive(:check_health).once
352
- @client.send(:reconnect).should be_true
353
- end
354
-
355
- it "recreates HTTP client and checks health" do
356
- flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
357
- flexmock(RightScale::BalancedHttpClient).should_receive(:new).and_return(@http_client).once
358
- @http_client.should_receive(:check_health).once
359
- @client.send(:reconnect).should be_true
360
- end
361
-
362
- context "when health check successful" do
363
- it "enables use of client" do
364
- flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
365
- flexmock(@client).should_receive(:enable_use).once
342
+ context 'given EventMachine is running' do
343
+ it "waits random interval for initial reconnect attempt" do
344
+ flexmock(@client).should_receive(:rand).with(15).and_return(10).once
345
+ flexmock(EM::PeriodicTimer).should_receive(:new).with(10, Proc).and_return(@timer).once
366
346
  @client.send(:reconnect).should be_true
367
347
  end
368
348
 
369
- it "rechecks state after enables use" do
349
+ it "attempts to connect even if currently connected" do
370
350
  flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
371
- flexmock(@client).should_receive(:enable_use).and_return { @client.instance_variable_set(:@state, :disconnected) }.once
351
+ @client.send(:create_http_client)
352
+ @client.send(:check_health).should == :connected
353
+ flexmock(@client).should_receive(:check_health).once
372
354
  @client.send(:reconnect).should be_true
373
- @client.instance_variable_get(:@reconnecting).should be true
374
355
  end
375
356
 
376
- it "disables timer" do
377
- @client.send(:reconnect); @client.instance_variable_set(:@reconnecting, nil) # to get @reconnect_timer initialized
378
- @client.instance_variable_set(:@reconnecting, nil)
379
- @timer.should_receive(:cancel).once
357
+ it "recreates HTTP client and checks health" do
380
358
  flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
359
+ flexmock(RightScale::BalancedHttpClient).should_receive(:new).and_return(@http_client).once
360
+ @http_client.should_receive(:check_health).once
381
361
  @client.send(:reconnect).should be_true
382
- @client.instance_variable_get(:@reconnecting).should be_nil
383
362
  end
384
363
 
385
- it "does not reset timer interval" do
386
- @timer.should_receive(:interval=).never
387
- flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
364
+ context "when health check successful" do
365
+ it "enables use of client" do
366
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
367
+ flexmock(@client).should_receive(:enable_use).once
368
+ @client.send(:reconnect).should be_true
369
+ end
370
+
371
+ it "rechecks state after enables use" do
372
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
373
+ flexmock(@client).should_receive(:enable_use).and_return { @client.instance_variable_set(:@state, :disconnected) }.once
374
+ @client.send(:reconnect).should be_true
375
+ @client.instance_variable_get(:@reconnecting).should be true
376
+ end
377
+
378
+ it "disables timer" do
379
+ @client.send(:reconnect); @client.instance_variable_set(:@reconnecting, nil) # to get @reconnect_timer initialized
380
+ @client.instance_variable_set(:@reconnecting, nil)
381
+ @timer.should_receive(:cancel).once
382
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
383
+ @client.send(:reconnect).should be_true
384
+ @client.instance_variable_get(:@reconnecting).should be_nil
385
+ end
386
+
387
+ it "does not reset timer interval" do
388
+ @timer.should_receive(:interval=).never
389
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
390
+ @client.send(:reconnect).should be_true
391
+ end
392
+ end
393
+
394
+ context "when reconnect fails" do
395
+ it "logs error if exception is raised" do
396
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
397
+ flexmock(@client).should_receive(:enable_use).and_raise(StandardError).once
398
+ @log.should_receive(:error).with("Failed test reconnect", StandardError, :caller).once
399
+ @client.send(:reconnect).should be_true
400
+ @client.state.should == :disconnected
401
+ end
402
+
403
+ it "resets the timer interval to the configured value" do
404
+ @client.send(:reconnect); @client.instance_variable_set(:@reconnecting, nil) # to get @reconnect_timer initialized
405
+ @log.should_receive(:error).with("Failed test health check", StandardError, :caller).once
406
+ @http_client.should_receive(:check_health).and_raise(StandardError).once
407
+ @timer.should_receive(:interval=).with(15).once
408
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
409
+ @client.send(:reconnect).should be_true
410
+ end
411
+ end
412
+
413
+ it "does nothing if already reconnecting" do
414
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).once
415
+ @client.send(:reconnect).should be_true
416
+ @client.instance_variable_get(:@reconnecting).should be_true
388
417
  @client.send(:reconnect).should be_true
418
+ @client.instance_variable_get(:@reconnecting).should be_true
389
419
  end
390
420
  end
391
421
 
392
- context "when reconnect fails" do
393
- it "logs error if exception is raised" do
394
- flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
395
- flexmock(@client).should_receive(:enable_use).and_raise(StandardError).once
396
- @log.should_receive(:error).with("Failed test reconnect", StandardError, :caller).once
397
- @client.send(:reconnect).should be_true
398
- @client.state.should == :disconnected
422
+ context 'given EventMachine is inactive' do
423
+ before(:each) do
424
+ flexmock(EM).should_receive(:reactor_running?).and_return(false)
399
425
  end
400
426
 
401
- it "resets the timer interval to the configured value" do
402
- @client.send(:reconnect); @client.instance_variable_set(:@reconnecting, nil) # to get @reconnect_timer initialized
403
- @log.should_receive(:error).with("Failed test health check", StandardError, :caller).once
404
- @http_client.should_receive(:check_health).and_raise(StandardError).once
405
- @timer.should_receive(:interval=).with(15).once
406
- flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).and_yield
427
+ it "tries once" do
407
428
  @client.send(:reconnect).should be_true
408
429
  end
409
- end
410
430
 
411
- it "does nothing if already reconnecting" do
412
- flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer).once
413
- @client.send(:reconnect).should be_true
414
- @client.instance_variable_get(:@reconnecting).should be_true
415
- @client.send(:reconnect).should be_true
416
- @client.instance_variable_get(:@reconnecting).should be_true
431
+ it "raises exceptions" do
432
+ lambda do
433
+ flexmock(@client).should_receive(:create_http_client).and_raise(Exception)
434
+
435
+ @client.send(:reconnect)
436
+ end.should raise_error(Exception)
437
+ end
417
438
  end
418
439
  end
419
440
 
@@ -431,6 +452,26 @@ describe RightScale::BaseRetryClient do
431
452
  @client.init(:test, @auth_client, @options)
432
453
  end
433
454
 
455
+ context 'given EventMachine is inactive' do
456
+ before(:each) do
457
+ flexmock(EM).should_receive(:reactor_running?).and_return(false)
458
+ end
459
+
460
+ it 'reconnects if necessary' do
461
+ @client.instance_variable_set(:@state, :disconnected)
462
+ @http_client.should_receive(:get).with(@path, @params, Hash).once
463
+ @client.send(:make_request, :get, @path, @params)
464
+ end
465
+
466
+ it 'raises connection errors' do
467
+ @client.instance_variable_set(:@state, :disconnected)
468
+ @http_client.should_receive(:check_health).and_raise(Exception)
469
+ lambda {
470
+ @client.send(:make_request, :get, @path, @params)
471
+ }.should raise_error(Exception)
472
+ end
473
+ end
474
+
434
475
  it "raises exception if terminating" do
435
476
  @client.close
436
477
  lambda { @client.send(:make_request, :get, @path) }.should raise_error(RightScale::Exceptions::Terminating)
@@ -20,7 +20,7 @@
20
20
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
 
23
- require 'hydraulic_brake'
23
+ require 'airbrake-ruby'
24
24
 
25
25
  require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
26
26
 
@@ -39,7 +39,7 @@ describe RightScale::ErrorTracker do
39
39
  @trace_level = RightScale::Agent::TRACE_LEVEL
40
40
  @tracker = RightScale::ErrorTracker.instance
41
41
  @log = flexmock(RightScale::Log)
42
- @brake = flexmock(HydraulicBrake)
42
+ @brake = flexmock(Airbrake)
43
43
  @options = {
44
44
  :shard_id => @shard_id,
45
45
  :trace_level => @trace_level,
@@ -161,82 +161,97 @@ describe RightScale::ErrorTracker do
161
161
  @exception = RuntimeError.new("error")
162
162
  @tracker.init(@agent, @agent_name, @options)
163
163
  @cgi_data = @tracker.instance_variable_get(:@cgi_data)
164
+ ENV['RAILS_ENV'] = 'development'
164
165
  end
165
166
 
166
- it "sends notification using HydraulicBrake" do
167
- @brake.should_receive(:notify).with(on { |a| a[:error_message] == "error" &&
168
- a[:error_class] == "RuntimeError" &&
169
- a[:backtrace].nil? &&
170
- ["test", "development"].include?(a[:environment_name]) &&
171
- a[:cgi_data].should == @cgi_data &&
172
- a.keys & [:component, :action, :parameters, :session_data] == [] }).once
167
+ after(:each) do
168
+ ENV['RAILS_ENV'] = nil
169
+ end
170
+
171
+ it "sends notification using Airbrake" do
172
+ @brake.should_receive(:notify).with(on { |a|
173
+ a[:errors].first[:type] == "RuntimeError" &&
174
+ a[:environment] == @cgi_data
175
+ }, {}, :right_agent).once
173
176
  @tracker.notify(@exception).should be true
174
177
  end
175
178
 
176
179
  it "includes packet data in notification" do
177
180
  request = RightScale::Request.new("/foo/bar", {:pay => "load"}, :token => "token")
178
- @brake.should_receive(:notify).with(on { |a| a[:error_message] == "error" &&
179
- a[:error_class] == "RuntimeError" &&
180
- a[:backtrace].nil? &&
181
- a[:action] == "bar" &&
182
- a[:parameters] == {:pay => "load"} &&
183
- ["test", "development"].include?(a[:environment_name]) &&
184
- a[:cgi_data] == @cgi_data &&
185
- a[:session_data] == {:uuid => "token"} }).once
181
+ @brake.should_receive(:notify).with(on { |a|
182
+ a[:errors].first[:message] == "error" &&
183
+ a[:context][:action] == 'bar' &&
184
+ a[:params] == { :pay => 'load' } &&
185
+ a[:session] == { :uuid => 'token' }
186
+ }, {}, :right_agent).once
187
+
186
188
  @tracker.notify(@exception, request).should be true
187
189
  end
188
190
 
189
191
  it "includes event data in notification" do
190
- @brake.should_receive(:notify).with(on { |a| a[:error_message] == "error" &&
191
- a[:error_class] == "RuntimeError" &&
192
- a[:backtrace].nil? &&
193
- a[:action] == "bar" &&
194
- a[:parameters] == {:pay => "load"} &&
195
- ["test", "development"].include?(a[:environment_name]) &&
196
- a[:cgi_data] == @cgi_data &&
197
- a[:session_data] == {:uuid => "token"} }).once
192
+ @brake.should_receive(:notify).with(on { |a|
193
+ a[:errors].first[:message] == "error" &&
194
+ a[:errors].first[:type] == "RuntimeError" &&
195
+ a[:context][:action] == 'bar' &&
196
+ a[:params] == { :pay => 'load' } &&
197
+ a[:session] == { :uuid => 'token' }
198
+ }, {}, :right_agent).once
199
+
198
200
  @tracker.notify(@exception, {"uuid" => "token", "path" => "/foo/bar", "data" => {:pay => "load"}}).should be true
199
201
  end
200
202
 
201
203
  it "adds agent class to :cgi_data in notification" do
202
- @brake.should_receive(:notify).with(on { |a| a[:cgi_data] == @cgi_data.merge(:agent_class => "AgentMock") }).once
204
+ @brake.should_receive(:notify).with(on { |a|
205
+ a[:environment] == @cgi_data.merge(:agent_class => 'AgentMock')
206
+ }, {}, :right_agent).once
207
+
203
208
  @tracker.notify(@exception, packet = nil, @agent).should be true
204
209
  end
205
210
 
206
211
  it "adds component to notification" do
207
- @brake.should_receive(:notify).with(on { |a| a[:component] == "component" }).once
212
+ @brake.should_receive(:notify).with(on { |a|
213
+ a[:context][:component] == 'component'
214
+ }, {}, :right_agent).once
208
215
  @tracker.notify(@exception, packet = nil, agent = nil, "component").should be true
209
216
  end
210
217
 
211
218
  it "converts non-nil, non-hash payload in packet to a hash" do
212
219
  request = RightScale::Request.new("/foo/bar", "payload", :token => "token")
213
- @brake.should_receive(:notify).with(on { |a| a[:parameters] == {:param => "payload"} }).once
220
+ @brake.should_receive(:notify).with(on { |a|
221
+ a[:params] == { :param => 'payload' }
222
+ }, {}, :right_agent).once
214
223
  @tracker.notify(@exception, request).should be true
215
224
  end
216
225
 
217
226
  it "converts non-nil, non-hash data in event to a hash" do
218
- @brake.should_receive(:notify).with(on { |a| a[:parameters] == {:param => "payload"} }).once
227
+ @brake.should_receive(:notify).with(on { |a|
228
+ a[:params] == { :param => 'payload' }
229
+ }, {}, :right_agent).once
219
230
  @tracker.notify(@exception, {"uuid" => "token", "path" => "/foo/bar", "data" => "payload"}).should be true
220
231
  end
221
232
 
222
233
  it "omits :parameters from notification if payload in packet is nil" do
223
234
  request = RightScale::Request.new("/foo/bar", nil, :token => "token")
224
- @brake.should_receive(:notify).with(on { |a| !a.has_key?(:parameters) }).once
235
+ @brake.should_receive(:notify).with(on { |a|
236
+ a[:params] == {}
237
+ }, {}, :right_agent).once
225
238
  @tracker.notify(@exception, request).should be true
226
239
  end
227
240
 
228
241
  it "omits :parameters from notification if data in packet is nil" do
229
- @brake.should_receive(:notify).with(on { |a| !a.has_key?(:parameters) }).once
242
+ @brake.should_receive(:notify).with(on { |a|
243
+ a[:params] == {}
244
+ }, {}, :right_agent).once
230
245
  @tracker.notify(@exception, {"uuid" => "token", "path" => "/foo/bar", "data" => nil}).should be true
231
246
  end
232
247
 
233
248
  it "functions even if cgi_data has not been initialized by notify_init" do
234
249
  @tracker.instance_variable_set(:@cgi_data, nil)
235
- @brake.should_receive(:notify).with(on { |a| a[:error_message] == "error" &&
236
- a[:error_class] == "RuntimeError" &&
237
- a[:backtrace].nil? &&
238
- ["test", "development"].include?(a[:environment_name]) &&
239
- a.keys & [:cgi_data, :component, :action, :parameters, :session_data] == [] }).once
250
+ @brake.should_receive(:notify).with(on { |a|
251
+ a[:errors].first[:message] == "error" &&
252
+ a[:errors].first[:type] == "RuntimeError" &&
253
+ a[:environment] == {}
254
+ }, {}, :right_agent).once
240
255
  @tracker.notify(@exception).should be true
241
256
  end
242
257
 
@@ -285,7 +300,7 @@ describe RightScale::ErrorTracker do
285
300
 
286
301
  context :notify_init do
287
302
  class ConfigMock
288
- attr_accessor :secure, :host, :port, :api_key, :project_root
303
+ attr_accessor :host, :api_key, :project_id, :project_key, :root_directory, :environment
289
304
  end
290
305
 
291
306
  it "does not initialize if Airbrake endpoint or API key is undefined" do
@@ -296,7 +311,10 @@ describe RightScale::ErrorTracker do
296
311
  @tracker.instance_variable_get(:@notify_enabled).should be false
297
312
  end
298
313
 
299
- it "initializes cgi data and configures HydraulicBrake" do
314
+ it "initializes cgi data and configures Airbrake" do
315
+ # dirty, but we need to make sure this is unset in order to progress
316
+ Airbrake.instance_variable_set(:@notifiers, {})
317
+
300
318
  config = ConfigMock.new
301
319
  @brake.should_receive(:configure).and_yield(config).once
302
320
  @tracker.send(:notify_init, @agent_name, @options).should be true
@@ -305,20 +323,19 @@ describe RightScale::ErrorTracker do
305
323
  cgi_data[:pid].should be_a Integer
306
324
  cgi_data[:process].should be_a String
307
325
  cgi_data[:shard_id].should == @shard_id
308
- config.secure.should be true
309
- config.host.should == "airbrake.com"
310
- config.port.should == 443
311
- config.api_key.should == @api_key
312
- config.project_root.should be_a String
326
+ config.host.should == "https://airbrake.com"
327
+ config.project_id.should == @api_key
328
+ config.project_key.should == @api_key
329
+ config.root_directory.should be_a String
313
330
  @tracker.instance_variable_get(:@notify_enabled).should be true
314
331
  @tracker.instance_variable_get(:@filter_params).should == ["password"]
315
332
  end
316
333
 
317
- it "raises exception if hydraulic_gem is not available" do
318
- flexmock(@tracker).should_receive(:require_succeeds?).with("hydraulic_brake").and_return(false)
334
+ it "raises exception if airbrake-ruby is not available" do
335
+ flexmock(@tracker).should_receive(:require_succeeds?).with("airbrake-ruby").and_return(false)
319
336
  lambda do
320
337
  @tracker.send(:notify_init, @agent_name, @options)
321
- end.should raise_error(RuntimeError, /hydraulic_brake gem missing/)
338
+ end.should raise_error(RuntimeError, /airbrake-ruby gem missing/)
322
339
  end
323
340
  end
324
341
 
@@ -23,6 +23,12 @@
23
23
  require 'rubygems'
24
24
  require 'bundler/setup'
25
25
 
26
+ begin
27
+ require 'pry'
28
+ rescue LoadError
29
+ #no-op; optional dependency
30
+ end
31
+
26
32
  require 'rspec'
27
33
  require 'flexmock'
28
34
  require 'simplecov'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: right_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.3
4
+ version: 2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Kirchhoff
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-09-16 00:00:00.000000000 Z
14
+ date: 2016-05-20 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: right_support
@@ -116,9 +116,6 @@ dependencies:
116
116
  - - "~>"
117
117
  - !ruby/object:Gem::Version
118
118
  version: '2.3'
119
- - - "<"
120
- - !ruby/object:Gem::Version
121
- version: '2.4'
122
119
  type: :runtime
123
120
  prerelease: false
124
121
  version_requirements: !ruby/object:Gem::Requirement
@@ -126,9 +123,6 @@ dependencies:
126
123
  - - "~>"
127
124
  - !ruby/object:Gem::Version
128
125
  version: '2.3'
129
- - - "<"
130
- - !ruby/object:Gem::Version
131
- version: '2.4'
132
126
  - !ruby/object:Gem::Dependency
133
127
  name: ffi
134
128
  requirement: !ruby/object:Gem::Requirement
@@ -376,8 +370,6 @@ files:
376
370
  - spec/serialize/secure_serializer_spec.rb
377
371
  - spec/serialize/serializable_spec.rb
378
372
  - spec/serialize/serializer_spec.rb
379
- - spec/spec.opts
380
- - spec/spec.win32.opts
381
373
  - spec/spec_helper.rb
382
374
  - spec/tracer_spec.rb
383
375
  homepage: https://github.com/rightscale/right_agent
@@ -403,9 +395,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
403
395
  version: '0'
404
396
  requirements: []
405
397
  rubyforge_project:
406
- rubygems_version: 2.2.2
398
+ rubygems_version: 2.2.5
407
399
  signing_key:
408
400
  specification_version: 4
409
401
  summary: Agent for interfacing server with RightScale system
410
402
  test_files: []
411
- has_rdoc: true
@@ -1,2 +0,0 @@
1
- --colour
2
- --format=nested
@@ -1 +0,0 @@
1
- --format=nested