newrelic_rpm 4.3.0.335 → 4.4.0.336
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/CHANGELOG.md +41 -0
- data/lib/new_relic/agent/agent.rb +5 -3
- data/lib/new_relic/agent/configuration/default_source.rb +32 -0
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +3 -2
- data/lib/new_relic/agent/system_info.rb +34 -0
- data/lib/new_relic/agent/utilization/aws.rb +18 -0
- data/lib/new_relic/agent/utilization/azure.rb +17 -0
- data/lib/new_relic/agent/utilization/gcp.rb +35 -0
- data/lib/new_relic/agent/utilization/pcf.rb +32 -0
- data/lib/new_relic/agent/utilization/vendor.rb +144 -0
- data/lib/new_relic/agent/utilization_data.rb +29 -10
- data/lib/new_relic/version.rb +1 -1
- data/newrelic_rpm.gemspec +1 -1
- data/test/agent_helper.rb +697 -0
- metadata +8 -3
- data/lib/new_relic/agent/aws_info.rb +0 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9d189b04c1171316153a227be91c6abad18f00a
|
4
|
+
data.tar.gz: 2b1c100c3778ba5fa95937d6d87bbe9949fb99a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e77e92639fc53364aaf68627c4d41f1bc9e61ad6f2ce1978732d206a3b7eaf84ee72f06a934a92087179b3c534ea4803d7da5fe6d134416bd32b14f1e7532483
|
7
|
+
data.tar.gz: 566143ee90b3f3c027cb4201824766986d62c66cc78f2311da53861f23dcd272deb528dabceb36efd37db5fcc8e9f8b28f45d12f3729362feea58044dbe87b76
|
data/.yardopts
CHANGED
@@ -7,6 +7,7 @@ lib/new_relic/agent/instrumentation/rack.rb
|
|
7
7
|
lib/new_relic/agent/instrumentation/metric_frame.rb
|
8
8
|
lib/new_relic/agent/stats_engine/metric_stats.rb
|
9
9
|
lib/new_relic/agent/datastores.rb
|
10
|
+
lib/new_relic/agent/messaging.rb
|
10
11
|
lib/new_relic/agent/sql_sampler.rb
|
11
12
|
lib/new_relic/agent/transaction.rb
|
12
13
|
lib/new_relic/agent/transaction_sampler.rb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,46 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes #
|
2
2
|
|
3
|
+
## v4.4.0 ##
|
4
|
+
|
5
|
+
* Include test helper for 3rd party use
|
6
|
+
|
7
|
+
In 4.2.0, all test files were excluded from being packaged in the gem. An
|
8
|
+
agent class method `NewRelic::Agent.require_test_helper` was used by 3rd
|
9
|
+
party gem authors to test extensions to the agent. The required file is now
|
10
|
+
included in the gem.
|
11
|
+
|
12
|
+
* Collect cloud metadata from Azure, GCP, PCF, and AWS cloud platform
|
13
|
+
|
14
|
+
The agent now collects additional metadata when running in AWS, GCP, Azure, and
|
15
|
+
PCF. This information is used to provide an enhanced experience when the agent
|
16
|
+
is deployed on those platforms.
|
17
|
+
|
18
|
+
* Install `at_exit` hook when running JRuby
|
19
|
+
|
20
|
+
The agent now installs an `at_exit` hook when running JRuby, which wasn't
|
21
|
+
done before because of constraints related to older JRuby versions that
|
22
|
+
are no longer supported.
|
23
|
+
|
24
|
+
* User/Utilization and System/Utilization metrics not recorded after Resque forks
|
25
|
+
|
26
|
+
The agent no longer records invalid User/Utilization and System/Utilization
|
27
|
+
metrics, which can lead to negative values, in forks of Resque processes.
|
28
|
+
|
29
|
+
* Add `identifier` field to agent connect settings
|
30
|
+
|
31
|
+
The agent now includes a unique identifier in its connect settings, ensuring
|
32
|
+
that when multiple agents connect to multiple different apps, data are reported
|
33
|
+
for each of the apps.
|
34
|
+
|
35
|
+
* Clear transaction state after forking now opt-in
|
36
|
+
|
37
|
+
The agent waits to connect until the first web request when it detects it's
|
38
|
+
running in a forking dispatcher. When clearing the transaction state in this
|
39
|
+
situation we lose the first frame of the transaction and the subsequent
|
40
|
+
trace becomes corrupted. We've made this feature opt-in and is turned off by
|
41
|
+
default. This behavior only affects the first transaction after a dispatcher
|
42
|
+
forks.
|
43
|
+
|
3
44
|
## v4.3.0 ##
|
4
45
|
|
5
46
|
* Instrumentation for the Bunny AMQP Client
|
@@ -377,7 +377,6 @@ module NewRelic
|
|
377
377
|
def should_install_exit_handler?
|
378
378
|
(
|
379
379
|
Agent.config[:send_data_on_exit] &&
|
380
|
-
!NewRelic::LanguageSupport.jruby? &&
|
381
380
|
!sinatra_classic_app?
|
382
381
|
)
|
383
382
|
end
|
@@ -543,7 +542,9 @@ module NewRelic
|
|
543
542
|
@transaction_event_recorder.drop_buffered_data
|
544
543
|
@custom_event_aggregator.reset!
|
545
544
|
@sql_sampler.reset!
|
546
|
-
|
545
|
+
if Agent.config[:clear_transaction_state_after_fork]
|
546
|
+
TransactionState.tl_clear
|
547
|
+
end
|
547
548
|
end
|
548
549
|
|
549
550
|
# Clear out state for any objects that we know lock from our parents
|
@@ -803,7 +804,8 @@ module NewRelic
|
|
803
804
|
:environment => @environment_report,
|
804
805
|
:settings => Agent.config.to_collector_hash,
|
805
806
|
:high_security => Agent.config[:high_security],
|
806
|
-
:utilization => UtilizationData.new.to_collector_hash
|
807
|
+
:utilization => UtilizationData.new.to_collector_hash,
|
808
|
+
:identifier => "ruby:#{local_host}:#{Agent.config.app_names.sort.join(',')}"
|
807
809
|
}
|
808
810
|
end
|
809
811
|
|
@@ -1561,8 +1561,33 @@ module NewRelic
|
|
1561
1561
|
:public => true,
|
1562
1562
|
:type => Boolean,
|
1563
1563
|
:allowed_from_server => false,
|
1564
|
+
:dynamic_name => true,
|
1564
1565
|
:description => 'If <code>true</code>, the agent automatically detects that it is running in an AWS environment.'
|
1565
1566
|
},
|
1567
|
+
:'utilization.detect_azure' => {
|
1568
|
+
:default => true,
|
1569
|
+
:public => true,
|
1570
|
+
:type => Boolean,
|
1571
|
+
:allowed_from_server => false,
|
1572
|
+
:dynamic_name => true,
|
1573
|
+
:description => 'If <code>true</code>, the agent automatically detects that it is running in an Azure environment.'
|
1574
|
+
},
|
1575
|
+
:'utilization.detect_gcp' => {
|
1576
|
+
:default => true,
|
1577
|
+
:public => true,
|
1578
|
+
:type => Boolean,
|
1579
|
+
:allowed_from_server => false,
|
1580
|
+
:dynamic_name => true,
|
1581
|
+
:description => 'If <code>true</code>, the agent automatically detects that it is running in an Google Cloud Platform environment.'
|
1582
|
+
},
|
1583
|
+
:'utilization.detect_pcf' => {
|
1584
|
+
:default => true,
|
1585
|
+
:public => true,
|
1586
|
+
:type => Boolean,
|
1587
|
+
:allowed_from_server => false,
|
1588
|
+
:dynamic_name => true,
|
1589
|
+
:description => 'If <code>true</code>, the agent automatically detects that it is running in a Pivotal Cloud Foundry environment.'
|
1590
|
+
},
|
1566
1591
|
:'utilization.detect_docker' => {
|
1567
1592
|
:default => true,
|
1568
1593
|
:public => true,
|
@@ -1607,6 +1632,13 @@ module NewRelic
|
|
1607
1632
|
:type => Boolean,
|
1608
1633
|
:allowed_from_server => false,
|
1609
1634
|
:description => 'If <code>false</code>, the agent will not add <code>database_name</code> parameter to transaction or slow sql traces.'
|
1635
|
+
},
|
1636
|
+
:'clear_transaction_state_after_fork' => {
|
1637
|
+
:default => false,
|
1638
|
+
:public => true,
|
1639
|
+
:type => Boolean,
|
1640
|
+
:allowed_from_server => false,
|
1641
|
+
:description => 'If <code>true</code>, the agent will clear <code>TransactionState</code> in <code>Agent.drop_buffered_data</code>.'
|
1610
1642
|
}
|
1611
1643
|
}.freeze
|
1612
1644
|
end
|
@@ -50,7 +50,8 @@ module NewRelic
|
|
50
50
|
def poll
|
51
51
|
now = Time.now
|
52
52
|
t = Process.times
|
53
|
-
|
53
|
+
|
54
|
+
if @last_time && t.utime != 0.0 && t.stime != 0.0
|
54
55
|
elapsed = now - @last_time
|
55
56
|
return if elapsed < 1 # Causing some kind of math underflow
|
56
57
|
|
@@ -62,10 +63,10 @@ module NewRelic
|
|
62
63
|
|
63
64
|
# Calculate the true utilization by taking cpu times and dividing by
|
64
65
|
# elapsed time X processor_count.
|
65
|
-
|
66
66
|
record_user_util(usertime / (elapsed * @processor_count))
|
67
67
|
record_system_util(systemtime / (elapsed * @processor_count))
|
68
68
|
end
|
69
|
+
|
69
70
|
@last_utime = t.utime
|
70
71
|
@last_stime = t.stime
|
71
72
|
@last_time = now
|
@@ -251,6 +251,40 @@ module NewRelic
|
|
251
251
|
nil
|
252
252
|
end
|
253
253
|
end
|
254
|
+
|
255
|
+
def self.boot_id
|
256
|
+
return nil unless linux?
|
257
|
+
if bid = proc_try_read('/proc/sys/kernel/random/boot_id')
|
258
|
+
bid.chomp!
|
259
|
+
|
260
|
+
if bid.ascii_only?
|
261
|
+
if bid.empty?
|
262
|
+
::NewRelic::Agent.logger.debug("boot_id not found in /proc/sys/kernel/random/boot_id")
|
263
|
+
::NewRelic::Agent.increment_metric "Supportability/utilization/boot_id/error"
|
264
|
+
nil
|
265
|
+
|
266
|
+
elsif bid.bytesize == 36
|
267
|
+
bid
|
268
|
+
|
269
|
+
else
|
270
|
+
::NewRelic::Agent.logger.debug("Found boot_id with invalid length: #{bid}")
|
271
|
+
::NewRelic::Agent.increment_metric "Supportability/utilization/boot_id/error"
|
272
|
+
bid[0,128]
|
273
|
+
|
274
|
+
end
|
275
|
+
else
|
276
|
+
::NewRelic::Agent.logger.debug("Found boot_id with non-ASCII characters: #{bid}")
|
277
|
+
::NewRelic::Agent.increment_metric "Supportability/utilization/boot_id/error"
|
278
|
+
nil
|
279
|
+
|
280
|
+
end
|
281
|
+
else
|
282
|
+
::NewRelic::Agent.logger.debug("boot_id not found in /proc/sys/kernel/random/boot_id")
|
283
|
+
::NewRelic::Agent.increment_metric "Supportability/utilization/boot_id/error"
|
284
|
+
nil
|
285
|
+
|
286
|
+
end
|
287
|
+
end
|
254
288
|
end
|
255
289
|
end
|
256
290
|
end
|
@@ -0,0 +1,18 @@
|
|
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/utilization/vendor'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Utilization
|
10
|
+
class AWS < Vendor
|
11
|
+
vendor_name "aws"
|
12
|
+
endpoint "http://169.254.169.254/2016-09-02/dynamic/instance-identity/document"
|
13
|
+
keys ["instanceId", "instanceType", "availabilityZone"]
|
14
|
+
key_transforms :to_sym
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
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
|
+
module Utilization
|
8
|
+
class Azure < Vendor
|
9
|
+
vendor_name "azure"
|
10
|
+
endpoint "http://169.254.169.254/metadata/instance/compute?api-version=2017-03-01"
|
11
|
+
headers "Metadata" => "true"
|
12
|
+
keys ["vmId", "name", "vmSize", "location"]
|
13
|
+
key_transforms :to_sym
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
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/utilization/vendor'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Utilization
|
10
|
+
class GCP < Vendor
|
11
|
+
vendor_name "gcp"
|
12
|
+
endpoint "http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true"
|
13
|
+
headers "Metadata-Flavor" => "Google"
|
14
|
+
keys ["id", "machineType", "name", "zone"]
|
15
|
+
key_transforms :to_sym
|
16
|
+
|
17
|
+
MACH_TYPE = 'machineType'.freeze
|
18
|
+
ZONE = 'zone'.freeze
|
19
|
+
|
20
|
+
def prepare_response response
|
21
|
+
body = JSON.parse response.body
|
22
|
+
body[MACH_TYPE] = trim_leading body[MACH_TYPE]
|
23
|
+
body[ZONE] = trim_leading body[ZONE]
|
24
|
+
body
|
25
|
+
end
|
26
|
+
|
27
|
+
SLASH = '/'.freeze
|
28
|
+
|
29
|
+
def trim_leading value
|
30
|
+
value.split(SLASH).last
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
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/utilization/vendor'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Utilization
|
10
|
+
class PCF < Vendor
|
11
|
+
vendor_name "pcf"
|
12
|
+
keys ["CF_INSTANCE_GUID", "CF_INSTANCE_IP", "MEMORY_LIMIT"]
|
13
|
+
key_transforms [:downcase, :to_sym]
|
14
|
+
|
15
|
+
def detect
|
16
|
+
begin
|
17
|
+
return false unless pcf_keys_present?
|
18
|
+
process_response ENV
|
19
|
+
rescue
|
20
|
+
NewRelic::Agent.logger.error "Error occurred detecting: #{vendor_name}", e
|
21
|
+
record_supportability_metric
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def pcf_keys_present?
|
27
|
+
!(ENV.keys & keys).empty?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,144 @@
|
|
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 'net/http'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Utilization
|
10
|
+
class Vendor
|
11
|
+
class << self
|
12
|
+
def vendor_name vendor_name = nil
|
13
|
+
vendor_name ? @vendor_name = vendor_name.freeze : @vendor_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def endpoint endpoint = nil
|
17
|
+
endpoint ? @endpoint = URI(endpoint) : @endpoint
|
18
|
+
end
|
19
|
+
|
20
|
+
def headers headers = nil
|
21
|
+
headers ? @headers = headers.freeze : @headers
|
22
|
+
end
|
23
|
+
|
24
|
+
def keys keys = nil
|
25
|
+
keys ? @keys = keys.freeze : @keys
|
26
|
+
end
|
27
|
+
|
28
|
+
def key_transforms key_transforms = nil
|
29
|
+
key_transforms ? @key_transforms = Array(key_transforms).freeze : @key_transforms
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :metadata
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
@metadata = {}
|
37
|
+
end
|
38
|
+
|
39
|
+
[:vendor_name, :endpoint, :headers, :keys, :key_transforms].each do |method_name|
|
40
|
+
define_method(method_name) { self.class.send(method_name) }
|
41
|
+
end
|
42
|
+
|
43
|
+
SUCCESS = '200'.freeze
|
44
|
+
|
45
|
+
def detect
|
46
|
+
response = request_metadata
|
47
|
+
return false unless response
|
48
|
+
|
49
|
+
begin
|
50
|
+
if response.code == SUCCESS
|
51
|
+
process_response prepare_response(response)
|
52
|
+
else
|
53
|
+
false
|
54
|
+
end
|
55
|
+
rescue => e
|
56
|
+
NewRelic::Agent.logger.error "Error occurred detecting: #{vendor_name}", e
|
57
|
+
record_supportability_metric
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def request_metadata
|
65
|
+
Timeout.timeout 1 do
|
66
|
+
response = nil
|
67
|
+
Net::HTTP.start endpoint.host, endpoint.port do |http|
|
68
|
+
req = Net::HTTP::Get.new endpoint, headers
|
69
|
+
response = http.request req
|
70
|
+
end
|
71
|
+
response
|
72
|
+
end
|
73
|
+
rescue
|
74
|
+
NewRelic::Agent.logger.debug "#{vendor_name} environment not detected"
|
75
|
+
end
|
76
|
+
|
77
|
+
def prepare_response response
|
78
|
+
JSON.parse response.body
|
79
|
+
end
|
80
|
+
|
81
|
+
def process_response response
|
82
|
+
keys.each do |key|
|
83
|
+
normalized = normalize response[key]
|
84
|
+
if normalized
|
85
|
+
@metadata[transform_key(key)] = normalized
|
86
|
+
else
|
87
|
+
@metadata.clear
|
88
|
+
record_supportability_metric
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
true
|
93
|
+
end
|
94
|
+
|
95
|
+
def normalize value
|
96
|
+
return if value.nil?
|
97
|
+
|
98
|
+
value = value.to_s
|
99
|
+
value = value.dup if value.frozen?
|
100
|
+
|
101
|
+
value.force_encoding Encoding::UTF_8
|
102
|
+
value.strip!
|
103
|
+
|
104
|
+
return unless valid_length? value
|
105
|
+
return unless valid_chars? value
|
106
|
+
|
107
|
+
value
|
108
|
+
end
|
109
|
+
|
110
|
+
def valid_length? value
|
111
|
+
if value.bytesize <= 255
|
112
|
+
true
|
113
|
+
else
|
114
|
+
NewRelic::Agent.logger.warn "Found invalid length value while detecting: #{vendor_name}"
|
115
|
+
false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
VALID_CHARS = /^[0-9a-zA-Z_ .\/-]$/
|
120
|
+
|
121
|
+
def valid_chars? value
|
122
|
+
value.each_char do |ch|
|
123
|
+
next if ch =~ VALID_CHARS
|
124
|
+
code_point = ch[0].ord # this works in Ruby 1.8.7 - 2.1.2
|
125
|
+
next if code_point >= 0x80
|
126
|
+
|
127
|
+
NewRelic::Agent.logger.warn "Found invalid character while detecting: #{vendor_name}"
|
128
|
+
return false # it's in neither set of valid characters
|
129
|
+
end
|
130
|
+
true
|
131
|
+
end
|
132
|
+
|
133
|
+
def transform_key key
|
134
|
+
return key unless key_transforms
|
135
|
+
key_transforms.inject(key) { |memo, transform| memo.send(transform) }
|
136
|
+
end
|
137
|
+
|
138
|
+
def record_supportability_metric
|
139
|
+
NewRelic::Agent.increment_metric "Supportability/utilization/#{vendor_name}/error"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|