newrelic_rpm 3.5.6.48.beta → 3.5.6.55

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gitignore +1 -0
  3. data/CHANGELOG +52 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/new_relic/agent.rb +3 -0
  6. data/lib/new_relic/agent/agent.rb +21 -14
  7. data/lib/new_relic/agent/agent_logger.rb +9 -1
  8. data/lib/new_relic/agent/configuration/defaults.rb +3 -3
  9. data/lib/new_relic/agent/configuration/mask_defaults.rb +1 -0
  10. data/lib/new_relic/agent/error_collector.rb +11 -2
  11. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +2 -2
  12. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
  13. data/lib/new_relic/agent/instrumentation/sinatra.rb +10 -2
  14. data/lib/new_relic/agent/new_relic_service.rb +90 -10
  15. data/lib/new_relic/agent/pipe_service.rb +9 -0
  16. data/lib/new_relic/agent/sql_sampler.rb +10 -3
  17. data/lib/new_relic/agent/thread_profiler.rb +20 -7
  18. data/lib/new_relic/coerce.rb +37 -0
  19. data/lib/new_relic/commands/deployments.rb +1 -1
  20. data/lib/new_relic/control/frameworks/rails.rb +12 -2
  21. data/lib/new_relic/control/frameworks/rails3.rb +2 -11
  22. data/lib/new_relic/control/instance_methods.rb +10 -6
  23. data/lib/new_relic/control/server_methods.rb +5 -37
  24. data/lib/new_relic/local_environment.rb +1 -1
  25. data/lib/new_relic/metric_data.rb +13 -2
  26. data/lib/new_relic/noticed_error.rb +8 -1
  27. data/lib/new_relic/transaction_sample.rb +12 -3
  28. data/lib/new_relic/transaction_sample/segment.rb +6 -3
  29. data/newrelic.yml +6 -19
  30. data/newrelic_rpm.gemspec +7 -0
  31. data/test/multiverse/lib/multiverse/environment.rb +1 -1
  32. data/test/multiverse/suites/agent_only/logging_test.rb +19 -0
  33. data/test/multiverse/suites/agent_only/ssl_test.rb +22 -0
  34. data/test/multiverse/suites/rails/config/newrelic.yml +3 -136
  35. data/test/multiverse/suites/rails/error_tracing_test.rb +39 -21
  36. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +26 -24
  37. data/test/multiverse/suites/resque/Rakefile +6 -0
  38. data/test/multiverse/suites/resque/instrumentation_test.rb +18 -5
  39. data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +38 -0
  40. data/test/multiverse/suites/sinatra/sinatra_test.rb +17 -0
  41. data/test/new_relic/agent/agent/connect_test.rb +7 -26
  42. data/test/new_relic/agent/agent_test.rb +27 -31
  43. data/test/new_relic/agent/browser_monitoring_test.rb +1 -1
  44. data/test/new_relic/agent/error_collector_test.rb +16 -0
  45. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +1 -1
  46. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +1 -0
  47. data/test/new_relic/agent/new_relic_service_test.rb +95 -2
  48. data/test/new_relic/agent/pipe_channel_manager_test.rb +3 -3
  49. data/test/new_relic/agent/pipe_service_test.rb +21 -1
  50. data/test/new_relic/agent/rpm_agent_test.rb +1 -1
  51. data/test/new_relic/agent/sql_sampler_test.rb +20 -0
  52. data/test/new_relic/agent/thread_profiler_test.rb +53 -8
  53. data/test/new_relic/agent/worker_loop_test.rb +4 -8
  54. data/test/new_relic/agent_test.rb +1 -2
  55. data/test/new_relic/coerce_test.rb +65 -0
  56. data/test/new_relic/command/deployments_test.rb +1 -1
  57. data/test/new_relic/control_test.rb +19 -44
  58. data/test/new_relic/fake_collector.rb +3 -2
  59. data/test/new_relic/local_environment_test.rb +1 -1
  60. data/test/new_relic/metric_data_test.rb +29 -0
  61. data/test/new_relic/noticed_error_test.rb +8 -0
  62. data/test/new_relic/transaction_sample/segment_test.rb +7 -0
  63. data/test/new_relic/transaction_sample_test.rb +36 -8
  64. data/test/test_contexts.rb +1 -1
  65. data/test/test_helper.rb +21 -2
  66. data/ui/helpers/google_pie_chart.rb +1 -0
  67. metadata +68 -10
  68. metadata.gz.sig +0 -0
  69. data/test/new_relic/fake_service.rb +0 -53
@@ -39,6 +39,13 @@ module NewRelic
39
39
  write_to_pipe('EOF')
40
40
  NewRelic::Agent::PipeChannelManager.channels[@channel_id].close
41
41
  end
42
+
43
+ # Invokes the block it is passed. This is used to implement HTTP
44
+ # keep-alive in the NewRelicService, and is a required interface for any
45
+ # Service class.
46
+ def session
47
+ yield
48
+ end
42
49
 
43
50
  private
44
51
 
@@ -52,6 +59,8 @@ module NewRelic
52
59
 
53
60
  def write_to_pipe(data)
54
61
  NewRelic::Agent::PipeChannelManager.channels[@channel_id].write(data)
62
+ rescue => e
63
+ NewRelic::Agent.logger.error("#{e.message}: Unable to send data to parent process, please see https://newrelic.com/docs/ruby/resque-instrumentation for more information.")
55
64
  end
56
65
  end
57
66
  end
@@ -189,7 +189,7 @@ module NewRelic
189
189
  @params = {} #FIXME
190
190
  @sql_id = consistent_hash(normalized_query)
191
191
  set_primary slow_sql, path, uri
192
- record_data_point slow_sql.duration
192
+ record_data_point(float(slow_sql.duration))
193
193
  end
194
194
 
195
195
  def set_primary(slow_sql, path, uri)
@@ -207,7 +207,7 @@ module NewRelic
207
207
  set_primary slow_sql, path, uri
208
208
  end
209
209
 
210
- record_data_point slow_sql.duration
210
+ record_data_point(float(slow_sql.duration))
211
211
  end
212
212
 
213
213
  def prepare_to_send
@@ -223,8 +223,15 @@ module NewRelic
223
223
  Agent.config[:'slow_sql.explain_enabled']
224
224
  end
225
225
 
226
+ include NewRelic::Coerce
227
+
226
228
  def to_collector_array(encoder)
227
- [ @path, @url, @sql_id, @sql, @database_metric_name, @call_count,
229
+ [ string(@path),
230
+ string(@url),
231
+ int(@sql_id),
232
+ string(@sql),
233
+ string(@database_metric_name),
234
+ int(@call_count),
228
235
  Helper.time_to_millis(@total_call_time),
229
236
  Helper.time_to_millis(@min_call_time),
230
237
  Helper.time_to_millis(@max_call_time),
@@ -202,6 +202,8 @@ EOF
202
202
 
203
203
  THREAD_PROFILER_NODES = 20_000
204
204
 
205
+ include NewRelic::Coerce
206
+
205
207
  def to_collector_array(encoder)
206
208
  prune!(THREAD_PROFILER_NODES)
207
209
 
@@ -212,11 +214,15 @@ EOF
212
214
  "BACKGROUND" => @traces[:background].map{|t| t.to_array }
213
215
  }
214
216
 
215
- [[@profile_id,
216
- @start_time.to_f, @stop_time.to_f,
217
- @poll_count,
218
- encoder.encode(traces),
219
- @sample_count, 0]]
217
+ [[
218
+ int(@profile_id),
219
+ float(@start_time),
220
+ float(@stop_time),
221
+ int(@poll_count),
222
+ string(encoder.encode(traces)),
223
+ int(@sample_count),
224
+ 0
225
+ ]]
220
226
  end
221
227
 
222
228
  def now_in_millis
@@ -280,9 +286,16 @@ EOF
280
286
  [-runnable_count, depth] <=> [-y.runnable_count, y.depth]
281
287
  end
282
288
 
289
+ include NewRelic::Coerce
290
+
283
291
  def to_array
284
- [[@file, @method, @line_no],
285
- @runnable_count, 0,
292
+ [[
293
+ string(@file),
294
+ string(@method),
295
+ int(@line_no)
296
+ ],
297
+ int(@runnable_count),
298
+ 0,
286
299
  @children.map {|c| c.to_array}]
287
300
  end
288
301
 
@@ -0,0 +1,37 @@
1
+ module NewRelic
2
+ # We really don't want to send bad values to the collector, and it doesn't
3
+ # accept types like Rational that have occasionally slipped into our data.
4
+ #
5
+ # These methods are intended to safely coerce things into the form we want,
6
+ # to provide documentation of expected types on to_collector_array methods,
7
+ # and to log failures if totally invalid data gets into outgoing data
8
+ module Coerce
9
+ def int(value, context=nil)
10
+ Integer(value)
11
+ rescue => error
12
+ log_failure(value, Integer, context, error)
13
+ 0
14
+ end
15
+
16
+ def float(value, context=nil)
17
+ Float(value)
18
+ rescue => error
19
+ log_failure(value, Float, context, error)
20
+ 0.0
21
+ end
22
+
23
+ def string(value, context=nil)
24
+ return value if value.nil?
25
+ String(value)
26
+ rescue => error
27
+ log_failure(value.class, String, context, error)
28
+ ""
29
+ end
30
+
31
+ def log_failure(value, type, context, error)
32
+ msg = "Unable to convert '#{value}' to #{type}"
33
+ msg += " in context '#{context}'" if context
34
+ NewRelic::Agent.logger.warn(msg, error)
35
+ end
36
+ end
37
+ end
@@ -54,7 +54,7 @@ class NewRelic::Command::Deployments < NewRelic::Command
54
54
  }.each do |k, v|
55
55
  create_params["deployment[#{k}]"] = v unless v.nil? || v == ''
56
56
  end
57
- http = control.http_connection(control.api_server)
57
+ http = ::NewRelic::Agent::NewRelicService.new(nil, control.api_server).http_connection
58
58
 
59
59
  uri = "/deployments.xml"
60
60
 
@@ -10,14 +10,24 @@ module NewRelic
10
10
  def env
11
11
  @env ||= RAILS_ENV.dup
12
12
  end
13
+
14
+ # Rails can return an empty string from this method, causing
15
+ # the agent not to start even when it is properly in a rails 3
16
+ # application, so we test the value to make sure it actually
17
+ # has contents, and bail to the parent class if it is empty.
13
18
  def root
14
- if defined?(RAILS_ROOT) && RAILS_ROOT.to_s != ''
15
- RAILS_ROOT.to_s
19
+ root = rails_root.to_s
20
+ if !root.empty?
21
+ root
16
22
  else
17
23
  super
18
24
  end
19
25
  end
20
26
 
27
+ def rails_root
28
+ RAILS_ROOT if defined?(RAILS_ROOT)
29
+ end
30
+
21
31
  def rails_config
22
32
  if defined?(::Rails) && ::Rails.respond_to?(:configuration)
23
33
  ::Rails.configuration
@@ -14,17 +14,8 @@ module NewRelic
14
14
  @env ||= ::Rails.env.to_s
15
15
  end
16
16
 
17
- # Rails can return an empty string from this method, causing
18
- # the agent not to start even when it is properly in a rails 3
19
- # application, so we test the value to make sure it actually
20
- # has contents, and bail to the parent class if it is empty.
21
- def root
22
- value = ::Rails.root.to_s
23
- if value.empty?
24
- super
25
- else
26
- value
27
- end
17
+ def rails_root
18
+ ::Rails.root.to_s
28
19
  end
29
20
 
30
21
  def init_config(options={})
@@ -49,7 +49,10 @@ module NewRelic
49
49
 
50
50
  Agent.config.replace_or_add_config(Agent::Configuration::ManualSource.new(options), 1)
51
51
 
52
- ::NewRelic::Agent.logger = NewRelic::Agent::AgentLogger.new(Agent.config, root, options.delete(:log))
52
+ # Be sure to only create once! RUBY-1020
53
+ if ::NewRelic::Agent.logger.is_startup_logger?
54
+ ::NewRelic::Agent.logger = NewRelic::Agent::AgentLogger.new(Agent.config, root, options.delete(:log))
55
+ end
53
56
 
54
57
  # Merge the stringified options into the config as overrides:
55
58
  environment_name = options.delete(:env) and self.env = environment_name
@@ -100,6 +103,12 @@ module NewRelic
100
103
  NewRelic::Agent.config[:dispatcher]
101
104
  end
102
105
 
106
+ # Delegates to the class method newrelic_root, implemented by
107
+ # each subclass
108
+ def newrelic_root
109
+ self.class.newrelic_root
110
+ end
111
+
103
112
  protected
104
113
 
105
114
  # Append framework specific environment information for uploading to
@@ -130,11 +139,6 @@ module NewRelic
130
139
  '.'
131
140
  end
132
141
 
133
- # Delegates to the class method newrelic_root, implemented by
134
- # each subclass
135
- def newrelic_root
136
- self.class.newrelic_root
137
- end
138
142
  end
139
143
  include InstanceMethods
140
144
  end
@@ -7,20 +7,20 @@ module NewRelic
7
7
  end
8
8
 
9
9
  ProxyServer = Struct.new :name, :port, :user, :password #:nodoc:
10
-
10
+
11
11
  # Contains methods that deal with connecting to the server
12
12
  module ServerMethods
13
-
13
+
14
14
  def server
15
15
  @remote_server ||= server_from_host(nil)
16
16
  end
17
-
17
+
18
18
  # the server we should contact for api requests, like uploading
19
19
  # deployments and the like
20
20
  def api_server
21
21
  @api_server ||= NewRelic::Control::Server.new(Agent.config[:api_host], Agent.config[:api_port], nil)
22
22
  end
23
-
23
+
24
24
  # a new instances of the proxy server - this passes through if
25
25
  # there is no proxy, otherwise it has proxy configuration
26
26
  # information pulled from the config file
@@ -30,7 +30,7 @@ module NewRelic
30
30
  Agent.config[:proxy_user],
31
31
  Agent.config[:proxy_pass])
32
32
  end
33
-
33
+
34
34
  # turns a hostname into an ip address and returns a
35
35
  # NewRelic::Control::Server that contains the configuration info
36
36
  def server_from_host(hostname=nil)
@@ -72,38 +72,6 @@ module NewRelic
72
72
  nil
73
73
  end
74
74
  end
75
-
76
- # The path to the certificate file used to verify the SSL
77
- # connection if verify_peer is enabled
78
- def cert_file_path
79
- File.expand_path(File.join(newrelic_root, 'cert', 'cacert.pem'))
80
- end
81
-
82
- # Return the Net::HTTP with proxy configuration given the NewRelic::Control::Server object.
83
- # Default is the collector but for api calls you need to pass api_server
84
- #
85
- # Experimental support for SSL verification:
86
- # swap 'VERIFY_NONE' for 'VERIFY_PEER' line to try it out
87
- # If verification fails, uncomment the 'http.ca_file' line
88
- # and it will use the included certificate.
89
- def http_connection(host = nil)
90
- host ||= server
91
- # Proxy returns regular HTTP if @proxy_host is nil (the default)
92
- http_class = Net::HTTP::Proxy(proxy_server.name, proxy_server.port,
93
- proxy_server.user, proxy_server.password)
94
- http = http_class.new(host.ip || host.name, host.port)
95
- ::NewRelic::Agent.logger.debug("Http Connection opened to #{host.ip||host.name}:#{host.port}")
96
- if Agent.config[:ssl]
97
- http.use_ssl = true
98
- if Agent.config[:verify_certificate]
99
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
100
- http.ca_file = cert_file_path
101
- else
102
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
103
- end
104
- end
105
- http
106
- end
107
75
  end
108
76
 
109
77
  include ServerMethods
@@ -242,7 +242,7 @@ module NewRelic
242
242
  # Although you can override the dispatcher with NEWRELIC_DISPATCHER this
243
243
  # is not advisable since it implies certain api's being available.
244
244
  def discover_dispatcher
245
- dispatchers = %w[passenger torquebox glassfish thin mongrel litespeed webrick fastcgi unicorn sinatra]
245
+ dispatchers = %w[passenger torquebox trinidad glassfish thin mongrel litespeed webrick fastcgi unicorn sinatra]
246
246
  while dispatchers.any? && @discovered_dispatcher.nil?
247
247
  send 'check_for_'+(dispatchers.shift)
248
248
  end
@@ -1,3 +1,5 @@
1
+ require 'new_relic/coerce'
2
+
1
3
  module NewRelic
2
4
  class MetricData
3
5
  # nil, or a NewRelic::MetricSpec object if we have no cached ID
@@ -49,11 +51,20 @@ module NewRelic
49
51
  "#<MetricData metric_spec:#{metric_spec.inspect}, stats:#{stats.inspect}, metric_id:#{metric_id.inspect}>"
50
52
  end
51
53
 
54
+ include NewRelic::Coerce
55
+
52
56
  def to_collector_array(encoder=nil)
53
57
  stat_key = metric_id || { 'name' => metric_spec.name, 'scope' => metric_spec.scope }
54
58
  [ stat_key,
55
- [ stats.call_count, stats.total_call_time, stats.total_exclusive_time,
56
- stats.min_call_time, stats.max_call_time, stats.sum_of_squares ] ]
59
+ [
60
+ int(stats.call_count, stat_key),
61
+ float(stats.total_call_time, stat_key),
62
+ float(stats.total_exclusive_time, stat_key),
63
+ float(stats.min_call_time, stat_key),
64
+ float(stats.max_call_time, stat_key),
65
+ float(stats.sum_of_squares, stat_key)
66
+ ]
67
+ ]
57
68
  end
58
69
  end
59
70
  end
@@ -1,3 +1,5 @@
1
+ require 'new_relic/helper'
2
+
1
3
  # This class encapsulates an error that was noticed by New Relic in a managed app.
2
4
  class NewRelic::NoticedError
3
5
  extend NewRelic::CollectionHelper
@@ -45,8 +47,13 @@ class NewRelic::NoticedError
45
47
  end
46
48
  end
47
49
 
50
+ include NewRelic::Coerce
51
+
48
52
  def to_collector_array(encoder=nil)
49
- [ (@timestamp.to_f * 1000).round, @path, @message, @exception_class,
53
+ [ NewRelic::Helper.time_to_millis(@timestamp),
54
+ string(@path),
55
+ string(@message),
56
+ string(@exception_class),
50
57
  @params ]
51
58
  end
52
59
  end
@@ -57,15 +57,24 @@ module NewRelic
57
57
  JSON.dump(self.to_array)
58
58
  end
59
59
 
60
+ include NewRelic::Coerce
61
+
60
62
  def to_array
61
- [ @start_time.to_f, @params[:request_params], @params[:custom_params],
63
+ [ float(@start_time),
64
+ @params[:request_params],
65
+ @params[:custom_params],
62
66
  @root_segment.to_array ]
63
67
  end
64
68
 
65
69
  def to_collector_array(encoder)
66
70
  trace_tree = encoder.encode(self.to_array)
67
- [ Helper.time_to_millis(@start_time), Helper.time_to_millis(duration),
68
- @params[:path], @params[:uri], trace_tree, @guid, nil,
71
+ [ Helper.time_to_millis(@start_time),
72
+ Helper.time_to_millis(duration),
73
+ string(@params[:path]),
74
+ string(@params[:uri]),
75
+ trace_tree,
76
+ string(@guid),
77
+ nil,
69
78
  !!@force_persist ]
70
79
  end
71
80
 
@@ -33,10 +33,13 @@ module NewRelic
33
33
  to_debug_str(0)
34
34
  end
35
35
 
36
+ include NewRelic::Coerce
37
+
36
38
  def to_array
37
- [ (@entry_timestamp.to_f * 1000).round,
38
- (@exit_timestamp.to_f * 1000).round,
39
- @metric_name, (@params || {}) ] +
39
+ [ NewRelic::Helper.time_to_millis(@entry_timestamp),
40
+ NewRelic::Helper.time_to_millis(@exit_timestamp),
41
+ string(@metric_name),
42
+ (@params || {}) ] +
40
43
  [ (@called_segments ? @called_segments.map{|s| s.to_array} : []) ]
41
44
  end
42
45
 
data/newrelic.yml CHANGED
@@ -68,25 +68,12 @@ common: &default_settings
68
68
  # Optionally set the name of the log file, defaults to 'newrelic_agent.log'
69
69
  # log_file_name: 'newrelic_agent.log'
70
70
 
71
- # The newrelic agent communicates with the service via http by
72
- # default. If you want to communicate via https to increase
73
- # security, then turn on SSL by setting this value to true. Note,
74
- # this will result in increased CPU overhead to perform the
75
- # encryption involved in SSL communication, but this work is done
76
- # asynchronously to the threads that process your application code,
77
- # so it should not impact response times.
78
- ssl: false
79
-
80
- # EXPERIMENTAL: enable verification of the SSL certificate sent by
81
- # the server. This setting has no effect unless SSL is enabled
82
- # above. This may block your application. Only enable it if the data
83
- # you send us needs end-to-end verified certificates.
84
- #
85
- # This means we cannot cache the DNS lookup, so each request to the
86
- # service will perform a lookup. It also means that we cannot
87
- # use a non-blocking lookup, so in a worst case, if you have DNS
88
- # problems, your app may block indefinitely.
89
- # verify_certificate: true
71
+ # The newrelic agent communicates with the service via https by default. This
72
+ # prevents eavesdropping on the performance metrics transmitted by the agent.
73
+ # The encryption required by SSL introduces a nominal amount of CPU overhead,
74
+ # which is performed asynchronously in a background thread. If you'd prefer
75
+ # to send your metrics over http uncomment the following line.
76
+ # ssl: false
90
77
 
91
78
  #============================== Browser Monitoring ===============================
92
79
  # New Relic Real User Monitoring gives you insight into the performance real users are