dolores_rpm 3.2.0.2

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 (257) hide show
  1. data/CHANGELOG +559 -0
  2. data/LICENSE +64 -0
  3. data/README.rdoc +179 -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 +118 -0
  8. data/cert/oldsite.pem +28 -0
  9. data/cert/site.pem +27 -0
  10. data/dolores_rpm-3.3.4.fork.gem +0 -0
  11. data/install.rb +9 -0
  12. data/lib/conditional_vendored_dependency_detection.rb +3 -0
  13. data/lib/conditional_vendored_metric_parser.rb +5 -0
  14. data/lib/new_relic/agent/agent.rb +1311 -0
  15. data/lib/new_relic/agent/beacon_configuration.rb +110 -0
  16. data/lib/new_relic/agent/browser_monitoring.rb +102 -0
  17. data/lib/new_relic/agent/busy_calculator.rb +99 -0
  18. data/lib/new_relic/agent/chained_call.rb +13 -0
  19. data/lib/new_relic/agent/database.rb +203 -0
  20. data/lib/new_relic/agent/error_collector.rb +251 -0
  21. data/lib/new_relic/agent/instrumentation/active_merchant.rb +27 -0
  22. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +68 -0
  23. data/lib/new_relic/agent/instrumentation/authlogic.rb +19 -0
  24. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +424 -0
  25. data/lib/new_relic/agent/instrumentation/data_mapper.rb +57 -0
  26. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +52 -0
  27. data/lib/new_relic/agent/instrumentation/memcache.rb +80 -0
  28. data/lib/new_relic/agent/instrumentation/merb/controller.rb +41 -0
  29. data/lib/new_relic/agent/instrumentation/merb/errors.rb +29 -0
  30. data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +80 -0
  31. data/lib/new_relic/agent/instrumentation/metric_frame.rb +332 -0
  32. data/lib/new_relic/agent/instrumentation/net.rb +29 -0
  33. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +36 -0
  34. data/lib/new_relic/agent/instrumentation/queue_time.rb +210 -0
  35. data/lib/new_relic/agent/instrumentation/rack.rb +98 -0
  36. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +114 -0
  37. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +42 -0
  38. data/lib/new_relic/agent/instrumentation/rails/active_record_instrumentation.rb +115 -0
  39. data/lib/new_relic/agent/instrumentation/rails/errors.rb +42 -0
  40. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +118 -0
  41. data/lib/new_relic/agent/instrumentation/rails3/active_record_instrumentation.rb +122 -0
  42. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +37 -0
  43. data/lib/new_relic/agent/instrumentation/sinatra.rb +58 -0
  44. data/lib/new_relic/agent/instrumentation/sunspot.rb +29 -0
  45. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +21 -0
  46. data/lib/new_relic/agent/instrumentation.rb +9 -0
  47. data/lib/new_relic/agent/method_tracer.rb +528 -0
  48. data/lib/new_relic/agent/sampler.rb +50 -0
  49. data/lib/new_relic/agent/samplers/cpu_sampler.rb +58 -0
  50. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +40 -0
  51. data/lib/new_relic/agent/samplers/memory_sampler.rb +144 -0
  52. data/lib/new_relic/agent/samplers/object_sampler.rb +26 -0
  53. data/lib/new_relic/agent/shim_agent.rb +29 -0
  54. data/lib/new_relic/agent/sql_sampler.rb +267 -0
  55. data/lib/new_relic/agent/stats_engine/metric_stats.rb +187 -0
  56. data/lib/new_relic/agent/stats_engine/samplers.rb +95 -0
  57. data/lib/new_relic/agent/stats_engine/transactions.rb +208 -0
  58. data/lib/new_relic/agent/stats_engine.rb +25 -0
  59. data/lib/new_relic/agent/transaction_sample_builder.rb +101 -0
  60. data/lib/new_relic/agent/transaction_sampler.rb +397 -0
  61. data/lib/new_relic/agent/worker_loop.rb +89 -0
  62. data/lib/new_relic/agent.rb +454 -0
  63. data/lib/new_relic/collection_helper.rb +75 -0
  64. data/lib/new_relic/command.rb +85 -0
  65. data/lib/new_relic/commands/deployments.rb +105 -0
  66. data/lib/new_relic/commands/install.rb +80 -0
  67. data/lib/new_relic/control/class_methods.rb +53 -0
  68. data/lib/new_relic/control/configuration.rb +202 -0
  69. data/lib/new_relic/control/frameworks/external.rb +16 -0
  70. data/lib/new_relic/control/frameworks/merb.rb +31 -0
  71. data/lib/new_relic/control/frameworks/rails.rb +164 -0
  72. data/lib/new_relic/control/frameworks/rails3.rb +75 -0
  73. data/lib/new_relic/control/frameworks/ruby.rb +42 -0
  74. data/lib/new_relic/control/frameworks/sinatra.rb +20 -0
  75. data/lib/new_relic/control/frameworks.rb +10 -0
  76. data/lib/new_relic/control/instance_methods.rb +179 -0
  77. data/lib/new_relic/control/instrumentation.rb +100 -0
  78. data/lib/new_relic/control/logging_methods.rb +143 -0
  79. data/lib/new_relic/control/profiling.rb +25 -0
  80. data/lib/new_relic/control/server_methods.rb +114 -0
  81. data/lib/new_relic/control.rb +46 -0
  82. data/lib/new_relic/data_serialization.rb +157 -0
  83. data/lib/new_relic/delayed_job_injection.rb +46 -0
  84. data/lib/new_relic/language_support.rb +69 -0
  85. data/lib/new_relic/local_environment.rb +414 -0
  86. data/lib/new_relic/merbtasks.rb +6 -0
  87. data/lib/new_relic/metric_data.rb +51 -0
  88. data/lib/new_relic/metric_spec.rb +75 -0
  89. data/lib/new_relic/metrics.rb +9 -0
  90. data/lib/new_relic/noticed_error.rb +24 -0
  91. data/lib/new_relic/rack/browser_monitoring.rb +68 -0
  92. data/lib/new_relic/rack/developer_mode.rb +268 -0
  93. data/lib/new_relic/recipes.rb +73 -0
  94. data/lib/new_relic/stats.rb +388 -0
  95. data/lib/new_relic/timer_lib.rb +27 -0
  96. data/lib/new_relic/transaction_analysis/segment_summary.rb +49 -0
  97. data/lib/new_relic/transaction_analysis.rb +77 -0
  98. data/lib/new_relic/transaction_sample/composite_segment.rb +27 -0
  99. data/lib/new_relic/transaction_sample/fake_segment.rb +9 -0
  100. data/lib/new_relic/transaction_sample/segment.rb +201 -0
  101. data/lib/new_relic/transaction_sample/summary_segment.rb +21 -0
  102. data/lib/new_relic/transaction_sample.rb +245 -0
  103. data/lib/new_relic/url_rule.rb +14 -0
  104. data/lib/new_relic/version.rb +55 -0
  105. data/lib/newrelic_rpm.rb +49 -0
  106. data/lib/tasks/all.rb +4 -0
  107. data/lib/tasks/install.rake +7 -0
  108. data/lib/tasks/tests.rake +19 -0
  109. data/newrelic.yml +265 -0
  110. data/recipes/newrelic.rb +6 -0
  111. data/test/active_record_fixtures.rb +77 -0
  112. data/test/config/newrelic.yml +48 -0
  113. data/test/config/test_control.rb +48 -0
  114. data/test/new_relic/agent/agent/connect_test.rb +410 -0
  115. data/test/new_relic/agent/agent/start_test.rb +255 -0
  116. data/test/new_relic/agent/agent/start_worker_thread_test.rb +153 -0
  117. data/test/new_relic/agent/agent_test.rb +139 -0
  118. data/test/new_relic/agent/agent_test_controller.rb +77 -0
  119. data/test/new_relic/agent/agent_test_controller_test.rb +363 -0
  120. data/test/new_relic/agent/apdex_from_server_test.rb +9 -0
  121. data/test/new_relic/agent/beacon_configuration_test.rb +108 -0
  122. data/test/new_relic/agent/browser_monitoring_test.rb +278 -0
  123. data/test/new_relic/agent/busy_calculator_test.rb +81 -0
  124. data/test/new_relic/agent/database_test.rb +162 -0
  125. data/test/new_relic/agent/error_collector/notice_error_test.rb +257 -0
  126. data/test/new_relic/agent/error_collector_test.rb +175 -0
  127. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +538 -0
  128. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +36 -0
  129. data/test/new_relic/agent/instrumentation/instrumentation_test.rb +11 -0
  130. data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +172 -0
  131. data/test/new_relic/agent/instrumentation/metric_frame_test.rb +50 -0
  132. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +84 -0
  133. data/test/new_relic/agent/instrumentation/queue_time_test.rb +387 -0
  134. data/test/new_relic/agent/instrumentation/rack_test.rb +35 -0
  135. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +184 -0
  136. data/test/new_relic/agent/memcache_instrumentation_test.rb +143 -0
  137. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +164 -0
  138. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +234 -0
  139. data/test/new_relic/agent/method_tracer_test.rb +386 -0
  140. data/test/new_relic/agent/mock_scope_listener.rb +23 -0
  141. data/test/new_relic/agent/rpm_agent_test.rb +149 -0
  142. data/test/new_relic/agent/sampler_test.rb +19 -0
  143. data/test/new_relic/agent/shim_agent_test.rb +20 -0
  144. data/test/new_relic/agent/sql_sampler_test.rb +160 -0
  145. data/test/new_relic/agent/stats_engine/metric_stats/harvest_test.rb +150 -0
  146. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +82 -0
  147. data/test/new_relic/agent/stats_engine/samplers_test.rb +99 -0
  148. data/test/new_relic/agent/stats_engine_test.rb +185 -0
  149. data/test/new_relic/agent/transaction_sample_builder_test.rb +195 -0
  150. data/test/new_relic/agent/transaction_sampler_test.rb +955 -0
  151. data/test/new_relic/agent/worker_loop_test.rb +66 -0
  152. data/test/new_relic/agent_test.rb +175 -0
  153. data/test/new_relic/collection_helper_test.rb +149 -0
  154. data/test/new_relic/command/deployments_test.rb +68 -0
  155. data/test/new_relic/control/class_methods_test.rb +62 -0
  156. data/test/new_relic/control/configuration_test.rb +72 -0
  157. data/test/new_relic/control/logging_methods_test.rb +185 -0
  158. data/test/new_relic/control_test.rb +254 -0
  159. data/test/new_relic/data_serialization_test.rb +208 -0
  160. data/test/new_relic/delayed_job_injection_test.rb +16 -0
  161. data/test/new_relic/local_environment_test.rb +72 -0
  162. data/test/new_relic/metric_data_test.rb +125 -0
  163. data/test/new_relic/metric_spec_test.rb +95 -0
  164. data/test/new_relic/rack/all_test.rb +11 -0
  165. data/test/new_relic/rack/browser_monitoring_test.rb +84 -0
  166. data/test/new_relic/rack/developer_mode_helper_test.rb +141 -0
  167. data/test/new_relic/rack/developer_mode_test.rb +43 -0
  168. data/test/new_relic/stats_test.rb +426 -0
  169. data/test/new_relic/transaction_analysis/segment_summary_test.rb +91 -0
  170. data/test/new_relic/transaction_analysis_test.rb +121 -0
  171. data/test/new_relic/transaction_sample/composite_segment_test.rb +35 -0
  172. data/test/new_relic/transaction_sample/fake_segment_test.rb +17 -0
  173. data/test/new_relic/transaction_sample/segment_test.rb +389 -0
  174. data/test/new_relic/transaction_sample/summary_segment_test.rb +31 -0
  175. data/test/new_relic/transaction_sample_subtest_test.rb +56 -0
  176. data/test/new_relic/transaction_sample_test.rb +164 -0
  177. data/test/new_relic/version_number_test.rb +89 -0
  178. data/test/test_contexts.rb +29 -0
  179. data/test/test_helper.rb +154 -0
  180. data/ui/helpers/developer_mode_helper.rb +357 -0
  181. data/ui/helpers/google_pie_chart.rb +48 -0
  182. data/ui/views/layouts/newrelic_default.rhtml +47 -0
  183. data/ui/views/newrelic/_explain_plans.rhtml +27 -0
  184. data/ui/views/newrelic/_sample.rhtml +20 -0
  185. data/ui/views/newrelic/_segment.rhtml +28 -0
  186. data/ui/views/newrelic/_segment_limit_message.rhtml +1 -0
  187. data/ui/views/newrelic/_segment_row.rhtml +12 -0
  188. data/ui/views/newrelic/_show_sample_detail.rhtml +24 -0
  189. data/ui/views/newrelic/_show_sample_sql.rhtml +24 -0
  190. data/ui/views/newrelic/_show_sample_summary.rhtml +3 -0
  191. data/ui/views/newrelic/_sql_row.rhtml +16 -0
  192. data/ui/views/newrelic/_stack_trace.rhtml +15 -0
  193. data/ui/views/newrelic/_table.rhtml +12 -0
  194. data/ui/views/newrelic/explain_sql.rhtml +43 -0
  195. data/ui/views/newrelic/file/images/arrow-close.png +0 -0
  196. data/ui/views/newrelic/file/images/arrow-open.png +0 -0
  197. data/ui/views/newrelic/file/images/blue_bar.gif +0 -0
  198. data/ui/views/newrelic/file/images/file_icon.png +0 -0
  199. data/ui/views/newrelic/file/images/gray_bar.gif +0 -0
  200. data/ui/views/newrelic/file/images/new-relic-rpm-desktop.gif +0 -0
  201. data/ui/views/newrelic/file/images/new_relic_rpm_desktop.gif +0 -0
  202. data/ui/views/newrelic/file/images/textmate.png +0 -0
  203. data/ui/views/newrelic/file/javascript/jquery-1.4.2.js +6240 -0
  204. data/ui/views/newrelic/file/javascript/transaction_sample.js +120 -0
  205. data/ui/views/newrelic/file/stylesheets/style.css +490 -0
  206. data/ui/views/newrelic/index.rhtml +71 -0
  207. data/ui/views/newrelic/sample_not_found.rhtml +2 -0
  208. data/ui/views/newrelic/show_sample.rhtml +80 -0
  209. data/ui/views/newrelic/show_source.rhtml +3 -0
  210. data/ui/views/newrelic/threads.rhtml +53 -0
  211. data/vendor/gems/dependency_detection-0.0.1.build/LICENSE +5 -0
  212. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection/version.rb +3 -0
  213. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +62 -0
  214. data/vendor/gems/metric_parser-0.1.0.pre1/lib/metric_parser.rb +1 -0
  215. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/action_mailer.rb +14 -0
  216. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_merchant.rb +31 -0
  217. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_record.rb +33 -0
  218. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/apdex.rb +89 -0
  219. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/background_transaction.rb +7 -0
  220. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/client.rb +46 -0
  221. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller.rb +67 -0
  222. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_cpu.rb +43 -0
  223. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_ext.rb +17 -0
  224. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database.rb +48 -0
  225. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database_pool.rb +24 -0
  226. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net.rb +28 -0
  227. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net_parser.rb +17 -0
  228. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/errors.rb +11 -0
  229. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/external.rb +55 -0
  230. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/frontend.rb +40 -0
  231. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/gc.rb +20 -0
  232. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/hibernate_session.rb +7 -0
  233. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +31 -0
  234. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java_parser.rb +17 -0
  235. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp.rb +34 -0
  236. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp_tag.rb +7 -0
  237. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/mem_cache.rb +55 -0
  238. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/metric_parser.rb +122 -0
  239. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/orm.rb +27 -0
  240. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/other_transaction.rb +40 -0
  241. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet.rb +7 -0
  242. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_context_listener.rb +7 -0
  243. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_filter.rb +7 -0
  244. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr.rb +27 -0
  245. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr_request_handler.rb +15 -0
  246. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring.rb +54 -0
  247. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_controller.rb +6 -0
  248. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_view.rb +6 -0
  249. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_action.rb +20 -0
  250. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_result.rb +20 -0
  251. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/version.rb +5 -0
  252. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +70 -0
  253. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_frontend.rb +18 -0
  254. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_service.rb +14 -0
  255. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_transaction.rb +133 -0
  256. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser.rb +64 -0
  257. metadata +398 -0
@@ -0,0 +1,955 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
2
+
3
+ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
4
+
5
+ module MockGCStats
6
+
7
+ def time
8
+ return 0 if @@values.empty?
9
+ raise "too many calls" if @@index >= @@values.size
10
+ @@curtime ||= 0
11
+ @@curtime += (@@values[@@index] * 1e09).to_i
12
+ @@index += 1
13
+ @@curtime
14
+ end
15
+
16
+ def self.mock_values= array
17
+ @@values = array
18
+ @@index = 0
19
+ end
20
+
21
+ end
22
+
23
+ def setup
24
+ Thread::current[:record_sql] = nil
25
+ agent = NewRelic::Agent.instance
26
+ stats_engine = NewRelic::Agent::StatsEngine.new
27
+ agent.stubs(:stats_engine).returns(stats_engine)
28
+ @sampler = NewRelic::Agent::TransactionSampler.new
29
+ stats_engine.transaction_sampler = @sampler
30
+ end
31
+
32
+ def teardown
33
+ super
34
+ Thread.current[:transaction_sample_builder] = nil
35
+ end
36
+
37
+ def test_initialize
38
+ defaults = {
39
+ :samples => [],
40
+ :harvest_count => 0,
41
+ :max_samples => 100,
42
+ :random_sample => nil,
43
+ }
44
+ defaults.each do |variable, default_value|
45
+ assert_equal(default_value, @sampler.instance_variable_get('@' + variable.to_s))
46
+ end
47
+
48
+ segment_limit = @sampler.instance_variable_get('@segment_limit')
49
+ assert(segment_limit.is_a?(Numeric), "Segment limit should be numeric")
50
+ assert(segment_limit > 0, "Segment limit should be above zero")
51
+
52
+ stack_trace_threshold = @sampler.instance_variable_get('@stack_trace_threshold')
53
+ assert(stack_trace_threshold.is_a?((0.1).class), "Stack trace threshold should be a #{(0.1).class.inspect}, but is #{stack_trace_threshold.inspect}")
54
+ assert(stack_trace_threshold > 0.0, "Stack trace threshold should be above zero")
55
+
56
+ lock = @sampler.instance_variable_get('@samples_lock')
57
+ assert(lock.is_a?(Mutex), "Samples lock should be a mutex, is: #{lock.inspect}")
58
+ end
59
+
60
+ def test_configure
61
+ control = NewRelic::Control.instance
62
+ control.merge_options('transaction_tracer' => {'stack_trace_threshold' => 5.0, 'limit_segments' => 20, 'explain_threshold' => 4.0})
63
+ @sampler.configure!
64
+ assert_equal 20, @sampler.instance_variable_get('@segment_limit')
65
+ assert_equal 5.0, @sampler.instance_variable_get('@stack_trace_threshold')
66
+ assert_equal 4.0, @sampler.instance_variable_get('@explain_threshold')
67
+ end
68
+
69
+ def test_current_sample_id_default
70
+ builder = mock('builder')
71
+ builder.expects(:sample_id).returns(11111)
72
+ @sampler.expects(:builder).returns(builder)
73
+ assert_equal(11111, @sampler.current_sample_id)
74
+ end
75
+
76
+ def test_current_sample_id_no_builder
77
+ @sampler.expects(:builder).returns(nil)
78
+ assert_equal(nil, @sampler.current_sample_id)
79
+ end
80
+
81
+ def test_enable
82
+ assert_equal(nil, @sampler.instance_variable_get('@disabled'))
83
+ @sampler.enable
84
+ assert_equal(false, @sampler.instance_variable_get('@disabled'))
85
+ assert_equal(@sampler, NewRelic::Agent.instance.stats_engine.instance_variable_get('@transaction_sampler'))
86
+ end
87
+
88
+ def test_disable
89
+ assert_nil @sampler.instance_variable_get('@disabled')
90
+ @sampler.disable
91
+ assert @sampler.instance_variable_get('@disabled')
92
+ assert_nil NewRelic::Agent.instance.stats_engine.instance_variable_get('@transaction_sampler')
93
+ end
94
+
95
+ def test_sampling_rate_equals_default
96
+ @sampler.sampling_rate = 1
97
+ assert_equal(1, @sampler.instance_variable_get('@sampling_rate'))
98
+ # rand(1) is always zero, so we can be sure here
99
+ assert_equal(0, @sampler.instance_variable_get('@harvest_count'))
100
+ end
101
+
102
+ def test_sampling_rate_equals_with_a_float
103
+ @sampler.sampling_rate = 5.5
104
+ assert_equal(5, @sampler.instance_variable_get('@sampling_rate'))
105
+ harvest_count = @sampler.instance_variable_get('@harvest_count')
106
+ assert((0..4).include?(harvest_count), "should be in the range 0..4")
107
+ end
108
+
109
+ def test_notice_first_scope_push_default
110
+ @sampler.expects(:disabled).returns(false)
111
+ @sampler.expects(:start_builder).with(100.0)
112
+ @sampler.notice_first_scope_push(Time.at(100))
113
+ end
114
+
115
+ def test_notice_first_scope_push_disabled
116
+ @sampler.expects(:disabled).returns(true)
117
+ @sampler.expects(:start_builder).never
118
+ @sampler.notice_first_scope_push(Time.at(100))
119
+ end
120
+
121
+ def test_notice_push_scope_no_builder
122
+ @sampler.expects(:builder)
123
+ assert_equal(nil, @sampler.notice_push_scope('a scope'))
124
+ end
125
+
126
+ def test_notice_push_scope_with_builder
127
+ NewRelic::Control.instance.expects(:developer_mode?).returns(false)
128
+ builder = mock('builder')
129
+ builder.expects(:trace_entry).with('a scope', 100.0)
130
+ @sampler.expects(:builder).returns(builder).twice
131
+
132
+ @sampler.notice_push_scope('a scope', Time.at(100))
133
+ end
134
+
135
+ def test_notice_push_scope_in_dev_mode
136
+ NewRelic::Control.instance.expects(:developer_mode?).returns(true)
137
+
138
+ builder = mock('builder')
139
+ builder.expects(:trace_entry).with('a scope', 100.0)
140
+ @sampler.expects(:builder).returns(builder).twice
141
+ @sampler.expects(:capture_segment_trace)
142
+
143
+ @sampler.notice_push_scope('a scope', Time.at(100))
144
+ end
145
+
146
+ def test_scope_depth_no_builder
147
+ @sampler.expects(:builder).returns(nil)
148
+ assert_equal(0, @sampler.scope_depth, "should default to zero with no builder")
149
+ end
150
+
151
+ def test_scope_depth_with_builder
152
+ builder = mock('builder')
153
+ builder.expects(:scope_depth).returns('scope_depth')
154
+ @sampler.expects(:builder).returns(builder).twice
155
+
156
+ assert_equal('scope_depth', @sampler.scope_depth, "should delegate scope depth to the builder")
157
+ end
158
+
159
+ def test_notice_pop_scope_no_builder
160
+ @sampler.expects(:builder).returns(nil)
161
+ assert_equal(nil, @sampler.notice_pop_scope('a scope', Time.at(100)))
162
+ end
163
+
164
+ def test_notice_pop_scope_with_frozen_sample
165
+ builder = mock('builder')
166
+ sample = mock('sample')
167
+ builder.expects(:sample).returns(sample)
168
+ sample.expects(:frozen?).returns(true)
169
+ @sampler.expects(:builder).returns(builder).twice
170
+
171
+ assert_raise(RuntimeError) do
172
+ @sampler.notice_pop_scope('a scope', Time.at(100))
173
+ end
174
+ end
175
+
176
+ def test_notice_pop_scope_builder_delegation
177
+ builder = mock('builder')
178
+ builder.expects(:trace_exit).with('a scope', 100.0)
179
+ sample = mock('sample')
180
+ builder.expects(:sample).returns(sample)
181
+ sample.expects(:frozen?).returns(false)
182
+ @sampler.expects(:builder).returns(builder).times(3)
183
+
184
+ @sampler.notice_pop_scope('a scope', Time.at(100))
185
+ end
186
+
187
+ def test_notice_scope_empty_no_builder
188
+ @sampler.expects(:builder).returns(nil)
189
+ assert_equal(nil, @sampler.notice_scope_empty)
190
+ end
191
+
192
+ def test_notice_scope_empty_ignored_transaction
193
+ builder = mock('builder')
194
+ # the builder should be cached, so only called once
195
+ @sampler.expects(:builder).returns(builder).once
196
+
197
+ builder.expects(:finish_trace).with(100.0)
198
+
199
+ @sampler.expects(:clear_builder)
200
+
201
+ builder.expects(:ignored?).returns(true)
202
+
203
+ assert_equal(nil, @sampler.notice_scope_empty(Time.at(100)))
204
+ end
205
+
206
+ def test_notice_scope_empty_with_builder
207
+ builder = mock('builder')
208
+ # the builder should be cached, so only called once
209
+ @sampler.expects(:builder).returns(builder).once
210
+
211
+
212
+ builder.expects(:finish_trace).with(100.0)
213
+ @sampler.expects(:clear_builder)
214
+
215
+ builder.expects(:ignored?).returns(false)
216
+
217
+ sample = mock('sample')
218
+ builder.expects(:sample).returns(sample)
219
+ @sampler.expects(:store_sample).with(sample)
220
+
221
+ @sampler.notice_scope_empty(Time.at(100))
222
+
223
+ assert_equal(sample, @sampler.instance_variable_get('@last_sample'))
224
+ end
225
+
226
+ def test_store_random_sample_no_random_sampling
227
+ @sampler.instance_eval { @random_sampling = false }
228
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
229
+ @sampler.store_random_sample(mock('sample'))
230
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
231
+ end
232
+
233
+ def test_store_random_sample_random_sampling
234
+ @sampler.instance_eval { @random_sampling = true }
235
+ sample = mock('sample')
236
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
237
+ @sampler.store_random_sample(sample)
238
+ assert_equal(sample, @sampler.instance_variable_get('@random_sample'))
239
+ end
240
+
241
+ def test_store_sample_for_developer_mode_in_dev_mode
242
+ NewRelic::Control.instance.expects(:developer_mode?).returns(true)
243
+ sample = mock('sample')
244
+ @sampler.expects(:truncate_samples)
245
+ @sampler.store_sample_for_developer_mode(sample)
246
+ assert_equal([sample], @sampler.instance_variable_get('@samples'))
247
+ end
248
+
249
+ def test_store_sample_for_developer_mode_no_dev
250
+ NewRelic::Control.instance.expects(:developer_mode?).returns(false)
251
+ sample = mock('sample')
252
+ @sampler.store_sample_for_developer_mode(sample)
253
+ assert_equal([], @sampler.instance_variable_get('@samples'))
254
+ end
255
+
256
+ def test_store_slowest_sample_new_is_slowest
257
+ old_sample = mock('old_sample')
258
+ new_sample = mock('new_sample')
259
+ @sampler.instance_eval { @slowest_sample = old_sample }
260
+ @sampler.expects(:slowest_sample?).with(old_sample, new_sample).returns(true)
261
+
262
+ @sampler.store_slowest_sample(new_sample)
263
+
264
+ assert_equal(new_sample, @sampler.instance_variable_get('@slowest_sample'))
265
+ end
266
+
267
+
268
+ def test_store_slowest_sample_not_slowest
269
+ old_sample = mock('old_sample')
270
+ new_sample = mock('new_sample')
271
+ @sampler.instance_eval { @slowest_sample = old_sample }
272
+ @sampler.expects(:slowest_sample?).with(old_sample, new_sample).returns(false)
273
+
274
+ @sampler.store_slowest_sample(new_sample)
275
+
276
+ assert_equal(old_sample, @sampler.instance_variable_get('@slowest_sample'))
277
+ end
278
+
279
+ def test_slowest_sample_no_sample
280
+ old_sample = nil
281
+ new_sample = mock('new_sample')
282
+ assert_equal(true, @sampler.slowest_sample?(old_sample, new_sample))
283
+ end
284
+
285
+ def test_slowest_sample_faster_sample
286
+ old_sample = mock('old_sample')
287
+ new_sample = mock('new_sample')
288
+ old_sample.expects(:duration).returns(1.0)
289
+ new_sample.expects(:duration).returns(0.5)
290
+ assert_equal(false, @sampler.slowest_sample?(old_sample, new_sample))
291
+ end
292
+
293
+ def test_slowest_sample_slower_sample
294
+ old_sample = mock('old_sample')
295
+ new_sample = mock('new_sample')
296
+ old_sample.expects(:duration).returns(0.5)
297
+ new_sample.expects(:duration).returns(1.0)
298
+ assert_equal(true, @sampler.slowest_sample?(old_sample, new_sample))
299
+ end
300
+
301
+ def test_truncate_samples_no_samples
302
+ @sampler.instance_eval { @max_samples = 10 }
303
+ @sampler.instance_eval { @samples = [] }
304
+ @sampler.truncate_samples
305
+ assert_equal([], @sampler.instance_variable_get('@samples'))
306
+ end
307
+
308
+ def test_truncate_samples_equal_samples
309
+ @sampler.instance_eval { @max_samples = 2 }
310
+ @sampler.instance_eval { @samples = [1, 2] }
311
+ @sampler.truncate_samples
312
+ assert_equal([1, 2], @sampler.instance_variable_get('@samples'))
313
+ end
314
+
315
+ def test_truncate_samples_extra_samples
316
+ @sampler.instance_eval { @max_samples = 2 }
317
+ @sampler.instance_eval { @samples = [1, 2, 3] }
318
+ @sampler.truncate_samples
319
+ assert_equal([2, 3], @sampler.instance_variable_get('@samples'))
320
+ end
321
+
322
+ def test_notice_transaction_disabled
323
+ @sampler.expects(:disabled).returns(true)
324
+ @sampler.expects(:builder).never # since we're disabled
325
+ @sampler.notice_transaction('foo')
326
+ end
327
+
328
+ def test_notice_transaction_no_builder
329
+ @sampler.expects(:disabled).returns(false)
330
+ @sampler.expects(:builder).returns(nil).once
331
+ @sampler.notice_transaction('foo')
332
+ end
333
+
334
+ def test_notice_transaction_with_builder
335
+ builder = mock('builder')
336
+ builder.expects(:set_transaction_info).with('a path', 'a uri', {:some => :params})
337
+ @sampler.expects(:builder).returns(builder).twice
338
+ @sampler.expects(:disabled).returns(false)
339
+ @sampler.notice_transaction('a path', 'a uri', {:some => :params})
340
+ end
341
+
342
+ def test_ignore_transaction_no_builder
343
+ @sampler.expects(:builder).returns(nil).once
344
+ @sampler.ignore_transaction
345
+ end
346
+
347
+ def test_ignore_transaction_with_builder
348
+ builder = mock('builder')
349
+ builder.expects(:ignore_transaction)
350
+ @sampler.expects(:builder).returns(builder).twice
351
+ @sampler.ignore_transaction
352
+ end
353
+
354
+ def test_notice_profile_no_builder
355
+ @sampler.expects(:builder).returns(nil).once
356
+ @sampler.notice_profile(nil)
357
+ end
358
+
359
+ def test_notice_profile_with_builder
360
+ profile = mock('profile')
361
+ builder = mock('builder')
362
+ @sampler.expects(:builder).returns(builder).twice
363
+ builder.expects(:set_profile).with(profile)
364
+
365
+ @sampler.notice_profile(profile)
366
+ end
367
+
368
+ def test_notice_transaction_cpu_time_no_builder
369
+ @sampler.expects(:builder).returns(nil).once
370
+ @sampler.notice_transaction_cpu_time(0.0)
371
+ end
372
+
373
+ def test_notice_transaction_cpu_time_with_builder
374
+ cpu_time = mock('cpu_time')
375
+ builder = mock('builder')
376
+ @sampler.expects(:builder).returns(builder).twice
377
+ builder.expects(:set_transaction_cpu_time).with(cpu_time)
378
+
379
+ @sampler.notice_transaction_cpu_time(cpu_time)
380
+ end
381
+
382
+ def test_notice_extra_data_no_builder
383
+ @sampler.expects(:builder).returns(nil).once
384
+ @sampler.send(:notice_extra_data, nil, nil, nil)
385
+ end
386
+
387
+ def test_notice_extra_data_no_segment
388
+ builder = mock('builder')
389
+ @sampler.expects(:builder).returns(builder).twice
390
+ builder.expects(:current_segment).returns(nil)
391
+ @sampler.send(:notice_extra_data, nil, nil, nil)
392
+ end
393
+
394
+ def test_notice_extra_data_with_segment_no_old_message_no_config_key
395
+ key = :a_key
396
+ builder = mock('builder')
397
+ segment = mock('segment')
398
+ @sampler.expects(:builder).returns(builder).twice
399
+ builder.expects(:current_segment).returns(segment)
400
+ segment.expects(:[]).with(key).returns(nil)
401
+ @sampler.expects(:append_new_message).with(nil, 'a message').returns('a message')
402
+ @sampler.expects(:truncate_message).with('a message').returns('truncated_message')
403
+ segment.expects(:[]=).with(key, 'truncated_message')
404
+ @sampler.expects(:append_backtrace).with(segment, 1.0)
405
+ @sampler.send(:notice_extra_data, 'a message', 1.0, key)
406
+ end
407
+
408
+ def test_truncate_message_short_message
409
+ message = 'a message'
410
+ assert_equal(message, @sampler.truncate_message(message))
411
+ end
412
+
413
+ def test_truncate_message_long_message
414
+ message = 'a' * 16384
415
+ truncated_message = @sampler.truncate_message(message)
416
+ assert_equal(16384, truncated_message.length)
417
+ assert_equal('a' * 16381 + '...', truncated_message)
418
+ end
419
+
420
+ def test_append_new_message_no_old_message
421
+ old_message = nil
422
+ new_message = 'a message'
423
+ assert_equal(new_message, @sampler.append_new_message(old_message, new_message))
424
+ end
425
+
426
+ def test_append_new_message_with_old_message
427
+ old_message = 'old message'
428
+ new_message = ' a message'
429
+ assert_equal("old message;\n a message", @sampler.append_new_message(old_message, new_message))
430
+ end
431
+
432
+ def test_append_backtrace_under_duration
433
+ @sampler.instance_eval { @stack_trace_threshold = 2.0 }
434
+ segment = mock('segment')
435
+ segment.expects(:[]=).with(:backtrace, any_parameters).never
436
+ @sampler.append_backtrace(mock('segment'), 1.0)
437
+ end
438
+
439
+ def test_append_backtrace_over_duration
440
+ @sampler.instance_eval { @stack_trace_threshold = 2.0 }
441
+ segment = mock('segment')
442
+ # note the mocha expectation matcher - you can't hardcode a
443
+ # backtrace so we match on any string, which should be okay.
444
+ segment.expects(:[]=).with(:backtrace, instance_of(String))
445
+ @sampler.append_backtrace(segment, 2.5)
446
+ end
447
+
448
+ def test_notice_sql_recording_sql
449
+ Thread.current[:record_sql] = true
450
+ @sampler.expects(:notice_extra_data).with('some sql', 1.0, :sql, 'a config', :connection_config)
451
+ @sampler.notice_sql('some sql', 'a config', 1.0)
452
+ end
453
+
454
+ def test_notice_sql_not_recording
455
+ Thread.current[:record_sql] = false
456
+ @sampler.expects(:notice_extra_data).with('some sql', 1.0, :sql, 'a config', :connection_config).never # <--- important
457
+ @sampler.notice_sql('some sql', 'a config', 1.0)
458
+ end
459
+
460
+ def test_notice_nosql
461
+ @sampler.expects(:notice_extra_data).with('a key', 1.0, :key)
462
+ @sampler.notice_nosql('a key', 1.0)
463
+ end
464
+
465
+ def test_harvest_when_disabled
466
+ @sampler.expects(:disabled).returns(true)
467
+ assert_equal([], @sampler.harvest)
468
+ end
469
+
470
+ def test_harvest_defaults
471
+ # making sure the sampler clears out the old samples
472
+ @sampler.instance_eval do
473
+ @slowest_sample = 'a sample'
474
+ @random_sample = 'a sample'
475
+ @last_sample = 'a sample'
476
+ end
477
+
478
+ @sampler.expects(:disabled).returns(false)
479
+ @sampler.expects(:add_samples_to).with([], 2.0).returns([])
480
+
481
+ assert_equal([], @sampler.harvest)
482
+
483
+ # make sure the samples have been cleared
484
+ assert_equal(nil, @sampler.instance_variable_get('@slowest_sample'))
485
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
486
+ assert_equal(nil, @sampler.instance_variable_get('@last_sample'))
487
+ end
488
+
489
+ def test_harvest_with_previous_samples
490
+ sample = mock('sample')
491
+ @sampler.expects(:disabled).returns(false)
492
+ @sampler.expects(:add_samples_to).with([sample], 2.0).returns([sample])
493
+ @sampler.instance_eval { @segment_limit = 2000 }
494
+ sample.expects(:truncate).with(2000)
495
+ assert_equal([sample], @sampler.harvest([sample]))
496
+ end
497
+
498
+ def test_add_random_sample_to_not_random_sampling
499
+ @sampler.instance_eval { @random_sampling = false }
500
+ result = []
501
+ @sampler.add_random_sample_to(result)
502
+ assert_equal([], result, "should not add anything to the array if we are not random sampling")
503
+ end
504
+
505
+ def test_add_random_sample_to_no_random_sample
506
+ @sampler.instance_eval { @random_sampling = true }
507
+ @sampler.instance_eval {
508
+ @harvest_count = 1
509
+ @sampling_rate = 2
510
+ @random_sample = nil
511
+ }
512
+ result = []
513
+ @sampler.add_random_sample_to(result)
514
+ assert_equal([], result, "should not add sample to the array when it is nil")
515
+ end
516
+
517
+ def test_add_random_sample_to_not_active
518
+ @sampler.instance_eval { @random_sampling = true }
519
+ sample = mock('sample')
520
+ @sampler.instance_eval {
521
+ @harvest_count = 4
522
+ @sampling_rate = 40 # 4 % 40 = 4, so the sample should not be added
523
+ @random_sample = sample
524
+ }
525
+ result = []
526
+ @sampler.add_random_sample_to(result)
527
+ assert_equal([], result, "should not add samples to the array when harvest count is not moduli sampling rate")
528
+ end
529
+
530
+ def test_add_random_sample_to_duplicate
531
+ @sampler.instance_eval { @random_sampling = true }
532
+ sample = mock('sample')
533
+ @sampler.instance_eval {
534
+ @harvest_count = 1
535
+ @sampling_rate = 2
536
+ @random_sample = sample
537
+ }
538
+ result = [sample]
539
+ @sampler.add_random_sample_to(result)
540
+ assert_equal([sample], result, "should not add duplicate samples to the array")
541
+ end
542
+
543
+ def test_add_random_sample_to_activated
544
+ @sampler.instance_eval { @random_sampling = true }
545
+ sample = mock('sample')
546
+ @sampler.instance_eval {
547
+ @harvest_count = 3
548
+ @sampling_rate = 1
549
+ @random_sample = sample
550
+ }
551
+ result = []
552
+ @sampler.add_random_sample_to(result)
553
+ assert_equal([sample], result, "should add the random sample to the array")
554
+ end
555
+
556
+ def test_add_random_sample_to_sampling_rate_zero
557
+ @sampler.instance_eval { @random_sampling = true }
558
+ sample = mock('sample')
559
+ @sampler.instance_eval {
560
+ @harvest_count = 3
561
+ @sampling_rate = 0
562
+ @random_sample = sample
563
+ }
564
+ result = []
565
+ @sampler.add_random_sample_to(result)
566
+ assert_equal([], result, "should not add the sample to the array")
567
+ end
568
+
569
+
570
+ def test_add_samples_to_no_data
571
+ result = []
572
+ slow_threshold = 2.0
573
+ @sampler.instance_eval { @slowest_sample = nil }
574
+ @sampler.expects(:add_random_sample_to).with([])
575
+ assert_equal([], @sampler.add_samples_to(result, slow_threshold))
576
+ end
577
+
578
+ def test_add_samples_to_one_result
579
+ sample = mock('sample')
580
+ sample.expects(:duration).returns(1).at_least_once
581
+ result = [sample]
582
+ slow_threshold = 2.0
583
+ @sampler.instance_eval { @slowest_sample = nil }
584
+ @sampler.expects(:add_random_sample_to).with([sample])
585
+ assert_equal([sample], @sampler.add_samples_to(result, slow_threshold))
586
+ end
587
+
588
+ def test_add_samples_to_adding_slowest
589
+ sample = mock('sample')
590
+ sample.expects(:duration).returns(2.5).at_least_once
591
+ result = []
592
+ slow_threshold = 2.0
593
+ @sampler.instance_eval { @slowest_sample = sample }
594
+ @sampler.expects(:add_random_sample_to).with([sample])
595
+ assert_equal([sample], @sampler.add_samples_to(result, slow_threshold))
596
+ end
597
+
598
+ def test_add_samples_to_under_threshold
599
+ result = []
600
+ slow_threshold = 2.0
601
+ sample = mock('sample')
602
+ sample.expects(:duration).returns(1.0).at_least_once
603
+ @sampler.instance_eval { @slowest_sample = sample }
604
+ @sampler.expects(:add_random_sample_to).with([])
605
+ assert_equal([], @sampler.add_samples_to(result, slow_threshold))
606
+ end
607
+
608
+ def test_add_samples_to_two_sample_enter_one_sample_leave
609
+ slower_sample = mock('slower')
610
+ slower_sample.expects(:duration).returns(10.0).at_least_once
611
+ faster_sample = mock('faster')
612
+ faster_sample.expects(:duration).returns(5.0).at_least_once
613
+ result = [faster_sample]
614
+ slow_threshold = 2.0
615
+ @sampler.instance_eval { @slowest_sample = slower_sample }
616
+ @sampler.expects(:add_random_sample_to).with([slower_sample])
617
+ assert_equal([slower_sample], @sampler.add_samples_to(result, slow_threshold))
618
+ end
619
+
620
+ def test_add_samples_to_keep_older_slower_sample
621
+ slower_sample = mock('slower')
622
+ slower_sample.expects(:duration).returns(10.0).at_least_once
623
+ faster_sample = mock('faster')
624
+ faster_sample.expects(:duration).returns(5.0).at_least_once
625
+ result = [slower_sample]
626
+ slow_threshold = 2.0
627
+ @sampler.instance_eval { @slowest_sample = faster_sample }
628
+ @sampler.expects(:add_random_sample_to).with([slower_sample])
629
+ assert_equal([slower_sample], @sampler.add_samples_to(result, slow_threshold))
630
+ end
631
+
632
+ def test_start_builder_default
633
+ Thread.current[:record_tt] = true
634
+ @sampler.expects(:disabled).returns(false)
635
+ NewRelic::Agent.expects(:is_execution_traced?).returns(true)
636
+ @sampler.send(:start_builder)
637
+ assert(Thread.current[:transaction_sample_builder].is_a?(NewRelic::Agent::TransactionSampleBuilder), "should set up a new builder by default")
638
+ end
639
+
640
+ def test_start_builder_disabled
641
+ Thread.current[:transaction_sample_builder] = 'not nil.'
642
+ @sampler.expects(:disabled).returns(true)
643
+ @sampler.send(:start_builder)
644
+ assert_equal(nil, Thread.current[:transaction_sample_builder], "should clear the transaction builder when disabled")
645
+ end
646
+
647
+ def test_start_builder_dont_replace_existing_builder
648
+ fake_builder = mock('transaction sample builder')
649
+ Thread.current[:transaction_sample_builder] = fake_builder
650
+ @sampler.expects(:disabled).returns(false)
651
+ @sampler.send(:start_builder)
652
+ assert_equal(fake_builder, Thread.current[:transaction_sample_builder], "should not overwrite an existing transaction sample builder")
653
+ Thread.current[:transaction_sample_builder] = nil
654
+ end
655
+
656
+ def test_builder
657
+ Thread.current[:transaction_sample_builder] = 'shamalamadingdong, brother.'
658
+ assert_equal('shamalamadingdong, brother.', @sampler.send(:builder), 'should return the value from the thread local variable')
659
+ Thread.current[:transaction_sample_builder] = nil
660
+ end
661
+
662
+ def test_clear_builder
663
+ Thread.current[:transaction_sample_builder] = 'shamalamadingdong, brother.'
664
+ assert_equal(nil, @sampler.send(:clear_builder), 'should clear the thread local variable')
665
+ end
666
+
667
+ # Tests below this line are functional tests for the sampler, not
668
+ # unit tests per se - some overlap with the tests above, but
669
+ # generally usefully so
670
+
671
+ def test_multiple_samples
672
+
673
+ run_sample_trace
674
+ run_sample_trace
675
+ run_sample_trace
676
+ run_sample_trace
677
+
678
+ samples = @sampler.samples
679
+ assert_equal 4, samples.length
680
+ assert_equal "a", samples.first.root_segment.called_segments[0].metric_name
681
+ assert_equal "a", samples.last.root_segment.called_segments[0].metric_name
682
+ end
683
+
684
+ def test_sample_tree
685
+ assert_equal 0, @sampler.scope_depth
686
+
687
+ @sampler.notice_first_scope_push Time.now.to_f
688
+ @sampler.notice_transaction "/path", nil, {}
689
+ @sampler.notice_push_scope "a"
690
+
691
+ @sampler.notice_push_scope "b"
692
+ @sampler.notice_pop_scope "b"
693
+
694
+ @sampler.notice_push_scope "c"
695
+ @sampler.notice_push_scope "d"
696
+ @sampler.notice_pop_scope "d"
697
+ @sampler.notice_pop_scope "c"
698
+
699
+ @sampler.notice_pop_scope "a"
700
+ @sampler.notice_scope_empty
701
+ sample = @sampler.harvest([],0.0).first
702
+ assert_equal "ROOT{a{b,c{d}}}", sample.to_s_compact
703
+
704
+ end
705
+
706
+ def test_sample__gc_stats
707
+ GC.extend MockGCStats
708
+ # These are effectively Garbage Collects, detected each time GC.time is
709
+ # called by the transaction sampler. One time value in seconds for each call.
710
+ MockGCStats.mock_values = [0,0,0,1,0,0,1,0,0,0,0,0,0,0,0]
711
+ assert_equal 0, @sampler.scope_depth
712
+
713
+ @sampler.notice_first_scope_push Time.now.to_f
714
+ @sampler.notice_transaction "/path", nil, {}
715
+ @sampler.notice_push_scope "a"
716
+
717
+ @sampler.notice_push_scope "b"
718
+ @sampler.notice_pop_scope "b"
719
+
720
+ @sampler.notice_push_scope "c"
721
+ @sampler.notice_push_scope "d"
722
+ @sampler.notice_pop_scope "d"
723
+ @sampler.notice_pop_scope "c"
724
+
725
+ @sampler.notice_pop_scope "a"
726
+ @sampler.notice_scope_empty
727
+
728
+ sample = @sampler.harvest([],0.0).first
729
+ assert_equal "ROOT{a{b,c{d}}}", sample.to_s_compact
730
+ ensure
731
+ MockGCStats.mock_values = []
732
+ end
733
+
734
+ def test_sample_id
735
+ run_sample_trace do
736
+ assert((@sampler.current_sample_id && @sampler.current_sample_id != 0), @sampler.current_sample_id.to_s + ' should not be zero')
737
+ end
738
+ end
739
+
740
+
741
+ # NB this test occasionally fails due to a GC during one of the
742
+ # sample traces, for example. It's unfortunate, but we can't
743
+ # reliably turn off GC on all versions of ruby under test
744
+ def test_harvest_slowest
745
+
746
+ run_sample_trace
747
+ run_sample_trace
748
+ run_sample_trace { sleep 0.1 }
749
+ run_sample_trace
750
+ run_sample_trace
751
+
752
+ slowest = @sampler.harvest(nil, 0)[0]
753
+ assert((slowest.duration >= 0.09), "expected sample duration >= 0.09, but was: #{slowest.duration.inspect}")
754
+ # this assert is here to make sure the test remains valid
755
+ assert((slowest.duration <= 0.15), "expected sample duration <= 0.15, but was: #{slowest.duration.inspect}")
756
+
757
+
758
+ run_sample_trace { sleep 0.0001 }
759
+ not_as_slow = @sampler.harvest(slowest, 0)[0]
760
+ assert((not_as_slow == slowest), "Should re-harvest the same transaction since it should be slower than the new transaction - expected #{slowest.inspect} but got #{not_as_slow.inspect}")
761
+
762
+ run_sample_trace { sleep 0.16 }
763
+ new_slowest = @sampler.harvest(slowest, 0)[0]
764
+ assert((new_slowest != slowest), "Should not harvest the same trace since the new one should be slower")
765
+ assert((new_slowest.duration >= 0.15), "Slowest duration must be >= 0.15, but was: #{new_slowest.duration.inspect}")
766
+ end
767
+
768
+
769
+ def test_prepare_to_send
770
+
771
+ run_sample_trace { sleep 0.002 }
772
+ sample = @sampler.harvest(nil, 0)[0]
773
+
774
+ ready_to_send = sample.prepare_to_send
775
+ assert sample.duration == ready_to_send.duration
776
+
777
+ assert ready_to_send.start_time.is_a?(Time)
778
+ end
779
+
780
+ def test_multithread
781
+ threads = []
782
+
783
+ 5.times do
784
+ t = Thread.new(@sampler) do |the_sampler|
785
+ @sampler = the_sampler
786
+ 10.times do
787
+ run_sample_trace { sleep 0.0001 }
788
+ end
789
+ end
790
+
791
+ threads << t
792
+ end
793
+ threads.each {|t| t.join }
794
+ end
795
+
796
+ def test_sample_with_parallel_paths
797
+
798
+ assert_equal 0, @sampler.scope_depth
799
+
800
+ @sampler.notice_first_scope_push Time.now.to_f
801
+ @sampler.notice_transaction "/path", nil, {}
802
+ @sampler.notice_push_scope "a"
803
+
804
+ assert_equal 1, @sampler.scope_depth
805
+
806
+ @sampler.notice_pop_scope "a"
807
+ @sampler.notice_scope_empty
808
+
809
+ assert_equal 0, @sampler.scope_depth
810
+
811
+ @sampler.notice_first_scope_push Time.now.to_f
812
+ @sampler.notice_transaction "/path", nil, {}
813
+ @sampler.notice_push_scope "a"
814
+ @sampler.notice_pop_scope "a"
815
+ @sampler.notice_scope_empty
816
+
817
+ assert_equal 0, @sampler.scope_depth
818
+ sample = @sampler.harvest(nil, 0.0).first
819
+ assert_equal "ROOT{a}", sample.to_s_compact
820
+ end
821
+
822
+ def test_double_scope_stack_empty
823
+
824
+ @sampler.notice_first_scope_push Time.now.to_f
825
+ @sampler.notice_transaction "/path", nil, {}
826
+ @sampler.notice_push_scope "a"
827
+ @sampler.notice_pop_scope "a"
828
+ @sampler.notice_scope_empty
829
+ @sampler.notice_scope_empty
830
+ @sampler.notice_scope_empty
831
+ @sampler.notice_scope_empty
832
+
833
+ assert_not_nil @sampler.harvest(nil, 0)[0]
834
+ end
835
+
836
+
837
+ def test_record_sql_off
838
+
839
+ @sampler.notice_first_scope_push Time.now.to_f
840
+
841
+ Thread::current[:record_sql] = false
842
+
843
+ @sampler.notice_sql("test", nil, 0)
844
+
845
+ segment = @sampler.send(:builder).current_segment
846
+
847
+ assert_nil segment[:sql]
848
+ end
849
+
850
+ def test_stack_trace__sql
851
+ @sampler.stack_trace_threshold = 0
852
+
853
+ @sampler.notice_first_scope_push Time.now.to_f
854
+
855
+ @sampler.notice_sql("test", nil, 1)
856
+
857
+ segment = @sampler.send(:builder).current_segment
858
+
859
+ assert segment[:sql]
860
+ assert segment[:backtrace]
861
+ end
862
+ def test_stack_trace__scope
863
+
864
+ @sampler.stack_trace_threshold = 0
865
+ t = Time.now
866
+ @sampler.notice_first_scope_push t.to_f
867
+ @sampler.notice_push_scope 'Bill', (t+1).to_f
868
+
869
+ segment = @sampler.send(:builder).current_segment
870
+ assert segment[:backtrace]
871
+ end
872
+
873
+ def test_nil_stacktrace
874
+
875
+ @sampler.stack_trace_threshold = 2
876
+
877
+ @sampler.notice_first_scope_push Time.now.to_f
878
+
879
+ @sampler.notice_sql("test", nil, 1)
880
+
881
+ segment = @sampler.send(:builder).current_segment
882
+
883
+ assert segment[:sql]
884
+ assert_nil segment[:backtrace]
885
+ end
886
+
887
+ def test_big_sql
888
+
889
+ @sampler.notice_first_scope_push Time.now.to_f
890
+
891
+ sql = "SADJKHASDHASD KAJSDH ASKDH ASKDHASDK JASHD KASJDH ASKDJHSAKDJHAS DKJHSADKJSAH DKJASHD SAKJDH SAKDJHS"
892
+
893
+ len = 0
894
+ while len <= 16384
895
+ @sampler.notice_sql(sql, nil, 0)
896
+ len += sql.length
897
+ end
898
+
899
+ segment = @sampler.send(:builder).current_segment
900
+
901
+ sql = segment[:sql]
902
+
903
+ assert sql.length <= 16384
904
+ end
905
+
906
+
907
+ def test_segment_obfuscated
908
+
909
+ @sampler.notice_first_scope_push Time.now.to_f
910
+ @sampler.notice_push_scope "foo"
911
+
912
+ orig_sql = "SELECT * from Jim where id=66"
913
+
914
+ @sampler.notice_sql(orig_sql, nil, 0)
915
+
916
+ segment = @sampler.send(:builder).current_segment
917
+
918
+ assert_equal orig_sql, segment[:sql]
919
+ assert_equal "SELECT * from Jim where id=?", segment.obfuscated_sql
920
+ @sampler.notice_pop_scope "foo"
921
+ end
922
+
923
+
924
+ def test_param_capture
925
+ [true, false].each do |capture|
926
+ NewRelic::Control.instance.stubs(:capture_params).returns(capture)
927
+ @sampler.notice_first_scope_push Time.now.to_f
928
+ @sampler.notice_transaction('/path', nil, {:param => 'hi'})
929
+ @sampler.notice_scope_empty
930
+
931
+ tt = @sampler.harvest(nil,0)[0]
932
+
933
+ assert_equal (capture) ? 1 : 0, tt.params[:request_params].length
934
+ end
935
+ end
936
+
937
+
938
+ private
939
+ def run_sample_trace(&proc)
940
+ @sampler.notice_first_scope_push Time.now.to_f
941
+ @sampler.notice_transaction '/path', nil, {}
942
+ @sampler.notice_push_scope "a"
943
+ @sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'wheat'", nil, 0)
944
+ @sampler.notice_push_scope "ab"
945
+ @sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'white'", nil, 0)
946
+ proc.call if proc
947
+ @sampler.notice_pop_scope "ab"
948
+ @sampler.notice_push_scope "lew"
949
+ @sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'french'", nil, 0)
950
+ @sampler.notice_pop_scope "lew"
951
+ @sampler.notice_pop_scope "a"
952
+ @sampler.notice_scope_empty
953
+ end
954
+
955
+ end