newrelic_rpm 3.6.7.152 → 3.6.7.159.beta

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -12,6 +12,22 @@
12
12
  All settings in newrelic.yml can now be configured via environment variables.
13
13
  See https://newrelic.com/docs/ruby/ruby-agent-configuration for full details.
14
14
 
15
+ * Additional locking option for Resque (3.6.7.159)
16
+
17
+ There have been reports of worker process deadlocks in Resque when using the
18
+ Ruby agent. An optional lock is now available to avoid those deadlocks. See
19
+ https://newrelic.com/docs/ruby/resque-instrumentation for more details.
20
+
21
+ * HTTP connection setup timeout (3.6.7.159)
22
+
23
+ HTTP initialization in the agent lacked an appropriate timeout,
24
+ leading to dropouts in reporting under certain network error conditions.
25
+
26
+ * Unnecessary requests from Resque jobs (3.6.7.159)
27
+
28
+ An issue causing Resque jobs to unnecessarily make requests against New Relic
29
+ servers was fixed.
30
+
15
31
  * Fix compatibility issues with excon and curb instrumentation
16
32
 
17
33
  This release of the agent fixes a warning seen under certain circumstances
@@ -46,7 +46,7 @@ module NewRelic
46
46
  @transaction_sampler = NewRelic::Agent::TransactionSampler.new
47
47
  @sql_sampler = NewRelic::Agent::SqlSampler.new
48
48
  @thread_profiler = NewRelic::Agent::Commands::ThreadProfiler.new
49
- @agent_command_router = NewRelic::Agent::Commands::AgentCommandRouter.new(@service, @thread_profiler)
49
+ @agent_command_router = NewRelic::Agent::Commands::AgentCommandRouter.new(@thread_profiler)
50
50
  @cross_app_monitor = NewRelic::Agent::CrossAppMonitor.new(@events)
51
51
  @error_collector = NewRelic::Agent::ErrorCollector.new
52
52
  @transaction_rules = NewRelic::Agent::RulesEngine.new
@@ -537,6 +537,7 @@ module NewRelic
537
537
  # might be holding locks for background thread that aren't there anymore.
538
538
  def reset_objects_with_locks
539
539
  @stats_engine = NewRelic::Agent::StatsEngine.new
540
+ reset_harvest_locks
540
541
  end
541
542
 
542
543
  def add_harvest_sampler(subclass)
@@ -556,6 +557,34 @@ module NewRelic
556
557
  ::NewRelic::Agent.logger.debug "Running worker loop"
557
558
  end
558
559
 
560
+ # Accessor for the harvest lock
561
+ def harvest_lock
562
+ return nil if @worker_loop.nil?
563
+ @worker_loop.lock
564
+ end
565
+
566
+ # Synchronize with the harvest loop. If the harvest thread has taken
567
+ # a lock (DNS lookups, backticks, agent-owned locks, etc), and we
568
+ # fork while locked, this can deadlock child processes. For more
569
+ # details, see https://github.com/resque/resque/issues/1101
570
+ def synchronize_with_harvest
571
+ if harvest_lock
572
+ harvest_lock.synchronize do
573
+ yield
574
+ end
575
+ else
576
+ yield
577
+ end
578
+ end
579
+
580
+ # Some forking cases (like Resque) end up with harvest lock from the
581
+ # parent process orphaned in the child. Let it go before we proceed.
582
+ def reset_harvest_locks
583
+ return if harvest_lock.nil?
584
+
585
+ harvest_lock.unlock if harvest_lock.locked?
586
+ end
587
+
559
588
  # Creates the worker loop and loads it with the instructions
560
589
  # it should run every @report_period seconds
561
590
  def create_and_run_worker_loop
@@ -14,24 +14,25 @@ module NewRelic
14
14
  module Agent
15
15
  module Commands
16
16
  class AgentCommandRouter
17
- attr_reader :service, :handlers
18
-
19
- def initialize(service, thread_profiler)
20
- @service = service
17
+ attr_reader :handlers
21
18
 
19
+ def initialize(thread_profiler)
22
20
  @handlers = Hash.new { |*| Proc.new { |cmd| self.unrecognized_agent_command(cmd) } }
23
-
24
21
  @handlers['start_profiler'] = Proc.new { |cmd| thread_profiler.handle_start_command(cmd) }
25
22
  @handlers['stop_profiler'] = Proc.new { |cmd| thread_profiler.handle_stop_command(cmd) }
26
23
  end
27
24
 
25
+ def new_relic_service
26
+ NewRelic::Agent.instance.service
27
+ end
28
+
28
29
  def handle_agent_commands
29
30
  results = invoke_commands(get_agent_commands)
30
- service.agent_command_results(results) unless results.empty?
31
+ new_relic_service.agent_command_results(results) unless results.empty?
31
32
  end
32
33
 
33
34
  def get_agent_commands
34
- commands = service.get_agent_commands
35
+ commands = new_relic_service.get_agent_commands
35
36
  NewRelic::Agent.logger.debug "Received get_agent_commands = #{commands.inspect}"
36
37
  commands
37
38
  end
@@ -393,6 +393,12 @@ module NewRelic
393
393
  :type => Boolean,
394
394
  :description => 'Enable or disable spawning of a background thread that listens for connections from child processes. Primarily used for Resque instrumentation.'
395
395
  },
396
+ :'resque.use_harvest_lock' => {
397
+ :default => false,
398
+ :public => true,
399
+ :type => Boolean,
400
+ :description => 'Enable or disable synchronizing Resque job forking with New Relic\'s harvest thread. Defaulted to false. This helps prevent Resque jobs from deadlocking, but pauses starting new jobs during harvest.'
401
+ },
396
402
  :data_report_period => {
397
403
  :default => 60,
398
404
  :public => false,
@@ -64,6 +64,26 @@ DependencyDetection.defer do
64
64
  end
65
65
 
66
66
  if NewRelic::LanguageSupport.can_fork?
67
+ # Resque::Worker#fork isn't around in Resque 2.x
68
+ if NewRelic::VersionNumber.new(::Resque::VERSION) < NewRelic::VersionNumber.new("2.0.0")
69
+ ::Resque::Worker.class_eval do
70
+ if NewRelic::Agent.config[:'resque.use_harvest_lock']
71
+ ::NewRelic::Agent.logger.info 'Installing Resque harvest/fork synchronization'
72
+ def fork_with_newrelic(*args, &block)
73
+ NewRelic::Agent.instance.synchronize_with_harvest do
74
+ fork_without_newrelic(*args, &block)
75
+
76
+ # Reached in parent, not expected in the child since Resque
77
+ # uses the block form of fork
78
+ end
79
+ end
80
+
81
+ alias_method :fork_without_newrelic, :fork
82
+ alias_method :fork, :fork_with_newrelic
83
+ end
84
+ end
85
+ end
86
+
67
87
  ::Resque.before_first_fork do
68
88
  NewRelic::Agent.manual_start(:dispatcher => :resque,
69
89
  :sync_startup => true,
@@ -170,16 +170,21 @@ module NewRelic
170
170
 
171
171
  # Immediately open a TCP connection to the server and leave it open for
172
172
  # multiple requests.
173
- ::NewRelic::Agent.logger.debug("Opening TCP connection to #{http.address}:#{http.port}")
174
- http.start
175
173
  begin
174
+ t0 = Time.now
175
+ ::NewRelic::Agent.logger.debug("Opening TCP connection to #{http.address}:#{http.port}")
176
+ NewRelic::TimerLib.timeout(@request_timeout) { http.start }
176
177
  @shared_tcp_connection = http
177
178
  block.call
179
+ rescue Timeout::Error
180
+ elapsed = Time.now - t0
181
+ ::NewRelic::Agent.logger.warn "Timed out opening connection to #{http.address}:#{http.port} after #{elapsed} seconds. If this problem persists, please see http://status.newrelic.com"
182
+ raise
178
183
  ensure
179
184
  @shared_tcp_connection = nil
180
185
  # Close the TCP socket
181
186
  ::NewRelic::Agent.logger.debug("Closing TCP connection to #{http.address}:#{http.port}")
182
- http.finish
187
+ http.finish if http.started?
183
188
  end
184
189
  end
185
190
 
@@ -13,7 +13,7 @@ module NewRelic
13
13
  super
14
14
  @agent = NewRelic::Agent::Agent.new
15
15
  @agent.service = default_service
16
- @agent.agent_command_router.stubs(:service).returns(@agent.service)
16
+ @agent.agent_command_router.stubs(:new_relic_service).returns(@agent.service)
17
17
  @agent.stubs(:start_worker_thread)
18
18
  end
19
19
 
@@ -335,6 +335,32 @@ module NewRelic
335
335
  assert_match( /No application name configured/i, logmsg )
336
336
  end
337
337
 
338
+ def test_synchronize_with_harvest
339
+ lock = Mutex.new
340
+ @agent.stubs(:harvest_lock).returns(lock)
341
+ @agent.harvest_lock.lock
342
+
343
+ started = false
344
+ done = false
345
+
346
+ thread = Thread.new do
347
+ started = true
348
+ @agent.synchronize_with_harvest do
349
+ done = true
350
+ end
351
+ end
352
+
353
+ until started do
354
+ sleep(0.001)
355
+ end
356
+ assert !done
357
+
358
+ @agent.harvest_lock.unlock
359
+ thread.join
360
+
361
+ assert done
362
+ end
363
+
338
364
  end
339
365
 
340
366
 
@@ -33,9 +33,10 @@ class AgentCommandRouterTest < Test::Unit::TestCase
33
33
 
34
34
  def setup
35
35
  @service = stub
36
+ NewRelic::Agent.agent.stubs(:service).returns(@service)
36
37
  @calls = []
37
38
 
38
- @agent_commands = NewRelic::Agent::Commands::AgentCommandRouter.new(@service, nil)
39
+ @agent_commands = NewRelic::Agent::Commands::AgentCommandRouter.new(nil)
39
40
  @agent_commands.handlers["bazzle"] = Proc.new { |args| handle_bazzle_command(args) }
40
41
  @agent_commands.handlers["boom"] = Proc.new { |args| handle_boom_command(args) }
41
42
  end
@@ -15,7 +15,25 @@ class NewRelicServiceKeepAliveTest < Test::Unit::TestCase
15
15
  end
16
16
 
17
17
  def stub_net_http_handle(overrides = {})
18
- stub('http_handle', :start => true, :finish => true, :address => '10.10.10.10', :port => 30303)
18
+ defaults = { :start => true, :finish => true, :address => '10.10.10.10', :port => 30303, :started? => true }
19
+ stub('http_handle', defaults.merge(overrides))
20
+ end
21
+
22
+ def test_session_handles_timeouts_opening_connection_gracefully
23
+ conn = stub_net_http_handle(:started? => false)
24
+ conn.stubs(:start).raises(Timeout::Error)
25
+ conn.stubs(:finish).raises(RuntimeError)
26
+ @service.stubs(:create_http_connection).returns(conn)
27
+
28
+ block_ran = false
29
+
30
+ assert_raises(Timeout::Error) do
31
+ @service.session do
32
+ block_ran = true
33
+ end
34
+ end
35
+
36
+ assert(!block_ran, "Expected block passed to #session to have not run")
19
37
  end
20
38
 
21
39
  def test_session_block_reuses_http_handle
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_rpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.7.152
5
- prerelease:
4
+ version: 3.6.7.159.beta
5
+ prerelease: 10
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jason Clark
@@ -41,7 +41,7 @@ cert_chain:
41
41
  cHUySWFQWE92bTNUOEc0TzZxWnZobkxoL1VpZW4rK0RqOGVGQmVjVFBvTThw
42
42
  VmpLM3BoNQpuL0V3dVpDY0U2Z2h0Q0NNCi0tLS0tRU5EIENFUlRJRklDQVRF
43
43
  LS0tLS0K
44
- date: 2013-09-05 00:00:00.000000000 Z
44
+ date: 2013-09-23 00:00:00.000000000 Z
45
45
  dependencies:
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rake
@@ -910,21 +910,28 @@ post_install_message: ! "# New Relic Ruby Agent Release Notes #\n\n## v3.6.7 ##\
910
910
  recognized by the\n Ruby agent. The agent now starts correctly in those worker
911
911
  processes.\n\n* Environment-based configuration\n\n All settings in newrelic.yml
912
912
  can now be configured via environment variables.\n See https://newrelic.com/docs/ruby/ruby-agent-configuration
913
- for full details.\n\n* Fix compatibility issues with excon and curb instrumentation\n\n
914
- \ This release of the agent fixes a warning seen under certain circumstances\n with
915
- the excon gem (most notably, when excon was used by fog), as well as\n a bug with
916
- the curb instrumentation that conflicted with the feedzirra gem.\n\n* Allow license
917
- key to be set by Capistrano variables\n\n A license key can be passed via a Capistrano
918
- variable where previously it\n could only be in newrelic.yml. Thanks Chris Marshall
919
- for the contribution!\n\n* Make HTTP client instrumentation aware of \"Host\" request
920
- header\n\n If a \"Host\" header is set explicitly on an HTTP request, that hostname
921
- will\n be used for external metrics. Thanks Mislav Marohnić for the contribution!\n\n*
922
- Fix ActiveSupport::Concern warnings with MethodTracer\n\n Including NewRelic::Agent::MethodTracer
923
- in a class using Concerns could cause\n deprecation warnings. Thanks Mike Połtyn
924
- for the contribution!\n\n* Fix Authlogic constant name\n\n Code checking for the
925
- Authlogic module was using in the wrong case. Thanks\n Dharam Gollapudi for the
926
- contribution!\n\nSee https://github.com/newrelic/rpm/blob/master/CHANGELOG for a
927
- full list of\nchanges.\n"
913
+ for full details.\n\n* Additional locking option for Resque (3.6.7.159)\n\n There
914
+ have been reports of worker process deadlocks in Resque when using the\n Ruby agent.
915
+ An optional lock is now available to avoid those deadlocks. See\n https://newrelic.com/docs/ruby/resque-instrumentation
916
+ for more details.\n\n* HTTP connection setup timeout (3.6.7.159)\n\n HTTP initialization
917
+ in the agent lacked an appropriate timeout,\n leading to dropouts in reporting
918
+ under certain network error conditions.\n\n* Unnecessary requests from Resque jobs
919
+ (3.6.7.159)\n\n An issue causing Resque jobs to unnecessarily make requests against
920
+ New Relic\n servers was fixed.\n\n* Fix compatibility issues with excon and curb
921
+ instrumentation\n\n This release of the agent fixes a warning seen under certain
922
+ circumstances\n with the excon gem (most notably, when excon was used by fog),
923
+ as well as\n a bug with the curb instrumentation that conflicted with the feedzirra
924
+ gem.\n\n* Allow license key to be set by Capistrano variables\n\n A license key
925
+ can be passed via a Capistrano variable where previously it\n could only be in
926
+ newrelic.yml. Thanks Chris Marshall for the contribution!\n\n* Make HTTP client
927
+ instrumentation aware of \"Host\" request header\n\n If a \"Host\" header is set
928
+ explicitly on an HTTP request, that hostname will\n be used for external metrics.
929
+ Thanks Mislav Marohnić for the contribution!\n\n* Fix ActiveSupport::Concern warnings
930
+ with MethodTracer\n\n Including NewRelic::Agent::MethodTracer in a class using
931
+ Concerns could cause\n deprecation warnings. Thanks Mike Połtyn for the contribution!\n\n*
932
+ Fix Authlogic constant name\n\n Code checking for the Authlogic module was using
933
+ in the wrong case. Thanks\n Dharam Gollapudi for the contribution!\n\nSee https://github.com/newrelic/rpm/blob/master/CHANGELOG
934
+ for a full list of\nchanges.\n"
928
935
  rdoc_options:
929
936
  - --line-numbers
930
937
  - --inline-source
metadata.gz.sig CHANGED
Binary file