newrelic_rpm 3.9.7.266 → 3.9.8.273
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +44 -1
- data/lib/new_relic/agent.rb +31 -0
- data/lib/new_relic/agent/agent.rb +34 -5
- data/lib/new_relic/agent/configuration/default_source.rb +25 -1
- data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
- data/lib/new_relic/agent/cross_app_monitor.rb +1 -1
- data/lib/new_relic/agent/custom_event_aggregator.rb +2 -4
- data/lib/new_relic/agent/error_collector.rb +17 -12
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +9 -8
- data/lib/new_relic/agent/instrumentation/grape.rb +67 -0
- data/lib/new_relic/agent/new_relic_service.rb +93 -43
- data/lib/new_relic/agent/pipe_service.rb +4 -0
- data/lib/new_relic/agent/synthetics_event_buffer.rb +42 -0
- data/lib/new_relic/agent/system_info.rb +44 -18
- data/lib/new_relic/agent/transaction_event_aggregator.rb +9 -2
- data/lib/new_relic/agent/utilization_data.rb +77 -0
- data/lib/new_relic/agent/vm/mri_vm.rb +3 -3
- data/lib/new_relic/rack/agent_hooks.rb +15 -15
- data/lib/new_relic/recipes/capistrano3.rb +2 -2
- data/lib/new_relic/version.rb +1 -1
- data/newrelic_rpm.gemspec +0 -1
- data/test/agent_helper.rb +13 -3
- data/test/environments/lib/environments/runner.rb +3 -19
- data/test/environments/rails42/Gemfile +5 -1
- data/test/fixtures/cross_agent_tests/README.md +1 -1
- data/test/fixtures/cross_agent_tests/cat_map.json +154 -88
- data/test/fixtures/cross_agent_tests/docker_container_id/cases.json +30 -6
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.1.2-lxc-driver.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.1.2-native-driver-fs.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.1.2-native-driver-systemd.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/heroku.txt +1 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/ubuntu-14.04-lxc-container.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/{lxc-containers-without-docker.txt → ubuntu-14.04-no-container.txt} +0 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/ubuntu-14.10-no-container.txt +10 -0
- data/test/multiverse/lib/multiverse/runner.rb +1 -0
- data/test/multiverse/lib/multiverse/suite.rb +6 -2
- data/test/multiverse/suites/active_record/.gitignore +1 -0
- data/test/multiverse/suites/active_record/Envfile +25 -7
- data/test/multiverse/suites/active_record/Rakefile +9 -0
- data/test/{new_relic/agent/instrumentation → multiverse/suites/active_record}/active_record_test.rb +82 -88
- data/test/multiverse/suites/active_record/app/models/models.rb +27 -0
- data/test/multiverse/suites/active_record/ar_method_aliasing.rb +5 -46
- data/test/multiverse/suites/active_record/before_suite.rb +23 -0
- data/test/multiverse/suites/active_record/config/database.rb +79 -0
- data/test/multiverse/suites/active_record/config/database.yml +19 -0
- data/test/multiverse/suites/active_record/db/migrate/20141105131800_create_users_and_aliases.rb +21 -0
- data/test/multiverse/suites/active_record/db/migrate/20141106082200_create_orders_and_shipments.rb +25 -0
- data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +4 -1
- data/test/multiverse/suites/agent_only/custom_analytics_events_test.rb +53 -0
- data/test/multiverse/suites/agent_only/keepalive_test.rb +3 -7
- data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +170 -0
- data/test/multiverse/suites/grape/Envfile +15 -0
- data/test/multiverse/suites/grape/config/newrelic.yml +18 -0
- data/test/multiverse/suites/grape/grape_test.rb +60 -0
- data/test/multiverse/suites/grape/grape_test_api.rb +43 -0
- data/test/multiverse/suites/grape/unsupported_version_test.rb +31 -0
- data/test/multiverse/suites/json/Envfile +3 -1
- data/test/multiverse/suites/rack/rack_env_mutation_test.rb +54 -0
- data/test/multiverse/suites/rails/Envfile +1 -1
- data/test/multiverse/suites/rails/view_instrumentation_test.rb +2 -1
- data/test/multiverse/suites/resque/resque_marshalling_test.rb +54 -0
- data/test/multiverse/suites/typhoeus/Envfile +4 -4
- data/test/new_relic/agent/agent_test.rb +37 -0
- data/test/new_relic/agent/configuration/default_source_test.rb +14 -0
- data/test/new_relic/agent/custom_event_aggregator_test.rb +3 -3
- data/test/new_relic/agent/error_collector/notice_error_test.rb +4 -4
- data/test/new_relic/agent/error_collector_test.rb +27 -4
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +23 -0
- data/test/new_relic/agent/new_relic_service_test.rb +208 -103
- data/test/new_relic/agent/pipe_service_test.rb +7 -0
- data/test/new_relic/agent/synthetics_event_buffer_test.rb +54 -0
- data/test/new_relic/agent/synthetics_monitor_test.rb +0 -3
- data/test/new_relic/agent/system_info_test.rb +6 -6
- data/test/new_relic/agent/transaction_event_aggregator_test.rb +43 -2
- data/test/new_relic/agent/utilization_data_test.rb +18 -0
- data/test/new_relic/collection_helper_test.rb +0 -1
- data/test/new_relic/data_container_tests.rb +11 -7
- data/test/new_relic/fake_collector.rb +23 -0
- data/test/new_relic/fake_instance_metadata_service.rb +45 -0
- data/test/new_relic/license_test.rb +2 -0
- data/test/new_relic/marshalling_test_cases.rb +89 -4
- data/test/new_relic/transaction_sample_test.rb +1 -0
- data/test/test_helper.rb +1 -0
- metadata +33 -6
- metadata.gz.sig +1 -2
- data/test/active_record_fixtures.rb +0 -79
- data/test/new_relic/rack/all_test.rb +0 -14
@@ -26,6 +26,10 @@ module NewRelic
|
|
26
26
|
# 1754: v3 (tag 2.3.0)
|
27
27
|
# 534: v2 (shows up in 2.1.0, our first tag)
|
28
28
|
|
29
|
+
# These include Errno connection errors, and all indicate that the
|
30
|
+
# underlying TCP connection may be in a bad state.
|
31
|
+
CONNECTION_ERRORS = [Timeout::Error, EOFError, SystemCallError, SocketError].freeze
|
32
|
+
|
29
33
|
attr_accessor :request_timeout, :agent_id
|
30
34
|
attr_reader :collector, :marshaller, :metric_id_cache
|
31
35
|
|
@@ -162,12 +166,20 @@ module NewRelic
|
|
162
166
|
invoke_remote(:get_xray_metadata, [@agent_id, *xray_ids])
|
163
167
|
end
|
164
168
|
|
165
|
-
# Send fine-grained analytic data to the collector.
|
166
169
|
def analytic_event_data(data)
|
167
170
|
invoke_remote(:analytic_event_data, [@agent_id, data],
|
168
171
|
:item_count => data.size)
|
169
172
|
end
|
170
173
|
|
174
|
+
def custom_event_data(data)
|
175
|
+
invoke_remote(:custom_event_data, [@agent_id, data],
|
176
|
+
:item_count => data.size)
|
177
|
+
end
|
178
|
+
|
179
|
+
def utilization_data(data)
|
180
|
+
invoke_remote(:utilization_data, data)
|
181
|
+
end
|
182
|
+
|
171
183
|
# We do not compress if content is smaller than 64kb. There are
|
172
184
|
# problems with bugs in Ruby in some versions that expose us
|
173
185
|
# to a risk of segfaults if we compress aggressively.
|
@@ -189,15 +201,17 @@ module NewRelic
|
|
189
201
|
|
190
202
|
begin
|
191
203
|
t0 = Time.now
|
204
|
+
@in_session = true
|
192
205
|
if NewRelic::Agent.config[:aggressive_keepalive]
|
193
206
|
session_with_keepalive(&block)
|
194
207
|
else
|
195
208
|
session_without_keepalive(&block)
|
196
209
|
end
|
197
|
-
rescue
|
210
|
+
rescue *CONNECTION_ERRORS => e
|
198
211
|
elapsed = Time.now - t0
|
199
|
-
|
200
|
-
|
212
|
+
raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to #{@collector} after #{elapsed} seconds: #{e}"
|
213
|
+
ensure
|
214
|
+
@in_session = false
|
201
215
|
end
|
202
216
|
end
|
203
217
|
|
@@ -217,10 +231,7 @@ module NewRelic
|
|
217
231
|
|
218
232
|
def establish_shared_connection
|
219
233
|
unless @shared_tcp_connection
|
220
|
-
|
221
|
-
NewRelic::Agent.logger.debug("Opening shared TCP connection to #{connection.address}:#{connection.port}")
|
222
|
-
NewRelic::TimerLib.timeout(@request_timeout) { connection.start }
|
223
|
-
@shared_tcp_connection = connection
|
234
|
+
@shared_tcp_connection = create_and_start_http_connection
|
224
235
|
end
|
225
236
|
@shared_tcp_connection
|
226
237
|
end
|
@@ -233,11 +244,54 @@ module NewRelic
|
|
233
244
|
end
|
234
245
|
end
|
235
246
|
|
247
|
+
def ssl_cert_store
|
248
|
+
path = cert_file_path
|
249
|
+
if !@ssl_cert_store || path != @cached_cert_store_path
|
250
|
+
::NewRelic::Agent.logger.debug("Creating SSL certificate store from file at #{path}")
|
251
|
+
@ssl_cert_store = OpenSSL::X509::Store.new
|
252
|
+
@ssl_cert_store.add_file(path)
|
253
|
+
@cached_cert_store_path = path
|
254
|
+
end
|
255
|
+
@ssl_cert_store
|
256
|
+
end
|
257
|
+
|
236
258
|
# Return a Net::HTTP connection object to make a call to the collector.
|
237
259
|
# We'll reuse the same handle for cases where we're using keep-alive, or
|
238
260
|
# otherwise create a new one.
|
239
261
|
def http_connection
|
240
|
-
@
|
262
|
+
if @in_session
|
263
|
+
establish_shared_connection
|
264
|
+
else
|
265
|
+
create_http_connection
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def setup_connection_for_ssl(conn)
|
270
|
+
# Jruby 1.6.8 requires a gem for full ssl support and will throw
|
271
|
+
# an error when use_ssl=(true) is called and jruby-openssl isn't
|
272
|
+
# installed
|
273
|
+
conn.use_ssl = true
|
274
|
+
conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
275
|
+
conn.cert_store = ssl_cert_store
|
276
|
+
rescue StandardError, LoadError
|
277
|
+
msg = "Agent is configured to use SSL, but SSL is not available in the environment. "
|
278
|
+
msg << "Either disable SSL in the agent configuration, or install SSL support."
|
279
|
+
raise UnrecoverableAgentException.new(msg)
|
280
|
+
end
|
281
|
+
|
282
|
+
def start_connection(conn)
|
283
|
+
NewRelic::Agent.logger.debug("Opening TCP connection to #{conn.address}:#{conn.port}")
|
284
|
+
NewRelic::TimerLib.timeout(@request_timeout) { conn.start }
|
285
|
+
conn
|
286
|
+
end
|
287
|
+
|
288
|
+
def setup_connection_timeouts(conn)
|
289
|
+
# We use Timeout explicitly instead of this
|
290
|
+
conn.read_timeout = nil
|
291
|
+
|
292
|
+
if conn.respond_to?(:keep_alive_timeout) && NewRelic::Agent.config[:aggressive_keepalive]
|
293
|
+
conn.keep_alive_timeout = NewRelic::Agent.config[:keep_alive_timeout]
|
294
|
+
end
|
241
295
|
end
|
242
296
|
|
243
297
|
# Return the Net::HTTP with proxy configuration given the NewRelic::Control::Server object.
|
@@ -247,30 +301,19 @@ module NewRelic
|
|
247
301
|
http_class = Net::HTTP::Proxy(proxy_server.name, proxy_server.port,
|
248
302
|
proxy_server.user, proxy_server.password)
|
249
303
|
|
250
|
-
|
251
|
-
if Agent.config[:ssl]
|
252
|
-
|
253
|
-
# Jruby 1.6.8 requires a gem for full ssl support and will throw
|
254
|
-
# an error when use_ssl=(true) is called and jruby-openssl isn't
|
255
|
-
# installed
|
256
|
-
http.use_ssl = true
|
257
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
258
|
-
http.ca_file = cert_file_path
|
259
|
-
rescue StandardError, LoadError
|
260
|
-
msg = "Agent is configured to use SSL, but SSL is not available in the environment. "
|
261
|
-
msg << "Either disable SSL in the agent configuration, or install SSL support."
|
262
|
-
raise UnrecoverableAgentException.new(msg)
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
if http.respond_to?(:keep_alive_timeout) && NewRelic::Agent.config[:aggressive_keepalive]
|
267
|
-
http.keep_alive_timeout = NewRelic::Agent.config[:keep_alive_timeout]
|
268
|
-
end
|
304
|
+
conn = http_class.new((@collector.ip || @collector.name), @collector.port)
|
305
|
+
setup_connection_for_ssl(conn) if Agent.config[:ssl]
|
306
|
+
setup_connection_timeouts(conn)
|
269
307
|
|
270
|
-
::NewRelic::Agent.logger.debug("Created net/http handle to #{
|
271
|
-
|
308
|
+
::NewRelic::Agent.logger.debug("Created net/http handle to #{conn.address}:#{conn.port}")
|
309
|
+
conn
|
272
310
|
end
|
273
311
|
|
312
|
+
def create_and_start_http_connection
|
313
|
+
conn = create_http_connection
|
314
|
+
start_connection(conn)
|
315
|
+
conn
|
316
|
+
end
|
274
317
|
|
275
318
|
# The path to the certificate file used to verify the SSL
|
276
319
|
# connection if verify_peer is enabled
|
@@ -405,13 +448,27 @@ module NewRelic
|
|
405
448
|
request.content_type = "application/octet-stream"
|
406
449
|
request.body = opts[:data]
|
407
450
|
|
408
|
-
response
|
409
|
-
|
410
|
-
|
411
|
-
|
451
|
+
response = nil
|
452
|
+
attempts = 0
|
453
|
+
max_attempts = 2
|
454
|
+
|
455
|
+
begin
|
456
|
+
attempts += 1
|
457
|
+
conn = http_connection
|
412
458
|
::NewRelic::Agent.logger.debug "Sending request to #{opts[:collector]}#{opts[:uri]}"
|
413
|
-
|
459
|
+
NewRelic::TimerLib.timeout(@request_timeout) do
|
460
|
+
response = conn.request(request)
|
461
|
+
end
|
462
|
+
rescue *CONNECTION_ERRORS => e
|
463
|
+
close_shared_connection
|
464
|
+
if attempts < max_attempts
|
465
|
+
::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
|
466
|
+
retry
|
467
|
+
else
|
468
|
+
raise ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
|
469
|
+
end
|
414
470
|
end
|
471
|
+
|
415
472
|
case response
|
416
473
|
when Net::HTTPSuccess
|
417
474
|
true # do nothing
|
@@ -420,7 +477,7 @@ module NewRelic
|
|
420
477
|
when Net::HTTPServiceUnavailable
|
421
478
|
raise ServerConnectionException, "Service unavailable (#{response.code}): #{response.message}"
|
422
479
|
when Net::HTTPGatewayTimeOut
|
423
|
-
raise
|
480
|
+
raise ServerConnectionException, "Gateway timeout (#{response.code}): #{response.message}"
|
424
481
|
when Net::HTTPRequestEntityTooLarge
|
425
482
|
raise UnrecoverableServerException, '413 Request Entity Too Large'
|
426
483
|
when Net::HTTPUnsupportedMediaType
|
@@ -429,15 +486,8 @@ module NewRelic
|
|
429
486
|
raise ServerConnectionException, "Unexpected response from server (#{response.code}): #{response.message}"
|
430
487
|
end
|
431
488
|
response
|
432
|
-
rescue Timeout::Error, EOFError, SystemCallError, SocketError => e
|
433
|
-
# These include Errno connection errors, and all signify that the
|
434
|
-
# connection may be in a bad state, so drop it and re-create if needed.
|
435
|
-
close_shared_connection
|
436
|
-
raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to #{@collector}: #{e}"
|
437
489
|
end
|
438
490
|
|
439
|
-
|
440
|
-
|
441
491
|
# Decompresses the response from the server, if it is gzip
|
442
492
|
# encoded, otherwise returns it verbatim
|
443
493
|
def decompress_response(response)
|
@@ -32,6 +32,10 @@ module NewRelic
|
|
32
32
|
write_to_pipe(:analytic_event_data, events) if events
|
33
33
|
end
|
34
34
|
|
35
|
+
def custom_event_data(events)
|
36
|
+
write_to_pipe(:custom_event_data, events) if events
|
37
|
+
end
|
38
|
+
|
35
39
|
def metric_data(unsent_timeslice_data)
|
36
40
|
write_to_pipe(:metric_data, unsent_timeslice_data)
|
37
41
|
{}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under New Relic's license terms.
|
3
|
+
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
+
|
5
|
+
require 'new_relic/agent/event_buffer'
|
6
|
+
require 'new_relic/agent/sized_buffer'
|
7
|
+
|
8
|
+
module NewRelic
|
9
|
+
module Agent
|
10
|
+
class SyntheticsEventBuffer < SizedBuffer
|
11
|
+
|
12
|
+
def append_with_reject(x)
|
13
|
+
@seen += 1
|
14
|
+
if full?
|
15
|
+
timestamp = timestamp_for(x)
|
16
|
+
latest_event = @items.max_by do |item|
|
17
|
+
timestamp_for(item)
|
18
|
+
end
|
19
|
+
|
20
|
+
if timestamp < timestamp_for(latest_event)
|
21
|
+
# Make room!
|
22
|
+
@items.delete(latest_event)
|
23
|
+
return [append_event(x), latest_event]
|
24
|
+
else
|
25
|
+
return [nil, x]
|
26
|
+
end
|
27
|
+
else
|
28
|
+
return [append_event(x), nil]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
TIMESTAMP = "timestamp".freeze
|
33
|
+
|
34
|
+
def timestamp_for(event)
|
35
|
+
main_event, _ = event
|
36
|
+
main_event[TIMESTAMP]
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -24,37 +24,41 @@ module NewRelic
|
|
24
24
|
if @processor_info.nil?
|
25
25
|
case ruby_os_identifier
|
26
26
|
|
27
|
-
when /darwin
|
27
|
+
when /darwin/
|
28
28
|
@processor_info = {
|
29
|
-
:num_physical_packages =>
|
30
|
-
:num_physical_cores =>
|
31
|
-
:num_logical_processors =>
|
29
|
+
:num_physical_packages => sysctl_value('hw.packages').to_i,
|
30
|
+
:num_physical_cores => sysctl_value('hw.physicalcpu_max').to_i,
|
31
|
+
:num_logical_processors => sysctl_value('hw.logicalcpu_max').to_i
|
32
32
|
}
|
33
33
|
# in case those don't work, try backup values
|
34
34
|
if @processor_info[:num_physical_cores] <= 0
|
35
|
-
@processor_info[:num_physical_cores] =
|
35
|
+
@processor_info[:num_physical_cores] = sysctl_value('hw.physicalcpu').to_i
|
36
36
|
end
|
37
37
|
if @processor_info[:num_logical_processors] <= 0
|
38
|
-
@processor_info[:num_logical_processors] =
|
38
|
+
@processor_info[:num_logical_processors] = sysctl_value('hw.logicalcpu').to_i
|
39
39
|
end
|
40
40
|
if @processor_info[:num_logical_processors] <= 0
|
41
|
-
@processor_info[:num_logical_processors] =
|
42
|
-
end
|
43
|
-
if @processor_info[:num_logical_processors] <= 0
|
44
|
-
@processor_info[:num_logical_processors] = `sysctl -n hw.availcpu`.to_i
|
45
|
-
end
|
46
|
-
if @processor_info[:num_logical_processors] <= 0
|
47
|
-
@processor_info[:num_logical_processors] = `sysctl -n hw.activecpu`.to_i
|
41
|
+
@processor_info[:num_logical_processors] = sysctl_value('hw.ncpu').to_i
|
48
42
|
end
|
49
43
|
|
50
44
|
when /linux/
|
51
45
|
cpuinfo = proc_try_read('/proc/cpuinfo')
|
52
46
|
@processor_info = cpuinfo ? parse_cpuinfo(cpuinfo) : {}
|
47
|
+
|
48
|
+
when /freebsd/
|
49
|
+
@processor_info = {
|
50
|
+
:num_physical_packages => nil,
|
51
|
+
:num_physical_cores => nil,
|
52
|
+
:num_logical_processors => sysctl_value('hw.ncpu').to_i
|
53
|
+
}
|
53
54
|
end
|
54
55
|
|
55
56
|
# give nils for obviously wrong values
|
56
57
|
@processor_info.keys.each do |key|
|
57
|
-
|
58
|
+
value = @processor_info[key]
|
59
|
+
if value.is_a?(Numeric) && value <= 0
|
60
|
+
@processor_info[key] = nil
|
61
|
+
end
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
@@ -63,6 +67,11 @@ module NewRelic
|
|
63
67
|
{}
|
64
68
|
end
|
65
69
|
|
70
|
+
def self.sysctl_value(name)
|
71
|
+
# make sure to redirect stderr so we don't spew if the name is unknown
|
72
|
+
`sysctl -n #{name} 2>/dev/null`
|
73
|
+
end
|
74
|
+
|
66
75
|
def self.parse_cpuinfo(cpuinfo)
|
67
76
|
# Build a hash of the form
|
68
77
|
# { [phys_id, core_id] => num_logical_processors_on_this_core }
|
@@ -135,8 +144,22 @@ module NewRelic
|
|
135
144
|
|
136
145
|
def self.parse_docker_container_id(cgroup_info)
|
137
146
|
cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu']
|
138
|
-
return unless cpu_cgroup
|
139
|
-
|
147
|
+
return unless cpu_cgroup
|
148
|
+
|
149
|
+
case cpu_cgroup
|
150
|
+
# docker native driver w/out systemd (fs)
|
151
|
+
when %r{^/docker/([0-9a-f]+)$} then $1
|
152
|
+
# docker native driver with systemd
|
153
|
+
when %r{^/system\.slice/docker-([0-9a-f]+)\.scope$} then $1
|
154
|
+
# docker lxc driver
|
155
|
+
when %r{^/lxc/([0-9a-f]+)$} then $1
|
156
|
+
# not in any cgroup
|
157
|
+
when '/' then nil
|
158
|
+
# in a cgroup, but we don't recognize its format
|
159
|
+
else
|
160
|
+
::NewRelic::Agent.logger.debug("Ignoring unrecognized cgroup ID format: '#{cpu_cgroup}'")
|
161
|
+
nil
|
162
|
+
end
|
140
163
|
end
|
141
164
|
|
142
165
|
def self.parse_cgroup_ids(cgroup_info)
|
@@ -145,8 +168,11 @@ module NewRelic
|
|
145
168
|
cgroup_info.split("\n").each do |line|
|
146
169
|
parts = line.split(':')
|
147
170
|
next unless parts.size == 3
|
148
|
-
_,
|
149
|
-
|
171
|
+
_, subsystems, cgroup_id = parts
|
172
|
+
subsystems = subsystems.split(',')
|
173
|
+
subsystems.each do |subsystem|
|
174
|
+
cgroup_ids[subsystem] = cgroup_id
|
175
|
+
end
|
150
176
|
end
|
151
177
|
|
152
178
|
cgroup_ids
|
@@ -39,7 +39,7 @@ class NewRelic::Agent::TransactionEventAggregator
|
|
39
39
|
@notified_full = false
|
40
40
|
|
41
41
|
@samples = ::NewRelic::Agent::SampledBuffer.new(NewRelic::Agent.config[:'analytics_events.max_samples_stored'])
|
42
|
-
@synthetics_samples = ::NewRelic::Agent::
|
42
|
+
@synthetics_samples = ::NewRelic::Agent::SyntheticsEventBuffer.new(NewRelic::Agent.config[:'synthetics.events_limit'])
|
43
43
|
|
44
44
|
event_listener.subscribe( :transaction_finished, &method(:on_transaction_finished) )
|
45
45
|
self.register_config_callbacks
|
@@ -152,8 +152,15 @@ class NewRelic::Agent::TransactionEventAggregator
|
|
152
152
|
|
153
153
|
def append_event(event)
|
154
154
|
main_event, _ = event
|
155
|
+
|
155
156
|
if main_event.include?(SYNTHETICS_RESOURCE_ID_KEY)
|
156
|
-
|
157
|
+
# Try adding to synthetics buffer. If anything is rejected, give it a
|
158
|
+
# shot in the main transaction events (where it may get sampled)
|
159
|
+
result, rejected = @synthetics_samples.append_with_reject(event)
|
160
|
+
|
161
|
+
if rejected
|
162
|
+
@samples.append(rejected)
|
163
|
+
end
|
157
164
|
else
|
158
165
|
@samples.append(event)
|
159
166
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under New Relic's license terms.
|
3
|
+
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
+
|
5
|
+
module NewRelic
|
6
|
+
module Agent
|
7
|
+
class UtilizationData
|
8
|
+
|
9
|
+
REMOTE_DATA_VALID_CHARS = /^[0-9a-zA-Z_ .\/-]$/.freeze
|
10
|
+
|
11
|
+
def harvest!
|
12
|
+
[hostname, container_id, cpu_count, instance_type]
|
13
|
+
end
|
14
|
+
|
15
|
+
# No persistent data, so no need for merging or resetting
|
16
|
+
def merge!(*_); end
|
17
|
+
def reset!(*_); end
|
18
|
+
|
19
|
+
def hostname
|
20
|
+
NewRelic::Agent::Hostname.get
|
21
|
+
end
|
22
|
+
|
23
|
+
def container_id
|
24
|
+
::NewRelic::Agent::SystemInfo.docker_container_id
|
25
|
+
end
|
26
|
+
|
27
|
+
def cpu_count
|
28
|
+
::NewRelic::Agent::SystemInfo.clear_processor_info
|
29
|
+
::NewRelic::Agent::SystemInfo.num_logical_processors
|
30
|
+
end
|
31
|
+
|
32
|
+
def instance_type
|
33
|
+
Timeout::timeout(1) do
|
34
|
+
remote_fetch('instance-type')
|
35
|
+
end
|
36
|
+
rescue Timeout::Error
|
37
|
+
NewRelic::Agent.logger.debug("UtilizationData timed out fetching remote keys.")
|
38
|
+
nil
|
39
|
+
rescue StandardError, LoadError => e
|
40
|
+
NewRelic::Agent.logger.debug("UtilizationData encountered error fetching remote keys:\n#{e}")
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
INSTANCE_HOST = '169.254.169.254'
|
45
|
+
API_VERSION = '2008-02-01'
|
46
|
+
|
47
|
+
def remote_fetch(remote_key)
|
48
|
+
uri = URI("http://#{INSTANCE_HOST}/#{API_VERSION}/meta-data/#{remote_key}")
|
49
|
+
request = Net::HTTP::get(uri)
|
50
|
+
|
51
|
+
data = validate_remote_data(request)
|
52
|
+
|
53
|
+
if request && data.nil?
|
54
|
+
NewRelic::Agent.logger.warn("Fetching instance metadata for #{remote_key.inspect} returned invalid data: #{request.inspect}")
|
55
|
+
end
|
56
|
+
|
57
|
+
data
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_remote_data(data_str)
|
61
|
+
return nil unless data_str.kind_of?(String)
|
62
|
+
return nil unless data_str.size <= 255
|
63
|
+
|
64
|
+
data_str.each_char do |ch|
|
65
|
+
next if ch =~ REMOTE_DATA_VALID_CHARS
|
66
|
+
code_point = ch[0].ord # this works in Ruby 1.8.7 - 2.1.2
|
67
|
+
next if code_point >= 0x80
|
68
|
+
|
69
|
+
return nil # it's in neither set of valid characters
|
70
|
+
end
|
71
|
+
|
72
|
+
data_str
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|