wd_newrelic_rpm 3.5.5 → 3.5.6

Sign up to get free protection for your applications and to get access to all the features.
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