newrelic_rpm 2.9.9 → 2.10.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of newrelic_rpm might be problematic. Click here for more details.

Files changed (120) hide show
  1. data/CHANGELOG +117 -49
  2. data/bin/mongrel_rpm +2 -2
  3. data/install.rb +42 -33
  4. data/lib/new_relic/agent.rb +149 -39
  5. data/lib/new_relic/agent/agent.rb +139 -122
  6. data/lib/new_relic/agent/busy_calculator.rb +91 -0
  7. data/lib/new_relic/agent/collection_helper.rb +11 -2
  8. data/lib/new_relic/agent/error_collector.rb +33 -27
  9. data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +30 -26
  10. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
  11. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +316 -105
  12. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
  13. data/lib/new_relic/agent/instrumentation/memcache.rb +18 -12
  14. data/lib/new_relic/agent/instrumentation/merb/errors.rb +2 -1
  15. data/lib/new_relic/agent/instrumentation/metric_frame.rb +258 -0
  16. data/lib/new_relic/agent/instrumentation/net.rb +7 -11
  17. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/rack.rb +109 -0
  19. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -5
  20. data/lib/new_relic/agent/instrumentation/rails/errors.rb +7 -7
  21. data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
  22. data/lib/new_relic/agent/method_tracer.rb +305 -150
  23. data/lib/new_relic/agent/sampler.rb +34 -0
  24. data/lib/new_relic/agent/samplers/cpu_sampler.rb +11 -1
  25. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
  26. data/lib/new_relic/agent/samplers/memory_sampler.rb +22 -10
  27. data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
  28. data/lib/new_relic/agent/shim_agent.rb +10 -0
  29. data/lib/new_relic/agent/stats_engine.rb +16 -278
  30. data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
  31. data/lib/new_relic/agent/stats_engine/samplers.rb +81 -0
  32. data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
  33. data/lib/new_relic/agent/transaction_sampler.rb +73 -67
  34. data/lib/new_relic/agent/worker_loop.rb +69 -68
  35. data/lib/new_relic/commands/deployments.rb +4 -6
  36. data/lib/new_relic/control.rb +121 -60
  37. data/lib/new_relic/control/external.rb +13 -0
  38. data/lib/new_relic/control/merb.rb +2 -0
  39. data/lib/new_relic/control/rails.rb +16 -6
  40. data/lib/new_relic/control/ruby.rb +8 -5
  41. data/lib/new_relic/control/sinatra.rb +18 -0
  42. data/lib/new_relic/delayed_job_injection.rb +25 -0
  43. data/lib/new_relic/histogram.rb +89 -0
  44. data/lib/new_relic/local_environment.rb +64 -30
  45. data/lib/new_relic/metric_data.rb +15 -6
  46. data/lib/new_relic/metric_parser.rb +14 -1
  47. data/lib/new_relic/metric_parser/active_record.rb +14 -0
  48. data/lib/new_relic/metric_parser/controller.rb +5 -2
  49. data/lib/new_relic/metric_parser/external.rb +50 -0
  50. data/lib/new_relic/metric_parser/other_transaction.rb +15 -0
  51. data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
  52. data/lib/new_relic/metric_spec.rb +39 -20
  53. data/lib/new_relic/metrics.rb +9 -7
  54. data/lib/new_relic/noticed_error.rb +6 -8
  55. data/lib/new_relic/rack/metric_app.rb +5 -4
  56. data/lib/new_relic/rack/{newrelic.ru → mongrel_rpm.ru} +4 -4
  57. data/lib/new_relic/rack/newrelic.yml +1 -0
  58. data/lib/new_relic/{rack.rb → rack_app.rb} +0 -0
  59. data/lib/new_relic/recipes.rb +1 -1
  60. data/lib/new_relic/stats.rb +40 -26
  61. data/lib/new_relic/transaction_analysis.rb +5 -2
  62. data/lib/new_relic/transaction_sample.rb +134 -55
  63. data/lib/new_relic/version.rb +27 -20
  64. data/lib/new_relic_api.rb +67 -47
  65. data/lib/newrelic_rpm.rb +5 -5
  66. data/lib/tasks/tests.rake +2 -0
  67. data/newrelic.yml +69 -29
  68. data/test/active_record_fixtures.rb +2 -2
  69. data/test/config/newrelic.yml +4 -7
  70. data/test/config/test_control.rb +1 -2
  71. data/test/new_relic/agent/active_record_instrumentation_test.rb +115 -31
  72. data/test/new_relic/agent/agent_controller_test.rb +274 -0
  73. data/test/new_relic/agent/agent_test_controller.rb +42 -6
  74. data/test/new_relic/agent/busy_calculator_test.rb +79 -0
  75. data/test/new_relic/agent/collection_helper_test.rb +10 -3
  76. data/test/new_relic/agent/error_collector_test.rb +35 -17
  77. data/test/new_relic/agent/method_tracer_test.rb +60 -20
  78. data/test/new_relic/agent/metric_data_test.rb +2 -2
  79. data/test/new_relic/agent/metric_frame_test.rb +51 -0
  80. data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
  81. data/test/new_relic/agent/{agent_test.rb → rpm_agent_test.rb} +26 -5
  82. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
  83. data/test/new_relic/{samplers_test.rb → agent/stats_engine/samplers_test.rb} +23 -22
  84. data/test/new_relic/agent/{stats_engine_test.rb → stats_engine/stats_engine_test.rb} +19 -101
  85. data/test/new_relic/agent/task_instrumentation_test.rb +176 -0
  86. data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -2
  87. data/test/new_relic/agent/transaction_sample_test.rb +53 -38
  88. data/test/new_relic/agent/transaction_sampler_test.rb +101 -33
  89. data/test/new_relic/agent/worker_loop_test.rb +16 -14
  90. data/test/new_relic/control_test.rb +26 -13
  91. data/test/new_relic/metric_parser_test.rb +31 -1
  92. data/test/new_relic/metric_spec_test.rb +2 -2
  93. data/test/new_relic/stats_test.rb +0 -8
  94. data/test/new_relic/version_number_test.rb +31 -1
  95. data/test/test_helper.rb +37 -1
  96. data/ui/controllers/newrelic_controller.rb +19 -11
  97. data/ui/helpers/google_pie_chart.rb +5 -11
  98. data/ui/helpers/newrelic_helper.rb +40 -35
  99. data/ui/views/layouts/newrelic_default.rhtml +7 -7
  100. data/ui/views/newrelic/_sample.rhtml +5 -1
  101. data/ui/views/newrelic/images/new-relic-rpm-desktop.gif +0 -0
  102. data/ui/views/newrelic/images/textmate.png +0 -0
  103. data/ui/views/newrelic/index.rhtml +13 -1
  104. data/ui/views/newrelic/show_sample.rhtml +5 -2
  105. data/ui/views/newrelic/stylesheets/style.css +54 -3
  106. metadata +65 -145
  107. data/Manifest +0 -143
  108. data/Rakefile +0 -22
  109. data/init.rb +0 -38
  110. data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +0 -127
  111. data/lib/new_relic/agent/instrumentation/error_instrumentation.rb +0 -14
  112. data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +0 -13
  113. data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +0 -38
  114. data/lib/new_relic/agent/patch_const_missing.rb +0 -125
  115. data/lib/new_relic/agent/samplers/mongrel_sampler.rb +0 -22
  116. data/lib/new_relic/metric_parser/database.rb +0 -23
  117. data/newrelic_rpm.gemspec +0 -35
  118. data/test/new_relic/agent/classloader_patch_test.rb +0 -56
  119. data/test/new_relic/agent/controller_test.rb +0 -107
  120. data/test/new_relic/agent/dispatcher_instrumentation_test.rb +0 -70
@@ -0,0 +1,274 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
2
+ require 'action_controller/base'
3
+ require 'new_relic/agent/agent_test_controller'
4
+
5
+ class AgentControllerTest < ActionController::TestCase
6
+
7
+ self.controller_class = NewRelic::Agent::AgentTestController
8
+
9
+ attr_accessor :agent, :engine
10
+
11
+ # Normally you can do this with #setup but for some reason in rails 2.0.2
12
+ # setup is not called.
13
+ def initialize name
14
+ super name
15
+ Thread.current[:newrelic_ignore_controller] = nil
16
+ NewRelic::Agent.manual_start
17
+ @agent = NewRelic::Agent.instance
18
+ # @agent.instrument_app
19
+ agent.transaction_sampler.harvest
20
+ NewRelic::Agent::AgentTestController.class_eval do
21
+ newrelic_ignore :only => [:action_to_ignore, :entry_action, :base_action]
22
+ newrelic_ignore_apdex :only => :action_to_ignore_apdex
23
+ end
24
+ @engine = @agent.stats_engine
25
+ end
26
+
27
+ def teardown
28
+ Thread.current[:newrelic_ignore_controller] = nil
29
+ super
30
+ NewRelic::Agent.shutdown
31
+ NewRelic::Agent::AgentTestController.clear_headers
32
+ end
33
+
34
+ def test_mongrel_queue
35
+ engine.clear_stats
36
+ NewRelic::Control.instance.local_env.stubs(:mongrel).returns( stub('mongrel', :workers => stub('workers', :list => stub('list', :length => '10'))))
37
+
38
+ get :index
39
+ assert_equal 1, stats('HttpDispatcher').call_count
40
+ assert_equal 1, engine.get_stats_no_scope('Mongrel/Queue Length').call_count
41
+ assert_equal 9, engine.get_stats_no_scope('Mongrel/Queue Length').total_call_time
42
+ assert_equal 0, engine.get_stats_no_scope('WebFrontend/Mongrel/Average Queue Time').call_count
43
+ end
44
+
45
+ def test_heroku_queue
46
+ engine.clear_stats
47
+ NewRelic::Control.instance.local_env.stubs(:mongrel).returns( stub('mongrel', :workers => stub('workers', :list => stub('list', :length => '10'))))
48
+ NewRelic::Agent::AgentTestController.set_some_headers 'HTTP_X_HEROKU_QUEUE_DEPTH'=>'15'
49
+ get :index
50
+ assert_equal 1, stats('HttpDispatcher').call_count
51
+ assert_equal 1, engine.get_stats_no_scope('Mongrel/Queue Length').call_count
52
+ assert_equal 15, engine.get_stats_no_scope('Mongrel/Queue Length').total_call_time
53
+ assert_equal 0, engine.get_stats_no_scope('WebFrontend/Mongrel/Average Queue Time').call_count
54
+
55
+ end
56
+ def test_metric__ignore
57
+ engine.clear_stats
58
+ compare_metrics [], engine.metrics
59
+ get :action_to_ignore
60
+ compare_metrics [], engine.metrics
61
+ end
62
+
63
+ def test_controller_rescued_error
64
+ engine.clear_stats
65
+ assert_raise RuntimeError do
66
+ get :action_with_error
67
+ end
68
+ metrics = ['Apdex',
69
+ 'Apdex/new_relic/agent/agent_test/action_with_error',
70
+ 'HttpDispatcher',
71
+ 'Controller/new_relic/agent/agent_test/action_with_error',
72
+ 'Errors/all']
73
+
74
+ compare_metrics metrics, engine.metrics.reject{|m| m.index('Response')==0 || m.index('CPU')==0}
75
+ assert_equal 1, engine.get_stats_no_scope("Controller/new_relic/agent/agent_test/action_with_error").call_count
76
+ assert_equal 1, engine.get_stats_no_scope("Errors/all").call_count
77
+ apdex = engine.get_stats_no_scope("Apdex")
78
+ score = apdex.get_apdex
79
+ assert_equal 1, score[2], 'failing'
80
+ assert_equal 0, score[1], 'tol'
81
+ assert_equal 0, score[0], 'satisfied'
82
+
83
+ end
84
+ def test_controller_error
85
+ engine.clear_stats
86
+ assert_raise RuntimeError do
87
+ get :action_with_error
88
+ end
89
+ metrics = ['Apdex',
90
+ 'Apdex/new_relic/agent/agent_test/action_with_error',
91
+ 'HttpDispatcher',
92
+ 'Controller/new_relic/agent/agent_test/action_with_error',
93
+ 'Errors/all']
94
+
95
+ compare_metrics metrics, engine.metrics.reject{|m| m.index('Response')==0 || m.index('CPU')==0}
96
+ assert_equal 1, engine.get_stats_no_scope("Controller/new_relic/agent/agent_test/action_with_error").call_count
97
+ assert_equal 1, engine.get_stats_no_scope("Errors/all").call_count
98
+ apdex = engine.get_stats_no_scope("Apdex")
99
+ score = apdex.get_apdex
100
+ assert_equal 1, score[2], 'failing'
101
+ assert_equal 0, score[1], 'tol'
102
+ assert_equal 0, score[0], 'satisfied'
103
+
104
+ end
105
+ def test_filter_error
106
+ engine.clear_stats
107
+ assert_raise RuntimeError do
108
+ get :action_with_before_filter_error
109
+ end
110
+ metrics = ['Apdex',
111
+ 'Apdex/new_relic/agent/agent_test/action_with_before_filter_error',
112
+ 'HttpDispatcher',
113
+ 'Controller/new_relic/agent/agent_test/action_with_before_filter_error',
114
+ 'Errors/all']
115
+
116
+ compare_metrics metrics, engine.metrics.reject{|m| m.index('Response')==0 || m.index('CPU')==0}
117
+ assert_equal 1, engine.get_stats_no_scope("Controller/new_relic/agent/agent_test/action_with_before_filter_error").call_count
118
+ assert_equal 1, engine.get_stats_no_scope("Errors/all").call_count
119
+ apdex = engine.get_stats_no_scope("Apdex")
120
+ score = apdex.get_apdex
121
+ assert_equal 1, score[2], 'failing'
122
+ assert_equal 0, score[1], 'tol'
123
+ assert_equal 0, score[0], 'satisfied'
124
+ end
125
+ def test_metric__ignore_base
126
+ engine.clear_stats
127
+ get :base_action
128
+ compare_metrics [], engine.metrics
129
+ end
130
+ def test_metric__no_ignore
131
+ path = 'new_relic/agent/agent_test/index'
132
+ index_stats = stats("Controller/#{path}")
133
+ index_apdex_stats = engine.get_custom_stats("Apdex/#{path}", NewRelic::ApdexStats)
134
+ assert_difference 'index_stats.call_count' do
135
+ assert_difference 'index_apdex_stats.call_count' do
136
+ get :index
137
+ end
138
+ end
139
+ assert_nil Thread.current[:newrelic_ignore_controller]
140
+ end
141
+ def test_metric__ignore_apdex
142
+ engine = @agent.stats_engine
143
+ path = 'new_relic/agent/agent_test/action_to_ignore_apdex'
144
+ cpu_stats = stats("ControllerCPU/#{path}")
145
+ index_stats = stats("Controller/#{path}")
146
+ index_apdex_stats = engine.get_custom_stats("Apdex/#{path}", NewRelic::ApdexStats)
147
+ assert_difference 'index_stats.call_count' do
148
+ assert_no_difference 'index_apdex_stats.call_count' do
149
+ get :action_to_ignore_apdex
150
+ end
151
+ end
152
+ assert_nil Thread.current[:newrelic_ignore_controller]
153
+
154
+ end
155
+ def test_metric__dispatched
156
+ engine = @agent.stats_engine
157
+ get :entry_action
158
+ assert_nil Thread.current[:newrelic_ignore_controller]
159
+ assert_nil engine.lookup_stat('Controller/agent_test/entry_action')
160
+ assert_nil engine.lookup_stat('Controller/agent_test_controller/entry_action')
161
+ assert_nil engine.lookup_stat('Controller/AgentTestController/entry_action')
162
+ assert_nil engine.lookup_stat('Controller/NewRelic::Agent::AgentTestController/internal_action')
163
+ assert_nil engine.lookup_stat('Controller/NewRelic::Agent::AgentTestController_controller/internal_action')
164
+ assert_not_nil engine.lookup_stat('Controller/NewRelic::Agent::AgentTestController/internal_traced_action')
165
+ end
166
+ def test_action_instrumentation
167
+ begin
168
+ get :index, :foo => 'bar'
169
+ assert_match /bar/, @response.body
170
+ #rescue ActionController::RoutingError
171
+ # you might get here if you don't have the default route installed.
172
+ end
173
+ end
174
+
175
+ def test_controller_params
176
+ assert agent.transaction_sampler
177
+ num_samples = NewRelic::Agent.instance.transaction_sampler.samples.length
178
+ assert_equal "[FILTERED]", @controller._filter_parameters({'social_security_number' => 'test'})['social_security_number']
179
+ get :index, 'social_security_number' => "001-555-1212"
180
+ samples = agent.transaction_sampler.samples
181
+ assert_equal num_samples + 1, samples.length
182
+ assert_equal "[FILTERED]", samples.last.params[:request_params]["social_security_number"]
183
+ end
184
+
185
+ def test_controller_params
186
+ agent.transaction_sampler.reset!
187
+ get :index, 'number' => "001-555-1212"
188
+ s = agent.transaction_sampler.harvest(nil, 0.0)
189
+ assert_equal 1, s.size
190
+ assert_equal 5, s.first.params.size
191
+ end
192
+
193
+
194
+ def test_busycalculation
195
+ engine.clear_stats
196
+
197
+ assert_equal 0, NewRelic::Agent::BusyCalculator.busy_count
198
+ get :index, 'social_security_number' => "001-555-1212", 'wait' => '1.0'
199
+ NewRelic::Agent::BusyCalculator.harvest_busy
200
+
201
+ assert_equal 1, stats('Instance/Busy').call_count
202
+ assert_equal 1, stats('HttpDispatcher').call_count
203
+ # We are probably busy about 99% of the time, but lets make sure it's at least 50
204
+ assert stats('Instance/Busy').total_call_time > 0.5, stats('Instance/Busy')
205
+ assert_equal 0, stats('WebFrontend/Mongrel/Average Queue Time').call_count
206
+ end
207
+
208
+ def test_histogram
209
+ engine.clear_stats
210
+ get :index, 'social_security_number' => "001-555-1212"
211
+ bucket = NewRelic::Agent.instance.stats_engine.metrics.find { | m | m =~ /^Response Times/ }
212
+ assert_not_nil bucket
213
+ bucket_stats = stats(bucket)
214
+ assert_equal 1, bucket_stats.call_count
215
+ end
216
+
217
+ def test_queue_headers
218
+ engine.clear_stats
219
+ queue_length_stat = stats('Mongrel/Queue Length')
220
+ queue_time_stat = stats('WebFrontend/Mongrel/Average Queue Time')
221
+
222
+ # no request start header
223
+ get :index
224
+ assert_equal 0, queue_length_stat.call_count
225
+
226
+ # apache version of header
227
+ request_start = ((Time.now.to_f - 0.2) * 1e6).to_i.to_s
228
+ NewRelic::Agent::AgentTestController.set_some_headers({'HTTP_X_REQUEST_START' => "t=#{request_start}"})
229
+ get :index
230
+ assert_equal(0, queue_length_stat.call_count, 'We should not be seeing a queue length yet')
231
+ assert_equal(1, queue_time_stat.call_count, 'We should have seen the queue header once')
232
+ assert(queue_time_stat.total_call_time > 0.1, "Queue time should be longer than 100ms")
233
+ assert(queue_time_stat.total_call_time < 10, "Queue time should be under 10 seconds (sanity check)")
234
+
235
+ engine.clear_stats
236
+ NewRelic::Agent::AgentTestController.clear_headers
237
+
238
+ queue_length_stat = stats('Mongrel/Queue Length')
239
+ queue_time_stat = stats('WebFrontend/Mongrel/Average Queue Time')
240
+
241
+ # heroku version
242
+ request_start = ((Time.now.to_f - 0.2) * 1e3).to_i.to_s
243
+ NewRelic::Agent::AgentTestController.set_some_headers({'HTTP_X_REQUEST_START' => request_start, 'HTTP_X_HEROKU_QUEUE_DEPTH' => '0'})
244
+ get :index
245
+ assert_equal(0, queue_length_stat.total_call_time, 'queue should be empty')
246
+ assert_equal(1, queue_time_stat.call_count, 'should have seen the queue header once')
247
+ assert(queue_time_stat.total_call_time > 0.1, "Queue time should be longer than 100ms")
248
+ assert(queue_time_stat.total_call_time < 10, "Queue time should be under 10 seconds (sanity check)")
249
+ engine.clear_stats
250
+ NewRelic::Agent::AgentTestController.clear_headers
251
+
252
+ queue_length_stat = stats('Mongrel/Queue Length')
253
+ queue_time_stat = stats('WebFrontend/Mongrel/Average Queue Time')
254
+
255
+ # heroku version with queue length > 0
256
+ request_start = ((Time.now.to_f - 0.2) * 1e3).to_i.to_s
257
+ NewRelic::Agent::AgentTestController.set_some_headers({'HTTP_X_REQUEST_START' => request_start, 'HTTP_X_HEROKU_QUEUE_DEPTH' => '3'})
258
+ get :index
259
+
260
+ assert_equal(1, queue_length_stat.call_count, 'queue should have been seen once')
261
+ assert_equal(1, queue_time_stat.call_count, 'should have seen the queue header once')
262
+ assert(queue_time_stat.total_call_time > 0.1, "Queue time should be longer than 100ms")
263
+ assert(queue_time_stat.total_call_time < 10, "Queue time should be under 10 seconds (sanity check)")
264
+ assert_equal(3, queue_length_stat.total_call_time, 'queue should be 3 long')
265
+
266
+ NewRelic::Agent::AgentTestController.clear_headers
267
+ end
268
+
269
+ private
270
+ def stats(name)
271
+ engine.get_stats_no_scope(name)
272
+ end
273
+
274
+ end
@@ -8,14 +8,16 @@ end
8
8
  # This is a controller class used in testing controller instrumentation
9
9
  class NewRelic::Agent::AgentTestController < NewRelic::Agent::SuperclassController
10
10
  filter_parameter_logging :social_security_number
11
-
12
- def rescue_action(e) raise e end
13
-
11
+
12
+ @@headers_to_add = nil
13
+
14
+ # def rescue_action(e) raise e end
15
+
14
16
  ActionController::Routing::Routes.draw do | map |
15
17
  map.connect ':controller/:action.:format'
16
18
  end
17
-
18
19
  def index
20
+ sleep params['wait'].to_i if params['wait']
19
21
  render :text => params.inspect
20
22
  end
21
23
  def _filter_parameters(params)
@@ -30,13 +32,47 @@ class NewRelic::Agent::AgentTestController < NewRelic::Agent::SuperclassControll
30
32
  def action_to_ignore_apdex
31
33
  render :text => 'unmeasured'
32
34
  end
35
+ before_filter :oops, :only => :action_with_before_filter_error
36
+ def action_with_before_filter_error
37
+ render :text => 'nothing'
38
+ end
39
+ def oops
40
+ raise "error in before filter"
41
+ end
42
+ class TestException < RuntimeError
43
+ end
44
+
45
+ def rescue_action_locally(exception)
46
+ if exception.is_a? TestException
47
+ raise "error in the handler"
48
+ end
49
+ end
50
+ def action_with_error
51
+ raise "error in action"
52
+ end
33
53
  def entry_action
34
54
  perform_action_with_newrelic_trace('internal_action') do
35
55
  internal_action
36
56
  end
37
57
  end
58
+
59
+ def self.set_some_headers(hash_of_headers)
60
+ @@headers_to_add ||= {}
61
+ @@headers_to_add.merge!(hash_of_headers)
62
+ end
63
+
64
+ def self.clear_headers
65
+ @@headers_to_add = nil
66
+ end
67
+
68
+ def newrelic_request_headers
69
+ @@headers_to_add ||= {}
70
+ end
71
+
38
72
  private
39
73
  def internal_action
40
- render :text => 'internal action'
74
+ perform_action_with_newrelic_trace(:name => 'internal_traced_action', :force => true) do
75
+ render :text => 'internal action'
76
+ end
41
77
  end
42
- end
78
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
2
+ class NewRelic::Agent::BusyCalculatorTest < Test::Unit::TestCase
3
+ attr_reader :now
4
+ def setup
5
+ @now = Time.now.to_f
6
+ NewRelic::Agent::BusyCalculator.reset
7
+ @instance_busy = NewRelic::MethodTraceStats.new
8
+ NewRelic::Agent::BusyCalculator.stubs(:instance_busy_stats).returns(@instance_busy)
9
+ end
10
+
11
+ def test_normal
12
+ # start the timewindow 10 seconds ago
13
+ # start a request at 10 seconds, 5 seconds long
14
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
15
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 10.0)
16
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 5.0)
17
+ assert_equal 5, NewRelic::Agent::BusyCalculator.accumulator
18
+ NewRelic::Agent::BusyCalculator.harvest_busy
19
+
20
+ assert_equal 1, @instance_busy.call_count
21
+ assert_in_delta 0.50, @instance_busy.total_call_time, 0.05
22
+ end
23
+ def test_split
24
+ # start the timewindow 10 seconds ago
25
+ # start a request at 5 seconds, don't finish
26
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
27
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 5.0)
28
+ NewRelic::Agent::BusyCalculator.harvest_busy
29
+
30
+ assert_equal 1, @instance_busy.call_count, @instance_busy
31
+ assert_in_delta 0.50, @instance_busy.total_call_time, 0.05
32
+ end
33
+ def test_reentrancy
34
+ # start the timewindow 10 seconds ago
35
+ # start a request at 5 seconds, don't finish, but make two more
36
+ # complete calls, which should be ignored.
37
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
38
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 5.0)
39
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 4.5)
40
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 4.0)
41
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 3.5)
42
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 3.0)
43
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 2.0)
44
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 1.0)
45
+ NewRelic::Agent::BusyCalculator.harvest_busy
46
+
47
+ assert_equal 1, @instance_busy.call_count
48
+ assert_in_delta 0.50, @instance_busy.total_call_time, 0.05
49
+ end
50
+ def test_concurrency
51
+ # start the timewindow 10 seconds ago
52
+ # start a request at 10 seconds, 5 seconds long
53
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
54
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 8.0)
55
+ worker = Thread.new do
56
+ # Get busy for 6 - 3 seconds
57
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 6.0)
58
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 5.0)
59
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 4.0)
60
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 3.0)
61
+ end
62
+ # Get busy for 8 - 2 seconds
63
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 2.0)
64
+ worker.join
65
+ NewRelic::Agent::BusyCalculator.harvest_busy
66
+
67
+ assert_equal 1, @instance_busy.call_count
68
+ # 3 + 6 = 9, or 90%
69
+ assert_in_delta 0.90, @instance_busy.total_call_time, 0.025
70
+
71
+ end
72
+ def test_dont_ignore_zero_counts
73
+ assert_equal 0, @instance_busy.call_count, "Problem with test--instance busy not starting off at zero."
74
+ NewRelic::Agent::BusyCalculator.harvest_busy
75
+ NewRelic::Agent::BusyCalculator.harvest_busy
76
+ NewRelic::Agent::BusyCalculator.harvest_busy
77
+ assert_equal 3, @instance_busy.call_count
78
+ end
79
+ end
@@ -13,8 +13,8 @@ class NewRelic::Agent::CollectionHelperTest < Test::Unit::TestCase
13
13
 
14
14
  include NewRelic::Agent::CollectionHelper
15
15
  def test_string
16
- val = ('A'..'Z').to_a.join * 100
17
- assert_equal val.first(256) + "...", normalize_params(val)
16
+ val = (('A'..'Z').to_a.join * 100).to_s
17
+ assert_equal val[0...256] + "...", normalize_params(val)
18
18
  end
19
19
  def test_array
20
20
  new_array = normalize_params [ 1000 ] * 50
@@ -23,7 +23,14 @@ class NewRelic::Agent::CollectionHelperTest < Test::Unit::TestCase
23
23
  end
24
24
  def test_boolean
25
25
  np = normalize_params(NewRelic::Control.instance.settings)
26
- assert_equal false, np['enabled']
26
+ assert_equal false, np['monitor_mode']
27
+ end
28
+ def test_string__singleton
29
+ val = "This String"
30
+ def val.hello; end
31
+ assert_equal "This String", normalize_params(val)
32
+ assert val.respond_to?(:hello)
33
+ assert !normalize_params(val).respond_to?(:hello)
27
34
  end
28
35
  class MyString < String; end
29
36
  def test_kind_of_string