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.
- data.tar.gz.sig +0 -0
- data/.gitignore +1 -0
- data/CHANGELOG +52 -0
- data/gem-public_cert.pem +20 -0
- data/lib/new_relic/agent.rb +3 -0
- data/lib/new_relic/agent/agent.rb +21 -14
- data/lib/new_relic/agent/agent_logger.rb +9 -1
- data/lib/new_relic/agent/configuration/defaults.rb +3 -3
- data/lib/new_relic/agent/configuration/mask_defaults.rb +1 -0
- data/lib/new_relic/agent/error_collector.rb +11 -2
- data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +2 -2
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sinatra.rb +10 -2
- data/lib/new_relic/agent/new_relic_service.rb +90 -10
- data/lib/new_relic/agent/pipe_service.rb +9 -0
- data/lib/new_relic/agent/sql_sampler.rb +10 -3
- data/lib/new_relic/agent/thread_profiler.rb +20 -7
- data/lib/new_relic/coerce.rb +37 -0
- data/lib/new_relic/commands/deployments.rb +1 -1
- data/lib/new_relic/control/frameworks/rails.rb +12 -2
- data/lib/new_relic/control/frameworks/rails3.rb +2 -11
- data/lib/new_relic/control/instance_methods.rb +10 -6
- data/lib/new_relic/control/server_methods.rb +5 -37
- data/lib/new_relic/local_environment.rb +1 -1
- data/lib/new_relic/metric_data.rb +13 -2
- data/lib/new_relic/noticed_error.rb +8 -1
- data/lib/new_relic/transaction_sample.rb +12 -3
- data/lib/new_relic/transaction_sample/segment.rb +6 -3
- data/newrelic.yml +6 -19
- data/newrelic_rpm.gemspec +7 -0
- data/test/multiverse/lib/multiverse/environment.rb +1 -1
- data/test/multiverse/suites/agent_only/logging_test.rb +19 -0
- data/test/multiverse/suites/agent_only/ssl_test.rb +22 -0
- data/test/multiverse/suites/rails/config/newrelic.yml +3 -136
- data/test/multiverse/suites/rails/error_tracing_test.rb +39 -21
- data/test/multiverse/suites/rails/gc_instrumentation_test.rb +26 -24
- data/test/multiverse/suites/resque/Rakefile +6 -0
- data/test/multiverse/suites/resque/instrumentation_test.rb +18 -5
- data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +38 -0
- data/test/multiverse/suites/sinatra/sinatra_test.rb +17 -0
- data/test/new_relic/agent/agent/connect_test.rb +7 -26
- data/test/new_relic/agent/agent_test.rb +27 -31
- data/test/new_relic/agent/browser_monitoring_test.rb +1 -1
- data/test/new_relic/agent/error_collector_test.rb +16 -0
- data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +1 -1
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +1 -0
- data/test/new_relic/agent/new_relic_service_test.rb +95 -2
- data/test/new_relic/agent/pipe_channel_manager_test.rb +3 -3
- data/test/new_relic/agent/pipe_service_test.rb +21 -1
- data/test/new_relic/agent/rpm_agent_test.rb +1 -1
- data/test/new_relic/agent/sql_sampler_test.rb +20 -0
- data/test/new_relic/agent/thread_profiler_test.rb +53 -8
- data/test/new_relic/agent/worker_loop_test.rb +4 -8
- data/test/new_relic/agent_test.rb +1 -2
- data/test/new_relic/coerce_test.rb +65 -0
- data/test/new_relic/command/deployments_test.rb +1 -1
- data/test/new_relic/control_test.rb +19 -44
- data/test/new_relic/fake_collector.rb +3 -2
- data/test/new_relic/local_environment_test.rb +1 -1
- data/test/new_relic/metric_data_test.rb +29 -0
- data/test/new_relic/noticed_error_test.rb +8 -0
- data/test/new_relic/transaction_sample/segment_test.rb +7 -0
- data/test/new_relic/transaction_sample_test.rb +36 -8
- data/test/test_contexts.rb +1 -1
- data/test/test_helper.rb +21 -2
- data/ui/helpers/google_pie_chart.rb +1 -0
- metadata +68 -10
- metadata.gz.sig +0 -0
- 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
|
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
|
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,
|
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
|
-
[[
|
216
|
-
@
|
217
|
-
@
|
218
|
-
|
219
|
-
@
|
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
|
-
[[
|
285
|
-
|
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 =
|
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
|
-
|
15
|
-
|
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
|
-
|
18
|
-
|
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
|
-
|
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
|
-
[
|
56
|
-
stats.
|
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
|
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
|
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),
|
68
|
-
|
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
|
38
|
-
(@exit_timestamp
|
39
|
-
@metric_name,
|
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
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
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
|