wd_newrelic_rpm 3.5.5 → 3.5.6

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.
Files changed (146) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGELOG +60 -0
  3. data/Rakefile +14 -18
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/new_relic/agent.rb +3 -0
  6. data/lib/new_relic/agent/agent.rb +86 -97
  7. data/lib/new_relic/agent/agent_logger.rb +9 -1
  8. data/lib/new_relic/agent/busy_calculator.rb +5 -0
  9. data/lib/new_relic/agent/configuration/defaults.rb +3 -3
  10. data/lib/new_relic/agent/configuration/manager.rb +12 -0
  11. data/lib/new_relic/agent/configuration/mask_defaults.rb +1 -0
  12. data/lib/new_relic/agent/configuration/yaml_source.rb +5 -1
  13. data/lib/new_relic/agent/cross_process_monitoring.rb +164 -20
  14. data/lib/new_relic/agent/error_collector.rb +13 -2
  15. data/lib/new_relic/agent/event_listener.rb +39 -0
  16. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +18 -8
  17. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/sinatra.rb +8 -1
  19. data/lib/new_relic/agent/new_relic_service.rb +90 -10
  20. data/lib/new_relic/agent/pipe_service.rb +9 -0
  21. data/lib/new_relic/agent/sql_sampler.rb +10 -3
  22. data/lib/new_relic/agent/stats_engine/transactions.rb +1 -0
  23. data/lib/new_relic/agent/thread_profiler.rb +20 -7
  24. data/lib/new_relic/agent/worker_loop.rb +2 -1
  25. data/lib/new_relic/coerce.rb +37 -0
  26. data/lib/new_relic/commands/deployments.rb +1 -1
  27. data/lib/new_relic/control/frameworks/rails.rb +29 -5
  28. data/lib/new_relic/control/frameworks/rails3.rb +2 -11
  29. data/lib/new_relic/control/instance_methods.rb +11 -7
  30. data/lib/new_relic/control/server_methods.rb +5 -37
  31. data/lib/new_relic/latest_changes.rb +31 -0
  32. data/lib/new_relic/local_environment.rb +1 -1
  33. data/lib/new_relic/metric_data.rb +13 -2
  34. data/lib/new_relic/noticed_error.rb +8 -1
  35. data/lib/new_relic/rack/agent_hooks.rb +20 -0
  36. data/lib/new_relic/rack/error_collector.rb +11 -1
  37. data/lib/new_relic/recipes.rb +32 -10
  38. data/lib/new_relic/transaction_sample.rb +12 -3
  39. data/lib/new_relic/transaction_sample/segment.rb +6 -3
  40. data/lib/new_relic/version.rb +10 -15
  41. data/newrelic.yml +12 -19
  42. data/newrelic_rpm.gemspec +22 -464
  43. data/test/multiverse/.gitignore +1 -0
  44. data/test/multiverse/lib/multiverse/environment.rb +1 -1
  45. data/test/multiverse/lib/multiverse/suite.rb +2 -0
  46. data/test/multiverse/suites/active_record/Envfile +3 -3
  47. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +1 -1
  48. data/test/multiverse/suites/active_record/config/newrelic.yml +2 -2
  49. data/test/multiverse/suites/agent_only/Envfile +2 -1
  50. data/test/multiverse/suites/agent_only/config/newrelic.yml +3 -1
  51. data/test/multiverse/suites/agent_only/cross_process_test.rb +56 -0
  52. data/test/multiverse/suites/{logging → agent_only}/logging_test.rb +42 -22
  53. data/test/multiverse/suites/agent_only/no_dns_resolv.rb +17 -0
  54. data/test/multiverse/suites/{rum_auto_instrumentation/sanity_test.rb → agent_only/rum_instrumentation_test.rb} +25 -46
  55. data/test/multiverse/suites/agent_only/service_timeout_test.rb +6 -3
  56. data/test/multiverse/suites/agent_only/ssl_test.rb +22 -0
  57. data/test/multiverse/suites/{no_load → agent_only}/start_up_test.rb +9 -2
  58. data/test/multiverse/suites/agent_only/testing_app.rb +17 -0
  59. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +6 -5
  60. data/test/multiverse/suites/datamapper/config/newrelic.yml +1 -1
  61. data/test/multiverse/suites/{rails_3_queue_time → rails}/Envfile +3 -0
  62. data/test/multiverse/suites/rails/app.rb +49 -0
  63. data/test/multiverse/suites/{rails_3_views → rails}/app/views/foos/_foo.html.haml +0 -0
  64. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_a_partial.html.erb +0 -0
  65. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_mid_partial.html.erb +0 -0
  66. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_top_partial.html.erb +0 -0
  67. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/deep_partial.html.erb +0 -0
  68. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/haml_view.html.haml +0 -0
  69. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/index.html.erb +0 -0
  70. data/test/multiverse/suites/rails/config/newrelic.yml +32 -0
  71. data/test/multiverse/suites/{rails_3_error_tracing → rails}/error_tracing_test.rb +51 -88
  72. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +79 -0
  73. data/test/multiverse/suites/{rails_3_queue_time → rails}/queue_time_test.rb +3 -23
  74. data/test/multiverse/suites/{rails_3_views → rails}/view_instrumentation_test.rb +21 -61
  75. data/test/multiverse/suites/resque/Envfile +7 -4
  76. data/test/multiverse/suites/resque/Rakefile +8 -0
  77. data/test/multiverse/suites/resque/config/newrelic.yml +1 -1
  78. data/test/multiverse/suites/resque/instrumentation_test.rb +118 -41
  79. data/test/multiverse/suites/resque/resque_setup.rb +15 -0
  80. data/test/multiverse/suites/sinatra/config/newrelic.yml +1 -2
  81. data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +38 -0
  82. data/test/multiverse/suites/sinatra/sinatra_test.rb +17 -0
  83. data/test/multiverse/test/suite_examples/one/a/config/newrelic.yml +1 -1
  84. data/test/multiverse/test/suite_examples/one/b/config/newrelic.yml +1 -1
  85. data/test/new_relic/agent/agent/connect_test.rb +24 -100
  86. data/test/new_relic/agent/agent/start_worker_thread_test.rb +3 -3
  87. data/test/new_relic/agent/agent_test.rb +126 -31
  88. data/test/new_relic/agent/browser_monitoring_test.rb +1 -1
  89. data/test/new_relic/agent/busy_calculator_test.rb +8 -0
  90. data/test/new_relic/agent/configuration/manager_test.rb +28 -0
  91. data/test/new_relic/agent/configuration/yaml_source_test.rb +12 -2
  92. data/test/new_relic/agent/cross_process_monitoring_test.rb +144 -31
  93. data/test/new_relic/agent/error_collector_test.rb +16 -0
  94. data/test/new_relic/agent/event_listener_test.rb +46 -0
  95. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +57 -30
  96. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +1 -0
  97. data/test/new_relic/agent/new_relic_service_test.rb +95 -2
  98. data/test/new_relic/agent/pipe_channel_manager_test.rb +3 -3
  99. data/test/new_relic/agent/pipe_service_test.rb +21 -1
  100. data/test/new_relic/agent/rpm_agent_test.rb +1 -1
  101. data/test/new_relic/agent/sql_sampler_test.rb +20 -0
  102. data/test/new_relic/agent/thread_profiler_test.rb +53 -8
  103. data/test/new_relic/agent/worker_loop_test.rb +19 -16
  104. data/test/new_relic/agent_test.rb +1 -2
  105. data/test/new_relic/coerce_test.rb +65 -0
  106. data/test/new_relic/command/deployments_test.rb +1 -1
  107. data/test/new_relic/control_test.rb +23 -44
  108. data/test/new_relic/fake_collector.rb +34 -6
  109. data/test/new_relic/local_environment_test.rb +1 -1
  110. data/test/new_relic/metric_data_test.rb +29 -0
  111. data/test/new_relic/noticed_error_test.rb +8 -0
  112. data/test/new_relic/rack/agent_hooks_test.rb +30 -0
  113. data/test/new_relic/rack/error_collector_test.rb +16 -0
  114. data/test/new_relic/transaction_sample/segment_test.rb +7 -0
  115. data/test/new_relic/transaction_sample_test.rb +36 -8
  116. data/test/new_relic/version_number_test.rb +6 -30
  117. data/test/script/ci.sh +6 -5
  118. data/test/test_contexts.rb +2 -1
  119. data/test/test_helper.rb +23 -6
  120. data/ui/helpers/google_pie_chart.rb +1 -0
  121. metadata +68 -67
  122. data/newrelic_rpm.gemspec.erb +0 -54
  123. data/test/fixtures/gemspec_no_build.rb +0 -442
  124. data/test/fixtures/gemspec_with_build.rb +0 -442
  125. data/test/fixtures/gemspec_with_build_and_stage.rb +0 -442
  126. data/test/multiverse/suites/logging/Envfile +0 -4
  127. data/test/multiverse/suites/logging/config/newrelic.yml +0 -22
  128. data/test/multiverse/suites/monitor_mode_false/Envfile +0 -2
  129. data/test/multiverse/suites/monitor_mode_false/config/newrelic.yml +0 -25
  130. data/test/multiverse/suites/monitor_mode_false/no_dns_resolv.rb +0 -29
  131. data/test/multiverse/suites/no_load/Envfile +0 -2
  132. data/test/multiverse/suites/no_load/config/newrelic.yml +0 -22
  133. data/test/multiverse/suites/rails_3_error_tracing/Envfile +0 -15
  134. data/test/multiverse/suites/rails_3_error_tracing/config/newrelic.yml +0 -165
  135. data/test/multiverse/suites/rails_3_gc/Envfile +0 -8
  136. data/test/multiverse/suites/rails_3_gc/config/newrelic.yml +0 -167
  137. data/test/multiverse/suites/rails_3_gc/instrumentation_test.rb +0 -92
  138. data/test/multiverse/suites/rails_3_queue_time/config/newrelic.yml +0 -165
  139. data/test/multiverse/suites/rails_3_views/.gitignore +0 -3
  140. data/test/multiverse/suites/rails_3_views/Envfile +0 -16
  141. data/test/multiverse/suites/rails_3_views/config/newrelic.yml +0 -164
  142. data/test/multiverse/suites/resque/dump.rdb +0 -0
  143. data/test/multiverse/suites/rum_auto_instrumentation/Envfile +0 -4
  144. data/test/multiverse/suites/rum_auto_instrumentation/config/newrelic.yml +0 -24
  145. data/test/multiverse/suites/rum_auto_instrumentation/responses/worst_case_small.html +0 -5000
  146. data/test/new_relic/fake_service.rb +0 -53
@@ -1,28 +1,9 @@
1
1
  # https://newrelic.atlassian.net/browse/RUBY-927
2
2
 
3
- ENV['NEW_RELIC_DISPATCHER'] = 'test'
4
-
5
- require 'action_controller/railtie'
6
- require 'rails/test_unit/railtie'
7
3
  require 'rails/test_help'
8
- require 'test/unit'
9
-
10
- # BEGIN RAILS APP
11
-
12
- class MyApp < Rails::Application
13
- # We need a secret token for session, cookies, etc.
14
- config.active_support.deprecation = :log
15
- config.secret_token = "49837489qkuweoiuoqwehisuakshdjksadhaisdy78o34y138974xyqp9rmye8yrpiokeuioqwzyoiuxftoyqiuxrhm3iou1hrzmjk"
16
- end
17
- MyApp.initialize!
18
-
19
- MyApp.routes.draw do
20
- match '/:controller(/:action(/:id))'
21
- end
22
-
23
- class ApplicationController < ActionController::Base; end
4
+ require './app'
24
5
 
25
- class TestController < ApplicationController
6
+ class QueueController < ApplicationController
26
7
  include Rails.application.routes.url_helpers
27
8
 
28
9
  def queued
@@ -31,7 +12,6 @@ class TestController < ApplicationController
31
12
  end
32
13
  end
33
14
  end
34
- # END RAILS APP
35
15
 
36
16
  class QueueTimeTest < ActionDispatch::IntegrationTest
37
17
  def setup
@@ -64,7 +44,7 @@ class QueueTimeTest < ActionDispatch::IntegrationTest
64
44
  end
65
45
 
66
46
  def get_queued(header="HTTP_X_QUEUE_START")
67
- get('/test/queued', nil, \
47
+ get('/queue/queued', nil, \
68
48
  header => "t=#{(Time.now.to_i * 1_000_000) - 1_000}")
69
49
  end
70
50
 
@@ -1,47 +1,8 @@
1
- require "action_controller/railtie"
2
- require "rails/test_unit/railtie"
3
- require 'rails/test_help'
4
- require 'test/unit'
5
-
6
- # BEGIN RAILS APP
1
+ require './app'
7
2
 
8
3
  ActionController::Base.view_paths = ['app/views']
9
4
 
10
- class MyApp < Rails::Application
11
- # We need a secret token for session, cookies, etc.
12
- config.active_support.deprecation = :log
13
- config.secret_token = "49837489qkuweoiuoqwehisuakshdjksadhaisdy78o34y138974xyqp9rmye8yrpiokeuioqwzyoiuxftoyqiuxrhm3iou1hrzmjk"
14
- config.after_initialize do
15
- NewRelic::Agent.manual_start
16
- end
17
- end
18
- MyApp.initialize!
19
-
20
- MyApp.routes.draw do
21
- match '/:controller(/:action(/:id))'
22
- end
23
-
24
- class ApplicationController < ActionController::Base; end
25
-
26
- # a basic active model compliant model we can render
27
- class Foo
28
- extend ActiveModel::Naming
29
- def to_model
30
- self
31
- end
32
-
33
- def valid?() true end
34
- def new_record?() true end
35
- def destroyed?() true end
36
-
37
- def errors
38
- obj = Object.new
39
- def obj.[](key) [] end
40
- def obj.full_messages() [] end
41
- obj
42
- end
43
- end
44
- class TestController < ApplicationController
5
+ class ViewsController < ApplicationController
45
6
  include Rails.application.routes.url_helpers
46
7
  def template_render_with_3_partial_renders
47
8
  render 'index'
@@ -68,7 +29,9 @@ class TestController < ApplicationController
68
29
  end
69
30
 
70
31
  def file_render
71
- render :file => File.expand_path(__FILE__), :content_type => 'text/plain', :layout => false
32
+ # We need any old file that's around, preferrably with ERB embedding
33
+ file = File.expand_path(File.join(File.dirname(__FILE__), "Envfile"))
34
+ render :file => file, :content_type => 'text/plain', :layout => false
72
35
  end
73
36
 
74
37
  def nothing_render
@@ -108,23 +71,20 @@ class TestController < ApplicationController
108
71
  end
109
72
  end
110
73
 
111
- # END RAILS APP
112
-
113
-
114
- class TestControllerTest < ActionController::TestCase
115
- tests TestController
74
+ class ViewControllerTest < ActionController::TestCase
75
+ tests ViewsController
116
76
  def setup
117
- @controller = TestController.new
77
+ @controller = ViewsController.new
118
78
  end
119
79
  end
120
80
 
121
81
  # SANITY TESTS - Make sure nothing raises errors,
122
82
  # unless it's supposed to
123
- class SanityTest < TestControllerTest
83
+ class SanityTest < ViewControllerTest
124
84
 
125
85
  # assert we can call any of these renders with no errors
126
86
  # (except the one that does raise an error)
127
- (TestController.action_methods - ["raise_render"]).each do |method|
87
+ (ViewsController.action_methods - ["raise_render"]).each do |method|
128
88
  test "should not raise errors on GET to #{method.inspect}" do
129
89
  get method.dup
130
90
  end
@@ -142,25 +102,25 @@ class SanityTest < TestControllerTest
142
102
  end
143
103
 
144
104
  # A controller action that renders 1 template and the same partial 3 times
145
- class NormalishRenderTest < TestControllerTest
105
+ class NormalishRenderTest < ViewControllerTest
146
106
  test "should count all the template and partial segments" do
147
107
  get :template_render_with_3_partial_renders
148
108
  sample = NewRelic::Agent.agent.transaction_sampler.samples.last
149
109
  assert_equal 5, sample.count_segments, "should be a node for the controller action, the template, and 3 partials (5)"
150
110
  end
151
111
 
152
- test "should have 3 segments with the metric name 'View/test/_a_partial.html.erb/Partial'" do
112
+ test "should have 3 segments with the metric name 'View/views/_a_partial.html.erb/Partial'" do
153
113
  get :template_render_with_3_partial_renders
154
114
  sample = NewRelic::Agent.agent.transaction_sampler.samples.last
155
115
 
156
116
  partial_segments = sample.root_segment.called_segments.first.called_segments.first.called_segments
157
117
  assert_equal 3, partial_segments.size, "sanity check"
158
118
 
159
- assert_equal ['View/test/_a_partial.html.erb/Partial'], partial_segments.map(&:metric_name).uniq
119
+ assert_equal ['View/views/_a_partial.html.erb/Partial'], partial_segments.map(&:metric_name).uniq
160
120
  end
161
121
  end
162
122
 
163
- class TextRenderTest < TestControllerTest
123
+ class TextRenderTest < ViewControllerTest
164
124
  # it doesn't seem worth it to get consistent behavior here.
165
125
  if Rails::VERSION::MINOR.to_i == 0
166
126
  test "should not instrument rendering of text" do
@@ -178,7 +138,7 @@ class TextRenderTest < TestControllerTest
178
138
  end
179
139
  end
180
140
 
181
- class InlineTemplateRenderTest < TestControllerTest
141
+ class InlineTemplateRenderTest < ViewControllerTest
182
142
  test "should create a metric for the rendered inline template" do
183
143
  get :inline_render
184
144
  sample = NewRelic::Agent.agent.transaction_sampler.samples.last
@@ -187,16 +147,16 @@ class InlineTemplateRenderTest < TestControllerTest
187
147
  end
188
148
  end
189
149
 
190
- class HamlRenderTest < TestControllerTest
150
+ class HamlRenderTest < ViewControllerTest
191
151
  test "should create a metric for the rendered haml template" do
192
152
  get :haml_render
193
153
  sample = NewRelic::Agent.agent.transaction_sampler.samples.last
194
154
  text_segment = sample.root_segment.called_segments.first.called_segments.first
195
- assert_equal 'View/test/haml_view.html.haml/Rendering', text_segment.metric_name
155
+ assert_equal 'View/views/haml_view.html.haml/Rendering', text_segment.metric_name
196
156
  end
197
157
  end
198
158
 
199
- class MissingTemplateTest < TestControllerTest
159
+ class MissingTemplateTest < ViewControllerTest
200
160
  # Rails 3.0 has different behavior for rendering an empty array. We're okay with this.
201
161
  if Rails::VERSION::MINOR.to_i == 0
202
162
  test "should create an proper metric when the template is unknown" do
@@ -215,7 +175,7 @@ class MissingTemplateTest < TestControllerTest
215
175
  end
216
176
  end
217
177
 
218
- class CollectionTemplateTest < TestControllerTest
178
+ class CollectionTemplateTest < ViewControllerTest
219
179
  test "should create a proper metric when we render a collection" do
220
180
  get :collection_render
221
181
  sample = NewRelic::Agent.agent.transaction_sampler.samples.last
@@ -224,7 +184,7 @@ class CollectionTemplateTest < TestControllerTest
224
184
  end
225
185
  end
226
186
 
227
- class UninstrumentedRendersTest < TestControllerTest
187
+ class UninstrumentedRendersTest < ViewControllerTest
228
188
  [:js_render, :xml_render, :proc_render, :json_render ].each do |action|
229
189
  test "should not instrument rendering of #{action.inspect}" do
230
190
  get action
@@ -234,7 +194,7 @@ class UninstrumentedRendersTest < TestControllerTest
234
194
  end
235
195
  end
236
196
 
237
- class FileRenderTest < TestControllerTest
197
+ class FileRenderTest < ViewControllerTest
238
198
  test "should create a metric for rendered file that does not include the filename so it doesn't metric explode" do
239
199
  get :file_render
240
200
  sample = NewRelic::Agent.agent.transaction_sampler.samples.last
@@ -1,21 +1,24 @@
1
- suite_condition("Resque not compatible with 1.8.6") do
2
- RUBY_VERSION != '1.8.6'
1
+ suite_condition("Resque tests not compatible with 1.8.6, JRuby") do
2
+ RUBY_VERSION != '1.8.6' && RUBY_PLATFORM != 'java'
3
3
  end
4
4
 
5
5
  gemfile <<-RB
6
6
  gem 'resque'
7
7
  gem 'json'
8
+ gem 'rake'
8
9
  if (RUBY_PLATFORM == 'java')
9
10
  gem "jruby-openssl"
10
11
  end
11
12
  RB
12
13
 
13
14
  before_suite do
14
- system('echo "daemonize yes" | redis-server -')
15
+ ENV["NEWRELIC_MULTIVERSE_REDIS_PORT"] = (20_000 + ($$ % 10_000)).to_s
16
+ ENV["NEWRELIC_MULTIVERSE_FAKE_COLLECTOR_PORT"] = (30_000 + ($$ % 10_000)).to_s
17
+ system("echo 'port #{ENV["NEWRELIC_MULTIVERSE_REDIS_PORT"]}' | redis-server - > /dev/null &")
15
18
  end
16
19
 
17
20
  after_suite do
18
- system('redis-cli shutdown')
21
+ system("redis-cli -p #{ENV["NEWRELIC_MULTIVERSE_REDIS_PORT"]} shutdown")
19
22
  end
20
23
 
21
24
  execute_mode 'spawn'
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), 'resque_setup')
2
+ require 'resque/tasks'
3
+
4
+ task "resque:setup" do
5
+ if ENV['BROKEN_AFTER_FORK']
6
+ Resque.before_fork = Proc.new { 'doot de doo' }
7
+ end
8
+ end
@@ -11,7 +11,7 @@ development:
11
11
  app_name: test
12
12
  host: 127.0.0.1
13
13
  api_host: 127.0.0.1
14
- port: 30303
14
+ port: <%= ENV['NEWRELIC_MULTIVERSE_FAKE_COLLECTOR_PORT'] %>
15
15
  transaction_tracer:
16
16
  record_sql: obfuscated
17
17
  enabled: true
@@ -5,69 +5,146 @@ require 'test/unit'
5
5
  require 'logger'
6
6
  require 'newrelic_rpm'
7
7
  require 'fake_collector'
8
-
9
- class JobForTesting
10
- @queue = :resque_test
11
-
12
- def self.perform(key, val, sleep_duration=0)
13
- sleep sleep_duration
14
- Redis.new.set(key, val)
15
- end
16
- end
8
+ require File.join(File.dirname(__FILE__), 'resque_setup')
17
9
 
18
10
  class ResqueTest < Test::Unit::TestCase
19
11
  JOB_COUNT = 5
12
+ COLLECTOR_PORT = ENV['NEWRELIC_MULTIVERSE_FAKE_COLLECTOR_PORT']
20
13
 
21
14
  def setup
22
- @redis = Redis.new
23
-
24
15
  $collector ||= NewRelic::FakeCollector.new
25
16
  $collector.reset
26
- $collector.run
17
+ $collector.run(COLLECTOR_PORT)
18
+ $redis.del('queue:resque_test')
19
+ $redis.set('index_key', 0)
20
+ @pidfile = "resque_test.#{$$}.pid"
21
+ JOB_COUNT.times do |i|
22
+ Resque.enqueue(JobForTesting, 'index_key', i + 1)
23
+ end
24
+ end
27
25
 
28
- NewRelic::Agent.manual_start
29
- DependencyDetection.detect!
26
+ def teardown
27
+ File.unlink(@pidfile) if File.file?(@pidfile)
28
+ end
30
29
 
31
- JOB_COUNT.times {|i| Resque.enqueue(JobForTesting, 'index_key', i + 1) }
32
- worker = Resque::Worker.new(:resque_test)
33
- Thread.new do
34
- worker.work
35
- end.abort_on_exception = true
36
- sleep 1 # give the worker some time to process
37
- worker.shutdown
30
+ def start_worker(opts={})
31
+ if opts[:background]
32
+ start_worker_background(opts[:env_vars])
33
+ else
34
+ start_worker_child(opts[:env_vars])
35
+ end
36
+ end
38
37
 
39
- NewRelic::Agent.shutdown
40
- sleep 0.5 # give the agent some time to report after shutdown
38
+ def stop_worker(opts={})
39
+ opts[:background] ? stop_worker_background : stop_worker_child
41
40
  end
42
41
 
43
- def teardown
44
- @redis.set('index_key', 0)
45
- Resque.redis.del('queue:resque_test')
46
- $collector.reset
42
+ def start_worker_child(env_vars=nil)
43
+ worker_cmd = "NEWRELIC_DISPATCHER=resque #{env_vars} QUEUE=* bundle exec rake resque:work"
44
+ @worker_pid = Process.fork
45
+ Process.exec(worker_cmd) if @worker_pid.nil?
46
+ end
47
+
48
+ def stop_worker_child
49
+ Process.kill("QUIT", @worker_pid)
50
+ Process.waitpid(@worker_pid)
51
+ end
52
+
53
+ def start_worker_background(env_vars=nil)
54
+ worker_cmd = "PIDFILE=#{@pidfile} TERM_CHILD=1 RESQUE_TERM_TIMEOUT=1 BACKGROUND=1 " +
55
+ "NEWRELIC_DISPATCHER=resque #{env_vars} QUEUE=* bundle exec rake resque:work"
56
+ system(worker_cmd)
47
57
  end
48
58
 
49
- def test_resque_instrumentation_is_installed
50
- assert DependencyDetection.installed?(:resque)
59
+ def stop_worker_background
60
+ daemon_pid = File.read(@pidfile).to_i
61
+
62
+ tries = 0
63
+ while process_alive?(daemon_pid) && tries < 3
64
+ Process.kill('TERM', daemon_pid)
65
+ sleep 4 # default resque TERM timeout
66
+ tries += 1
67
+ end
68
+
69
+ if process_alive?(daemon_pid)
70
+ $stderr.puts "Oops. Daemon (pid #{daemon_pid}) is still running. Trying to halt it with SIGQUIT"
71
+ Process.kill('QUIT', daemon_pid)
72
+ sleep 1
73
+
74
+ # If it's still alive, someone will likely have to go kill the process manually.
75
+ # Alternatively, we could kill -9 it, but I decided to err on the side of caution
76
+ if process_alive?(daemon_pid)
77
+ raise "Resque is zombified. You might have to clean up process #{daemon_pid} manually."
78
+ end
79
+ end
80
+ end
81
+
82
+ def process_alive?(pid)
83
+ Process.kill(0, pid)
84
+ return true
85
+ rescue Errno::ESRCH
86
+ return false
87
+ end
88
+
89
+ def wait_for_jobs
90
+ time_for_jobs = 5
91
+ begin
92
+ Timeout.timeout(time_for_jobs) { sleep(0.1) until Resque.info[:pending].zero? }
93
+ rescue Timeout::Error => err
94
+ raise err.exception("waiting #{time_for_jobs}s for completion of #{JOB_COUNT} jobs")
95
+ end
96
+ end
97
+
98
+ def run_worker(opts={})
99
+ begin
100
+ start_worker(opts)
101
+ wait_for_jobs
102
+ ensure
103
+ stop_worker(opts)
104
+ end
105
+ end
106
+
107
+ METRIC_VALUES_POSITION = 3
108
+
109
+ def assert_metric_and_call_count(name, expected_call_count)
110
+ metric_data = $collector.calls_for('metric_data')
111
+ assert_equal(1, metric_data.size, "expected exactly one metric_data post from agent")
112
+
113
+ metric = metric_data.first[METRIC_VALUES_POSITION].find { |m| m[0]['name'] == name }
114
+ assert(metric, "could not find metric named #{name}")
115
+
116
+ call_count = metric[1][0]
117
+ assert_equal(expected_call_count, call_count)
51
118
  end
52
119
 
53
120
  def test_all_jobs_ran
54
- assert_equal JOB_COUNT, @redis.get('index_key').to_i
121
+ run_worker
122
+ assert_equal(JOB_COUNT, $redis.get('index_key').to_i)
55
123
  end
56
124
 
57
- def test_agent_makes_only_one_metric_post
58
- assert_equal(1, $collector.agent_data.select{|x| x.action == 'metric_data'}.size,
59
- "wrong number of metric_data posts in #{$collector.agent_data.inspect}")
125
+ def test_agent_posts_correct_metric_data
126
+ run_worker
127
+ assert_metric_and_call_count('OtherTransaction/ResqueJob/all', JOB_COUNT)
60
128
  end
61
129
 
62
- def test_agent_posts_correct_call_count
63
- test_metric = 'OtherTransaction/ResqueJob/all'
64
- metric_data = $collector.agent_data.find{|x| x.action == 'metric_data'}
130
+ def test_log_properly_when_fork_callbacks_are_broken
131
+ log_path = File.join(File.dirname(__FILE__), 'agent.log', 'newrelic_agent.log')
132
+ File.delete(log_path)
133
+
134
+ run_worker(:env_vars => 'BROKEN_AFTER_FORK=true')
135
+
136
+ assert File.read(log_path).include?('Unable to send data to parent process')
137
+ end
65
138
 
66
- metric_names = metric_data.body[3].map{|m| m[0]['name']}
67
- assert(metric_names.include?(test_metric),
68
- "#{metric_names.inspect} should include '#{test_metric}'")
139
+ if RUBY_VERSION >= '1.9'
140
+ def test_all_jobs_ran_background
141
+ run_worker(:background => true)
142
+ assert_equal(JOB_COUNT, $redis.get('index_key').to_i)
143
+ end
69
144
 
70
- call_count = metric_data.body[3].find{|m| m[0]['name'] == test_metric}[1][0]
71
- assert_equal JOB_COUNT, call_count
145
+ def test_agent_posts_correct_metric_data_background
146
+ run_worker(:background => true)
147
+ assert_metric_and_call_count('OtherTransaction/ResqueJob/all', JOB_COUNT)
148
+ end
72
149
  end
73
150
  end