newrelic_rpm 3.6.6.147 → 3.6.7.152

Sign up to get free protection for your applications and to get access to all the features.
Files changed (265) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gitignore +0 -1
  3. data/CHANGELOG +55 -17
  4. data/Guardfile +7 -0
  5. data/Rakefile +6 -0
  6. data/bin/mongrel_rpm +33 -0
  7. data/bin/newrelic +13 -0
  8. data/bin/newrelic_cmd +5 -0
  9. data/bin/nrdebug +273 -0
  10. data/install.rb +3 -3
  11. data/lib/new_relic/agent.rb +4 -6
  12. data/lib/new_relic/agent/agent.rb +76 -72
  13. data/lib/new_relic/agent/autostart.rb +18 -5
  14. data/lib/new_relic/agent/browser_monitoring.rb +41 -35
  15. data/lib/new_relic/agent/browser_token.rb +38 -0
  16. data/lib/new_relic/agent/busy_calculator.rb +7 -5
  17. data/lib/new_relic/agent/commands/agent_command.rb +19 -0
  18. data/lib/new_relic/agent/commands/agent_command_router.rb +88 -0
  19. data/lib/new_relic/agent/commands/thread_profiler.rb +80 -0
  20. data/lib/new_relic/agent/configuration/default_source.rb +700 -0
  21. data/lib/new_relic/agent/configuration/environment_source.rb +83 -30
  22. data/lib/new_relic/agent/configuration/manager.rb +8 -8
  23. data/lib/new_relic/agent/configuration/mask_defaults.rb +2 -2
  24. data/lib/new_relic/agent/cross_app_monitor.rb +10 -21
  25. data/lib/new_relic/agent/cross_app_tracing.rb +3 -3
  26. data/lib/new_relic/agent/error_collector.rb +7 -10
  27. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +1 -1
  28. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +5 -1
  29. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +5 -1
  30. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +5 -1
  31. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +5 -12
  33. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +4 -0
  34. data/lib/new_relic/agent/instrumentation/{rails4/active_record.rb → active_record_4.rb} +1 -1
  35. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +11 -11
  36. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -6
  37. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +12 -6
  38. data/lib/new_relic/agent/instrumentation/curb.rb +11 -2
  39. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +1 -3
  40. data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +11 -2
  41. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +13 -4
  42. data/lib/new_relic/agent/instrumentation/puma.rb +2 -1
  43. data/lib/new_relic/agent/instrumentation/rack.rb +15 -17
  44. data/lib/new_relic/agent/method_tracer.rb +181 -191
  45. data/lib/new_relic/agent/new_relic_service.rb +16 -14
  46. data/lib/new_relic/agent/pipe_channel_manager.rb +1 -1
  47. data/lib/new_relic/agent/request_sampler.rb +32 -165
  48. data/lib/new_relic/agent/sampled_buffer.rb +79 -0
  49. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +1 -8
  50. data/lib/new_relic/agent/sql_sampler.rb +3 -3
  51. data/lib/new_relic/agent/stats_engine.rb +1 -1
  52. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +1 -1
  53. data/lib/new_relic/agent/stats_engine/metric_stats.rb +2 -3
  54. data/lib/new_relic/agent/stats_engine/transactions.rb +2 -22
  55. data/lib/new_relic/agent/threading/agent_thread.rb +41 -0
  56. data/lib/new_relic/agent/threading/backtrace_node.rb +71 -0
  57. data/lib/new_relic/agent/threading/thread_profile.rb +172 -0
  58. data/lib/new_relic/agent/transaction.rb +16 -4
  59. data/lib/new_relic/agent/transaction_sample_builder.rb +13 -3
  60. data/lib/new_relic/agent/transaction_sampler.rb +5 -8
  61. data/lib/new_relic/agent/transaction_state.rb +166 -0
  62. data/lib/new_relic/agent/transaction_timings.rb +53 -0
  63. data/lib/new_relic/cli/command.rb +91 -0
  64. data/lib/new_relic/{commands → cli}/deployments.rb +13 -9
  65. data/lib/new_relic/{commands → cli}/install.rb +2 -2
  66. data/lib/new_relic/control/frameworks/rails.rb +1 -8
  67. data/lib/new_relic/control/instance_methods.rb +1 -2
  68. data/lib/new_relic/helper.rb +9 -0
  69. data/lib/new_relic/local_environment.rb +16 -63
  70. data/lib/new_relic/rack/browser_monitoring.rb +8 -5
  71. data/lib/new_relic/recipes.rb +44 -31
  72. data/lib/new_relic/transaction_sample.rb +6 -2
  73. data/lib/new_relic/version.rb +1 -1
  74. data/lib/tasks/install.rake +21 -1
  75. data/newrelic_rpm.gemspec +5 -1
  76. data/test/agent_helper.rb +4 -9
  77. data/test/environments/.gitignore +16 -0
  78. data/test/environments/lib/environments/runner.rb +104 -0
  79. data/test/environments/norails/Gemfile +11 -0
  80. data/test/environments/norails/Rakefile +9 -0
  81. data/test/environments/rails21/Gemfile +24 -0
  82. data/test/environments/rails21/Rakefile +12 -0
  83. data/test/environments/rails21/app/controllers/application.rb +20 -0
  84. data/test/environments/rails21/config/boot.rb +113 -0
  85. data/test/environments/rails21/config/database.yml +31 -0
  86. data/test/environments/rails21/config/environment.rb +28 -0
  87. data/test/environments/rails21/config/environments/development.rb +16 -0
  88. data/test/environments/rails21/config/environments/production.rb +8 -0
  89. data/test/environments/rails21/config/environments/test.rb +10 -0
  90. data/test/environments/rails21/config/routes.rb +5 -0
  91. data/test/environments/rails21/db/schema.rb +5 -0
  92. data/test/environments/rails22/Gemfile +29 -0
  93. data/test/environments/rails22/Rakefile +12 -0
  94. data/test/environments/rails22/app/controllers/application.rb +20 -0
  95. data/test/environments/rails22/config/boot.rb +113 -0
  96. data/test/environments/rails22/config/database.yml +31 -0
  97. data/test/environments/rails22/config/environment.rb +27 -0
  98. data/test/environments/rails22/config/environments/development.rb +16 -0
  99. data/test/environments/rails22/config/environments/production.rb +8 -0
  100. data/test/environments/rails22/config/environments/test.rb +10 -0
  101. data/test/environments/rails22/config/routes.rb +5 -0
  102. data/test/environments/rails22/db/schema.rb +5 -0
  103. data/test/environments/rails23/Gemfile +22 -0
  104. data/test/environments/rails23/Rakefile +12 -0
  105. data/test/environments/rails23/app/controllers/application.rb +20 -0
  106. data/test/environments/rails23/config/boot.rb +127 -0
  107. data/test/environments/rails23/config/database.yml +31 -0
  108. data/test/environments/rails23/config/environment.rb +25 -0
  109. data/test/environments/rails23/config/environments/development.rb +16 -0
  110. data/test/environments/rails23/config/environments/production.rb +8 -0
  111. data/test/environments/rails23/config/environments/test.rb +10 -0
  112. data/test/environments/rails23/config/preinitializer.rb +25 -0
  113. data/test/environments/rails23/config/routes.rb +5 -0
  114. data/test/environments/rails23/db/schema.rb +5 -0
  115. data/test/environments/rails30/Gemfile +19 -0
  116. data/test/environments/rails30/Rakefile +9 -0
  117. data/test/environments/rails30/config/application.rb +17 -0
  118. data/test/environments/rails30/config/boot.rb +10 -0
  119. data/test/environments/rails30/config/database.yml +31 -0
  120. data/test/environments/rails30/config/environment.rb +6 -0
  121. data/test/environments/rails30/config/initializers/new_rails_defaults.rb +11 -0
  122. data/test/environments/rails30/db/schema.rb +5 -0
  123. data/test/environments/rails31/Gemfile +19 -0
  124. data/test/environments/rails31/Rakefile +9 -0
  125. data/test/environments/rails31/config/application.rb +18 -0
  126. data/test/environments/rails31/config/boot.rb +10 -0
  127. data/test/environments/rails31/config/database.yml +31 -0
  128. data/test/environments/rails31/config/environment.rb +6 -0
  129. data/test/environments/rails31/config/initializers/new_rails_defaults.rb +21 -0
  130. data/test/environments/rails31/db/schema.rb +5 -0
  131. data/test/environments/rails32/Gemfile +25 -0
  132. data/test/environments/rails32/Rakefile +9 -0
  133. data/test/environments/rails32/config/application.rb +19 -0
  134. data/test/environments/rails32/config/boot.rb +10 -0
  135. data/test/environments/rails32/config/database.yml +31 -0
  136. data/test/environments/rails32/config/environment.rb +6 -0
  137. data/test/environments/rails32/db/schema.rb +5 -0
  138. data/test/environments/rails40/Gemfile +25 -0
  139. data/test/environments/rails40/Rakefile +9 -0
  140. data/test/environments/rails40/config/application.rb +18 -0
  141. data/test/environments/rails40/config/boot.rb +10 -0
  142. data/test/environments/rails40/config/database.yml +31 -0
  143. data/test/environments/rails40/config/environment.rb +6 -0
  144. data/test/environments/rails40/db/schema.rb +5 -0
  145. data/test/multiverse/lib/multiverse/suite.rb +24 -12
  146. data/test/multiverse/suites/agent_only/logging_test.rb +18 -1
  147. data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +1 -8
  148. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +10 -7
  149. data/test/multiverse/suites/curb/curb_test.rb +17 -3
  150. data/test/multiverse/suites/excon/Envfile +1 -1
  151. data/test/multiverse/suites/excon/excon_test.rb +18 -2
  152. data/test/multiverse/suites/httpclient/httpclient_test.rb +2 -2
  153. data/test/multiverse/suites/net_http/net_http_test.rb +2 -2
  154. data/test/multiverse/suites/rails/error_tracing_test.rb +35 -8
  155. data/test/multiverse/suites/rails/ignore_test.rb +48 -0
  156. data/test/multiverse/suites/rails/mongrel_queue_depth_test.rb +44 -0
  157. data/test/multiverse/suites/sequel/sequel_test.rb +11 -0
  158. data/test/multiverse/suites/sinatra/ignoring_test.rb +2 -2
  159. data/test/multiverse/suites/typhoeus/Envfile +9 -2
  160. data/test/multiverse/suites/typhoeus/typhoeus_test.rb +3 -2
  161. data/test/new_relic/agent/agent/start_test.rb +3 -22
  162. data/test/new_relic/agent/agent_test.rb +6 -5
  163. data/test/new_relic/agent/autostart_test.rb +39 -1
  164. data/test/new_relic/agent/browser_monitoring_test.rb +43 -88
  165. data/test/new_relic/agent/browser_token_test.rb +52 -0
  166. data/test/new_relic/agent/busy_calculator_test.rb +1 -1
  167. data/test/new_relic/agent/commands/agent_command_router_test.rb +98 -0
  168. data/test/new_relic/agent/commands/agent_command_test.rb +37 -0
  169. data/test/new_relic/agent/commands/thread_profiler_test.rb +177 -0
  170. data/test/new_relic/agent/configuration/default_source_test.rb +81 -0
  171. data/test/new_relic/agent/configuration/environment_source_test.rb +81 -7
  172. data/test/new_relic/agent/configuration/manager_test.rb +16 -1
  173. data/test/new_relic/agent/cross_app_monitor_test.rb +3 -5
  174. data/test/new_relic/agent/error_collector_test.rb +14 -0
  175. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +1 -1
  176. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +2 -3
  177. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +29 -31
  178. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +22 -0
  179. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +2 -2
  180. data/test/new_relic/agent/method_tracer_test.rb +2 -2
  181. data/test/new_relic/agent/new_relic_service_test.rb +5 -49
  182. data/test/new_relic/agent/pipe_channel_manager_test.rb +1 -0
  183. data/test/new_relic/agent/request_sampler_test.rb +32 -95
  184. data/test/new_relic/agent/rpm_agent_test.rb +7 -5
  185. data/test/new_relic/agent/sampled_buffer_test.rb +178 -0
  186. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +0 -1
  187. data/test/new_relic/agent/stats_engine_test.rb +10 -17
  188. data/test/new_relic/agent/threading/agent_thread_test.rb +107 -0
  189. data/test/new_relic/agent/threading/backtrace_node_test.rb +96 -0
  190. data/test/new_relic/agent/{threaded_test.rb → threading/fake_thread.rb} +0 -25
  191. data/test/new_relic/agent/threading/thread_profile_test.rb +308 -0
  192. data/test/new_relic/agent/threading/threaded_test_case.rb +33 -0
  193. data/test/new_relic/agent/transaction/pop_test.rb +0 -16
  194. data/test/new_relic/agent/transaction_sample_builder_test.rb +23 -4
  195. data/test/new_relic/agent/transaction_sampler_test.rb +14 -15
  196. data/test/new_relic/agent/transaction_state_test.rb +75 -0
  197. data/test/new_relic/agent/transaction_test.rb +15 -0
  198. data/test/new_relic/agent/transaction_timings_test.rb +81 -0
  199. data/test/new_relic/agent_test.rb +12 -14
  200. data/test/new_relic/{command → cli}/deployments_test.rb +41 -13
  201. data/test/new_relic/control/frameworks/rails_test.rb +1 -2
  202. data/test/new_relic/control_test.rb +1 -2
  203. data/test/new_relic/dependency_detection_test.rb +14 -0
  204. data/test/new_relic/fake_collector.rb +1 -0
  205. data/test/new_relic/helper_test.rb +7 -2
  206. data/test/new_relic/http_client_test_cases.rb +33 -1
  207. data/test/new_relic/local_environment_test.rb +0 -23
  208. data/test/new_relic/metric_data_test.rb +4 -0
  209. data/test/new_relic/rack/browser_monitoring_test.rb +31 -30
  210. data/test/performance/lib/performance/result.rb +15 -4
  211. data/test/performance/lib/performance/timer.rb +7 -1
  212. data/test/performance/script/baselines +102 -0
  213. data/test/performance/suites/rum_autoinsertion.rb +57 -0
  214. data/test/rum/basic.result.html +10 -0
  215. data/test/rum/basic.source.html +10 -0
  216. data/test/rum/comments1.result.html +24 -0
  217. data/test/rum/comments1.source.html +24 -0
  218. data/test/rum/comments2.result.html +24 -0
  219. data/test/rum/comments2.source.html +24 -0
  220. data/test/rum/gt_in_quotes1.result.html +27 -0
  221. data/test/rum/gt_in_quotes1.source.html +27 -0
  222. data/test/rum/gt_in_quotes2.result.html +24 -0
  223. data/test/rum/gt_in_quotes2.source.html +24 -0
  224. data/test/rum/gt_in_quotes_mismatch.result.html +24 -0
  225. data/test/rum/gt_in_quotes_mismatch.source.html +24 -0
  226. data/test/rum/gt_in_single_quotes1.result.html +25 -0
  227. data/test/rum/gt_in_single_quotes1.source.html +25 -0
  228. data/test/rum/gt_in_single_quotes_mismatch.result.html +25 -0
  229. data/test/rum/gt_in_single_quotes_mismatch.source.html +25 -0
  230. data/test/rum/incomplete_non_meta_tags.result.html +10 -0
  231. data/test/rum/incomplete_non_meta_tags.source.html +10 -0
  232. data/test/rum/no_body.result.html +21 -0
  233. data/test/rum/no_body.source.html +21 -0
  234. data/test/rum/no_header.result.html +7 -0
  235. data/test/rum/no_header.source.html +7 -0
  236. data/test/rum/no_start_header.result.html +9 -0
  237. data/test/rum/no_start_header.source.html +9 -0
  238. data/test/rum/script1.result.html +19 -0
  239. data/test/rum/script1.source.html +19 -0
  240. data/test/rum/script2.result.html +17 -0
  241. data/test/rum/script2.source.html +17 -0
  242. data/test/rum/x_ua_meta_tag.result.html +10 -0
  243. data/test/rum/x_ua_meta_tag.source.html +10 -0
  244. data/test/rum/x_ua_meta_tag_multiline.result.html +11 -0
  245. data/test/rum/x_ua_meta_tag_multiline.source.html +11 -0
  246. data/test/rum/x_ua_meta_tag_with_others.result.html +11 -0
  247. data/test/rum/x_ua_meta_tag_with_others.source.html +11 -0
  248. data/test/rum/x_ua_meta_tag_with_spaces.result.html +10 -0
  249. data/test/rum/x_ua_meta_tag_with_spaces.source.html +10 -0
  250. data/test/script/ci.sh +1 -12
  251. data/test/test_helper.rb +1 -0
  252. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +11 -0
  253. metadata +225 -32
  254. metadata.gz.sig +0 -0
  255. data/lib/new_relic/agent/configuration/defaults.rb +0 -157
  256. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +0 -56
  257. data/lib/new_relic/agent/thread.rb +0 -37
  258. data/lib/new_relic/agent/thread_profiler.rb +0 -323
  259. data/lib/new_relic/agent/transaction_info.rb +0 -114
  260. data/lib/new_relic/command.rb +0 -89
  261. data/test/new_relic/agent/agent_test_controller_test.rb +0 -348
  262. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +0 -70
  263. data/test/new_relic/agent/thread_profiler_test.rb +0 -586
  264. data/test/new_relic/agent/thread_test.rb +0 -93
  265. data/test/new_relic/agent/transaction_info_test.rb +0 -99
data/install.rb CHANGED
@@ -4,10 +4,10 @@
4
4
 
5
5
  if __FILE__ == $0 || $0 =~ /script\/plugin/
6
6
  $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
7
- require 'new_relic/command'
7
+ require 'new_relic/cli/command'
8
8
  begin
9
- NewRelic::Command::Install.new(:quiet => true, :app_name => 'My Application').run
10
- rescue NewRelic::Command::CommandFailure => e
9
+ NewRelic::Cli::Install.new(:quiet => true, :app_name => 'My Application').run
10
+ rescue NewRelic::Cli::CommandFailure => e
11
11
  $stderr.puts e.message
12
12
  end
13
13
  end
@@ -89,13 +89,12 @@ module NewRelic
89
89
  require 'new_relic/agent/stats_engine'
90
90
  require 'new_relic/agent/transaction_sampler'
91
91
  require 'new_relic/agent/sql_sampler'
92
- require 'new_relic/agent/thread_profiler'
92
+ require 'new_relic/agent/commands/thread_profiler'
93
93
  require 'new_relic/agent/error_collector'
94
94
  require 'new_relic/agent/busy_calculator'
95
95
  require 'new_relic/agent/sampler'
96
96
  require 'new_relic/agent/database'
97
97
  require 'new_relic/agent/pipe_channel_manager'
98
- require 'new_relic/agent/transaction_info'
99
98
  require 'new_relic/agent/configuration'
100
99
  require 'new_relic/agent/rules_engine'
101
100
  require 'new_relic/agent/http_clients/uri_util'
@@ -384,20 +383,19 @@ module NewRelic
384
383
 
385
384
  # Check to see if we are capturing metrics currently on this thread.
386
385
  def is_execution_traced?
387
- untraced = Thread.current[:newrelic_untraced]
388
- untraced.nil? || untraced.last != false
386
+ NewRelic::Agent::TransactionState.get.is_traced?
389
387
  end
390
388
 
391
389
  # helper method to check the thread local to determine whether the
392
390
  # transaction in progress is traced or not
393
391
  def is_transaction_traced?
394
- Thread::current[:record_tt] != false
392
+ NewRelic::Agent::TransactionState.get.is_transaction_traced?
395
393
  end
396
394
 
397
395
  # helper method to check the thread local to determine whether sql
398
396
  # is being recorded or not
399
397
  def is_sql_recorded?
400
- Thread::current[:record_sql] != false
398
+ NewRelic::Agent::TransactionState.get.is_sql_recorded?
401
399
  end
402
400
 
403
401
  # Set a filter to be applied to errors that the Ruby Agent will
@@ -8,12 +8,14 @@ require 'net/http'
8
8
  require 'logger'
9
9
  require 'zlib'
10
10
  require 'stringio'
11
+ require 'new_relic/agent/sampled_buffer'
11
12
  require 'new_relic/agent/autostart'
12
13
  require 'new_relic/agent/new_relic_service'
13
14
  require 'new_relic/agent/pipe_service'
14
15
  require 'new_relic/agent/configuration/manager'
15
16
  require 'new_relic/agent/database'
16
- require 'new_relic/agent/thread_profiler'
17
+ require 'new_relic/agent/commands/agent_command_router'
18
+ require 'new_relic/agent/commands/thread_profiler'
17
19
  require 'new_relic/agent/event_listener'
18
20
  require 'new_relic/agent/cross_app_monitor'
19
21
  require 'new_relic/agent/request_sampler'
@@ -31,13 +33,20 @@ module NewRelic
31
33
  extend NewRelic::Agent::Configuration::Instance
32
34
 
33
35
  def initialize
36
+ # FIXME: temporary work around for RUBY-839
37
+ # This should be handled with a configuration callback
38
+ if Agent.config[:monitor_mode]
39
+ @service = NewRelic::Agent::NewRelicService.new
40
+ end
41
+
34
42
  @launch_time = Time.now
35
43
 
36
44
  @events = NewRelic::Agent::EventListener.new
37
45
  @stats_engine = NewRelic::Agent::StatsEngine.new
38
46
  @transaction_sampler = NewRelic::Agent::TransactionSampler.new
39
47
  @sql_sampler = NewRelic::Agent::SqlSampler.new
40
- @thread_profiler = NewRelic::Agent::ThreadProfiler.new
48
+ @thread_profiler = NewRelic::Agent::Commands::ThreadProfiler.new
49
+ @agent_command_router = NewRelic::Agent::Commands::AgentCommandRouter.new(@service, @thread_profiler)
41
50
  @cross_app_monitor = NewRelic::Agent::CrossAppMonitor.new(@events)
42
51
  @error_collector = NewRelic::Agent::ErrorCollector.new
43
52
  @transaction_rules = NewRelic::Agent::RulesEngine.new
@@ -51,12 +60,6 @@ module NewRelic
51
60
 
52
61
  @last_harvest_time = Time.now
53
62
  @obfuscator = lambda {|sql| NewRelic::Agent::Database.default_sql_obfuscator(sql) }
54
-
55
- # FIXME: temporary work around for RUBY-839
56
- # This should be handled with a configuration callback
57
- if Agent.config[:monitor_mode]
58
- @service = NewRelic::Agent::NewRelicService.new
59
- end
60
63
  end
61
64
 
62
65
  # contains all the class-level methods for NewRelic::Agent::Agent
@@ -81,6 +84,7 @@ module NewRelic
81
84
  attr_reader :sql_sampler
82
85
  # begins a thread profile session when instructed by agent commands
83
86
  attr_reader :thread_profiler
87
+ attr_reader :agent_command_router
84
88
  # error collector is a simple collection of recorded errors
85
89
  attr_reader :error_collector
86
90
  attr_reader :harvest_samplers
@@ -266,8 +270,8 @@ module NewRelic
266
270
  # should not record sql in the current thread. Returns the
267
271
  # previous value, if there is one
268
272
  def set_record_sql(should_record)
269
- prev = Thread::current[:record_sql]
270
- Thread::current[:record_sql] = should_record
273
+ prev = TransactionState.get.record_sql
274
+ TransactionState.get.record_sql = should_record
271
275
  prev.nil? || prev
272
276
  end
273
277
 
@@ -275,8 +279,8 @@ module NewRelic
275
279
  # should not record transaction traces in the current
276
280
  # thread. Returns the previous value, if there is one
277
281
  def set_record_tt(should_record)
278
- prev = Thread::current[:record_tt]
279
- Thread::current[:record_tt] = should_record
282
+ prev = TransactionState.get.record_tt
283
+ TransactionState.get.record_tt = should_record
280
284
  prev.nil? || prev
281
285
  end
282
286
 
@@ -285,18 +289,13 @@ module NewRelic
285
289
  # children of a transaction without affecting the tracing of
286
290
  # the whole transaction
287
291
  def push_trace_execution_flag(should_trace=false)
288
- value = Thread.current[:newrelic_untraced]
289
- if (value.nil?)
290
- Thread.current[:newrelic_untraced] = []
291
- end
292
-
293
- Thread.current[:newrelic_untraced] << should_trace
292
+ TransactionState.get.push_traced(should_trace)
294
293
  end
295
294
 
296
295
  # Pop the current trace execution status. Restore trace execution status
297
296
  # to what it was before we pushed the current flag.
298
297
  def pop_trace_execution_flag
299
- Thread.current[:newrelic_untraced].pop if Thread.current[:newrelic_untraced]
298
+ TransactionState.get.pop_traced
300
299
  end
301
300
 
302
301
  # Herein lies the corpse of the former 'start' method. May
@@ -335,8 +334,12 @@ module NewRelic
335
334
  # assist with proper dispatcher detection
336
335
  def log_dispatcher
337
336
  dispatcher_name = Agent.config[:dispatcher].to_s
338
- return if log_if(dispatcher_name.empty?, :info, "No known dispatcher detected.")
339
- ::NewRelic::Agent.logger.info "Dispatcher: #{dispatcher_name}"
337
+
338
+ if dispatcher_name.empty?
339
+ ::NewRelic::Agent.logger.info 'No known dispatcher detected.'
340
+ else
341
+ ::NewRelic::Agent.logger.info "Dispatcher: #{dispatcher_name}"
342
+ end
340
343
  end
341
344
 
342
345
  def log_app_name
@@ -400,35 +403,27 @@ module NewRelic
400
403
  ::NewRelic::Agent.logger.debug "New Relic Ruby Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}"
401
404
  end
402
405
 
403
- # A helper method that logs a condition if that condition is
404
- # true. Mentally cleaner than having every method set a
405
- # local and log if it is true
406
- def log_if(boolean, level, message)
407
- ::NewRelic::Agent.logger.send(level, message) if boolean
408
- boolean
409
- end
410
-
411
- # A helper method that logs a condition unless that
412
- # condition is true. Mentally cleaner than having every
413
- # method set a local and log unless it is true
414
- def log_unless(boolean, level, message)
415
- ::NewRelic::Agent.logger.send(level, message) unless boolean
416
- boolean
417
- end
418
-
419
406
  # Warn the user if they have configured their agent not to
420
407
  # send data, that way we can see this clearly in the log file
421
408
  def monitoring?
422
- log_unless(Agent.config[:monitor_mode], :warn,
423
- "Agent configured not to send data in this environment.")
409
+ if Agent.config[:monitor_mode]
410
+ true
411
+ else
412
+ ::NewRelic::Agent.logger.warn('Agent configured not to send data in this environment.')
413
+ false
414
+ end
424
415
  end
425
416
 
426
417
  # Tell the user when the license key is missing so they can
427
418
  # fix it by adding it to the file
428
419
  def has_license_key?
429
- log_unless(Agent.config[:license_key], :warn,
430
- "No license key found in newrelic.yml config. " +
431
- "This often means your newrelic.yml is missing a section for the running environment '#{NewRelic::Control.instance.env}'")
420
+ if Agent.config[:license_key] && Agent.config[:license_key].length > 0
421
+ true
422
+ else
423
+ ::NewRelic::Agent.logger.warn("No license key found in newrelic.yml config. " +
424
+ "This often means your newrelic.yml is missing a section for the running environment '#{NewRelic::Control.instance.env}'")
425
+ false
426
+ end
432
427
  end
433
428
 
434
429
  # A correct license key exists and is of the proper length
@@ -440,15 +435,25 @@ module NewRelic
440
435
  # usually looks something like a SHA1 hash
441
436
  def correct_license_length
442
437
  key = Agent.config[:license_key]
443
- log_unless((key.length == 40), :error, "Invalid license key: #{key}")
438
+
439
+ if key.length == 40
440
+ true
441
+ else
442
+ ::NewRelic::Agent.logger.error("Invalid license key: #{key}")
443
+ false
444
+ end
444
445
  end
445
446
 
446
447
  # If we're using a dispatcher that forks before serving
447
448
  # requests, we need to wait until the children are forked
448
449
  # before connecting, otherwise the parent process sends odd data
449
450
  def using_forking_dispatcher?
450
- log_if([:passenger, :rainbows, :unicorn].include?(Agent.config[:dispatcher]),
451
- :info, "Connecting workers after forking.")
451
+ if [:passenger, :rainbows, :unicorn].include? Agent.config[:dispatcher]
452
+ ::NewRelic::Agent.logger.info 'Connecting workers after forking.'
453
+ true
454
+ else
455
+ false
456
+ end
452
457
  end
453
458
 
454
459
  # Return true if we're using resque and it hasn't had a chance to (potentially)
@@ -651,7 +656,7 @@ module NewRelic
651
656
  end
652
657
 
653
658
  ::NewRelic::Agent.logger.debug "Creating Ruby Agent worker thread."
654
- @worker_thread = NewRelic::Agent::AgentThread.new('Worker Loop') do
659
+ @worker_thread = NewRelic::Agent::Threading::AgentThread.new('Worker Loop') do
655
660
  deferred_work!(connection_options)
656
661
  end
657
662
  end
@@ -977,21 +982,10 @@ module NewRelic
977
982
  # unnecessary overhead of running explains on fast queries.)
978
983
  def harvest_and_send_slowest_sample
979
984
  harvest_transaction_traces
980
- unless @traces.empty?
981
- now = Time.now
982
- ::NewRelic::Agent.logger.debug "Sending (#{@traces.length}) transaction traces"
983
985
 
986
+ unless @traces.empty?
984
987
  begin
985
- options = { :keep_backtraces => true }
986
- if !(NewRelic::Agent::Database.record_sql_method == :off)
987
- options[:record_sql] = NewRelic::Agent::Database.record_sql_method
988
- end
989
- if Agent.config[:'transaction_tracer.explain_enabled']
990
- options[:explain_sql] = Agent.config[:'transaction_tracer.explain_threshold']
991
- end
992
- traces = @traces.map {|trace| trace.prepare_to_send(options) }
993
- @service.transaction_sample_data(traces)
994
- ::NewRelic::Agent.logger.debug "Sent slowest sample (#{@service.agent_id}) in #{Time.now - now} seconds"
988
+ send_slowest_sample
995
989
  rescue UnrecoverableServerException => e
996
990
  ::NewRelic::Agent.logger.debug e.message
997
991
  end
@@ -1003,6 +997,25 @@ module NewRelic
1003
997
  @traces = nil
1004
998
  end
1005
999
 
1000
+ def send_slowest_sample
1001
+ start_time = Time.now
1002
+ ::NewRelic::Agent.logger.debug "Sending (#{@traces.length}) transaction traces"
1003
+
1004
+ options = { :keep_backtraces => true }
1005
+ unless NewRelic::Agent::Database.record_sql_method == :off
1006
+ options[:record_sql] = NewRelic::Agent::Database.record_sql_method
1007
+ end
1008
+
1009
+ if Agent.config[:'transaction_tracer.explain_enabled']
1010
+ options[:explain_sql] = Agent.config[:'transaction_tracer.explain_threshold']
1011
+ end
1012
+
1013
+ traces = @traces.map {|trace| trace.prepare_to_send(options) }
1014
+
1015
+ @service.transaction_sample_data(traces)
1016
+ ::NewRelic::Agent.logger.debug "Sent slowest sample (#{@service.agent_id}) in #{Time.now - start_time} seconds"
1017
+ end
1018
+
1006
1019
  def harvest_and_send_thread_profile(disconnecting=false)
1007
1020
  @thread_profiler.stop(true) if disconnecting
1008
1021
 
@@ -1048,19 +1061,10 @@ module NewRelic
1048
1061
  samples = @request_sampler.samples
1049
1062
  @service.analytic_event_data(samples) unless samples.empty?
1050
1063
  @request_sampler.reset
1051
- rescue => e
1052
- NewRelic::Agent.logger.debug "Failed to sent analytics; throttling to conserve memory"
1053
- @request_sampler.throttle
1054
- raise
1055
1064
  end
1056
1065
 
1057
- def check_for_agent_commands
1058
- commands = @service.get_agent_commands
1059
- ::NewRelic::Agent.logger.debug "Received get_agent_commands = #{commands.inspect}"
1060
-
1061
- @thread_profiler.respond_to_commands(commands) do |command_id, error|
1062
- @service.agent_command_results(command_id, error)
1063
- end
1066
+ def handle_agent_commands
1067
+ @agent_command_router.handle_agent_commands
1064
1068
  end
1065
1069
 
1066
1070
  def transmit_data(disconnecting=false)
@@ -1074,9 +1078,9 @@ module NewRelic
1074
1078
  harvest_and_send_slowest_sql
1075
1079
  harvest_and_send_timeslice_data
1076
1080
  harvest_and_send_analytic_event_data
1077
- harvest_and_send_thread_profile(disconnecting)
1078
1081
 
1079
- check_for_agent_commands
1082
+ handle_agent_commands
1083
+ harvest_and_send_thread_profile(disconnecting)
1080
1084
  end
1081
1085
  rescue EOFError => e
1082
1086
  ::NewRelic::Agent.logger.warn("EOFError after #{Time.now - now}s when transmitting data to New Relic Service.")
@@ -24,10 +24,8 @@ module NewRelic
24
24
  # 'autostart.blacklisted_executables' and
25
25
  # 'autostart.blacklisted_rake_tasks'
26
26
  def agent_should_start?
27
- !::NewRelic::Agent.config['autostart.blacklisted_constants'] \
28
- .split(/\s*,\s*/).any?{ |name| constant_is_defined?(name) } &&
29
- !::NewRelic::Agent.config['autostart.blacklisted_executables'] \
30
- .split(/\s*,\s*/).any?{ |bin| File.basename($0) == bin } &&
27
+ !blacklisted?('autostart.blacklisted_constants') { |name| constant_is_defined?(name) } &&
28
+ !blacklisted?('autostart.blacklisted_executables') { |bin| File.basename($0) == bin } &&
31
29
  !in_blacklisted_rake_task?
32
30
  end
33
31
 
@@ -36,13 +34,28 @@ module NewRelic
36
34
  def constant_is_defined?(const_name)
37
35
  const_name.to_s.sub(/\A::/,'').split('::').inject(Object) do |namespace, name|
38
36
  begin
39
- namespace.const_get(name)
37
+ result = namespace.const_get(name)
38
+
39
+ # const_get looks up the inheritence chain, so if it's a class
40
+ # in the constant make sure we found the one in our namespace.
41
+ #
42
+ # Can't help if the constant isn't a class...
43
+ if result.is_a?(Module)
44
+ expected_name = "#{namespace}::#{name}".gsub(/^Object::/, "")
45
+ return false unless expected_name == result.to_s
46
+ end
47
+
48
+ result
40
49
  rescue NameError
41
50
  false
42
51
  end
43
52
  end
44
53
  end
45
54
 
55
+ def blacklisted?(key, &block)
56
+ ::NewRelic::Agent.config[key].split(/\s*,\s*/).any?(&block)
57
+ end
58
+
46
59
  def in_blacklisted_rake_task?
47
60
  tasks = begin
48
61
  ::Rake.application.top_level_tasks
@@ -4,12 +4,17 @@
4
4
 
5
5
  require 'base64'
6
6
  require 'new_relic/agent/beacon_configuration'
7
+ require 'new_relic/agent/transaction_timings'
8
+
7
9
  module NewRelic
8
10
  module Agent
9
11
  # This module contains support for Real User Monitoring - the
10
12
  # javascript generation and configuration
11
13
  module BrowserMonitoring
12
14
  class DummyTransaction
15
+
16
+ attr_accessor :start_time
17
+
13
18
  def initialize
14
19
  @attributes = {}
15
20
  end
@@ -22,6 +27,10 @@ module NewRelic
22
27
  0.0
23
28
  end
24
29
 
30
+ def timings
31
+ NewRelic::Agent::TransactionTimings.new(0.0, NewRelic::Agent::TransactionState.get)
32
+ end
33
+
25
34
  def name
26
35
  ::NewRelic::Agent::UNKNOWN_METRIC
27
36
  end
@@ -39,11 +48,7 @@ module NewRelic
39
48
  # page as is reasonably possible - that is, before any style or
40
49
  # javascript inclusions, but after any header-related meta tags
41
50
  def browser_timing_header
42
- if insert_js?
43
- NewRelic::Agent.instance.beacon_configuration.browser_timing_header
44
- else
45
- ""
46
- end
51
+ insert_js? ? header_js_string : ""
47
52
  end
48
53
 
49
54
  # This method returns a string suitable for inclusion in a page
@@ -67,6 +72,9 @@ module NewRelic
67
72
 
68
73
  def obfuscate(config, text)
69
74
  obfuscated = ""
75
+ if defined?(::Encoding::ASCII_8BIT)
76
+ obfuscated.force_encoding(::Encoding::ASCII_8BIT)
77
+ end
70
78
  key_bytes = config.license_bytes
71
79
  index = 0
72
80
  text.each_byte{|byte|
@@ -78,34 +86,15 @@ module NewRelic
78
86
  end
79
87
 
80
88
  def browser_monitoring_transaction_name
81
- current_transaction.name || ::NewRelic::Agent::UNKNOWN_METRIC
82
- end
83
-
84
- def browser_monitoring_queue_time
85
- clamp_to_positive((current_transaction.queue_time.to_f * 1000.0).round)
86
- end
87
-
88
- def browser_monitoring_app_time
89
- clamp_to_positive(((Time.now - browser_monitoring_start_time).to_f * 1000.0).round)
89
+ current_timings.transaction_name || ::NewRelic::Agent::UNKNOWN_METRIC
90
90
  end
91
91
 
92
92
  def current_transaction
93
- NewRelic::Agent::TransactionInfo.get.transaction || @@dummy_txn
93
+ NewRelic::Agent::TransactionState.get.transaction || @@dummy_txn
94
94
  end
95
95
 
96
- def clamp_to_positive(value)
97
- return 0.0 if value < 0
98
- value
99
- end
100
-
101
- def browser_monitoring_start_time
102
- NewRelic::Agent::TransactionInfo.get.start_time
103
- end
104
-
105
- def self.timings
106
- NewRelic::Agent::Instrumentation::BrowserMonitoringTimings.new(
107
- current_transaction.queue_time,
108
- NewRelic::Agent::TransactionInfo.get)
96
+ def current_timings
97
+ NewRelic::Agent::TransactionState.get.timings
109
98
  end
110
99
 
111
100
  def insert_mobile_response_header(request, response)
@@ -116,7 +105,7 @@ module NewRelic
116
105
 
117
106
  response['X-NewRelic-Beacon-Url'] = beacon_url(request)
118
107
 
119
- payload = %[ ["#{Agent.config[:application_id]}","#{obfuscate(config, browser_monitoring_transaction_name)}",#{browser_monitoring_queue_time},#{browser_monitoring_app_time}] ]
108
+ payload = %[ ["#{Agent.config[:application_id]}","#{obfuscate(config, browser_monitoring_transaction_name)}",#{current_timings.queue_time_in_millis},#{current_timings.app_time_in_millis}] ]
120
109
  response['X-NewRelic-App-Server-Metrics'] = payload
121
110
  end
122
111
  end
@@ -152,7 +141,7 @@ module NewRelic
152
141
  elsif ! NewRelic::Agent.is_execution_traced?
153
142
  ::NewRelic::Agent.logger.debug "Execution is not traced. Skipping browser instrumentation."
154
143
  false
155
- elsif NewRelic::Agent::TransactionInfo.get.ignore_end_user?
144
+ elsif NewRelic::Agent::TransactionState.get.request_ignore_enduser
156
145
  ::NewRelic::Agent.logger.debug "Ignore end user for this transaction is set. Skipping browser instrumentation."
157
146
  false
158
147
  else
@@ -161,7 +150,7 @@ module NewRelic
161
150
  end
162
151
 
163
152
  def generate_footer_js(config)
164
- if browser_monitoring_start_time
153
+ if current_transaction.start_time
165
154
  footer_js_string(config)
166
155
  else
167
156
  ''
@@ -173,15 +162,28 @@ module NewRelic
173
162
  end
174
163
 
175
164
  def tt_guid
176
- transaction = NewRelic::Agent::TransactionInfo.get
177
- return transaction.guid if transaction.include_guid?
165
+ state = NewRelic::Agent::TransactionState.get
166
+ return state.request_guid if include_guid?(state)
178
167
  ""
179
168
  end
180
169
 
170
+ def include_guid?(state)
171
+ state.request_token &&
172
+ state.timings.app_time_in_seconds > state.transaction.apdex_t
173
+ end
174
+
181
175
  def tt_token
182
- return NewRelic::Agent::TransactionInfo.get.token
176
+ return NewRelic::Agent::TransactionState.get.request_token
177
+ end
178
+
179
+ # NOTE: This method may be overridden for internal prototyping, so should
180
+ # remain stable.
181
+ def header_js_string
182
+ NewRelic::Agent.instance.beacon_configuration.browser_timing_header
183
183
  end
184
184
 
185
+ # NOTE: This method may be overridden for internal prototyping, so should
186
+ # remain stable.
185
187
  def footer_js_string(config)
186
188
  obfuscated_transaction_name = obfuscate(config, browser_monitoring_transaction_name)
187
189
 
@@ -189,7 +191,11 @@ module NewRelic
189
191
  account = obfuscate(config, transaction_attribute(:account))
190
192
  product = obfuscate(config, transaction_attribute(:product))
191
193
 
192
- html_safe_if_needed(%'<script type="text/javascript">#{config.browser_timing_static_footer}NREUMQ.push(["#{config.finish_command}","#{Agent.config[:beacon]}","#{Agent.config[:browser_key]}","#{Agent.config[:application_id]}","#{obfuscated_transaction_name}",#{browser_monitoring_queue_time},#{browser_monitoring_app_time},new Date().getTime(),"#{tt_guid}","#{tt_token}","#{user}","#{account}","#{product}"]);</script>')
194
+ # This is slightly varied from other agents' RUM footer to ensure that
195
+ # NREUMQ is defined. Our experimental header placement has some holes
196
+ # where it could end up in a comment and not define NREUMQ as the footer
197
+ # assumes. We protect against that here.
198
+ html_safe_if_needed(%'<script type="text/javascript">if (typeof NREUMQ !== "undefined") { #{config.browser_timing_static_footer}NREUMQ.push(["#{config.finish_command}","#{Agent.config[:beacon]}","#{Agent.config[:browser_key]}","#{Agent.config[:application_id]}","#{obfuscated_transaction_name}",#{current_timings.queue_time_in_millis},#{current_timings.app_time_in_millis},new Date().getTime(),"#{tt_guid}","#{tt_token}","#{user}","#{account}","#{product}"]);}</script>')
193
199
  end
194
200
 
195
201
  def html_safe_if_needed(string)