ghazel-newrelic_rpm 3.4.0.2 → 3.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (231) hide show
  1. data/.gitignore +21 -0
  2. data/.project +23 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +180 -1
  5. data/GUIDELINES_FOR_CONTRIBUTING.md +73 -0
  6. data/Gemfile +16 -0
  7. data/InstallationNotes.md +15 -0
  8. data/LICENSE +1 -1
  9. data/{README.rdoc → README.md} +71 -55
  10. data/Rakefile +54 -0
  11. data/config.dot +290 -0
  12. data/config/database.yml +5 -0
  13. data/init.rb +38 -0
  14. data/lib/new_relic/agent.rb +9 -4
  15. data/lib/new_relic/agent/agent.rb +189 -230
  16. data/lib/new_relic/agent/beacon_configuration.rb +34 -48
  17. data/lib/new_relic/agent/browser_monitoring.rb +108 -61
  18. data/lib/new_relic/agent/busy_calculator.rb +12 -4
  19. data/lib/new_relic/agent/configuration.rb +49 -0
  20. data/lib/new_relic/agent/configuration/defaults.rb +89 -0
  21. data/lib/new_relic/agent/configuration/environment_source.rb +56 -0
  22. data/lib/new_relic/agent/configuration/manager.rb +116 -0
  23. data/lib/new_relic/agent/configuration/server_source.rb +27 -0
  24. data/lib/new_relic/agent/configuration/yaml_source.rb +61 -0
  25. data/lib/new_relic/agent/database.rb +37 -22
  26. data/lib/new_relic/agent/error_collector.rb +47 -43
  27. data/lib/new_relic/agent/instrumentation/active_record.rb +1 -5
  28. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +27 -6
  29. data/lib/new_relic/agent/instrumentation/data_mapper.rb +2 -10
  30. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +1 -1
  31. data/lib/new_relic/agent/instrumentation/memcache.rb +2 -2
  32. data/lib/new_relic/agent/instrumentation/metric_frame.rb +4 -14
  33. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +4 -18
  34. data/lib/new_relic/agent/instrumentation/rack.rb +1 -1
  35. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +3 -3
  36. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +2 -2
  37. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +5 -1
  38. data/lib/new_relic/agent/instrumentation/resque.rb +1 -1
  39. data/lib/new_relic/agent/instrumentation/sinatra.rb +14 -10
  40. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +4 -3
  41. data/lib/new_relic/agent/method_tracer.rb +5 -1
  42. data/lib/new_relic/agent/new_relic_service.rb +231 -61
  43. data/lib/new_relic/agent/pipe_channel_manager.rb +37 -23
  44. data/lib/new_relic/agent/pipe_service.rb +5 -1
  45. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +2 -5
  46. data/lib/new_relic/agent/samplers/memory_sampler.rb +2 -2
  47. data/lib/new_relic/agent/sql_sampler.rb +44 -68
  48. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +40 -24
  49. data/lib/new_relic/agent/stats_engine/metric_stats.rb +89 -14
  50. data/lib/new_relic/agent/stats_engine/samplers.rb +7 -3
  51. data/lib/new_relic/agent/stats_engine/transactions.rb +19 -11
  52. data/lib/new_relic/agent/thread.rb +27 -0
  53. data/lib/new_relic/agent/thread_profiler.rb +295 -0
  54. data/lib/new_relic/agent/transaction_info.rb +24 -4
  55. data/lib/new_relic/agent/transaction_sample_builder.rb +11 -11
  56. data/lib/new_relic/agent/transaction_sampler.rb +51 -61
  57. data/lib/new_relic/agent/worker_loop.rb +29 -15
  58. data/lib/new_relic/collection_helper.rb +1 -1
  59. data/lib/new_relic/commands/deployments.rb +19 -10
  60. data/lib/new_relic/control.rb +0 -1
  61. data/lib/new_relic/control/class_methods.rb +2 -3
  62. data/lib/new_relic/control/frameworks/rails.rb +24 -18
  63. data/lib/new_relic/control/frameworks/rails3.rb +18 -1
  64. data/lib/new_relic/control/frameworks/ruby.rb +2 -2
  65. data/lib/new_relic/control/instance_methods.rb +36 -53
  66. data/lib/new_relic/control/logging_methods.rb +5 -23
  67. data/lib/new_relic/control/server_methods.rb +11 -13
  68. data/lib/new_relic/delayed_job_injection.rb +1 -1
  69. data/lib/new_relic/helper.rb +13 -0
  70. data/lib/new_relic/language_support.rb +19 -22
  71. data/lib/new_relic/local_environment.rb +2 -3
  72. data/lib/new_relic/metric_data.rb +10 -2
  73. data/lib/new_relic/metric_spec.rb +6 -2
  74. data/lib/new_relic/noticed_error.rb +24 -9
  75. data/lib/new_relic/rack.rb +4 -0
  76. data/lib/new_relic/rack/browser_monitoring.rb +28 -10
  77. data/lib/new_relic/rack/developer_mode.rb +3 -0
  78. data/lib/new_relic/rack/error_collector.rb +56 -0
  79. data/lib/new_relic/transaction_sample.rb +23 -13
  80. data/lib/new_relic/transaction_sample/segment.rb +13 -15
  81. data/lib/new_relic/version.rb +3 -3
  82. data/lib/tasks/tests.rake +8 -8
  83. data/newrelic.yml +15 -32
  84. data/newrelic_rpm.gemspec +158 -38
  85. data/newrelic_rpm.gemspec.erb +55 -0
  86. data/test/config/newrelic.yml +3 -2
  87. data/test/intentional_fail.rb +10 -0
  88. data/test/multiverse/.gitignore +10 -0
  89. data/test/multiverse/README.md +90 -0
  90. data/test/multiverse/Rakefile +17 -0
  91. data/test/multiverse/lib/multiverse/color.rb +13 -0
  92. data/test/multiverse/lib/multiverse/envfile.rb +66 -0
  93. data/test/multiverse/lib/multiverse/environment.rb +16 -0
  94. data/test/multiverse/lib/multiverse/output_collector.rb +29 -0
  95. data/test/multiverse/lib/multiverse/runner.rb +44 -0
  96. data/test/multiverse/lib/multiverse/suite.rb +162 -0
  97. data/test/multiverse/script/run_one +3 -0
  98. data/test/multiverse/script/runner +9 -0
  99. data/test/multiverse/suites/active_record/Envfile +13 -0
  100. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +94 -0
  101. data/test/multiverse/suites/active_record/config/newrelic.yml +22 -0
  102. data/test/multiverse/suites/active_record/encoding_test.rb +26 -0
  103. data/test/multiverse/suites/agent_only/Envfile +3 -0
  104. data/test/multiverse/suites/agent_only/config/newrelic.yml +22 -0
  105. data/test/multiverse/suites/agent_only/http_response_code_test.rb +53 -0
  106. data/test/multiverse/suites/agent_only/marshaling_test.rb +109 -0
  107. data/test/multiverse/suites/agent_only/method_visibility_test.rb +98 -0
  108. data/test/multiverse/suites/agent_only/pipe_manager_test.rb +33 -0
  109. data/test/multiverse/suites/agent_only/service_timeout_test.rb +29 -0
  110. data/test/multiverse/suites/agent_only/test_trace_method_with_punctuation.rb +30 -0
  111. data/test/multiverse/suites/agent_only/test_trace_transaction_with_punctuation.rb +32 -0
  112. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +80 -0
  113. data/test/multiverse/suites/datamapper/Envfile +8 -0
  114. data/test/multiverse/suites/datamapper/config/newrelic.yml +22 -0
  115. data/test/multiverse/suites/datamapper/encoding_test.rb +36 -0
  116. data/test/multiverse/suites/monitor_mode_false/Envfile +2 -0
  117. data/test/multiverse/suites/monitor_mode_false/config/newrelic.yml +25 -0
  118. data/test/multiverse/suites/monitor_mode_false/no_dns_resolv.rb +29 -0
  119. data/test/multiverse/suites/no_load/Envfile +2 -0
  120. data/test/multiverse/suites/no_load/config/newrelic.yml +23 -0
  121. data/test/multiverse/suites/no_load/start_up_test.rb +14 -0
  122. data/test/multiverse/suites/rails_3_error_tracing/Envfile +15 -0
  123. data/test/multiverse/suites/rails_3_error_tracing/config/newrelic.yml +165 -0
  124. data/test/multiverse/suites/rails_3_error_tracing/error_tracing_test.rb +236 -0
  125. data/test/multiverse/suites/rails_3_gc/Envfile +8 -0
  126. data/test/multiverse/suites/rails_3_gc/config/newrelic.yml +167 -0
  127. data/test/multiverse/suites/rails_3_gc/instrumentation_test.rb +92 -0
  128. data/test/multiverse/suites/rails_3_queue_time/Envfile +15 -0
  129. data/test/multiverse/suites/rails_3_queue_time/config/newrelic.yml +165 -0
  130. data/test/multiverse/suites/rails_3_queue_time/queue_time_test.rb +75 -0
  131. data/test/multiverse/suites/rails_3_views/.gitignore +3 -0
  132. data/test/multiverse/suites/rails_3_views/Envfile +16 -0
  133. data/test/multiverse/suites/rails_3_views/app/views/foos/_foo.html.haml +1 -0
  134. data/test/multiverse/suites/rails_3_views/app/views/test/_a_partial.html.erb +1 -0
  135. data/test/multiverse/suites/rails_3_views/app/views/test/_mid_partial.html.erb +1 -0
  136. data/test/multiverse/suites/rails_3_views/app/views/test/_top_partial.html.erb +3 -0
  137. data/test/multiverse/suites/rails_3_views/app/views/test/deep_partial.html.erb +3 -0
  138. data/test/multiverse/suites/rails_3_views/app/views/test/haml_view.html.haml +6 -0
  139. data/test/multiverse/suites/rails_3_views/app/views/test/index.html.erb +4 -0
  140. data/test/multiverse/suites/rails_3_views/config/newrelic.yml +164 -0
  141. data/test/multiverse/suites/rails_3_views/view_instrumentation_test.rb +245 -0
  142. data/test/multiverse/suites/resque/Envfile +21 -0
  143. data/test/multiverse/suites/resque/config/newrelic.yml +22 -0
  144. data/test/multiverse/suites/resque/dump.rdb +0 -0
  145. data/test/multiverse/suites/resque/instrumentation_test.rb +73 -0
  146. data/test/multiverse/suites/rum_auto_instrumentation/Envfile +4 -0
  147. data/test/multiverse/suites/rum_auto_instrumentation/config/newrelic.yml +24 -0
  148. data/test/multiverse/suites/rum_auto_instrumentation/problem_response.html +422 -0
  149. data/test/multiverse/suites/rum_auto_instrumentation/responses/worst_case_small.html +5000 -0
  150. data/test/multiverse/suites/rum_auto_instrumentation/sanity_test.rb +115 -0
  151. data/test/multiverse/suites/sinatra/Envfile +13 -0
  152. data/test/multiverse/suites/sinatra/config/newrelic.yml +24 -0
  153. data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +76 -0
  154. data/test/multiverse/suites/sinatra/sinatra_routes_test.rb +46 -0
  155. data/test/multiverse/test/multiverse_test.rb +55 -0
  156. data/test/multiverse/test/suite_examples/one/a/Envfile +3 -0
  157. data/test/multiverse/test/suite_examples/one/a/a_test.rb +11 -0
  158. data/test/multiverse/test/suite_examples/one/a/config/newrelic.yml +24 -0
  159. data/test/multiverse/test/suite_examples/one/b/Envfile +3 -0
  160. data/test/multiverse/test/suite_examples/one/b/b_test.rb +11 -0
  161. data/test/multiverse/test/suite_examples/one/b/config/newrelic.yml +24 -0
  162. data/test/multiverse/test/suite_examples/three/a/Envfile +2 -0
  163. data/test/multiverse/test/suite_examples/three/a/fail_test.rb +6 -0
  164. data/test/multiverse/test/suite_examples/three/b/Envfile +2 -0
  165. data/test/multiverse/test/suite_examples/three/b/win_test.rb +6 -0
  166. data/test/multiverse/test/suite_examples/two/a/Envfile +1 -0
  167. data/test/multiverse/test/suite_examples/two/a/fail_test.rb +6 -0
  168. data/test/new_relic/agent/agent/connect_test.rb +134 -164
  169. data/test/new_relic/agent/agent/start_test.rb +111 -81
  170. data/test/new_relic/agent/agent/start_worker_thread_test.rb +6 -33
  171. data/test/new_relic/agent/agent_test.rb +88 -9
  172. data/test/new_relic/agent/agent_test_controller.rb +1 -1
  173. data/test/new_relic/agent/agent_test_controller_test.rb +42 -10
  174. data/test/new_relic/agent/beacon_configuration_test.rb +63 -67
  175. data/test/new_relic/agent/browser_monitoring_test.rb +150 -79
  176. data/test/new_relic/agent/configuration/environment_source_test.rb +74 -0
  177. data/test/new_relic/agent/configuration/manager_test.rb +149 -0
  178. data/test/new_relic/agent/configuration/server_source_test.rb +45 -0
  179. data/test/new_relic/agent/configuration/yaml_source_test.rb +56 -0
  180. data/test/new_relic/agent/error_collector/notice_error_test.rb +63 -50
  181. data/test/new_relic/agent/error_collector_test.rb +22 -12
  182. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +21 -11
  183. data/test/new_relic/agent/instrumentation/metric_frame_test.rb +6 -0
  184. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
  185. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +5 -5
  186. data/test/new_relic/agent/method_tracer_test.rb +6 -6
  187. data/test/new_relic/agent/mock_scope_listener.rb +3 -0
  188. data/test/new_relic/agent/new_relic_service_test.rb +208 -23
  189. data/test/new_relic/agent/pipe_channel_manager_test.rb +34 -17
  190. data/test/new_relic/agent/rpm_agent_test.rb +27 -23
  191. data/test/new_relic/agent/sql_sampler_test.rb +81 -56
  192. data/test/new_relic/agent/stats_engine/metric_stats/harvest_test.rb +3 -20
  193. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +12 -1
  194. data/test/new_relic/agent/stats_engine_test.rb +17 -8
  195. data/test/new_relic/agent/thread_profiler_test.rb +536 -0
  196. data/test/new_relic/agent/thread_test.rb +76 -0
  197. data/test/new_relic/agent/threaded_test.rb +65 -0
  198. data/test/new_relic/agent/transaction_info_test.rb +45 -4
  199. data/test/new_relic/agent/transaction_sample_builder_test.rb +8 -6
  200. data/test/new_relic/agent/transaction_sampler_test.rb +193 -204
  201. data/test/new_relic/agent/worker_loop_test.rb +20 -0
  202. data/test/new_relic/agent_test.rb +69 -41
  203. data/test/new_relic/collection_helper_test.rb +7 -8
  204. data/test/new_relic/command/deployments_test.rb +18 -2
  205. data/test/new_relic/control/frameworks/rails_test.rb +26 -0
  206. data/test/new_relic/control/logging_methods_test.rb +78 -52
  207. data/test/new_relic/control_test.rb +91 -129
  208. data/test/new_relic/fake_collector.rb +103 -31
  209. data/test/new_relic/fake_service.rb +8 -2
  210. data/test/new_relic/load_test.rb +13 -0
  211. data/test/new_relic/local_environment_test.rb +7 -10
  212. data/test/new_relic/metric_data_test.rb +45 -16
  213. data/test/new_relic/noticed_error_test.rb +14 -0
  214. data/test/new_relic/rack/browser_monitoring_test.rb +15 -9
  215. data/test/new_relic/rack/developer_mode_test.rb +13 -7
  216. data/test/new_relic/rack/error_collector_test.rb +74 -0
  217. data/test/new_relic/transaction_sample/segment_test.rb +23 -4
  218. data/test/new_relic/transaction_sample_test.rb +47 -2
  219. data/test/script/build_test_gem.sh +9 -3
  220. data/test/script/ci.sh +48 -21
  221. data/test/script/ci_multiverse_runner.sh +11 -11
  222. data/test/test_helper.rb +37 -18
  223. data/ui/helpers/developer_mode_helper.rb +21 -11
  224. data/ui/views/layouts/newrelic_default.rhtml +1 -0
  225. data/ui/views/newrelic/show_sample.rhtml +1 -1
  226. data/ui/views/newrelic/threads.rhtml +2 -10
  227. data/vendor/gems/metric_parser-0.1.0.pre1/.specification +116 -0
  228. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_init.rb +7 -0
  229. metadata +132 -58
  230. data/lib/new_relic/control/configuration.rb +0 -206
  231. data/test/new_relic/control/configuration_test.rb +0 -77
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake/testtask'
3
+ require "#{File.dirname(__FILE__)}/lib/new_relic/version.rb"
4
+ require "#{File.dirname(__FILE__)}/lib/tasks/all.rb"
5
+
6
+ task :default => :test
7
+
8
+ task :test => 'test:newrelic'
9
+
10
+ namespace :test do
11
+ desc "Run all tests"
12
+ task :all => %w{newrelic multiverse}
13
+
14
+ agent_home = File.expand_path(File.dirname(__FILE__))
15
+
16
+ desc "Run functional test suite for newrelic"
17
+ task :multiverse, [:suite, :mode] => [:gemspec] do |t, args|
18
+ args.with_defaults(:suite => "", :mode => "")
19
+ if args.mode == "run_one"
20
+ puts `#{agent_home}/test/multiverse/script/run_one #{args.suite}`
21
+ else
22
+ ruby "#{agent_home}/test/multiverse/script/runner #{args.suite}"
23
+ end
24
+ end
25
+
26
+ Rake::TestTask.new(:intentional_fail) do |t|
27
+ t.libs << "#{agent_home}/test"
28
+ t.libs << "#{agent_home}/lib"
29
+ t.pattern = "#{agent_home}/test/intentional_fail.rb"
30
+ t.verbose = true
31
+ end
32
+
33
+ # Note unit testing task is defined in lib/tasks/tests.rake to facilitate
34
+ # running them in a rails application environment.
35
+
36
+ end
37
+
38
+ desc 'Generate gemspec [ build_number, stage ]'
39
+ task :gemspec, [ :build_number, :stage ] do |t, args|
40
+ require 'erb'
41
+ version = NewRelic::VERSION::STRING.split('.')[0..2]
42
+ version << args.build_number.to_s if args.build_number
43
+ version << args.stage.to_s if args.stage
44
+
45
+ version_string = version.join('.')
46
+ gem_version = Gem::VERSION
47
+ date = Time.now.strftime('%Y-%m-%d')
48
+ files = `git ls-files`.split + ['newrelic_rpm.gemspec']
49
+
50
+ template = ERB.new(File.read('newrelic_rpm.gemspec.erb'))
51
+ File.open('newrelic_rpm.gemspec', 'w') do |gemspec|
52
+ gemspec.write(template.result(binding))
53
+ end
54
+ end
@@ -0,0 +1,290 @@
1
+ digraph AgentEnabled {
2
+ node[color=green]
3
+ "[agent_enabled]"
4
+ "[developer_mode]"
5
+ "[monitor_mode]"
6
+ "[slow_sql.explain_threshold]"
7
+ "[slow_sql.stack_trace_threshold]"
8
+ "[slow_sql.explain_enabled]"
9
+ "[slow_sql.enabled]"
10
+ "[slow_sql.record_sql]"
11
+ "[transaction_tracer.limit_segments]"
12
+ "[transaction_tracer.stack_trace_threshold]"
13
+ "[transaction_tracer.explain_threshold]"
14
+ "[transaction_tracer.explain_enabled]"
15
+ "[transaction_tracer.transaction_threshold]"
16
+ "[transaction_tracer.record_sql]"
17
+ "[transaction_tracer.random_sample]"
18
+ "[transaction_tracer.enabled]"
19
+ "[error_collector.capture_source]"
20
+ "[error_collector.enabled]"
21
+ "[error_collector.ignore_errors]"
22
+ "[browser_monitoring.auto_instrument]"
23
+ "[license_key]"
24
+ "[ssl]"
25
+ "[verify_certificate]"
26
+ "[api_host]"
27
+ "[api_port]"
28
+ "[proxy_host]"
29
+ "[proxy_port]"
30
+ "[proxy_user]"
31
+ "[proxy_pass]"
32
+ "[host]"
33
+ "[port]"
34
+ "[timeout]"
35
+ "[log_level]"
36
+ "[apdex_t]"
37
+ "[capture_params]"
38
+ "[app_name]"
39
+ "[multi_homed]"
40
+ "[disable_samplers]"
41
+ "[log_file_name]"
42
+ "[log_file_path]"
43
+ "[dispatcher]"
44
+ "[force_send]"
45
+ "[disable_mobile_headers]"
46
+ "[textmate]"
47
+ "[post_size_limit]"
48
+ "[sync_startup]"
49
+ "[send_data_on_exit]"
50
+ "[high_security]"
51
+ "[validate_seed]"
52
+ "[validate_token]"
53
+ "[disable_backtrace_cleanup]"
54
+ "[disable_activerecord_instrumentation]"
55
+ "[disable_dj]"
56
+ "[capture_memcache_keys]"
57
+ "[disable_memcache_instrumentation]"
58
+ "[disable_view_instrumentation]"
59
+ "[disable_resque]"
60
+
61
+ node[shape=box,color=orange]
62
+ "Control#init_plugin"
63
+ "Control#api_server"
64
+ "Control#proxy_server"
65
+ "Control#server_from_host"
66
+ "Control#http_connection"
67
+ "Control#set_log_level!"
68
+ "Control#log_path"
69
+ "Control#log_to_stdout?"
70
+ "Control#convert_to_ip_address"
71
+ "Control#server"
72
+ "Control#setup_log"
73
+ "Control#should_log?"
74
+ "Control#log!"
75
+
76
+ node[color=green]
77
+ "Config#app_names"
78
+
79
+ node[color=black]
80
+ "Agent#initialize"
81
+ "Agent#after_fork"
82
+ "Agent#disabled?"
83
+ "Agent#shutdown"
84
+ "Agent#using_forking_dispatcher?"
85
+ "Agent#has_license_key?"
86
+ "Agent#correct_license_length"
87
+ "Agent#apdex_f"
88
+ "Agent#check_config_and_start_agent"
89
+ "Agent#install_exit_handler"
90
+ "Agent#log_app_names"
91
+ "Agent#connect_settings"
92
+ "Agent#log_seed_token"
93
+ "Agent#log_error"
94
+ "Agent#monitoring?"
95
+ "Agent#check_trasaction_sampler_status"
96
+ "Agent#check_sql_sampler_status"
97
+ "Agent#config_transaction_tracer"
98
+ "Agent#set_sql_recording!"
99
+ "Agent#already_started?"
100
+ "Agent#log_connection"
101
+ "Agent#manual_start"
102
+
103
+ "MethodTracer#remove_method_tracer"
104
+
105
+ "ErrorCollector#initialize"
106
+ "ErrorCollector#request_params_from_opts"
107
+
108
+ "ControllerInstrumentation#perform_action_with_newrelic_trace"
109
+
110
+ "NewRelicService#initialize"
111
+ "NewRelicService#check_post_size"
112
+ "NewRelicService#connect"
113
+ "NewRelicService#send_request"
114
+
115
+ "SqlSampler#configure!"
116
+
117
+ "TransactionSampler#configure!"
118
+ "TransactionSampler#notice_push_scope"
119
+ "TransactionSampler#capture_segment_trace"
120
+ "TransactionSampler#store_segment_for_developer_mode"
121
+
122
+ "NoticedError#initialize"
123
+
124
+ "BeaconConfiguration#license_bytes"
125
+
126
+ "ActiveRecord#depends_on"
127
+ "DelayedJobInstrumentation#depends_on"
128
+ "Memcache#memcache_key_snippet"
129
+ "Memcache#depends_on"
130
+ "Rails::ActionController#depends_on"
131
+ "Rails3::ActionController#depends_on"
132
+ "Resque#depends_on"
133
+
134
+ "DelayedJobSampler#initialize"
135
+ "DelayedJobInjection#depends_on"
136
+
137
+ "MetricFrame.update_apdex"
138
+
139
+ "TranactionInfo#force_persist_sample?"
140
+ "TranactionInfo#include_guid?"
141
+
142
+ "TransactionSampleBuilder#initialize"
143
+ "TransactionSampleBuilder#set_transaction_info"
144
+
145
+ "Rails#install_browser_monitoring"
146
+ "Rails#log!"
147
+ "Rails3#log!"
148
+
149
+ "CollectionHelper#strip_nr_from_backtrace"
150
+
151
+ "Deployments#initialize"
152
+
153
+ #######
154
+
155
+ "Control#init_plugin" -> "[agent_enabled]"
156
+ "Control#init_plugin" -> "Control#setup_log"
157
+ "Control#init_plugin" -> "[disable_samplers]"
158
+ "Control#should_log?" -> "[agent_enabled]"
159
+ "Control#api_server" -> "[api_host]"
160
+ "Control#api_server" -> "[api_port]"
161
+ "Control#proxy_server" -> "[proxy_host]"
162
+ "Control#proxy_server" -> "[proxy_port]"
163
+ "Control#proxy_server" -> "[proxy_user]"
164
+ "Control#proxy_server" -> "[proxy_pass]"
165
+ "Control#server_from_host" -> "[host]"
166
+ "Control#server_from_host" -> "[port]"
167
+ "Control#server_from_host" -> "Control#convert_to_ip_address"
168
+ "Control#http_connection" -> "[ssl]"
169
+ "Control#http_connection" -> "[verify_certificate]"
170
+ "Control#http_connection" -> "Control#proxy_server"
171
+ "Control#set_log_level!" -> "[log_level]"
172
+ "Control#log_path" -> "[log_file_path]"
173
+ "Control#log_path" -> "Control#log_to_stdout?"
174
+ "Control#log_to_stdout?" -> "[log_file_path]"
175
+ "Control#convert_to_ip_address" -> "[ssl]"
176
+ "Control#convert_to_ip_address" -> "[verify_certificate]"
177
+ "Control#server" -> "Control#server_from_host"
178
+ "Control#setup_log" -> "Control#set_log_level!"
179
+ "Control#setup_log" -> "Control#log_path"
180
+ "Control#setup_log" -> "Control#log_to_stdout?"
181
+ "Control#setup_log" -> "[log_file_name]"
182
+ "Control#log!" -> "Control#should_log?"
183
+ "Control#log!" -> "Control#log_path"
184
+
185
+ "Agent#initialize" -> "[monitor_mode]"
186
+ "Agent#after_fork" -> "[agent_enabled]"
187
+ "Agent#after_fork" -> "[monitor_mode]"
188
+ "Agent#disabled?" -> "[agent_enabled]"
189
+ "Agent#shutdown" -> "[force_send]"
190
+ "Agent#shutdown" -> "[dispatcher]"
191
+ "Agent#using_forking_dispatcher?" -> "[dispatcher]"
192
+ "Agent#has_license_key?" -> "[license_key]"
193
+ "Agent#correct_license_length" -> "[license_key]"
194
+ "Agent#apdex_f" -> "[apdex_t]"
195
+ "Agent#check_config_and_start_agent" -> "[sync_startup]"
196
+ "Agent#install_exit_handler" -> "[send_data_on_exit]"
197
+ "Agent#log_app_names" -> "Config#app_names"
198
+ "Agent#connect_settings" -> "Config#app_names"
199
+ "Agent#log_seed_token" -> "[validate_seed]"
200
+ "Agent#log_seed_token" -> "[validate_token]"
201
+ "Agent#validate_settings" -> "[validate_seed]"
202
+ "Agent#validate_settings" -> "[validate_token]"
203
+ "Agent#log_error" -> "Control#server"
204
+ "Agent#monitoring?" -> "[monitor_mode]"
205
+ "Agent#check_trasaction_sampler_status" -> "[developer_mode]"
206
+ "Agent#check_sql_sampler_status" -> "[slow_sql.enabled]"
207
+ "Agent#check_sql_sampler_status" -> "[slow_sql.record_sql]"
208
+ "Agent#check_sql_sampler_status" -> "[transaction_tracer.enabled]"
209
+ "Agent#config_transaction_tracer" -> "[transaction_tracer.enabled]"
210
+ "Agent#config_transaction_tracer" -> "[transaction_tracer.random_sample]"
211
+ "Agent#config_transaction_tracer" -> "[transaction_tracer.transaction_threshold]"
212
+ "Agent#set_sql_recording!" -> "[transaction_tracer.record_sql]"
213
+ "Agent#already_started?" -> "Control#log!"
214
+ "Agent#log_connection" -> "Control#log!"
215
+ "Agent#manual_start" -> "Control#init_plugin"
216
+
217
+ "MethodTracer#remove_method_tracer" -> "[agent_enabled]"
218
+
219
+ "Rails#init_config" -> "[agent_enabled]"
220
+ "Rails#init_config" -> "[developer_mode]"
221
+
222
+ "ErrorCollector#initialize" -> "[error_collector.enabled]"
223
+ "ErrorCollector#initialize" -> "[error_collector.capture_source]"
224
+ "ErrorCollector#initialize" -> "[error_collector.ignore_errors]"
225
+ "ErrorCollector#request_params_from_opts" -> "[capture_params]"
226
+
227
+ "ControllerInstrumentation#perform_action_with_newrelic_trace" -> "[disable_mobile_headers]"
228
+
229
+ "NewRelicService#initialize" -> "[timeout]"
230
+ "NewRelicService#initialize" -> "[license_key]"
231
+ "NewRelicService#initialize" -> "Control#server"
232
+ "NewRelicService#check_post_size" -> "[post_size_limit]"
233
+ "NewRelicService#connect" -> "Control#server_from_host"
234
+ "NewRelicService#send_request" -> "Control#http_connection"
235
+
236
+ "SqlSampler#configure!" -> "[slow_sql.explain_threshold]"
237
+ "SqlSampler#configure!" -> "[slow_sql.explain_enabled]"
238
+ "SqlSampler#configure!" -> "[slow_sql.stack_trace_threshold]"
239
+ "SqlSampler#configure!" -> "[slow_sql.enabled]"
240
+
241
+ "TransactionSampler#configure!" -> "[transaction_tracer.limit_segments]"
242
+ "TransactionSampler#configure!" -> "[transaction_tracer.stack_trace_threshold]"
243
+ "TransactionSampler#configure!" -> "[transaction_tracer.explain_threshold]"
244
+ "TransactionSampler#configure!" -> "[transaction_tracer.explain_enabled]"
245
+ "TransactionSampler#configure!" -> "[transaction_tracer.transaction_threshold]"
246
+ "TransactionSampler#configure!" -> "[developer_mode]"
247
+ "TransactionSampler#notice_push_scope" -> "[developer_mode]"
248
+ "TransactionSampler#capture_segment_trace" -> "[developer_mode]"
249
+ "TransactionSampler#store_segment_for_developer_mode" -> "[developer_mode]"
250
+
251
+ "NoticedError#initialize" -> "[high_security]"
252
+
253
+ "BeaconConfiguration#license_bytes" -> "[license_key]"
254
+
255
+ "ActiveRecord#depends_on" -> "[disable_activerecord_instrumentation]"
256
+
257
+ "DelayedJobInstrumentation#depends_on" -> "[disable_dj]"
258
+
259
+ "Memcache#memcache_key_snippet" -> "[capture_memcache_keys]"
260
+ "Memcache#depends_on" -> "[disable_memcache_instrumentation]"
261
+
262
+ "Rails::ActionController#depends_on" -> "[disable_view_instrumentation]"
263
+ "Rails3::ActionController#depends_on" -> "[disable_view_instrumentation]"
264
+ "Resque#depends_on" -> "[disable_resque]"
265
+
266
+ "DelayedJobSampler#initialize" -> "[disable_dj]"
267
+ "DelayedJobInjection#depends_on" -> "[disable_dj]"
268
+ "DelayedJobInjection#executes" -> "Control#init_plugin"
269
+
270
+ "MetricFrame.update_apdex" -> "[apdex_t]"
271
+
272
+ "TranactionInfo#force_persist_sample?" -> "[apdex_t]"
273
+ "TranactionInfo#include_guid?" -> "[apdex_t]"
274
+
275
+ "TransactionSampleBuilder#initialize" -> "[transaction_tracer.limit_segments]"
276
+ "TransactionSampleBuilder#set_transaction_info" -> "[capture_params]"
277
+
278
+ "Rails#install_browser_monitoring" -> "[browser_monitoring.auto_instrument]"
279
+ "Rails#log!" -> "Control#should_log?"
280
+ "Rails3#log!" -> "Control#should_log?"
281
+
282
+ "CollectionHelper#strip_nr_from_backtrace" -> "[disable_backtrace_cleanup]"
283
+
284
+ "Deployments#initialize" -> "Config#app_names"
285
+ "Deployments#run" -> "Control#http_connection"
286
+ "Deployments#run" -> "[license_key]"
287
+ "Deployments#run" -> "Control#api_server"
288
+
289
+ "Config#app_names" -> "[app_name]"
290
+ }
@@ -0,0 +1,5 @@
1
+ # This config is used when setting up a basic rails environment for running the
2
+ # unit tests.
3
+ test:
4
+ database: ':memory:'
5
+ adapter: 'sqlite3'
data/init.rb ADDED
@@ -0,0 +1,38 @@
1
+ # This is the initialization for the New Relic Ruby Agent when used as
2
+ # a plugin
3
+ require 'new_relic/control'
4
+
5
+ # If you are having problems seeing data, be sure and check the
6
+ # newrelic_agent.log files in the log diretory of your application
7
+ #
8
+ # If you can't find any log files and you don't see anything in your
9
+ # application log files, try uncommenting the two lines at the
10
+ # bottom of this file to verify the plugin is being loaded,
11
+ # then send the output to support@newrelic.com if you are unable to
12
+ # resolve the issue.
13
+
14
+ # Initializer for the NewRelic Ruby Agent
15
+
16
+ # After verison 2.0 of Rails we can access the configuration directly.
17
+ # We need it to add dev mode routes after initialization finished.
18
+
19
+ begin
20
+
21
+ current_config = if defined?(config)
22
+ config
23
+ elsif defined?(Rails.configuration)
24
+ Rails.configuration
25
+ end
26
+
27
+ NewRelic::Control.instance.init_plugin :config => current_config
28
+
29
+ rescue => e
30
+ NewRelic::Control.instance.log! "Error initializing New Relic plugin (#{e})", :error
31
+ NewRelic::Control.instance.log! e.backtrace.join("\n"), :error
32
+ NewRelic::Control.instance.log! "Agent is disabled."
33
+ end
34
+
35
+ #ClassLoadingWatcher.flag_const_missing = nil
36
+ #
37
+ # ::RAILS_DEFAULT_LOGGER.warn "New Relic detected environment: #{NewRelic::Control.instance.local_env.to_s}, RAILS_ENV: #{RAILS_ENV}"
38
+ # ::RAILS_DEFAULT_LOGGER.warn "Enabled? #{NewRelic::Control.instance.agent_enabled?}"
@@ -84,12 +84,14 @@ module NewRelic
84
84
  require 'new_relic/agent/stats_engine'
85
85
  require 'new_relic/agent/transaction_sampler'
86
86
  require 'new_relic/agent/sql_sampler'
87
+ require 'new_relic/agent/thread_profiler'
87
88
  require 'new_relic/agent/error_collector'
88
89
  require 'new_relic/agent/busy_calculator'
89
90
  require 'new_relic/agent/sampler'
90
91
  require 'new_relic/agent/database'
91
92
  require 'new_relic/agent/pipe_channel_manager'
92
93
  require 'new_relic/agent/transaction_info'
94
+ require 'new_relic/agent/configuration'
93
95
 
94
96
  require 'new_relic/agent/instrumentation/controller_instrumentation'
95
97
 
@@ -101,6 +103,8 @@ module NewRelic
101
103
  require 'thread'
102
104
  require 'resolv'
103
105
 
106
+ extend NewRelic::Agent::Configuration::Instance
107
+
104
108
  # An exception that is thrown by the server if the agent license is invalid.
105
109
  class LicenseException < StandardError; end
106
110
 
@@ -114,9 +118,9 @@ module NewRelic
114
118
  # failures.
115
119
  class ServerConnectionException < StandardError; end
116
120
 
117
- # Used for when a transaction trace or error report has too much
118
- # data, so we reset the queue to clear the extra-large item
119
- class PostTooBigException < ServerConnectionException; end
121
+ # When a post is either too large or poorly formatted we should
122
+ # drop it and not try to resend
123
+ class UnrecoverableServerException < ServerConnectionException; end
120
124
 
121
125
  # Reserved for future use. Meant to represent a problem on the server side.
122
126
  class ServerError < StandardError; end
@@ -302,7 +306,8 @@ module NewRelic
302
306
 
303
307
  # Check to see if we are capturing metrics currently on this thread.
304
308
  def is_execution_traced?
305
- Thread.current[:newrelic_untraced].nil? || Thread.current[:newrelic_untraced].last != false
309
+ untraced = Thread.current[:newrelic_untraced]
310
+ untraced.nil? || untraced.last != false
306
311
  end
307
312
 
308
313
  # helper method to check the thread local to determine whether the
@@ -6,6 +6,9 @@ require 'zlib'
6
6
  require 'stringio'
7
7
  require 'new_relic/agent/new_relic_service'
8
8
  require 'new_relic/agent/pipe_service'
9
+ require 'new_relic/agent/configuration/manager'
10
+ require 'new_relic/agent/database'
11
+ require 'new_relic/agent/thread_profiler'
9
12
 
10
13
  module NewRelic
11
14
  module Agent
@@ -15,6 +18,8 @@ module NewRelic
15
18
  # in realtime as the application runs, and periodically sends that
16
19
  # data to the NewRelic server.
17
20
  class Agent
21
+ extend NewRelic::Agent::Configuration::Instance
22
+
18
23
  def initialize
19
24
  @launch_time = Time.now
20
25
 
@@ -22,7 +27,7 @@ module NewRelic
22
27
  @stats_engine = NewRelic::Agent::StatsEngine.new
23
28
  @transaction_sampler = NewRelic::Agent::TransactionSampler.new
24
29
  @sql_sampler = NewRelic::Agent::SqlSampler.new
25
- @stats_engine.transaction_sampler = @transaction_sampler
30
+ @thread_profiler = NewRelic::Agent::ThreadProfiler.new
26
31
  @error_collector = NewRelic::Agent::ErrorCollector.new
27
32
  @connect_attempts = 0
28
33
 
@@ -31,9 +36,20 @@ module NewRelic
31
36
  @forked = false
32
37
 
33
38
  # FIXME: temporary work around for RUBY-839
34
- if control.monitor_mode?
35
- @service = NewRelic::Agent::NewRelicService.new(control.license_key, control.server)
39
+ if Agent.config[:monitor_mode]
40
+ @service = NewRelic::Agent::NewRelicService.new
41
+ end
42
+
43
+ txn_tracer_enabler = Proc.new do
44
+ if NewRelic::Agent.config[:'transaction_tracer.enabled'] ||
45
+ NewRelic::Agent.config[:developer_mode]
46
+ @stats_engine.transaction_sampler = @transaction_sampler
47
+ else
48
+ @stats_engine.transaction_sampler = nil
49
+ end
36
50
  end
51
+ Agent.config.register_callback(:'transaction_tracer.enabled', &txn_tracer_enabler)
52
+ Agent.config.register_callback(:developer_mode, &txn_tracer_enabler)
37
53
  end
38
54
 
39
55
  # contains all the class-level methods for NewRelic::Agent::Agent
@@ -44,11 +60,11 @@ module NewRelic
44
60
  @instance ||= self.new
45
61
  end
46
62
  end
47
-
63
+
48
64
  # Holds all the methods defined on NewRelic::Agent::Agent
49
65
  # instances
50
66
  module InstanceMethods
51
-
67
+
52
68
  # holds a proc that is used to obfuscate sql statements
53
69
  attr_reader :obfuscator
54
70
  # the statistics engine that holds all the timeslice data
@@ -56,6 +72,8 @@ module NewRelic
56
72
  # the transaction sampler that handles recording transactions
57
73
  attr_reader :transaction_sampler
58
74
  attr_reader :sql_sampler
75
+ # begins a thread profile session when instructed by agent commands
76
+ attr_reader :thread_profiler
59
77
  # error collector is a simple collection of recorded errors
60
78
  attr_reader :error_collector
61
79
  # whether we should record raw, obfuscated, or no sql
@@ -72,19 +90,19 @@ module NewRelic
72
90
  # into pages
73
91
  attr_reader :beacon_configuration
74
92
  attr_accessor :service
75
-
93
+
76
94
  # Returns the length of the unsent errors array, if it exists,
77
95
  # otherwise nil
78
96
  def unsent_errors_size
79
97
  @unsent_errors.length if @unsent_errors
80
98
  end
81
-
99
+
82
100
  # Returns the length of the traces array, if it exists,
83
101
  # otherwise nil
84
102
  def unsent_traces_size
85
103
  @traces.length if @traces
86
104
  end
87
-
105
+
88
106
  # Initializes the unsent timeslice data hash, if needed, and
89
107
  # returns the number of keys it contains
90
108
  def unsent_timeslice_data
@@ -95,7 +113,7 @@ module NewRelic
95
113
  # fakes out a transaction that did not happen in this process
96
114
  # by creating apdex, summary metrics, and recording statistics
97
115
  # for the transaction
98
- #
116
+ #
99
117
  # This method is *deprecated* - it may be removed in future
100
118
  # versions of the agent
101
119
  def record_transaction(duration_seconds, options={})
@@ -150,23 +168,25 @@ module NewRelic
150
168
  # quickly if there is some kind of latency with the server.
151
169
  def after_fork(options={})
152
170
  @forked = true
171
+ Agent.config.apply_config(NewRelic::Agent::Configuration::ManualSource.new(options), 1)
172
+
153
173
  # @connected gets false after we fail to connect or have an error
154
174
  # connecting. @connected has nil if we haven't finished trying to connect.
155
175
  # or we didn't attempt a connection because this is the master process
156
-
176
+
157
177
  if channel_id = options[:report_to_channel]
158
178
  @service = NewRelic::Agent::PipeService.new(channel_id)
159
179
  @connected_pid = $$
160
180
  @metric_ids = {}
161
181
  end
162
-
182
+
163
183
  # log.debug "Agent received after_fork notice in #$$: [#{control.agent_enabled?}; monitor=#{control.monitor_mode?}; connected: #{@connected.inspect}; thread=#{@worker_thread.inspect}]"
164
- return if !control.agent_enabled? or
165
- !control.monitor_mode? or
166
- @connected == false or
184
+ return if !Agent.config[:agent_enabled] ||
185
+ !Agent.config[:monitor_mode] ||
186
+ @connected == false ||
167
187
  @worker_thread && @worker_thread.alive?
168
188
 
169
- log.info "Starting the worker thread in #$$ after forking."
189
+ log.info "Starting the worker thread in #{$$} after forking."
170
190
 
171
191
  # Clear out stats that are left over from parent process
172
192
  reset_stats
@@ -176,11 +196,11 @@ module NewRelic
176
196
  start_worker_thread(options)
177
197
  @stats_engine.start_sampler_thread
178
198
  end
179
-
199
+
180
200
  def forked?
181
201
  @forked
182
202
  end
183
-
203
+
184
204
  # True if we have initialized and completed 'start'
185
205
  def started?
186
206
  @started
@@ -199,7 +219,7 @@ module NewRelic
199
219
  # :force_send => (true/false) # force the agent to send data
200
220
  # before shutting down
201
221
  def shutdown(options={})
202
- run_loop_before_exit = options.fetch(:force_send, false)
222
+ run_loop_before_exit = Agent.config[:force_send]
203
223
  return if not started?
204
224
  if @worker_loop
205
225
  @worker_loop.run_task if run_loop_before_exit
@@ -211,7 +231,7 @@ module NewRelic
211
231
  # if litespeed, then ignore all future SIGUSR1 - it's
212
232
  # litespeed trying to shut us down
213
233
 
214
- if control.dispatcher == :litespeed
234
+ if Agent.config[:dispatcher] == :litespeed
215
235
  Signal.trap("SIGUSR1", "IGNORE")
216
236
  Signal.trap("SIGTERM", "IGNORE")
217
237
  end
@@ -224,6 +244,10 @@ module NewRelic
224
244
  log.error e
225
245
  log.error e.backtrace.join("\n")
226
246
  end
247
+ NewRelic::Agent.config.remove_config do |config|
248
+ config.class == NewRelic::Agent::Configuration::ManualSource ||
249
+ config.class == NewRelic::Agent::Configuration::ServerSource
250
+ end
227
251
  @started = nil
228
252
  end
229
253
 
@@ -280,7 +304,7 @@ module NewRelic
280
304
  end
281
305
 
282
306
  # Herein lies the corpse of the former 'start' method. May
283
- # it's unmatched flog score rest in pieces.
307
+ # its unmatched flog score rest in pieces.
284
308
  module Start
285
309
  # Check whether we have already started, which is an error condition
286
310
  def already_started?
@@ -294,23 +318,28 @@ module NewRelic
294
318
  # 'agent_enabled' option (e.g. in a manual start), or
295
319
  # enabled normally through the configuration file
296
320
  def disabled?
297
- !control.agent_enabled?
321
+ !Agent.config[:agent_enabled]
298
322
  end
299
323
 
300
324
  # Logs the dispatcher to the log file to assist with
301
325
  # debugging. When no debugger is present, logs this fact to
302
326
  # assist with proper dispatcher detection
303
327
  def log_dispatcher
304
- dispatcher_name = control.dispatcher.to_s
328
+ dispatcher_name = Agent.config[:dispatcher].to_s
305
329
  return if log_if(dispatcher_name.empty?, :info, "No dispatcher detected.")
306
330
  log.info "Dispatcher: #{dispatcher_name}"
307
331
  end
308
332
 
309
333
  # Logs the configured application names
310
334
  def log_app_names
311
- log.info "Application: #{control.app_names.join(", ")}"
335
+ names = Agent.config.app_names
336
+ if names.respond_to?(:any?) && names.any?
337
+ log.info "Application: #{names.join(", ")}"
338
+ else
339
+ log.error 'Unable to determine application name. Please set the application name in your newrelic.yml or in a NEW_RELIC_APP_NAME environment variable.'
340
+ end
312
341
  end
313
-
342
+
314
343
  # Connecting in the foreground blocks further startup of the
315
344
  # agent until we have a connection - useful in cases where
316
345
  # you're trying to log a very-short-running process and want
@@ -338,9 +367,20 @@ module NewRelic
338
367
  # behavior of at_exit blocks to make sure it runs last, by
339
368
  # doing an at_exit within an at_exit block.
340
369
  def install_exit_handler
341
- if control.send_data_on_exit && !weird_ruby?
342
- # Our shutdown handler needs to run after other shutdown handlers
343
- at_exit { at_exit { shutdown } }
370
+ if Agent.config[:send_data_on_exit] && !weird_ruby?
371
+ at_exit do
372
+ # Workaround for MRI 1.9 bug that loses exit codes in at_exit blocks.
373
+ # This is necessary to get correct exit codes for the agent's
374
+ # test suites.
375
+ # http://bugs.ruby-lang.org/issues/5218
376
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/)
377
+ exit_status = $!.status if $!.is_a?(SystemExit)
378
+ shutdown
379
+ exit exit_status if exit_status
380
+ else
381
+ shutdown
382
+ end
383
+ end
344
384
  end
345
385
  end
346
386
 
@@ -380,13 +420,15 @@ module NewRelic
380
420
  # Warn the user if they have configured their agent not to
381
421
  # send data, that way we can see this clearly in the log file
382
422
  def monitoring?
383
- log_unless(control.monitor_mode?, :warn, "Agent configured not to send data in this environment - edit newrelic.yml to change this")
423
+ log_unless(Agent.config[:monitor_mode], :warn,
424
+ "Agent configured not to send data in this environment.")
384
425
  end
385
426
 
386
427
  # Tell the user when the license key is missing so they can
387
428
  # fix it by adding it to the file
388
429
  def has_license_key?
389
- log_unless(control.license_key, :error, "No license key found. Please edit your newrelic.yml file and insert your license key.")
430
+ log_unless(Agent.config[:license_key], :warn,
431
+ "No license key found in newrelic.yml config.")
390
432
  end
391
433
 
392
434
  # A correct license key exists and is of the proper length
@@ -397,7 +439,7 @@ module NewRelic
397
439
  # A license key is an arbitrary 40 character string,
398
440
  # usually looks something like a SHA1 hash
399
441
  def correct_license_length
400
- key = control.license_key
442
+ key = Agent.config[:license_key]
401
443
  log_unless((key.length == 40), :error, "Invalid license key: #{key}")
402
444
  end
403
445
 
@@ -405,7 +447,8 @@ module NewRelic
405
447
  # requests, we need to wait until the children are forked
406
448
  # before connecting, otherwise the parent process sends odd data
407
449
  def using_forking_dispatcher?
408
- log_if([:passenger, :unicorn, :rainbows].include?(control.dispatcher), :info, "Connecting workers after forking.")
450
+ log_if([:passenger, :unicorn, :rainbows].include?(Agent.config[:dispatcher]),
451
+ :info, "Connecting workers after forking.")
409
452
  end
410
453
 
411
454
  # Sanity-check the agent configuration and start the agent,
@@ -414,7 +457,7 @@ module NewRelic
414
457
  def check_config_and_start_agent
415
458
  return unless monitoring? && has_correct_license_key?
416
459
  return if using_forking_dispatcher?
417
- connect_in_foreground if control.sync_startup
460
+ connect_in_foreground if Agent.config[:sync_startup]
418
461
  start_worker_thread
419
462
  install_exit_handler
420
463
  end
@@ -429,7 +472,6 @@ module NewRelic
429
472
  @local_host = determine_host
430
473
  log_dispatcher
431
474
  log_app_names
432
- config_transaction_tracer
433
475
  check_config_and_start_agent
434
476
  log_version_and_pid
435
477
  notify_log_file_location
@@ -447,36 +489,15 @@ module NewRelic
447
489
  end
448
490
 
449
491
  private
450
-
492
+
451
493
  # All of this module used to be contained in the
452
494
  # start_worker_thread method - this is an artifact of
453
495
  # refactoring and can be moved, renamed, etc at will
454
496
  module StartWorkerThread
455
-
456
- # disable transaction sampling if disabled by the server
457
- # and we're not in dev mode
458
- def check_transaction_sampler_status
459
- if control.developer_mode? || @should_send_samples
460
- @transaction_sampler.enable
461
- else
462
- @transaction_sampler.disable
463
- end
464
- end
465
-
466
- def check_sql_sampler_status
467
- # disable sql sampling if disabled by the server
468
- # and we're not in dev mode
469
- if @sql_sampler.config.fetch('enabled', true) && ['raw', 'obfuscated'].include?(@sql_sampler.config.fetch('record_sql', 'obfuscated').to_s) && @transaction_sampler.config.fetch('enabled', true)
470
- @sql_sampler.enable
471
- else
472
- @sql_sampler.disable
473
- end
474
- end
475
-
476
497
  # logs info about the worker loop so users can see when the
477
498
  # agent actually begins running in the background
478
499
  def log_worker_loop_start
479
- log.info "Reporting performance data every #{@report_period} seconds."
500
+ log.info "Reporting performance data every #{Agent.config[:data_report_period]} seconds."
480
501
  log.debug "Running worker loop"
481
502
  end
482
503
 
@@ -484,7 +505,7 @@ module NewRelic
484
505
  # it should run every @report_period seconds
485
506
  def create_and_run_worker_loop
486
507
  @worker_loop = WorkerLoop.new
487
- @worker_loop.run(@report_period) do
508
+ @worker_loop.run(Agent.config[:data_report_period]) do
488
509
  transmit_data
489
510
  end
490
511
  end
@@ -557,8 +578,6 @@ module NewRelic
557
578
  # that means it didn't try to connect because we're in the master.
558
579
  connect(connection_options)
559
580
  if @connected
560
- check_transaction_sampler_status
561
- check_sql_sampler_status
562
581
  log_worker_loop_start
563
582
  create_and_run_worker_loop
564
583
  # never reaches here unless there is a problem or
@@ -577,17 +596,16 @@ module NewRelic
577
596
  # See #connect for a description of connection_options.
578
597
  def start_worker_thread(connection_options = {})
579
598
  log.debug "Creating Ruby Agent worker thread."
580
- @worker_thread = Thread.new do
599
+ @worker_thread = NewRelic::Agent::Thread.new('Worker Loop') do
581
600
  deferred_work!(connection_options)
582
- end # thread new
583
- @worker_thread['newrelic_label'] = 'Worker Loop'
601
+ end
584
602
  end
585
603
 
586
604
  # A shorthand for NewRelic::Control.instance
587
605
  def control
588
606
  NewRelic::Control.instance
589
607
  end
590
-
608
+
591
609
  # This module is an artifact of a refactoring of the connect
592
610
  # method - all of its methods are used in that context, so it
593
611
  # can be refactored at will. It should be fully tested
@@ -673,15 +691,15 @@ module NewRelic
673
691
  # should debug log that fact so that debug logs include a
674
692
  # clue that token authentication is what will be used
675
693
  def log_seed_token
676
- if control.validate_seed
677
- log.debug "Connecting with validation seed/token: #{control.validate_seed}/#{control.validate_token}"
694
+ if Agent.config[:validate_seed]
695
+ log.debug "Connecting with validation seed/token: #{Agent.config[:validate_seed]}/#{Agent.config[:validate_token]}"
678
696
  end
679
697
  end
680
698
 
681
699
  # Checks whether we should send environment info, and if so,
682
700
  # returns the snapshot from the local environment
683
701
  def environment_for_connect
684
- control['send_environment_info'] != false ? control.local_env.snapshot : []
702
+ Agent.config[:send_environment_info] ? Control.instance.local_env.snapshot : []
685
703
  end
686
704
 
687
705
  # These validation settings are used for cases where a
@@ -690,8 +708,8 @@ module NewRelic
690
708
  # allowed to connect, rather than setting a unique hostname
691
709
  def validate_settings
692
710
  {
693
- :seed => control.validate_seed,
694
- :token => control.validate_token
711
+ :seed => Agent.config[:validate_seed],
712
+ :token => Agent.config[:validate_token]
695
713
  }
696
714
  end
697
715
 
@@ -701,11 +719,11 @@ module NewRelic
701
719
  {
702
720
  :pid => $$,
703
721
  :host => @local_host,
704
- :app_name => control.app_names,
722
+ :app_name => Agent.config.app_names,
705
723
  :language => 'ruby',
706
724
  :agent_version => NewRelic::VERSION::STRING,
707
725
  :environment => environment_for_connect,
708
- :settings => control.settings,
726
+ :settings => Agent.config.flattened_config,
709
727
  :validate => validate_settings
710
728
  }
711
729
  end
@@ -718,127 +736,11 @@ module NewRelic
718
736
  @service.connect(connect_settings)
719
737
  end
720
738
 
721
- # Configures the error collector if the server says that we
722
- # are allowed to send errors. Pretty simple, and logs at
723
- # debug whether errors will or will not be sent.
724
- def configure_error_collector!(server_enabled)
725
- # Reinitialize the error collector
726
- @error_collector = NewRelic::Agent::ErrorCollector.new
727
- # Ask for permission to collect error data
728
- enabled = if error_collector.config_enabled && server_enabled
729
- error_collector.enabled = true
730
- else
731
- error_collector.enabled = false
732
- end
733
- log.debug "Errors will #{enabled ? '' : 'not '}be sent to the New Relic service."
734
- end
735
-
736
- # Random sampling is enabled based on a sample rate, which
737
- # is the n in "every 1/n transactions is added regardless of
738
- # its length".
739
- #
740
- # uses a sane default for sampling rate if the sampling rate
741
- # is zero, since the collector currently sends '0' as a
742
- # sampling rate for all accounts, which is probably for
743
- # legacy reasons
744
- def enable_random_samples!(sample_rate)
745
- sample_rate = 10 unless sample_rate.to_i > 0
746
- @transaction_sampler.random_sampling = true
747
- @transaction_sampler.sampling_rate = sample_rate
748
- log.info "Transaction sampling enabled, rate = #{@transaction_sampler.sampling_rate}"
749
- end
750
-
751
- # this entire method should be done on the transaction
752
- # sampler object, rather than here. We should pass in the
753
- # sampler config.
754
- def config_transaction_tracer
755
- # Reconfigure the transaction tracer
756
- @transaction_sampler.configure!
757
- @sql_sampler.configure!
758
- @should_send_samples = @config_should_send_samples = @transaction_sampler.config.fetch('enabled', true)
759
- @should_send_random_samples = @transaction_sampler.config.fetch('random_sample', false)
760
- set_sql_recording!
761
-
762
- # default to 2.0, string 'apdex_f' will turn into your
763
- # apdex * 4
764
- @slowest_transaction_threshold = @transaction_sampler.config.fetch('transaction_threshold', 2.0).to_f
765
- @slowest_transaction_threshold = apdex_f if apdex_f_threshold?
766
- end
767
-
768
- # Enables or disables the transaction tracer and sets its
769
- # options based on the options provided to the
770
- # method.
771
- def configure_transaction_tracer!(server_enabled, sample_rate)
772
- # Ask the server for permission to send transaction samples.
773
- # determined by subscription license.
774
- @transaction_sampler.config['enabled'] = server_enabled
775
- @sql_sampler.configure!
776
- @should_send_samples = @config_should_send_samples && server_enabled
777
-
778
- if @should_send_samples
779
- # I don't think this is ever true, but...
780
- enable_random_samples!(sample_rate) if @should_send_random_samples
781
-
782
- @transaction_sampler.slow_capture_threshold = @slowest_transaction_threshold
783
-
784
- log.debug "Transaction tracing threshold is #{@slowest_transaction_threshold} seconds."
785
- else
786
- log.debug "Transaction traces will not be sent to the New Relic service."
787
- end
788
- end
789
-
790
739
  # apdex_f is always 4 times the apdex_t
791
740
  def apdex_f
792
- (4 * NewRelic::Control.instance.apdex_t).to_f
793
- end
794
-
795
- # If the transaction threshold is set to the string
796
- # 'apdex_f', we use 4 times the apdex_t value to record
797
- # transactions. This gears well with using apdex since you
798
- # will attempt to send any transactions that register as 'failing'
799
- def apdex_f_threshold?
800
- @transaction_sampler.config.fetch('transaction_threshold', '') =~ /apdex_f/i
801
- end
802
-
803
- # Sets the sql recording configuration by trying to detect
804
- # any attempt to disable the sql collection - 'off',
805
- # 'false', 'none', and friends. Otherwise, we accept 'raw',
806
- # and unrecognized values default to 'obfuscated'
807
- def set_sql_recording!
808
- record_sql_config = @transaction_sampler.config.fetch('record_sql', :obfuscated)
809
- case record_sql_config.to_s
810
- when 'off'
811
- @record_sql = :off
812
- when 'none'
813
- @record_sql = :off
814
- when 'false'
815
- @record_sql = :off
816
- when 'raw'
817
- @record_sql = :raw
818
- else
819
- @record_sql = :obfuscated
820
- end
821
-
822
- log_sql_transmission_warning?
823
- end
824
-
825
- # Warn the user when we are sending raw sql across the wire
826
- # - they should probably be using ssl when this is true
827
- def log_sql_transmission_warning?
828
- log.warn("Agent is configured to send raw SQL to the service") if @record_sql == :raw
741
+ (4 * Agent.config[:apdex_t]).to_f
829
742
  end
830
743
 
831
- # Asks the collector to tell us which sub-collector we
832
- # should be reporting to, and then does the name resolution
833
- # on that host so we don't block on DNS during the normal
834
- # course of agent processing
835
- # def set_collector_host!
836
- # host = invoke_remote(:get_redirect_host)
837
- # if host
838
- # @collector = control.server_from_host(host)
839
- # end
840
- # end
841
-
842
744
  # Sets the collector host and connects to the server, then
843
745
  # invokes the final configuration with the returned data
844
746
  def query_server_for_configuration
@@ -854,30 +756,36 @@ module NewRelic
854
756
  # ignored unless we say to do something with it here.
855
757
  def finish_setup(config_data)
856
758
  return if config_data == nil
857
- @service.agent_id = config_data['agent_run_id']
858
- @report_period = config_data['data_report_period']
859
- @url_rules = config_data['url_rules']
860
- @beacon_configuration = BeaconConfiguration.new(config_data)
861
- @server_side_config_enabled = config_data['listen_to_server_config']
862
759
 
863
- if @server_side_config_enabled
760
+ @service.agent_id = config_data['agent_run_id'] if @service
761
+
762
+ if config_data['agent_config']
864
763
  log.info "Using config from server"
865
- log.debug "Server provided config: #{config_data.inspect}"
866
764
  end
867
765
 
868
- control.merge_server_side_config(config_data) if @server_side_config_enabled
869
- config_transaction_tracer
870
- log_connection!(config_data)
871
- configure_transaction_tracer!(config_data['collect_traces'], config_data['sample_rate'])
872
- configure_error_collector!(config_data['collect_errors'])
766
+ log.debug "Server provided config: #{config_data.inspect}"
767
+ server_config = NewRelic::Agent::Configuration::ServerSource.new(config_data)
768
+ Agent.config.apply_config(server_config, 1)
769
+ log_connection!(config_data) if @service
770
+
771
+ @beacon_configuration = BeaconConfiguration.new
873
772
  end
874
-
773
+
875
774
  # Logs when we connect to the server, for debugging purposes
876
775
  # - makes sure we know if an agent has not connected
877
776
  def log_connection!(config_data)
878
- control.log! "Connected to NewRelic Service at #{@service.collector.name}"
777
+ log.info "Connected to NewRelic Service at #{@service.collector.name}"
879
778
  log.debug "Agent Run = #{@service.agent_id}."
880
779
  log.debug "Connection data = #{config_data.inspect}"
780
+ if config_data['messages'] && config_data['messages'].any?
781
+ log_collector_messages(config_data['messages'])
782
+ end
783
+ end
784
+
785
+ def log_collector_messages(messages)
786
+ messages.each do |message|
787
+ log.send(message['level'].downcase.to_sym, message['message'])
788
+ end
881
789
  end
882
790
  end
883
791
  include Connect
@@ -999,7 +907,9 @@ module NewRelic
999
907
  # metric cache so we can save the collector some work by
1000
908
  # sending integers instead of strings
1001
909
  def fill_metric_id_cache(pairs_of_specs_and_ids)
1002
- Array(pairs_of_specs_and_ids).each do |metric_spec, metric_id|
910
+ Array(pairs_of_specs_and_ids).each do |metric_spec_hash, metric_id|
911
+ metric_spec = MetricSpec.new(metric_spec_hash['name'],
912
+ metric_spec_hash['scope'])
1003
913
  @metric_ids[metric_spec] = metric_id
1004
914
  end
1005
915
  end
@@ -1012,11 +922,16 @@ module NewRelic
1012
922
  NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote').record_data_point(0.0)
1013
923
  NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/metric_data').record_data_point(0.0)
1014
924
  harvest_timeslice_data(now)
1015
- # In this version of the protocol, we get back an assoc array of spec to id.
1016
- metric_specs_and_ids = @service.metric_data(@last_harvest_time.to_f,
1017
- now.to_f,
1018
- @unsent_timeslice_data.values)
1019
- metric_specs_and_ids ||= []
925
+ # In this version of the protocol
926
+ # we get back an assoc array of spec to id.
927
+ metric_specs_and_ids = []
928
+ begin
929
+ metric_specs_and_ids = @service.metric_data(@last_harvest_time.to_f,
930
+ now.to_f,
931
+ @unsent_timeslice_data.values)
932
+ rescue UnrecoverableServerException => e
933
+ log.debug e.message
934
+ end
1020
935
  fill_metric_id_cache(metric_specs_and_ids)
1021
936
 
1022
937
  log.debug "#{now}: sent #{@unsent_timeslice_data.length} timeslices (#{@service.agent_id}) in #{Time.now - now} seconds"
@@ -1030,7 +945,7 @@ module NewRelic
1030
945
  # the transaction sampler, subject to the setting for slowest
1031
946
  # transaction threshold
1032
947
  def harvest_transaction_traces
1033
- @traces = @transaction_sampler.harvest(@traces, @slowest_transaction_threshold)
948
+ @traces = @transaction_sampler.harvest(@traces)
1034
949
  @traces
1035
950
  end
1036
951
 
@@ -1041,8 +956,11 @@ module NewRelic
1041
956
  log.debug "Sending (#{sql_traces.size}) sql traces"
1042
957
  begin
1043
958
  @service.sql_trace_data(sql_traces)
1044
- rescue
1045
- @sql_sampler.merge sql_traces
959
+ rescue UnrecoverableServerException => e
960
+ log.debug e.message
961
+ rescue => e
962
+ log.debug "Remerging SQL traces after #{e.class.name}: #{e.message}"
963
+ @sql_sampler.merge sql_traces
1046
964
  end
1047
965
  end
1048
966
  end
@@ -1058,22 +976,21 @@ module NewRelic
1058
976
  unless @traces.empty?
1059
977
  now = Time.now
1060
978
  log.debug "Sending (#{@traces.length}) transaction traces"
1061
-
979
+
1062
980
  begin
1063
981
  options = { :keep_backtraces => true }
1064
- options[:record_sql] = @record_sql unless @record_sql == :off
1065
- if @transaction_sampler.explain_enabled
1066
- options[:explain_sql] = @transaction_sampler.explain_threshold
982
+ if !(NewRelic::Agent::Database.record_sql_method == :off)
983
+ options[:record_sql] = NewRelic::Agent::Database.record_sql_method
984
+ end
985
+ if Agent.config[:'transaction_tracer.explain_enabled']
986
+ options[:explain_sql] = Agent.config[:'transaction_tracer.explain_threshold']
1067
987
  end
1068
- traces = @traces.collect {|trace| trace.prepare_to_send(options)}
988
+ traces = @traces.map {|trace| trace.prepare_to_send(options) }
1069
989
  @service.transaction_sample_data(traces)
1070
- rescue PostTooBigException
1071
- # we tried to send too much data, drop the first trace and
1072
- # try again
1073
- retry if @traces.shift
990
+ log.debug "Sent slowest sample (#{@service.agent_id}) in #{Time.now - now} seconds"
991
+ rescue UnrecoverableServerException => e
992
+ log.debug e.message
1074
993
  end
1075
-
1076
- log.debug "Sent slowest sample (#{@service.agent_id}) in #{Time.now - now} seconds"
1077
994
  end
1078
995
 
1079
996
  # if we succeed sending this sample, then we don't need to keep
@@ -1082,6 +999,17 @@ module NewRelic
1082
999
  @traces = nil
1083
1000
  end
1084
1001
 
1002
+ def harvest_and_send_thread_profile(disconnecting=false)
1003
+ @thread_profiler.stop(true) if disconnecting
1004
+
1005
+ if @thread_profiler.finished?
1006
+ profile = @thread_profiler.harvest
1007
+
1008
+ log.debug "Sending thread profile #{profile.profile_id}"
1009
+ @service.profile_data(profile)
1010
+ end
1011
+ end
1012
+
1085
1013
  # Gets the collection of unsent errors from the error
1086
1014
  # collector. We pass back in an existing array of errors that
1087
1015
  # may be left over from a previous send
@@ -1100,9 +1028,8 @@ module NewRelic
1100
1028
  log.debug "Sending #{@unsent_errors.length} errors"
1101
1029
  begin
1102
1030
  @service.error_data(@unsent_errors)
1103
- rescue PostTooBigException
1104
- @unsent_errors.shift
1105
- retry
1031
+ rescue UnrecoverableServerException => e
1032
+ log.debug e.message
1106
1033
  end
1107
1034
  # if the remote invocation fails, then we never clear
1108
1035
  # @unsent_errors, and therefore we can re-attempt to send on
@@ -1111,20 +1038,50 @@ module NewRelic
1111
1038
  @unsent_errors = []
1112
1039
  end
1113
1040
  end
1114
-
1115
- def transmit_data
1041
+
1042
+ # Only JSON marshalling appears to work with collector on
1043
+ # get_agent_commands and agent_command_results. We only support
1044
+ # these features on Ruby versions that can hack JSON out of the box
1045
+ def agent_commands_supported?
1046
+ RUBY_VERSION >= "1.9.2"
1047
+ end
1048
+
1049
+ def check_for_agent_commands
1050
+ if !agent_commands_supported?
1051
+ log.debug("Skipping agent commands, as they aren't supported on this environment")
1052
+ return
1053
+ end
1054
+
1055
+ commands = @service.get_agent_commands
1056
+ log.debug "Received get_agent_commands = #{commands}"
1057
+
1058
+ @thread_profiler.respond_to_commands(commands) do |command_id, error|
1059
+ @service.agent_command_results(command_id, error)
1060
+ end
1061
+ end
1062
+
1063
+ def transmit_data(disconnecting=false)
1064
+ now = Time.now
1116
1065
  log.debug "Sending data to New Relic Service"
1117
1066
  harvest_and_send_errors
1118
1067
  harvest_and_send_slowest_sample
1119
1068
  harvest_and_send_slowest_sql
1120
1069
  harvest_and_send_timeslice_data
1070
+ harvest_and_send_thread_profile(disconnecting)
1071
+
1072
+ check_for_agent_commands
1121
1073
  rescue => e
1122
1074
  retry_count ||= 0
1123
1075
  retry_count += 1
1124
- retry unless retry_count > 1
1076
+ if retry_count <= 1
1077
+ log.debug "retrying transmit_data after #{e}"
1078
+ retry
1079
+ end
1125
1080
  raise e
1126
1081
  ensure
1127
1082
  NewRelic::Agent::Database.close_connections unless forked?
1083
+ @stats_engine.get_stats_no_scope('Supportability/Harvest') \
1084
+ .record_data_point((Time.now - now).to_f)
1128
1085
  end
1129
1086
 
1130
1087
  # This method contacts the server to send remaining data and
@@ -1138,7 +1095,8 @@ module NewRelic
1138
1095
  if @connected
1139
1096
  begin
1140
1097
  @service.request_timeout = 10
1141
- transmit_data
1098
+ transmit_data(true)
1099
+
1142
1100
  if @connected_pid == $$ && !@service.kind_of?(NewRelic::Agent::NewRelicService)
1143
1101
  log.debug "Sending New Relic service agent run shutdown message"
1144
1102
  @service.shutdown(Time.now.to_f)
@@ -1146,14 +1104,15 @@ module NewRelic
1146
1104
  log.debug "This agent connected from parent process #{@connected_pid}--not sending shutdown"
1147
1105
  end
1148
1106
  log.debug "Graceful disconnect complete"
1149
- rescue Timeout::Error, StandardError
1107
+ rescue Timeout::Error, StandardError => e
1108
+ log.debug "Error when disconnecting #{e.class.name}: #{e.message}"
1150
1109
  end
1151
1110
  else
1152
1111
  log.debug "Bypassing graceful disconnect - agent not connected"
1153
1112
  end
1154
1113
  end
1155
1114
  end
1156
-
1115
+
1157
1116
  extend ClassMethods
1158
1117
  include InstanceMethods
1159
1118
  include BrowserMonitoring