honkster-newrelic_rpm 2.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/CHANGELOG +462 -0
  2. data/LICENSE +37 -0
  3. data/README.rdoc +172 -0
  4. data/bin/mongrel_rpm +33 -0
  5. data/bin/newrelic +13 -0
  6. data/bin/newrelic_cmd +5 -0
  7. data/cert/cacert.pem +34 -0
  8. data/install.rb +9 -0
  9. data/lib/new_relic/agent.rb +382 -0
  10. data/lib/new_relic/agent/agent.rb +741 -0
  11. data/lib/new_relic/agent/busy_calculator.rb +91 -0
  12. data/lib/new_relic/agent/chained_call.rb +13 -0
  13. data/lib/new_relic/agent/error_collector.rb +131 -0
  14. data/lib/new_relic/agent/instrumentation/active_merchant.rb +18 -0
  15. data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +92 -0
  16. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +45 -0
  17. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
  18. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +409 -0
  19. data/lib/new_relic/agent/instrumentation/data_mapper.rb +58 -0
  20. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
  21. data/lib/new_relic/agent/instrumentation/memcache.rb +40 -0
  22. data/lib/new_relic/agent/instrumentation/merb/controller.rb +26 -0
  23. data/lib/new_relic/agent/instrumentation/merb/errors.rb +9 -0
  24. data/lib/new_relic/agent/instrumentation/metric_frame.rb +319 -0
  25. data/lib/new_relic/agent/instrumentation/net.rb +17 -0
  26. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +22 -0
  27. data/lib/new_relic/agent/instrumentation/rack.rb +98 -0
  28. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +59 -0
  29. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +27 -0
  30. data/lib/new_relic/agent/instrumentation/rails/errors.rb +24 -0
  31. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +45 -0
  32. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +21 -0
  33. data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
  34. data/lib/new_relic/agent/instrumentation/sunspot.rb +17 -0
  35. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +10 -0
  36. data/lib/new_relic/agent/method_tracer.rb +350 -0
  37. data/lib/new_relic/agent/sampler.rb +50 -0
  38. data/lib/new_relic/agent/samplers/cpu_sampler.rb +54 -0
  39. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
  40. data/lib/new_relic/agent/samplers/memory_sampler.rb +142 -0
  41. data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
  42. data/lib/new_relic/agent/shim_agent.rb +25 -0
  43. data/lib/new_relic/agent/stats_engine.rb +24 -0
  44. data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
  45. data/lib/new_relic/agent/stats_engine/samplers.rb +83 -0
  46. data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
  47. data/lib/new_relic/agent/transaction_sampler.rb +330 -0
  48. data/lib/new_relic/agent/worker_loop.rb +81 -0
  49. data/lib/new_relic/collection_helper.rb +71 -0
  50. data/lib/new_relic/command.rb +85 -0
  51. data/lib/new_relic/commands/deployments.rb +105 -0
  52. data/lib/new_relic/commands/install.rb +81 -0
  53. data/lib/new_relic/control.rb +203 -0
  54. data/lib/new_relic/control/configuration.rb +149 -0
  55. data/lib/new_relic/control/frameworks/external.rb +13 -0
  56. data/lib/new_relic/control/frameworks/merb.rb +24 -0
  57. data/lib/new_relic/control/frameworks/rails.rb +126 -0
  58. data/lib/new_relic/control/frameworks/rails3.rb +60 -0
  59. data/lib/new_relic/control/frameworks/ruby.rb +36 -0
  60. data/lib/new_relic/control/frameworks/sinatra.rb +18 -0
  61. data/lib/new_relic/control/instrumentation.rb +95 -0
  62. data/lib/new_relic/control/logging_methods.rb +74 -0
  63. data/lib/new_relic/control/profiling.rb +24 -0
  64. data/lib/new_relic/control/server_methods.rb +88 -0
  65. data/lib/new_relic/delayed_job_injection.rb +27 -0
  66. data/lib/new_relic/histogram.rb +91 -0
  67. data/lib/new_relic/local_environment.rb +333 -0
  68. data/lib/new_relic/merbtasks.rb +6 -0
  69. data/lib/new_relic/metric_data.rb +42 -0
  70. data/lib/new_relic/metric_parser.rb +136 -0
  71. data/lib/new_relic/metric_parser/action_mailer.rb +9 -0
  72. data/lib/new_relic/metric_parser/active_merchant.rb +26 -0
  73. data/lib/new_relic/metric_parser/active_record.rb +28 -0
  74. data/lib/new_relic/metric_parser/apdex.rb +88 -0
  75. data/lib/new_relic/metric_parser/controller.rb +62 -0
  76. data/lib/new_relic/metric_parser/controller_cpu.rb +38 -0
  77. data/lib/new_relic/metric_parser/errors.rb +6 -0
  78. data/lib/new_relic/metric_parser/external.rb +50 -0
  79. data/lib/new_relic/metric_parser/mem_cache.rb +50 -0
  80. data/lib/new_relic/metric_parser/other_transaction.rb +36 -0
  81. data/lib/new_relic/metric_parser/view.rb +61 -0
  82. data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
  83. data/lib/new_relic/metric_parser/web_service.rb +9 -0
  84. data/lib/new_relic/metric_spec.rb +67 -0
  85. data/lib/new_relic/metrics.rb +9 -0
  86. data/lib/new_relic/noticed_error.rb +24 -0
  87. data/lib/new_relic/rack/developer_mode.rb +257 -0
  88. data/lib/new_relic/rack/metric_app.rb +64 -0
  89. data/lib/new_relic/rack/mongrel_rpm.ru +26 -0
  90. data/lib/new_relic/rack/newrelic.yml +27 -0
  91. data/lib/new_relic/rack_app.rb +6 -0
  92. data/lib/new_relic/recipes.rb +82 -0
  93. data/lib/new_relic/stats.rb +368 -0
  94. data/lib/new_relic/timer_lib.rb +27 -0
  95. data/lib/new_relic/transaction_analysis.rb +119 -0
  96. data/lib/new_relic/transaction_sample.rb +586 -0
  97. data/lib/new_relic/url_rule.rb +14 -0
  98. data/lib/new_relic/version.rb +55 -0
  99. data/lib/new_relic_api.rb +276 -0
  100. data/lib/newrelic_rpm.rb +49 -0
  101. data/lib/tasks/all.rb +4 -0
  102. data/lib/tasks/install.rake +7 -0
  103. data/lib/tasks/tests.rake +15 -0
  104. data/newrelic.yml +246 -0
  105. data/newrelic_rpm.gemspec +254 -0
  106. data/recipes/newrelic.rb +6 -0
  107. data/test/active_record_fixtures.rb +55 -0
  108. data/test/config/newrelic.yml +48 -0
  109. data/test/config/test_control.rb +36 -0
  110. data/test/new_relic/agent/active_record_instrumentation_test.rb +286 -0
  111. data/test/new_relic/agent/agent_controller_test.rb +294 -0
  112. data/test/new_relic/agent/agent_test_controller.rb +77 -0
  113. data/test/new_relic/agent/busy_calculator_test.rb +81 -0
  114. data/test/new_relic/agent/collection_helper_test.rb +125 -0
  115. data/test/new_relic/agent/error_collector_test.rb +163 -0
  116. data/test/new_relic/agent/memcache_instrumentation_test.rb +103 -0
  117. data/test/new_relic/agent/method_tracer_test.rb +340 -0
  118. data/test/new_relic/agent/metric_data_test.rb +53 -0
  119. data/test/new_relic/agent/metric_frame_test.rb +51 -0
  120. data/test/new_relic/agent/mock_scope_listener.rb +23 -0
  121. data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
  122. data/test/new_relic/agent/rpm_agent_test.rb +142 -0
  123. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
  124. data/test/new_relic/agent/stats_engine/samplers_test.rb +72 -0
  125. data/test/new_relic/agent/stats_engine/stats_engine_test.rb +184 -0
  126. data/test/new_relic/agent/task_instrumentation_test.rb +188 -0
  127. data/test/new_relic/agent/testable_agent.rb +13 -0
  128. data/test/new_relic/agent/transaction_sample_builder_test.rb +195 -0
  129. data/test/new_relic/agent/transaction_sample_test.rb +192 -0
  130. data/test/new_relic/agent/transaction_sampler_test.rb +385 -0
  131. data/test/new_relic/agent/worker_loop_test.rb +66 -0
  132. data/test/new_relic/control_test.rb +127 -0
  133. data/test/new_relic/deployments_api_test.rb +69 -0
  134. data/test/new_relic/environment_test.rb +75 -0
  135. data/test/new_relic/metric_parser_test.rb +226 -0
  136. data/test/new_relic/metric_spec_test.rb +177 -0
  137. data/test/new_relic/rack/episodes_test.rb +318 -0
  138. data/test/new_relic/shim_agent_test.rb +9 -0
  139. data/test/new_relic/stats_test.rb +312 -0
  140. data/test/new_relic/version_number_test.rb +89 -0
  141. data/test/test_contexts.rb +28 -0
  142. data/test/test_helper.rb +72 -0
  143. data/ui/helpers/developer_mode_helper.rb +359 -0
  144. data/ui/helpers/google_pie_chart.rb +49 -0
  145. data/ui/views/layouts/newrelic_default.rhtml +47 -0
  146. data/ui/views/newrelic/_explain_plans.rhtml +27 -0
  147. data/ui/views/newrelic/_sample.rhtml +20 -0
  148. data/ui/views/newrelic/_segment.rhtml +29 -0
  149. data/ui/views/newrelic/_segment_limit_message.rhtml +1 -0
  150. data/ui/views/newrelic/_segment_row.rhtml +14 -0
  151. data/ui/views/newrelic/_show_sample_detail.rhtml +24 -0
  152. data/ui/views/newrelic/_show_sample_sql.rhtml +20 -0
  153. data/ui/views/newrelic/_show_sample_summary.rhtml +3 -0
  154. data/ui/views/newrelic/_sql_row.rhtml +16 -0
  155. data/ui/views/newrelic/_stack_trace.rhtml +15 -0
  156. data/ui/views/newrelic/_table.rhtml +12 -0
  157. data/ui/views/newrelic/explain_sql.rhtml +43 -0
  158. data/ui/views/newrelic/file/images/arrow-close.png +0 -0
  159. data/ui/views/newrelic/file/images/arrow-open.png +0 -0
  160. data/ui/views/newrelic/file/images/blue_bar.gif +0 -0
  161. data/ui/views/newrelic/file/images/file_icon.png +0 -0
  162. data/ui/views/newrelic/file/images/gray_bar.gif +0 -0
  163. data/ui/views/newrelic/file/images/new-relic-rpm-desktop.gif +0 -0
  164. data/ui/views/newrelic/file/images/new_relic_rpm_desktop.gif +0 -0
  165. data/ui/views/newrelic/file/images/textmate.png +0 -0
  166. data/ui/views/newrelic/file/javascript/jquery-1.4.2.js +6240 -0
  167. data/ui/views/newrelic/file/javascript/transaction_sample.js +120 -0
  168. data/ui/views/newrelic/file/stylesheets/style.css +484 -0
  169. data/ui/views/newrelic/index.rhtml +59 -0
  170. data/ui/views/newrelic/sample_not_found.rhtml +2 -0
  171. data/ui/views/newrelic/show_sample.rhtml +79 -0
  172. data/ui/views/newrelic/show_source.rhtml +3 -0
  173. data/ui/views/newrelic/threads.rhtml +52 -0
  174. metadata +307 -0
@@ -0,0 +1,294 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
2
+
3
+ class AgentControllerTest < ActionController::TestCase
4
+ require 'action_controller/base'
5
+ require 'new_relic/agent/agent_test_controller'
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
+
16
+ # Suggested by cee-dub for merb tests. I'm actually amazed if our tests work with merb.
17
+ if defined?(Merb::Router)
18
+ Merb::Router.prepare do |r|
19
+ match('/:controller(/:action)(.:format)').register
20
+ end
21
+ else
22
+ ActionController::Routing::Routes.draw do | map |
23
+ map.connect '/:controller/:action.:format'
24
+ map.connect '/:controller/:action'
25
+ end
26
+ end
27
+
28
+ Thread.current[:newrelic_ignore_controller] = nil
29
+ NewRelic::Agent.manual_start
30
+ @agent = NewRelic::Agent.instance
31
+ # @agent.instrument_app
32
+ agent.transaction_sampler.harvest
33
+ NewRelic::Agent::AgentTestController.class_eval do
34
+ newrelic_ignore :only => [:action_to_ignore, :entry_action, :base_action]
35
+ newrelic_ignore_apdex :only => :action_to_ignore_apdex
36
+ end
37
+ @engine = @agent.stats_engine
38
+ end
39
+
40
+ def teardown
41
+ Thread.current[:newrelic_ignore_controller] = nil
42
+ super
43
+ NewRelic::Agent.shutdown
44
+ NewRelic::Agent::AgentTestController.clear_headers
45
+ end
46
+
47
+ def test_mongrel_queue
48
+ engine.clear_stats
49
+ NewRelic::Control.instance.local_env.stubs(:mongrel).returns( stub('mongrel', :workers => stub('workers', :list => stub('list', :length => '10'))))
50
+
51
+ get :index
52
+ assert_equal 1, stats('HttpDispatcher').call_count
53
+ assert_equal 1, engine.get_stats_no_scope('Mongrel/Queue Length').call_count
54
+ assert_equal 9, engine.get_stats_no_scope('Mongrel/Queue Length').total_call_time
55
+ assert_equal 0, engine.get_stats_no_scope('WebFrontend/Mongrel/Average Queue Time').call_count
56
+ end
57
+
58
+ def test_heroku_queue
59
+ engine.clear_stats
60
+ NewRelic::Control.instance.local_env.stubs(:mongrel).returns( stub('mongrel', :workers => stub('workers', :list => stub('list', :length => '10'))))
61
+ NewRelic::Agent::AgentTestController.set_some_headers 'HTTP_X_HEROKU_QUEUE_DEPTH'=>'15'
62
+ get :index
63
+ assert_equal 1, stats('HttpDispatcher').call_count
64
+ assert_equal 1, engine.get_stats_no_scope('Mongrel/Queue Length').call_count
65
+ assert_equal 15, engine.get_stats_no_scope('Mongrel/Queue Length').total_call_time
66
+ assert_equal 0, engine.get_stats_no_scope('WebFrontend/Mongrel/Average Queue Time').call_count
67
+ end
68
+
69
+ def test_render_inline
70
+ engine.clear_stats
71
+ get :action_inline
72
+ assert_equal 'foofah', @response.body
73
+ compare_metrics %w[Controller/new_relic/agent/agent_test/action_inline], engine.metrics.grep(/^Controller/)
74
+ end
75
+ def test_metric__ignore
76
+ engine.clear_stats
77
+ compare_metrics [], engine.metrics
78
+ get :action_to_ignore
79
+ compare_metrics [], engine.metrics
80
+ end
81
+
82
+ def test_controller_rescued_error
83
+ engine.clear_stats
84
+ assert_raise RuntimeError do
85
+ get :action_with_error
86
+ end
87
+ metrics = ['Apdex',
88
+ 'Apdex/new_relic/agent/agent_test/action_with_error',
89
+ 'HttpDispatcher',
90
+ 'Controller/new_relic/agent/agent_test/action_with_error',
91
+ 'Errors/all']
92
+
93
+ compare_metrics metrics, engine.metrics.reject{|m| m.index('Response')==0 || m.index('CPU')==0}
94
+ assert_equal 1, engine.get_stats_no_scope("Controller/new_relic/agent/agent_test/action_with_error").call_count
95
+ assert_equal 1, engine.get_stats_no_scope("Errors/all").call_count
96
+ apdex = engine.get_stats_no_scope("Apdex")
97
+ score = apdex.get_apdex
98
+ assert_equal 1, score[2], 'failing'
99
+ assert_equal 0, score[1], 'tol'
100
+ assert_equal 0, score[0], 'satisfied'
101
+
102
+ end
103
+ def test_controller_error
104
+ engine.clear_stats
105
+ assert_raise RuntimeError do
106
+ get :action_with_error
107
+ end
108
+ metrics = ['Apdex',
109
+ 'Apdex/new_relic/agent/agent_test/action_with_error',
110
+ 'HttpDispatcher',
111
+ 'Controller/new_relic/agent/agent_test/action_with_error',
112
+ 'Errors/all']
113
+
114
+ compare_metrics metrics, engine.metrics.reject{|m| m.index('Response')==0 || m.index('CPU')==0}
115
+ assert_equal 1, engine.get_stats_no_scope("Controller/new_relic/agent/agent_test/action_with_error").call_count
116
+ assert_equal 1, engine.get_stats_no_scope("Errors/all").call_count
117
+ apdex = engine.get_stats_no_scope("Apdex")
118
+ score = apdex.get_apdex
119
+ assert_equal 1, score[2], 'failing'
120
+ assert_equal 0, score[1], 'tol'
121
+ assert_equal 0, score[0], 'satisfied'
122
+
123
+ end
124
+ def test_filter_error
125
+ engine.clear_stats
126
+ assert_raise RuntimeError do
127
+ get :action_with_before_filter_error
128
+ end
129
+ metrics = ['Apdex',
130
+ 'Apdex/new_relic/agent/agent_test/action_with_before_filter_error',
131
+ 'HttpDispatcher',
132
+ 'Controller/new_relic/agent/agent_test/action_with_before_filter_error',
133
+ 'Errors/all']
134
+
135
+ compare_metrics metrics, engine.metrics.reject{|m| m.index('Response')==0 || m.index('CPU')==0}
136
+ assert_equal 1, engine.get_stats_no_scope("Controller/new_relic/agent/agent_test/action_with_before_filter_error").call_count
137
+ assert_equal 1, engine.get_stats_no_scope("Errors/all").call_count
138
+ apdex = engine.get_stats_no_scope("Apdex")
139
+ score = apdex.get_apdex
140
+ assert_equal 1, score[2], 'failing'
141
+ assert_equal 0, score[1], 'tol'
142
+ assert_equal 0, score[0], 'satisfied'
143
+ end
144
+ def test_metric__ignore_base
145
+ engine.clear_stats
146
+ get :base_action
147
+ compare_metrics [], engine.metrics
148
+ end
149
+ def test_metric__no_ignore
150
+ path = 'new_relic/agent/agent_test/index'
151
+ index_stats = stats("Controller/#{path}")
152
+ index_apdex_stats = engine.get_custom_stats("Apdex/#{path}", NewRelic::ApdexStats)
153
+ assert_difference 'index_stats.call_count' do
154
+ assert_difference 'index_apdex_stats.call_count' do
155
+ get :index
156
+ end
157
+ end
158
+ assert_nil Thread.current[:newrelic_ignore_controller]
159
+ end
160
+ def test_metric__ignore_apdex
161
+ engine = @agent.stats_engine
162
+ path = 'new_relic/agent/agent_test/action_to_ignore_apdex'
163
+ cpu_stats = stats("ControllerCPU/#{path}")
164
+ index_stats = stats("Controller/#{path}")
165
+ index_apdex_stats = engine.get_custom_stats("Apdex/#{path}", NewRelic::ApdexStats)
166
+ assert_difference 'index_stats.call_count' do
167
+ assert_no_difference 'index_apdex_stats.call_count' do
168
+ get :action_to_ignore_apdex
169
+ end
170
+ end
171
+ assert_nil Thread.current[:newrelic_ignore_controller]
172
+
173
+ end
174
+ def test_metric__dispatched
175
+ engine = @agent.stats_engine
176
+ get :entry_action
177
+ assert_nil Thread.current[:newrelic_ignore_controller]
178
+ assert_nil engine.lookup_stat('Controller/agent_test/entry_action')
179
+ assert_nil engine.lookup_stat('Controller/agent_test_controller/entry_action')
180
+ assert_nil engine.lookup_stat('Controller/AgentTestController/entry_action')
181
+ assert_nil engine.lookup_stat('Controller/NewRelic::Agent::AgentTestController/internal_action')
182
+ assert_nil engine.lookup_stat('Controller/NewRelic::Agent::AgentTestController_controller/internal_action')
183
+ assert_not_nil engine.lookup_stat('Controller/NewRelic::Agent::AgentTestController/internal_traced_action')
184
+ end
185
+ def test_action_instrumentation
186
+ begin
187
+ get :index, :foo => 'bar'
188
+ assert_match /bar/, @response.body
189
+ #rescue ActionController::RoutingError
190
+ # you might get here if you don't have the default route installed.
191
+ end
192
+ end
193
+
194
+ def test_controller_params
195
+ assert agent.transaction_sampler
196
+ num_samples = NewRelic::Agent.instance.transaction_sampler.samples.length
197
+ assert_equal "[FILTERED]", @controller._filter_parameters({'social_security_number' => 'test'})['social_security_number']
198
+ get :index, 'social_security_number' => "001-555-1212"
199
+ samples = agent.transaction_sampler.samples
200
+ assert_equal num_samples + 1, samples.length
201
+ assert_equal "[FILTERED]", samples.last.params[:request_params]["social_security_number"]
202
+ end
203
+
204
+ def test_controller_params
205
+ agent.transaction_sampler.reset!
206
+ get :index, 'number' => "001-555-1212"
207
+ s = agent.transaction_sampler.harvest(nil, 0.0)
208
+ assert_equal 1, s.size
209
+ assert_equal 5, s.first.params.size
210
+ end
211
+
212
+
213
+ def test_busycalculation
214
+ engine.clear_stats
215
+
216
+ assert_equal 0, NewRelic::Agent::BusyCalculator.busy_count
217
+ get :index, 'social_security_number' => "001-555-1212", 'wait' => '1.0'
218
+ NewRelic::Agent::BusyCalculator.harvest_busy
219
+
220
+ assert_equal 1, stats('Instance/Busy').call_count
221
+ assert_equal 1, stats('HttpDispatcher').call_count
222
+ # We are probably busy about 99% of the time, but lets make sure it's at least 50
223
+ assert stats('Instance/Busy').total_call_time > 0.5, stats('Instance/Busy')
224
+ assert_equal 0, stats('WebFrontend/Mongrel/Average Queue Time').call_count
225
+ end
226
+
227
+ def test_histogram
228
+ engine.clear_stats
229
+ get :index, 'social_security_number' => "001-555-1212"
230
+ bucket = NewRelic::Agent.instance.stats_engine.metrics.find { | m | m =~ /^Response Times/ }
231
+ assert_not_nil bucket
232
+ bucket_stats = stats(bucket)
233
+ assert_equal 1, bucket_stats.call_count
234
+ end
235
+
236
+ def test_queue_headers
237
+ engine.clear_stats
238
+ queue_length_stat = stats('Mongrel/Queue Length')
239
+ queue_time_stat = stats('WebFrontend/Mongrel/Average Queue Time')
240
+
241
+ # no request start header
242
+ get 'index'
243
+ assert_equal 0, queue_length_stat.call_count
244
+
245
+ # apache version of header
246
+ request_start = ((Time.now.to_f - 0.2) * 1e6).to_i.to_s
247
+ NewRelic::Agent::AgentTestController.set_some_headers({'HTTP_X_REQUEST_START' => "t=#{request_start}"})
248
+ get :index
249
+ assert_equal(0, queue_length_stat.call_count, 'We should not be seeing a queue length yet')
250
+ assert_equal(1, queue_time_stat.call_count, 'We should have seen the queue header once')
251
+ assert(queue_time_stat.total_call_time > 0.1, "Queue time should be longer than 100ms")
252
+ assert(queue_time_stat.total_call_time < 10, "Queue time should be under 10 seconds (sanity check)")
253
+
254
+ engine.clear_stats
255
+ NewRelic::Agent::AgentTestController.clear_headers
256
+
257
+ queue_length_stat = stats('Mongrel/Queue Length')
258
+ queue_time_stat = stats('WebFrontend/Mongrel/Average Queue Time')
259
+
260
+ # heroku version
261
+ request_start = ((Time.now.to_f - 0.2) * 1e3).to_i.to_s
262
+ NewRelic::Agent::AgentTestController.set_some_headers({'HTTP_X_REQUEST_START' => request_start, 'HTTP_X_HEROKU_QUEUE_DEPTH' => '0'})
263
+ get :index
264
+ assert_equal(0, queue_length_stat.total_call_time, 'queue should be empty')
265
+ assert_equal(1, queue_time_stat.call_count, 'should have seen the queue header once')
266
+ assert(queue_time_stat.total_call_time > 0.1, "Queue time should be longer than 100ms")
267
+ assert(queue_time_stat.total_call_time < 10, "Queue time should be under 10 seconds (sanity check)")
268
+ engine.clear_stats
269
+ NewRelic::Agent::AgentTestController.clear_headers
270
+
271
+ queue_length_stat = stats('Mongrel/Queue Length')
272
+ queue_time_stat = stats('WebFrontend/Mongrel/Average Queue Time')
273
+
274
+ # heroku version with queue length > 0
275
+ request_start = ((Time.now.to_f - 0.2) * 1e3).to_i.to_s
276
+ NewRelic::Agent::AgentTestController.set_some_headers({'HTTP_X_REQUEST_START' => request_start, 'HTTP_X_HEROKU_QUEUE_DEPTH' => '3'})
277
+ get :index
278
+
279
+ assert_equal(1, queue_length_stat.call_count, 'queue should have been seen once')
280
+ assert_equal(1, queue_time_stat.call_count, 'should have seen the queue header once')
281
+ assert(queue_time_stat.total_call_time > 0.1, "Queue time should be longer than 100ms")
282
+ assert(queue_time_stat.total_call_time < 10, "Queue time should be under 10 seconds (sanity check)")
283
+ assert_equal(3, queue_length_stat.total_call_time, 'queue should be 3 long')
284
+
285
+ NewRelic::Agent::AgentTestController.clear_headers
286
+ end
287
+
288
+ private
289
+ def stats(name)
290
+ engine.get_stats_no_scope(name)
291
+ end
292
+
293
+ end if defined? Rails
294
+
@@ -0,0 +1,77 @@
1
+ # Defining a test controller class with a superclass, used to
2
+ # verify correct attribute inheritence
3
+ class NewRelic::Agent::SuperclassController < ActionController::Base
4
+ def base_action
5
+ render :text => 'none'
6
+ end
7
+ end
8
+ # This is a controller class used in testing controller instrumentation
9
+ class NewRelic::Agent::AgentTestController < NewRelic::Agent::SuperclassController
10
+ filter_parameter_logging :social_security_number
11
+
12
+ @@headers_to_add = nil
13
+
14
+ def index
15
+ sleep params['wait'].to_i if params['wait']
16
+ render :text => params.inspect
17
+ end
18
+ def _filter_parameters(params)
19
+ filter_parameters params
20
+ end
21
+ def action_inline
22
+ render(:inline => "<%= 'foo' %>fah")
23
+ end
24
+
25
+ def action_to_render
26
+ render :text => params.inspect
27
+ end
28
+ def action_to_ignore
29
+ render :text => 'unmeasured'
30
+ end
31
+ def action_to_ignore_apdex
32
+ render :text => 'unmeasured'
33
+ end
34
+ before_filter :oops, :only => :action_with_before_filter_error
35
+ def action_with_before_filter_error
36
+ render :text => 'nothing'
37
+ end
38
+ def oops
39
+ raise "error in before filter"
40
+ end
41
+ class TestException < RuntimeError
42
+ end
43
+
44
+ def rescue_action_locally(exception)
45
+ if exception.is_a? TestException
46
+ raise "error in the handler"
47
+ end
48
+ end
49
+ def action_with_error
50
+ raise "error in action"
51
+ end
52
+ def entry_action
53
+ perform_action_with_newrelic_trace('internal_action') do
54
+ internal_action
55
+ end
56
+ end
57
+
58
+ def self.set_some_headers(hash_of_headers)
59
+ @@headers_to_add ||= {}
60
+ @@headers_to_add.merge!(hash_of_headers)
61
+ end
62
+
63
+ def self.clear_headers
64
+ @@headers_to_add = nil
65
+ end
66
+
67
+ def newrelic_request_headers
68
+ @@headers_to_add ||= {}
69
+ end
70
+
71
+ private
72
+ def internal_action
73
+ perform_action_with_newrelic_trace(:name => 'internal_traced_action', :force => true) do
74
+ render :text => 'internal action'
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,81 @@
1
+ # Run faster standalone
2
+ ENV['SKIP_RAILS'] = 'true'
3
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
4
+ class NewRelic::Agent::BusyCalculatorTest < Test::Unit::TestCase
5
+ attr_reader :now
6
+ def setup
7
+ @now = Time.now.to_f
8
+ NewRelic::Agent::BusyCalculator.reset
9
+ @instance_busy = NewRelic::MethodTraceStats.new
10
+ NewRelic::Agent::BusyCalculator.stubs(:instance_busy_stats).returns(@instance_busy)
11
+ end
12
+
13
+ def test_normal
14
+ # start the timewindow 10 seconds ago
15
+ # start a request at 10 seconds, 5 seconds long
16
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
17
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 10.0)
18
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 5.0)
19
+ assert_equal 5, NewRelic::Agent::BusyCalculator.accumulator
20
+ NewRelic::Agent::BusyCalculator.harvest_busy
21
+
22
+ assert_equal 1, @instance_busy.call_count
23
+ assert_in_delta 0.50, @instance_busy.total_call_time, 0.05
24
+ end
25
+ def test_split
26
+ # start the timewindow 10 seconds ago
27
+ # start a request at 5 seconds, don't finish
28
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
29
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 5.0)
30
+ NewRelic::Agent::BusyCalculator.harvest_busy
31
+
32
+ assert_equal 1, @instance_busy.call_count, @instance_busy
33
+ assert_in_delta 0.50, @instance_busy.total_call_time, 0.05
34
+ end
35
+ def test_reentrancy
36
+ # start the timewindow 10 seconds ago
37
+ # start a request at 5 seconds, don't finish, but make two more
38
+ # complete calls, which should be ignored.
39
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
40
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 5.0)
41
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 4.5)
42
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 4.0)
43
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 3.5)
44
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 3.0)
45
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 2.0)
46
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 1.0)
47
+ NewRelic::Agent::BusyCalculator.harvest_busy
48
+
49
+ assert_equal 1, @instance_busy.call_count
50
+ assert_in_delta 0.50, @instance_busy.total_call_time, 0.05
51
+ end
52
+ def test_concurrency
53
+ # start the timewindow 10 seconds ago
54
+ # start a request at 10 seconds, 5 seconds long
55
+ NewRelic::Agent::BusyCalculator.stubs(:harvest_start).returns(now - 10.0)
56
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 8.0)
57
+ worker = Thread.new do
58
+ # Get busy for 6 - 3 seconds
59
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 6.0)
60
+ NewRelic::Agent::BusyCalculator.dispatcher_start(now - 5.0)
61
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 4.0)
62
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 3.0)
63
+ end
64
+ # Get busy for 8 - 2 seconds
65
+ NewRelic::Agent::BusyCalculator.dispatcher_finish(now - 2.0)
66
+ worker.join
67
+ NewRelic::Agent::BusyCalculator.harvest_busy
68
+
69
+ assert_equal 1, @instance_busy.call_count
70
+ # 3 + 6 = 9, or 90%
71
+ assert_in_delta 0.90, @instance_busy.total_call_time, 0.025
72
+
73
+ end
74
+ def test_dont_ignore_zero_counts
75
+ assert_equal 0, @instance_busy.call_count, "Problem with test--instance busy not starting off at zero."
76
+ NewRelic::Agent::BusyCalculator.harvest_busy
77
+ NewRelic::Agent::BusyCalculator.harvest_busy
78
+ NewRelic::Agent::BusyCalculator.harvest_busy
79
+ assert_equal 3, @instance_busy.call_count
80
+ end
81
+ end