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
@@ -1,8 +1,15 @@
1
+ require 'base64'
2
+
1
3
  module NewRelic
2
4
  module Agent
5
+
6
+ #--
7
+ # Manages the registering and servicing of pipes used by child
8
+ # processes to report data to their parent, rather than directly
9
+ # to the collector.
3
10
  module PipeChannelManager
4
11
  extend self
5
-
12
+
6
13
  def register_report_channel(id)
7
14
  listener.register_pipe(id)
8
15
  end
@@ -10,15 +17,15 @@ module NewRelic
10
17
  def channels
11
18
  listener.pipes
12
19
  end
13
-
20
+
14
21
  def listener
15
22
  @listener ||= Listener.new
16
23
  end
17
-
24
+
18
25
  class Pipe
19
26
  attr_accessor :in, :out
20
27
  attr_reader :last_read
21
-
28
+
22
29
  def initialize
23
30
  @out, @in = IO.pipe
24
31
  if defined?(::Encoding::ASCII_8BIT)
@@ -26,7 +33,7 @@ module NewRelic
26
33
  end
27
34
  @last_read = Time.now
28
35
  end
29
-
36
+
30
37
  def close
31
38
  @out.close unless @out.closed?
32
39
  @in.close unless @in.closed?
@@ -34,9 +41,12 @@ module NewRelic
34
41
 
35
42
  def write(data)
36
43
  @out.close unless @out.closed?
37
- @in << Marshal.dump(data) + "\n\n"
44
+ @in << NewRelic::LanguageSupport.with_cautious_gc do
45
+ Marshal.dump(data)
46
+ end
47
+ @in << "\n\n"
38
48
  end
39
-
49
+
40
50
  def read
41
51
  @in.close unless @in.closed?
42
52
  @last_read = Time.now
@@ -47,7 +57,7 @@ module NewRelic
47
57
  @out.closed? && @in.closed?
48
58
  end
49
59
  end
50
-
60
+
51
61
  class Listener
52
62
  attr_reader :thread
53
63
  attr_accessor :pipes, :timeout, :select_timeout
@@ -66,11 +76,16 @@ module NewRelic
66
76
  def start
67
77
  return if @started == true
68
78
  @started = true
69
- @thread = Thread.new do
79
+ @thread = NewRelic::Agent::Thread.new('Pipe Channel Manager') do
80
+ now = nil
70
81
  loop do
71
82
  clean_up_pipes
72
83
  pipes_to_listen_to = @pipes.values.map{|pipe| pipe.out} + [wake.out]
73
- if ready = IO.select(pipes_to_listen_to, [], [], @select_timeout)
84
+ NewRelic::Agent.instance.stats_engine \
85
+ .get_stats_no_scope('Supportability/Listeners') \
86
+ .record_data_point((Time.now - now).to_f) if now
87
+ if ready = IO.select(pipes_to_listen_to, [], [], @select_timeout)
88
+ now = Time.now
74
89
  pipe = ready[0][0]
75
90
  if pipe == wake.out
76
91
  pipe.read(1)
@@ -78,14 +93,13 @@ module NewRelic
78
93
  merge_data_from_pipe(pipe)
79
94
  end
80
95
  end
81
-
96
+
82
97
  break if !should_keep_listening?
83
98
  end
84
99
  end
85
- @thread #.abort_on_exception = true
86
100
  sleep 0.001 # give time for the thread to spawn
87
101
  end
88
-
102
+
89
103
  def stop
90
104
  return unless @started == true
91
105
  @started = false
@@ -102,7 +116,7 @@ module NewRelic
102
116
  end
103
117
  @pipes = {}
104
118
  end
105
-
119
+
106
120
  def wake
107
121
  @wake ||= Pipe.new
108
122
  end
@@ -116,12 +130,12 @@ module NewRelic
116
130
  def merge_data_from_pipe(pipe_handle)
117
131
  pipe = find_pipe_for_handle(pipe_handle)
118
132
  got = pipe.read
119
-
133
+
120
134
  if got && !got.empty?
121
135
  payload = unmarshal(got)
122
136
  if payload == 'EOF'
123
137
  pipe.close
124
- else
138
+ elsif payload
125
139
  NewRelic::Agent.agent.merge_data_from([payload[:stats],
126
140
  payload[:transaction_traces],
127
141
  payload[:error_traces]])
@@ -130,19 +144,19 @@ module NewRelic
130
144
  end
131
145
 
132
146
  def unmarshal(data)
133
- if NewRelic::LanguageSupport.broken_gc?
134
- NewRelic::LanguageSupport.with_disabled_gc do
135
- Marshal.load(data)
136
- end
137
- else
147
+ NewRelic::LanguageSupport.with_cautious_gc do
138
148
  Marshal.load(data)
139
149
  end
150
+ rescue StandardError => e
151
+ msg = "#{e.class.name} '#{e.message}' trying to load #{Base64.encode64(data)}"
152
+ NewRelic::Control.instance.log.debug(msg)
153
+ nil
140
154
  end
141
-
155
+
142
156
  def should_keep_listening?
143
157
  @started || @pipes.values.find{|pipe| !pipe.in.closed?}
144
158
  end
145
-
159
+
146
160
  def clean_up_pipes
147
161
  @pipes.values.each do |pipe|
148
162
  if pipe.last_read.to_f + @timeout < Time.now.to_f
@@ -13,7 +13,11 @@ module NewRelic
13
13
  def connect(config)
14
14
  nil
15
15
  end
16
-
16
+
17
+ def get_agent_commands
18
+ []
19
+ end
20
+
17
21
  def metric_data(last_harvest_time, now, unsent_timeslice_data)
18
22
  write_to_pipe(:stats => hash_from_metric_data(unsent_timeslice_data))
19
23
  {}
@@ -14,7 +14,7 @@ module NewRelic
14
14
  class DelayedJobSampler < NewRelic::Agent::Sampler
15
15
  def initialize
16
16
  super :delayed_job_queue
17
- raise Unsupported, "DJ instrumentation disabled" if NewRelic::Control.instance['disable_dj']
17
+ raise Unsupported, "DJ instrumentation disabled" if Agent.config[:disable_dj]
18
18
  raise Unsupported, "No DJ worker present" unless NewRelic::DelayedJobInjection.worker_name
19
19
  end
20
20
 
@@ -33,9 +33,6 @@ module NewRelic
33
33
  local_env.dispatcher_instance_id
34
34
  end
35
35
 
36
- def queued_jobs
37
- Delayed::Job.count(:conditions => ['run_at < ? and failed_at is NULL', Time.now])
38
- end
39
36
  def failed_jobs
40
37
  Delayed::Job.count(:conditions => 'failed_at is not NULL')
41
38
  end
@@ -62,7 +59,7 @@ module NewRelic
62
59
 
63
60
  def record_queue_length_across_dimension(column)
64
61
  all_count = 0
65
- Delayed::Job.count(:group => column).each do | column_val, count |
62
+ Delayed::Job.count(:group => column, :conditions => ['run_at < ? and failed_at is NULL', Time.now]).each do | column_val, count |
66
63
  all_count += count
67
64
  record stats_engine.get_stats("Workers/DelayedJob/queue_length/#{column == 'queue' ? 'name' : column}/#{column_val}", false), count
68
65
  end
@@ -22,7 +22,7 @@ module NewRelic
22
22
  end
23
23
  elsif platform =~ /darwin9/ # 10.5
24
24
  @sampler = ShellPS.new("ps -o rsz")
25
- elsif platform =~ /darwin1[01]/ # 10.6 & 10.7
25
+ elsif platform =~ /darwin1\d+/ # >= 10.6
26
26
  @sampler = ShellPS.new("ps -o rss")
27
27
  elsif platform =~ /freebsd/
28
28
  @sampler = ShellPS.new("ps -o rss")
@@ -35,7 +35,7 @@ module NewRelic
35
35
  end
36
36
 
37
37
  def self.supported_on_this_platform?
38
- defined?(JRuby) or platform =~ /linux|darwin9|darwin10|freebsd|solaris/
38
+ defined?(JRuby) or platform =~ /linux|darwin|freebsd|solaris/
39
39
  end
40
40
 
41
41
  def self.platform
@@ -1,5 +1,10 @@
1
+ require 'zlib'
2
+ require 'base64'
3
+ require 'digest/md5'
4
+
1
5
  require 'new_relic/agent'
2
6
  require 'new_relic/control'
7
+
3
8
  module NewRelic
4
9
  module Agent
5
10
 
@@ -18,7 +23,6 @@ module NewRelic
18
23
  attr_reader :sql_traces
19
24
 
20
25
  def initialize
21
- configure!
22
26
  @sql_traces = {}
23
27
  clear_transaction_data
24
28
 
@@ -27,59 +31,21 @@ module NewRelic
27
31
  # any 'honest-to-god'-multithreaded system
28
32
  @samples_lock = Mutex.new
29
33
  end
30
-
31
- def configure!
32
- @explain_threshold = config.fetch('explain_threshold', 0.5).to_f
33
- @explain_enabled = config.fetch('explain_enabled', true)
34
- @stack_trace_threshold = config.fetch('stack_trace_threshold',
35
- 0.5).to_f
36
- if config.fetch('enabled', true) &&
37
- NewRelic::Control.instance['transaction_tracer'] &&
38
- NewRelic::Control.instance['transaction_tracer'].fetch('enabled',
39
- true) &&
40
- NewRelic::Control.instance.fetch('collect_traces', true)
41
- enable
42
- else
43
- disable
44
- end
45
- end
46
-
47
- def config
48
- self.class.config
49
- end
50
-
51
- def self.config
52
- control = NewRelic::Control.instance
53
- txn_config = control.fetch('transaction_tracer', {})
54
-
55
- if txn_config.fetch('enabled', true) && control.has_slow_sql_config?
56
- txn_config['enabled'] = control['slow_sql']['enabled']
57
- end
58
-
59
- txn_config
60
- end
61
-
62
- # Enable the sql sampler - this also registers it with
63
- # the statistics engine.
64
- def enable
65
- @disabled = false
66
- end
67
-
68
- # Disable the sql sampler - this also deregisters it
69
- # with the statistics engine.
70
- def disable
71
- @disabled = true
72
- end
73
34
 
74
35
  def enabled?
75
- !@disabled
36
+ Agent.config[:'slow_sql.enabled'] &&
37
+ (Agent.config[:'slow_sql.record_sql'] == 'raw' ||
38
+ Agent.config[:'slow_sql.record_sql'] == 'obfuscated') &&
39
+ Agent.config[:'transaction_tracer.enabled']
76
40
  end
77
41
 
78
42
  def notice_transaction(path, uri=nil, params={})
79
43
  if NewRelic::Agent.instance.transaction_sampler.builder
80
44
  guid = NewRelic::Agent.instance.transaction_sampler.builder.sample.guid
81
45
  end
82
- transaction_data.set_transaction_info(path, uri, params, guid) if !disabled && transaction_data
46
+ if Agent.config[:'slow_sql.enabled'] && transaction_data
47
+ transaction_data.set_transaction_info(path, uri, params, guid)
48
+ end
83
49
  end
84
50
 
85
51
  def notice_first_scope_push(time)
@@ -131,7 +97,7 @@ module NewRelic
131
97
  def notice_sql(sql, metric_name, config, duration)
132
98
  return unless transaction_data
133
99
  if NewRelic::Agent.is_sql_recorded?
134
- if duration > @explain_threshold
100
+ if duration > Agent.config[:'slow_sql.explain_threshold']
135
101
  backtrace = caller.join("\n")
136
102
  transaction_data.sql_data << SlowSql.new(sql, metric_name, config,
137
103
  duration, backtrace)
@@ -147,12 +113,12 @@ module NewRelic
147
113
  end
148
114
 
149
115
  def harvest
150
- return [] if disabled
116
+ return [] if !Agent.config[:'slow_sql.enabled']
151
117
  result = []
152
118
  @samples_lock.synchronize do
153
119
  result = @sql_traces.values
154
120
  @sql_traces = {}
155
- end
121
+ end
156
122
  slowest = result.sort{|a,b| b.max_call_time <=> a.max_call_time}[0,10]
157
123
  slowest.each {|trace| trace.prepare_to_send }
158
124
  slowest
@@ -243,39 +209,49 @@ module NewRelic
243
209
 
244
210
  record_data_point slow_sql.duration
245
211
  end
246
-
212
+
247
213
  def prepare_to_send
248
214
  params[:explain_plan] = @slow_sql.explain if need_to_explain?
249
215
  @sql = @slow_sql.obfuscate if need_to_obfuscate?
250
216
  end
251
-
252
- def agent_config
253
- NewRelic::Agent::SqlSampler.config
254
- end
255
-
217
+
256
218
  def need_to_obfuscate?
257
- agent_config['record_sql'] == 'obfuscated'
219
+ Agent.config[:'slow_sql.record_sql'].to_s == 'obfuscated'
258
220
  end
259
221
 
260
222
  def need_to_explain?
261
- agent_config['explain_enabled']
223
+ Agent.config[:'slow_sql.explain_enabled']
262
224
  end
263
-
264
- def to_json(*a)
265
- [@path, @url, @sql_id, @sql, @database_metric_name, @call_count, @total_call_time, @min_call_time, @max_call_time, @params].to_json(*a)
225
+
226
+ def to_collector_array(marshaller)
227
+ params = if marshaller.respond_to?(:encode_compress)
228
+ marshaller.encode_compress(@params)
229
+ else
230
+ @params
231
+ end
232
+
233
+ [ @path, @url, @sql_id, @sql, @database_metric_name, @call_count,
234
+ Helper.time_to_millis(@total_call_time),
235
+ Helper.time_to_millis(@min_call_time),
236
+ Helper.time_to_millis(@max_call_time),
237
+ params ]
266
238
  end
267
239
 
268
240
  private
269
241
 
270
- def consistent_hash(string)
271
- if NewRelic::LanguageSupport.using_version?('1.9.2')
272
- # String#hash is salted differently on every VM start in 1.9
273
- require 'digest/md5'
274
- Digest::MD5.hexdigest(string).hex
242
+ def compress(data)
243
+ if NewRelic::Agent::NewRelicService::JsonMarshaller.is_supported?
244
+ require 'json'
245
+ Base64.encode64(Zlib::Deflate.deflate(JSON.dump(data), Zlib::DEFAULT_COMPRESSION))
275
246
  else
276
- string.hash
277
- end.modulo(2**31-1)
278
- # modulo ensures sql_id fits in an INT(11)
247
+ data
248
+ end
249
+ end
250
+
251
+ def consistent_hash(string)
252
+ # need to hash the same way in every process
253
+ Digest::MD5.hexdigest(string).hex \
254
+ .modulo(2**31-1) # ensure sql_id fits in an INT(11)
279
255
  end
280
256
  end
281
257
  end
@@ -7,12 +7,13 @@ module NewRelic
7
7
  @profiler = RailsBench.new if RailsBench.enabled?
8
8
  @profiler = Ruby19.new if Ruby19.enabled?
9
9
  @profiler = Rubinius.new if Rubinius.enabled?
10
+ @profiler = RubiniusAgent.new if RubiniusAgent.enabled?
10
11
  end
11
12
 
12
13
  def self.capture
13
14
  @profiler.capture if @profiler
14
15
  end
15
-
16
+
16
17
  class Profiler
17
18
  def initialize
18
19
  if self.class.enabled?
@@ -20,75 +21,76 @@ module NewRelic
20
21
  @last_count = call_count
21
22
  end
22
23
  end
23
-
24
+
24
25
  def capture
25
26
  return unless self.class.enabled?
26
27
  return if !scope_stack.empty? && scope_stack.last.name == "GC/cumulative"
27
-
28
+
28
29
  num_calls = call_count - @last_count
29
- elapsed = (call_time - @last_timestamp).to_f
30
+ # microseconds to seconds
31
+ elapsed = (call_time - @last_timestamp).to_f / 1_000_000.0
30
32
  @last_timestamp = call_time
31
33
  @last_count = call_count
32
34
  reset
33
-
35
+
34
36
  record_gc_metric(num_calls, elapsed)
37
+ elapsed
35
38
  end
36
39
 
37
40
  def reset; end
38
-
41
+
39
42
  protected
40
-
43
+
41
44
  def record_gc_metric(num_calls, elapsed)
42
45
  if num_calls > 0
43
- # microseconds to seconds
44
- elapsed = elapsed / 1_000_000.0
45
- # Allocate the GC time to a scope as if the GC just ended
46
- # right now.
47
- time = Time.now.to_f
48
- gc_scope = NewRelic::Agent.instance.stats_engine.push_scope("GC/cumulative", time - elapsed)
49
46
  # GC stats are collected into a blamed metric which allows
50
47
  # us to show the stats controller by controller
51
- gc_stats = NewRelic::Agent.get_stats(gc_scope.name, true)
48
+ gc_stats = NewRelic::Agent.instance.stats_engine \
49
+ .get_stats('GC/cumulative', true, false,
50
+ NewRelic::Agent::TransactionInfo.get.transaction_name)
52
51
  gc_stats.record_multiple_data_points(elapsed, num_calls)
53
- NewRelic::Agent.instance.stats_engine.pop_scope(gc_scope, elapsed, time)
54
52
  end
55
53
  end
56
54
 
57
55
  def scope_stack
58
56
  Thread::current[:newrelic_scope_stack] ||= []
59
- end
57
+ end
60
58
  end
61
-
59
+
62
60
  class RailsBench < Profiler
63
61
  def self.enabled?
64
62
  ::GC.respond_to?(:time) && ::GC.respond_to?(:collections)
65
63
  end
66
-
64
+
67
65
  # microseconds spent in GC
68
66
  def call_time
69
67
  ::GC.time # this should already be microseconds
70
68
  end
71
-
69
+
72
70
  def call_count
73
71
  ::GC.collections
74
72
  end
73
+
74
+ def reset
75
+ ::GC.clear_stats
76
+ end
75
77
  end
76
-
78
+
77
79
  class Ruby19 < Profiler
78
80
  def self.enabled?
79
81
  defined?(::GC::Profiler) && ::GC::Profiler.enabled?
80
82
  end
81
-
83
+
82
84
  # microseconds spent in GC
83
85
  # 1.9 total_time returns seconds. Don't trust the docs. It's seconds.
84
86
  def call_time
85
87
  ::GC::Profiler.total_time * 1_000_000.0 # convert seconds to microseconds
86
88
  end
87
-
89
+
88
90
  def call_count
89
91
  ::GC.count
90
92
  end
91
-
93
+
92
94
  def reset
93
95
  ::GC::Profiler.clear
94
96
  @last_timestamp = 0
@@ -96,6 +98,20 @@ module NewRelic
96
98
  end
97
99
 
98
100
  class Rubinius < Profiler
101
+ def self.enabled?
102
+ defined?(::Rubinius) && defined?(::Rubinius::GC) && ::Rubinius::GC.respond_to?(:count)
103
+ end
104
+
105
+ def call_time
106
+ ::Rubinius::GC.time * 1000
107
+ end
108
+
109
+ def call_count
110
+ ::Rubinius::GC.count
111
+ end
112
+ end
113
+
114
+ class RubiniusAgent < Profiler
99
115
  def self.enabled?
100
116
  if NewRelic::LanguageSupport.using_engine?('rbx')
101
117
  require 'rubinius/agent'
@@ -115,7 +131,7 @@ module NewRelic
115
131
  agent = ::Rubinius::Agent.loopback
116
132
  agent.get('system.gc.young.count')[1] +
117
133
  agent.get('system.gc.full.count')[1]
118
- end
134
+ end
119
135
  end
120
136
  end
121
137
  end