newrelic_rpm 5.5.0.348 → 5.6.0.349
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +26 -1
- data/CHANGELOG.md +50 -0
- data/README.md +1 -1
- data/config.dot +1 -0
- data/lib/new_relic/agent/agent.rb +7 -5
- data/lib/new_relic/agent/attribute_filter.rb +77 -17
- data/lib/new_relic/agent/configuration/default_source.rb +61 -0
- data/lib/new_relic/agent/configuration/security_policy_source.rb +14 -0
- data/lib/new_relic/agent/error_collector.rb +3 -5
- data/lib/new_relic/agent/instrumentation/active_storage.rb +23 -0
- data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +59 -0
- data/lib/new_relic/agent/span_event_primitive.rb +26 -16
- data/lib/new_relic/agent/transaction.rb +3 -1
- data/lib/new_relic/agent/transaction/datastore_segment.rb +0 -2
- data/lib/new_relic/agent/transaction/trace_node.rb +4 -2
- data/lib/new_relic/agent/transaction_time_aggregator.rb +32 -22
- data/lib/new_relic/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eafe4315178abb8fe388bdae54e2c201fa080b142d093d0aa66678e2dff39596
|
4
|
+
data.tar.gz: 1c7d5d213331e77c5e3c78c1bf58cc956336615aa5d08bc7331a56ca2293a351
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8027ef671be103e04bc674a35fccfed2c292abe47873281d0007738a306b88422493283eb04881cb6794478b9c10307db3a89c342d149456bc21e73cffbcf83
|
7
|
+
data.tar.gz: 8d6006908631d158b0edc1757c80960a80e7d415599faf5516635fa96dafe16e228e20263dbf1961f82e7cc6483f7ebbdd26f4dc8e8602846bc8e1e6a114ab72
|
data/.travis.yml
CHANGED
@@ -9,7 +9,9 @@ language: ruby
|
|
9
9
|
sudo: required
|
10
10
|
|
11
11
|
before_install:
|
12
|
-
|
12
|
+
# RUBY-2072 Prevent Travis setup failure before our test even starts
|
13
|
+
- sudo rm -f /etc/apt/sources.list.d/travis_ci_zeromq3.list
|
14
|
+
|
13
15
|
- gem --version
|
14
16
|
- gem update --system
|
15
17
|
- ./test/script/before_install/gemstash_mirror.sh
|
@@ -19,7 +21,11 @@ install: bundle install
|
|
19
21
|
|
20
22
|
addons:
|
21
23
|
apt:
|
24
|
+
update: true
|
22
25
|
packages:
|
26
|
+
- openssl
|
27
|
+
- libssl-dev
|
28
|
+
- build-essential
|
23
29
|
- haveged
|
24
30
|
|
25
31
|
before_script: ./test/script/before_script/install_mongodb.sh
|
@@ -40,6 +46,7 @@ notifications:
|
|
40
46
|
rvm:
|
41
47
|
# Run slowest builds first to try and optimize overall cycle time.
|
42
48
|
- jruby-9.1.13.0
|
49
|
+
- 2.6.0-preview3
|
43
50
|
- 2.5.0
|
44
51
|
- 2.4.2
|
45
52
|
- 2.3.5
|
@@ -88,6 +95,24 @@ matrix:
|
|
88
95
|
fast_finish: true
|
89
96
|
exclude:
|
90
97
|
# Unsupported Rails/Ruby combinations
|
98
|
+
# 2.6
|
99
|
+
- rvm: 2.6.0-preview3
|
100
|
+
env: TYPE=UNIT ENVIRONMENT=rails21
|
101
|
+
- rvm: 2.6.0-preview3
|
102
|
+
env: TYPE=UNIT ENVIRONMENT=rails22
|
103
|
+
- rvm: 2.6.0-preview3
|
104
|
+
env: TYPE=UNIT ENVIRONMENT=rails23
|
105
|
+
- rvm: 2.6.0-preview3
|
106
|
+
env: TYPE=UNIT ENVIRONMENT=rails30
|
107
|
+
- rvm: 2.6.0-preview3
|
108
|
+
env: TYPE=UNIT ENVIRONMENT=rails31
|
109
|
+
- rvm: 2.6.0-preview3
|
110
|
+
env: TYPE=UNIT ENVIRONMENT=rails32
|
111
|
+
- rvm: 2.6.0-preview3
|
112
|
+
env: TYPE=UNIT ENVIRONMENT=rails40
|
113
|
+
- rvm: 2.6.0-preview3
|
114
|
+
env: TYPE=UNIT ENVIRONMENT=rails41
|
115
|
+
|
91
116
|
# 2.5
|
92
117
|
- rvm: 2.5.0
|
93
118
|
env: TYPE=UNIT ENVIRONMENT=rails21
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,55 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes #
|
2
2
|
|
3
|
+
## v5.6.0
|
4
|
+
|
5
|
+
* Bugfix for transactions with `ActionController::Live`
|
6
|
+
|
7
|
+
Previously, transactions containing `ActionController::Live` resulted in
|
8
|
+
incorrect calculations of capacity analysis as well as error backtraces
|
9
|
+
appearing in agent logs in agent versions 5.4 and later. The agent now
|
10
|
+
correctly calculates capacity for transactions with `ActionController::Live`.
|
11
|
+
|
12
|
+
* Add ability to exclude attributes from span events and transaction
|
13
|
+
segments
|
14
|
+
|
15
|
+
Agent versions 5.5 and lower could selectively exclude attributes
|
16
|
+
from page views, error traces, transaction traces, and
|
17
|
+
transaction events. With agent version 5.6 and higher, you can
|
18
|
+
also exclude attributes from span events (via the
|
19
|
+
`span_events.include/exclude` options) and from transaction
|
20
|
+
segments (via the `transaction_segments.include/exclude` options).
|
21
|
+
|
22
|
+
As with other attribute destinations, these new options will
|
23
|
+
inherit values from the top-level `attributes.include/exclude`
|
24
|
+
settings. See the
|
25
|
+
[documentation](https://docs.newrelic.com/docs/agents/ruby-agent/attributes/enabling-disabling-attributes-ruby)
|
26
|
+
for more information.
|
27
|
+
|
28
|
+
* Increasing backoff sequence on failing to connect to New Relic
|
29
|
+
|
30
|
+
If the agent cannot reach New Relic, it will now wait for an
|
31
|
+
increasing amount of time after each failed attempt. We are also
|
32
|
+
starting with a shorter delay initially, which will help customer
|
33
|
+
apps bounce back more quickly from transient network errors.
|
34
|
+
|
35
|
+
* Truncation of long stack traces
|
36
|
+
|
37
|
+
Previous versions of the agent would truncate long stack traces to
|
38
|
+
50 frames. To give customers more flexibility, we have added the
|
39
|
+
`error_collector.max_backtrace_frames` configuration option.
|
40
|
+
Thanks to Patrick Tulskie for the contribution!
|
41
|
+
|
42
|
+
* Update link in documentation
|
43
|
+
|
44
|
+
The community forum link in `README.md` now goes to the updated
|
45
|
+
location. Thanks to Sam Killgallon for the contribution!
|
46
|
+
|
47
|
+
* Active Storage instrumentation
|
48
|
+
|
49
|
+
The agent now provides instrumentation for Active Storage, introduced in
|
50
|
+
Rails 5.2. Customers will see Active Storage operations represented as
|
51
|
+
segments within transaction traces.
|
52
|
+
|
3
53
|
## v5.5.0
|
4
54
|
|
5
55
|
* Bugfix for `perform` instrumentation with curb gem
|
data/README.md
CHANGED
@@ -127,7 +127,7 @@ You can find more detailed documentation [on our website](http://newrelic.com/do
|
|
127
127
|
and specifically in the [Ruby category](http://newrelic.com/docs/ruby).
|
128
128
|
|
129
129
|
If you can't find what you're looking for there, reach out to us on our [support
|
130
|
-
site](http://support.newrelic.com/) or our [community forum](
|
130
|
+
site](http://support.newrelic.com/) or our [community forum](https://discuss.newrelic.com/)
|
131
131
|
and we'll be happy to help you.
|
132
132
|
|
133
133
|
Find a bug? Contact us via [support.newrelic.com](http://support.newrelic.com/),
|
data/config.dot
CHANGED
@@ -727,12 +727,14 @@ module NewRelic
|
|
727
727
|
force || (!connected? && !disconnected?)
|
728
728
|
end
|
729
729
|
|
730
|
-
#
|
731
|
-
#
|
732
|
-
#
|
733
|
-
#
|
730
|
+
# Per the spec at
|
731
|
+
# /agents/agent-specs/Collector-Response-Handling.md, retry
|
732
|
+
# connections after a specific backoff sequence to prevent
|
733
|
+
# hammering the server.
|
734
|
+
CONNECT_RETRY_PERIODS = [15, 15, 30, 60, 120, 300]
|
735
|
+
|
734
736
|
def connect_retry_period
|
735
|
-
[
|
737
|
+
CONNECT_RETRY_PERIODS[connect_attempts] || 300
|
736
738
|
end
|
737
739
|
|
738
740
|
def note_connect_failure
|
@@ -64,42 +64,55 @@ module NewRelic
|
|
64
64
|
class AttributeFilter
|
65
65
|
DST_NONE = 0x0
|
66
66
|
|
67
|
-
DST_TRANSACTION_EVENTS
|
68
|
-
DST_TRANSACTION_TRACER
|
69
|
-
DST_ERROR_COLLECTOR
|
70
|
-
DST_BROWSER_MONITORING
|
67
|
+
DST_TRANSACTION_EVENTS = 1 << 0
|
68
|
+
DST_TRANSACTION_TRACER = 1 << 1
|
69
|
+
DST_ERROR_COLLECTOR = 1 << 2
|
70
|
+
DST_BROWSER_MONITORING = 1 << 3
|
71
|
+
DST_SPAN_EVENTS = 1 << 4
|
72
|
+
DST_TRANSACTION_SEGMENTS = 1 << 5
|
71
73
|
|
72
|
-
DST_ALL
|
74
|
+
DST_ALL = 0x3f
|
73
75
|
|
74
76
|
attr_reader :rules
|
75
77
|
|
76
78
|
def initialize(config)
|
77
79
|
@enabled_destinations = DST_NONE
|
78
80
|
|
79
|
-
@enabled_destinations |= DST_TRANSACTION_TRACER
|
80
|
-
@enabled_destinations |= DST_TRANSACTION_EVENTS
|
81
|
-
@enabled_destinations |= DST_ERROR_COLLECTOR
|
82
|
-
@enabled_destinations |= DST_BROWSER_MONITORING
|
81
|
+
@enabled_destinations |= DST_TRANSACTION_TRACER if config[:'transaction_tracer.attributes.enabled']
|
82
|
+
@enabled_destinations |= DST_TRANSACTION_EVENTS if config[:'transaction_events.attributes.enabled']
|
83
|
+
@enabled_destinations |= DST_ERROR_COLLECTOR if config[:'error_collector.attributes.enabled']
|
84
|
+
@enabled_destinations |= DST_BROWSER_MONITORING if config[:'browser_monitoring.attributes.enabled']
|
85
|
+
@enabled_destinations |= DST_SPAN_EVENTS if config[:'span_events.attributes.enabled']
|
86
|
+
@enabled_destinations |= DST_TRANSACTION_SEGMENTS if config[:'transaction_segments.attributes.enabled']
|
83
87
|
|
84
88
|
@enabled_destinations = DST_NONE unless config[:'attributes.enabled']
|
85
89
|
|
86
90
|
@rules = []
|
87
91
|
|
88
92
|
build_rule(config[:'attributes.exclude'], DST_ALL, false)
|
89
|
-
build_rule(config[:'transaction_tracer.attributes.exclude'],
|
90
|
-
build_rule(config[:'transaction_events.attributes.exclude'],
|
91
|
-
build_rule(config[:'error_collector.attributes.exclude'],
|
92
|
-
build_rule(config[:'browser_monitoring.attributes.exclude'],
|
93
|
+
build_rule(config[:'transaction_tracer.attributes.exclude'], DST_TRANSACTION_TRACER, false)
|
94
|
+
build_rule(config[:'transaction_events.attributes.exclude'], DST_TRANSACTION_EVENTS, false)
|
95
|
+
build_rule(config[:'error_collector.attributes.exclude'], DST_ERROR_COLLECTOR, false)
|
96
|
+
build_rule(config[:'browser_monitoring.attributes.exclude'], DST_BROWSER_MONITORING, false)
|
97
|
+
build_rule(config[:'span_events.attributes.exclude'], DST_SPAN_EVENTS, false)
|
98
|
+
build_rule(config[:'transaction_segments.attributes.exclude'], DST_TRANSACTION_SEGMENTS, false)
|
93
99
|
|
94
100
|
build_rule(['request.parameters.*'], include_destinations_for_capture_params(config[:capture_params]), true)
|
95
101
|
build_rule(['job.resque.args.*'], include_destinations_for_capture_params(config[:'resque.capture_params']), true)
|
96
102
|
build_rule(['job.sidekiq.args.*'], include_destinations_for_capture_params(config[:'sidekiq.capture_params']), true)
|
97
103
|
|
104
|
+
build_rule(['host', 'port_path_or_id'], DST_TRANSACTION_SEGMENTS, config[:'datastore_tracer.instance_reporting.enabled'])
|
105
|
+
build_rule(['database_name'], DST_TRANSACTION_SEGMENTS, config[:'datastore_tracer.database_name_reporting.enabled'])
|
106
|
+
|
98
107
|
build_rule(config[:'attributes.include'], DST_ALL, true)
|
99
|
-
build_rule(config[:'transaction_tracer.attributes.include'],
|
100
|
-
build_rule(config[:'transaction_events.attributes.include'],
|
101
|
-
build_rule(config[:'error_collector.attributes.include'],
|
102
|
-
build_rule(config[:'browser_monitoring.attributes.include'],
|
108
|
+
build_rule(config[:'transaction_tracer.attributes.include'], DST_TRANSACTION_TRACER, true)
|
109
|
+
build_rule(config[:'transaction_events.attributes.include'], DST_TRANSACTION_EVENTS, true)
|
110
|
+
build_rule(config[:'error_collector.attributes.include'], DST_ERROR_COLLECTOR, true)
|
111
|
+
build_rule(config[:'browser_monitoring.attributes.include'], DST_BROWSER_MONITORING, true)
|
112
|
+
build_rule(config[:'span_events.attributes.include'], DST_SPAN_EVENTS, true)
|
113
|
+
build_rule(config[:'transaction_segments.attributes.include'], DST_TRANSACTION_SEGMENTS, true)
|
114
|
+
|
115
|
+
build_uri_rule(config[:'attributes.exclude'])
|
103
116
|
|
104
117
|
@rules.sort!
|
105
118
|
|
@@ -107,9 +120,35 @@ module NewRelic
|
|
107
120
|
# filter is re-generated on any significant config change.
|
108
121
|
@high_security = config[:high_security]
|
109
122
|
|
123
|
+
setup_key_cache
|
110
124
|
cache_prefix_blacklist
|
111
125
|
end
|
112
126
|
|
127
|
+
# Note the key_cache is a global cache, accessible by multiple threads,
|
128
|
+
# but is intentionally left unsynchronized for liveness. Writes will always
|
129
|
+
# involve writing the same boolean value for each key, so there is no
|
130
|
+
# worry of one value clobbering another. For reads, if a value hasn't been
|
131
|
+
# written to the cache yet, the worst that will happen is that it will run
|
132
|
+
# through the filter rules again. Both reads and writes will become
|
133
|
+
# eventually consistent.
|
134
|
+
|
135
|
+
def setup_key_cache
|
136
|
+
destinations = [
|
137
|
+
DST_TRANSACTION_EVENTS,
|
138
|
+
DST_TRANSACTION_TRACER,
|
139
|
+
DST_ERROR_COLLECTOR,
|
140
|
+
DST_BROWSER_MONITORING,
|
141
|
+
DST_SPAN_EVENTS,
|
142
|
+
DST_TRANSACTION_SEGMENTS,
|
143
|
+
DST_ALL
|
144
|
+
]
|
145
|
+
|
146
|
+
@key_cache = destinations.inject({}) do |memo, destination|
|
147
|
+
memo[destination] = {}
|
148
|
+
memo
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
113
152
|
def include_destinations_for_capture_params(capturing)
|
114
153
|
if capturing
|
115
154
|
DST_TRANSACTION_TRACER | DST_ERROR_COLLECTOR
|
@@ -125,6 +164,14 @@ module NewRelic
|
|
125
164
|
end
|
126
165
|
end
|
127
166
|
|
167
|
+
def build_uri_rule(excluded_attributes)
|
168
|
+
uri_aliases = %w(uri url request_uri request.uri http.url)
|
169
|
+
|
170
|
+
if (excluded_attributes & uri_aliases).size > 0
|
171
|
+
build_rule(uri_aliases - excluded_attributes, DST_ALL, false)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
128
175
|
def apply(attribute_name, default_destinations)
|
129
176
|
return DST_NONE if @enabled_destinations == DST_NONE
|
130
177
|
|
@@ -148,6 +195,19 @@ module NewRelic
|
|
148
195
|
allowed_destinations & requested_destination == requested_destination
|
149
196
|
end
|
150
197
|
|
198
|
+
def allows_key?(key, destination)
|
199
|
+
return false unless destination & @enabled_destinations == destination
|
200
|
+
|
201
|
+
value = @key_cache[destination][key]
|
202
|
+
|
203
|
+
if value.nil?
|
204
|
+
allowed_destinations = apply(key, destination)
|
205
|
+
@key_cache[destination][key] = allows?(allowed_destinations, destination)
|
206
|
+
else
|
207
|
+
value
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
151
211
|
def high_security?
|
152
212
|
@high_security
|
153
213
|
end
|
@@ -719,6 +719,14 @@ module NewRelic
|
|
719
719
|
:allowed_from_server => false,
|
720
720
|
:description => 'If <code>true</code>, disables Action Cable instrumentation.'
|
721
721
|
},
|
722
|
+
:disable_active_storage => {
|
723
|
+
:default => false,
|
724
|
+
:public => true,
|
725
|
+
:type => Boolean,
|
726
|
+
:dynamic_name => true,
|
727
|
+
:allowed_from_server => false,
|
728
|
+
:description => 'If <code>true</code>, disables ActiveStorage instrumentation.'
|
729
|
+
},
|
722
730
|
:disable_memcached => {
|
723
731
|
:default => value_of(:disable_memcache_instrumentation),
|
724
732
|
:public => true,
|
@@ -981,6 +989,13 @@ module NewRelic
|
|
981
989
|
:allowed_from_server => true,
|
982
990
|
:description => 'Specify a comma-delimited list of error classes that the agent should ignore.'
|
983
991
|
},
|
992
|
+
:'error_collector.max_backtrace_frames' => {
|
993
|
+
:default => 50,
|
994
|
+
:public => true,
|
995
|
+
:type => Integer,
|
996
|
+
:allowed_from_server => false,
|
997
|
+
:description => 'Defines the maximum number of frames in an error backtrace. Backtraces over this amount are truncated at the beginning and end.'
|
998
|
+
},
|
984
999
|
:'error_collector.capture_events' => {
|
985
1000
|
:default => value_of(:'error_collector.enabled'),
|
986
1001
|
:public => true,
|
@@ -1505,6 +1520,20 @@ module NewRelic
|
|
1505
1520
|
:allowed_from_server => false,
|
1506
1521
|
:description => 'If <code>true</code>, the agent captures attributes from browser monitoring.'
|
1507
1522
|
},
|
1523
|
+
:'span_events.attributes.enabled' => {
|
1524
|
+
:default => true,
|
1525
|
+
:public => true,
|
1526
|
+
:type => Boolean,
|
1527
|
+
:allowed_from_server => false,
|
1528
|
+
:description => 'If <code>true</code>, the agent captures attributes on span events.'
|
1529
|
+
},
|
1530
|
+
:'transaction_segments.attributes.enabled' => {
|
1531
|
+
:default => true,
|
1532
|
+
:public => true,
|
1533
|
+
:type => Boolean,
|
1534
|
+
:allowed_from_server => false,
|
1535
|
+
:description => 'If <code>true</code>, the agent captures attributes on transaction segments.'
|
1536
|
+
},
|
1508
1537
|
:'attributes.exclude' => {
|
1509
1538
|
:default => [],
|
1510
1539
|
:public => true,
|
@@ -1545,6 +1574,22 @@ module NewRelic
|
|
1545
1574
|
:transform => DefaultSource.method(:convert_to_list),
|
1546
1575
|
:description => 'Prefix of attributes to exclude from browser monitoring. Allows <code>*</code> as wildcard at end.'
|
1547
1576
|
},
|
1577
|
+
:'span_events.attributes.exclude' => {
|
1578
|
+
:default => [],
|
1579
|
+
:public => true,
|
1580
|
+
:type => Array,
|
1581
|
+
:allowed_from_server => false,
|
1582
|
+
:transform => DefaultSource.method(:convert_to_list),
|
1583
|
+
:description => 'Prefix of attributes to exclude from span events. Allows <code>*</code> as wildcard at end.'
|
1584
|
+
},
|
1585
|
+
:'transaction_segments.attributes.exclude' => {
|
1586
|
+
:default => [],
|
1587
|
+
:public => true,
|
1588
|
+
:type => Array,
|
1589
|
+
:allowed_from_server => false,
|
1590
|
+
:transform => DefaultSource.method(:convert_to_list),
|
1591
|
+
:description => 'Prefix of attributes to exclude from transaction segments. Allows <code>*</code> as wildcard at end.'
|
1592
|
+
},
|
1548
1593
|
:'attributes.include' => {
|
1549
1594
|
:default => [],
|
1550
1595
|
:public => true,
|
@@ -1585,6 +1630,22 @@ module NewRelic
|
|
1585
1630
|
:transform => DefaultSource.method(:convert_to_list),
|
1586
1631
|
:description => 'Prefix of attributes to include in browser monitoring. Allows <code>*</code> as wildcard at end.'
|
1587
1632
|
},
|
1633
|
+
:'span_events.attributes.include' => {
|
1634
|
+
:default => [],
|
1635
|
+
:public => true,
|
1636
|
+
:type => Array,
|
1637
|
+
:allowed_from_server => false,
|
1638
|
+
:transform => DefaultSource.method(:convert_to_list),
|
1639
|
+
:description => 'Prefix of attributes to include on span events. Allows <code>*</code> as wildcard at end.'
|
1640
|
+
},
|
1641
|
+
:'transaction_segments.attributes.include' => {
|
1642
|
+
:default => [],
|
1643
|
+
:public => true,
|
1644
|
+
:type => Array,
|
1645
|
+
:allowed_from_server => false,
|
1646
|
+
:transform => DefaultSource.method(:convert_to_list),
|
1647
|
+
:description => 'Prefix of attributes to include on transaction segments. Allows <code>*</code> as wildcard at end.'
|
1648
|
+
},
|
1588
1649
|
:'custom_attributes.enabled' => {
|
1589
1650
|
:default => true,
|
1590
1651
|
:public => true,
|
@@ -121,6 +121,20 @@ module NewRelic
|
|
121
121
|
enabled_fn: method(:not_empty?),
|
122
122
|
disabled_value: [],
|
123
123
|
permitted_fn: nil
|
124
|
+
},
|
125
|
+
{
|
126
|
+
option: :'span_events.attributes.include',
|
127
|
+
supported: true,
|
128
|
+
enabled_fn: method(:not_empty?),
|
129
|
+
disabled_value: [],
|
130
|
+
permitted_fn: nil
|
131
|
+
},
|
132
|
+
{
|
133
|
+
option: :'transaction_segments.attributes.include',
|
134
|
+
supported: true,
|
135
|
+
enabled_fn: method(:not_empty?),
|
136
|
+
disabled_value: [],
|
137
|
+
permitted_fn: nil
|
124
138
|
}
|
125
139
|
],
|
126
140
|
"allow_raw_exception_messages" => [
|
@@ -13,9 +13,6 @@ module NewRelic
|
|
13
13
|
# made configurable in the future. This is a tradeoff between
|
14
14
|
# memory and data retention
|
15
15
|
MAX_ERROR_QUEUE_LENGTH = 20
|
16
|
-
# Maximum number of frames in backtraces. May be made configurable
|
17
|
-
# in the future.
|
18
|
-
MAX_BACKTRACE_FRAMES = 50
|
19
16
|
EXCEPTION_TAG_IVAR = :'@__nr_seen_exception'
|
20
17
|
|
21
18
|
attr_reader :error_trace_aggregator, :error_event_aggregator
|
@@ -216,8 +213,9 @@ module NewRelic
|
|
216
213
|
nil
|
217
214
|
end
|
218
215
|
|
219
|
-
def truncate_trace(trace, keep_frames=
|
220
|
-
|
216
|
+
def truncate_trace(trace, keep_frames=nil)
|
217
|
+
keep_frames ||= Agent.config[:'error_collector.max_backtrace_frames']
|
218
|
+
return trace if !keep_frames || trace.length < keep_frames || trace.length == 0
|
221
219
|
|
222
220
|
# If keep_frames is odd, we will split things up favoring the top of the trace
|
223
221
|
keep_top = (keep_frames / 2.0).ceil
|
@@ -0,0 +1,23 @@
|
|
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/instrumentation/active_storage_subscriber'
|
6
|
+
|
7
|
+
DependencyDetection.defer do
|
8
|
+
named :active_storage
|
9
|
+
|
10
|
+
depends_on do
|
11
|
+
defined?(::ActiveStorage) &&
|
12
|
+
!NewRelic::Agent::Instrumentation::ActiveStorageSubscriber.subscribed?
|
13
|
+
end
|
14
|
+
|
15
|
+
executes do
|
16
|
+
::NewRelic::Agent.logger.info 'Installing ActiveStorage 5 instrumentation'
|
17
|
+
end
|
18
|
+
|
19
|
+
executes do
|
20
|
+
ActiveSupport::Notifications.subscribe(/\.active_storage$/,
|
21
|
+
NewRelic::Agent::Instrumentation::ActiveStorageSubscriber.new)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
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
|
+
require 'new_relic/agent/instrumentation/evented_subscriber'
|
5
|
+
|
6
|
+
module NewRelic
|
7
|
+
module Agent
|
8
|
+
module Instrumentation
|
9
|
+
class ActiveStorageSubscriber < EventedSubscriber
|
10
|
+
def start name, id, payload
|
11
|
+
return unless state.is_execution_traced?
|
12
|
+
start_segment name, id, payload
|
13
|
+
rescue => e
|
14
|
+
log_notification_error e, name, 'start'
|
15
|
+
end
|
16
|
+
|
17
|
+
def finish name, id, payload
|
18
|
+
return unless state.is_execution_traced?
|
19
|
+
finish_segment id
|
20
|
+
rescue => e
|
21
|
+
log_notification_error e, name, 'finish'
|
22
|
+
end
|
23
|
+
|
24
|
+
def start_segment name, id, payload
|
25
|
+
segment = Transaction.start_segment name: metric_name(name, payload)
|
26
|
+
segment.params[:key] = payload[:key]
|
27
|
+
segment.params[:exist] = payload[:exist] if payload.key? :exist
|
28
|
+
event_stack[id].push segment
|
29
|
+
end
|
30
|
+
|
31
|
+
def finish_segment id
|
32
|
+
segment = event_stack[id].pop
|
33
|
+
segment.finish if segment
|
34
|
+
end
|
35
|
+
|
36
|
+
def metric_name name, payload
|
37
|
+
service = payload[:service]
|
38
|
+
method = method_from_name name
|
39
|
+
"Ruby/ActiveStorage/#{service}Service/#{method}"
|
40
|
+
end
|
41
|
+
|
42
|
+
PATTERN = /\Aservice_([^\.]*)\.active_storage\z/
|
43
|
+
UNKNOWN = "unknown".freeze
|
44
|
+
|
45
|
+
METHOD_NAME_MAPPING = Hash.new do |h, k|
|
46
|
+
if PATTERN =~ k
|
47
|
+
h[k] = $1
|
48
|
+
else
|
49
|
+
h[k] = UNKNOWN
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_from_name name
|
54
|
+
METHOD_NAME_MAPPING[name]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -57,40 +57,46 @@ module NewRelic
|
|
57
57
|
def for_external_request_segment(segment)
|
58
58
|
intrinsics = intrinsics_for(segment)
|
59
59
|
|
60
|
-
intrinsics[HTTP_URL_KEY] = truncate(segment.uri)
|
61
60
|
intrinsics[COMPONENT_KEY] = segment.library
|
62
61
|
intrinsics[HTTP_METHOD_KEY] = segment.procedure
|
63
62
|
intrinsics[CATEGORY_KEY] = HTTP_CATEGORY
|
64
63
|
intrinsics[SPAN_KIND_KEY] = CLIENT
|
65
64
|
|
66
|
-
|
65
|
+
agent_attributes = {}
|
66
|
+
|
67
|
+
if allowed?(HTTP_URL_KEY)
|
68
|
+
agent_attributes[HTTP_URL_KEY] = truncate(segment.uri)
|
69
|
+
end
|
70
|
+
|
71
|
+
[intrinsics, EMPTY_HASH, agent_attributes]
|
67
72
|
end
|
68
73
|
|
69
74
|
def for_datastore_segment(segment)
|
70
75
|
intrinsics = intrinsics_for(segment)
|
71
76
|
|
72
77
|
intrinsics[COMPONENT_KEY] = segment.product
|
78
|
+
intrinsics[SPAN_KIND_KEY] = CLIENT
|
79
|
+
intrinsics[CATEGORY_KEY] = DATASTORE_CATEGORY
|
80
|
+
|
81
|
+
agent_attributes = {}
|
73
82
|
|
74
|
-
if segment.database_name
|
75
|
-
|
83
|
+
if segment.database_name && allowed?(DB_INSTANCE_KEY)
|
84
|
+
agent_attributes[DB_INSTANCE_KEY] = truncate(segment.database_name)
|
76
85
|
end
|
77
|
-
if segment.host && segment.port_path_or_id
|
78
|
-
|
86
|
+
if segment.host && segment.port_path_or_id && allowed?(PEER_ADDRESS_KEY)
|
87
|
+
agent_attributes[PEER_ADDRESS_KEY] = truncate("#{segment.host}:#{segment.port_path_or_id}")
|
79
88
|
end
|
80
|
-
if segment.host
|
81
|
-
|
89
|
+
if segment.host && allowed?(PEER_HOSTNAME_KEY)
|
90
|
+
agent_attributes[PEER_HOSTNAME_KEY] = truncate(segment.host)
|
82
91
|
end
|
83
92
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
intrinsics[DB_STATEMENT_KEY] = truncate(segment.sql_statement.safe_sql, 2000)
|
89
|
-
elsif segment.nosql_statement
|
90
|
-
intrinsics[DB_STATEMENT_KEY] = truncate(segment.nosql_statement, 2000)
|
93
|
+
if segment.sql_statement && allowed?(DB_STATEMENT_KEY)
|
94
|
+
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.sql_statement.safe_sql, 2000)
|
95
|
+
elsif segment.nosql_statement && allowed?(DB_STATEMENT_KEY)
|
96
|
+
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.nosql_statement, 2000)
|
91
97
|
end
|
92
98
|
|
93
|
-
[intrinsics, EMPTY_HASH,
|
99
|
+
[intrinsics, EMPTY_HASH, agent_attributes]
|
94
100
|
end
|
95
101
|
|
96
102
|
private
|
@@ -139,6 +145,10 @@ module NewRelic
|
|
139
145
|
value
|
140
146
|
end
|
141
147
|
end
|
148
|
+
|
149
|
+
def allowed?(key)
|
150
|
+
NewRelic::Agent.instance.attribute_filter.allows_key?(key, AttributeFilter::DST_SPAN_EVENTS)
|
151
|
+
end
|
142
152
|
end
|
143
153
|
end
|
144
154
|
end
|
@@ -288,6 +288,8 @@ module NewRelic
|
|
288
288
|
@sampled = nil
|
289
289
|
@priority = nil
|
290
290
|
|
291
|
+
@starting_thread_id = Thread.current.object_id
|
292
|
+
|
291
293
|
@attributes = Attributes.new(NewRelic::Agent.instance.attribute_filter)
|
292
294
|
|
293
295
|
merge_request_parameters(@filtered_params)
|
@@ -541,7 +543,7 @@ module NewRelic
|
|
541
543
|
|
542
544
|
outermost_frame.finish
|
543
545
|
|
544
|
-
NewRelic::Agent::TransactionTimeAggregator.transaction_stop(@end_time)
|
546
|
+
NewRelic::Agent::TransactionTimeAggregator.transaction_stop(@end_time, @starting_thread_id)
|
545
547
|
|
546
548
|
commit!(outermost_frame.name) unless @ignore_this_transaction
|
547
549
|
end
|
@@ -109,13 +109,11 @@ module NewRelic
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def add_instance_parameters
|
112
|
-
return unless NewRelic::Agent.config[:'datastore_tracer.instance_reporting.enabled']
|
113
112
|
params[:host] = host if host
|
114
113
|
params[:port_path_or_id] = port_path_or_id if port_path_or_id
|
115
114
|
end
|
116
115
|
|
117
116
|
def add_database_name_parameter
|
118
|
-
return unless NewRelic::Agent.config[:'datastore_tracer.database_name_reporting.enabled']
|
119
117
|
params[:database_name] = database_name if database_name
|
120
118
|
end
|
121
119
|
|
@@ -21,8 +21,10 @@ module NewRelic
|
|
21
21
|
@entry_timestamp = relative_start
|
22
22
|
@metric_name = metric_name || UNKNOWN_NODE_NAME
|
23
23
|
@exit_timestamp = relative_end
|
24
|
-
@children
|
25
|
-
@params = params
|
24
|
+
@children = nil
|
25
|
+
@params = params.select do |p|
|
26
|
+
NewRelic::Agent.instance.attribute_filter.allows_key? p, AttributeFilter::DST_TRANSACTION_SEGMENTS
|
27
|
+
end if params
|
26
28
|
@parent_node = parent
|
27
29
|
end
|
28
30
|
|
@@ -23,37 +23,37 @@ module NewRelic
|
|
23
23
|
h[k] = TransactionStats.new nil, 0.0
|
24
24
|
end
|
25
25
|
|
26
|
-
def reset!(
|
27
|
-
@harvest_cycle_started_at =
|
26
|
+
def reset!(timestamp = Time.now)
|
27
|
+
@harvest_cycle_started_at = timestamp
|
28
28
|
@stats.clear
|
29
29
|
end
|
30
30
|
|
31
|
-
def transaction_start(
|
31
|
+
def transaction_start(timestamp = Time.now)
|
32
32
|
@lock.synchronize do
|
33
|
-
set_transaction_start_time
|
33
|
+
set_transaction_start_time timestamp
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def transaction_stop(
|
37
|
+
def transaction_stop(timestamp = Time.now, starting_thread_id = current_thread)
|
38
38
|
@lock.synchronize do
|
39
|
-
record_elapsed_transaction_time_until
|
40
|
-
set_transaction_start_time nil
|
39
|
+
record_elapsed_transaction_time_until timestamp, starting_thread_id
|
40
|
+
set_transaction_start_time nil, starting_thread_id
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
INSTANCE_BUSY_METRIC = 'Instance/Busy'.freeze
|
45
45
|
|
46
|
-
def harvest!(
|
46
|
+
def harvest!(timestamp = Time.now)
|
47
47
|
active_threads = 0
|
48
48
|
result = @lock.synchronize do
|
49
49
|
# Sum up the transaction times spent in each thread
|
50
50
|
elapsed_transaction_time = @stats.inject(0.0) do |total, (thread_id, entry)|
|
51
|
-
total + transaction_time_in_thread(thread_id, entry
|
51
|
+
total + transaction_time_in_thread(timestamp, thread_id, entry)
|
52
52
|
end
|
53
53
|
|
54
54
|
active_threads = @stats.size
|
55
|
-
elapsed_harvest_time = (
|
56
|
-
@harvest_cycle_started_at =
|
55
|
+
elapsed_harvest_time = (timestamp - @harvest_cycle_started_at) * active_threads
|
56
|
+
@harvest_cycle_started_at = timestamp
|
57
57
|
|
58
58
|
# Clear out the stats for all threads, _except_ the live ones
|
59
59
|
# that have transactions still open (we'll count the rest of
|
@@ -81,12 +81,16 @@ module NewRelic
|
|
81
81
|
:transaction_stop,
|
82
82
|
:harvest!
|
83
83
|
|
84
|
-
class <<self
|
84
|
+
class << self
|
85
85
|
private
|
86
86
|
|
87
|
-
def record_elapsed_transaction_time_until(timestamp, thread_id
|
88
|
-
@stats[thread_id].
|
89
|
-
|
87
|
+
def record_elapsed_transaction_time_until(timestamp, thread_id = current_thread)
|
88
|
+
if @stats[thread_id].transaction_started_at
|
89
|
+
@stats[thread_id].elapsed_transaction_time +=
|
90
|
+
(timestamp - (@stats[thread_id].transaction_started_at || 0.0))
|
91
|
+
else
|
92
|
+
log_missing_elapsed_transaction_time
|
93
|
+
end
|
90
94
|
end
|
91
95
|
|
92
96
|
def in_transaction?(thread_id = current_thread)
|
@@ -104,27 +108,33 @@ module NewRelic
|
|
104
108
|
false
|
105
109
|
end
|
106
110
|
|
107
|
-
def set_transaction_start_time(timestamp)
|
108
|
-
@stats[
|
111
|
+
def set_transaction_start_time(timestamp, thread_id = current_thread)
|
112
|
+
@stats[thread_id].transaction_started_at = timestamp
|
109
113
|
end
|
110
114
|
|
111
|
-
def split_transaction_at_harvest(
|
115
|
+
def split_transaction_at_harvest(timestamp, thread_id = nil)
|
112
116
|
raise ArgumentError, 'thread_id required' unless thread_id
|
113
|
-
@stats[thread_id].transaction_started_at =
|
117
|
+
@stats[thread_id].transaction_started_at = timestamp
|
114
118
|
@stats[thread_id].elapsed_transaction_time = 0.0
|
115
119
|
end
|
116
120
|
|
117
|
-
def transaction_time_in_thread thread_id, entry
|
121
|
+
def transaction_time_in_thread timestamp, thread_id, entry
|
118
122
|
return entry.elapsed_transaction_time unless in_transaction? thread_id
|
119
123
|
|
120
124
|
# Count the portion of the transaction that's elapsed so far,...
|
121
|
-
elapsed = record_elapsed_transaction_time_until
|
125
|
+
elapsed = record_elapsed_transaction_time_until timestamp, thread_id
|
122
126
|
|
123
127
|
# ...then readjust the transaction start time to the next harvest
|
124
|
-
split_transaction_at_harvest
|
128
|
+
split_transaction_at_harvest timestamp, thread_id
|
125
129
|
|
126
130
|
elapsed
|
127
131
|
end
|
132
|
+
|
133
|
+
def log_missing_elapsed_transaction_time
|
134
|
+
state = NewRelic::Agent::TransactionState.tl_get
|
135
|
+
transaction_name = state.current_transaction.best_name
|
136
|
+
NewRelic::Agent.logger.warn("Unable to calculate elapsed transaction time for #{transaction_name}")
|
137
|
+
end
|
128
138
|
end
|
129
139
|
end
|
130
140
|
end
|
data/lib/new_relic/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newrelic_rpm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.6.0.349
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Wear
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2018-
|
14
|
+
date: 2018-12-08 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rake
|
@@ -273,6 +273,8 @@ files:
|
|
273
273
|
- lib/new_relic/agent/instrumentation/active_record_helper.rb
|
274
274
|
- lib/new_relic/agent/instrumentation/active_record_prepend.rb
|
275
275
|
- lib/new_relic/agent/instrumentation/active_record_subscriber.rb
|
276
|
+
- lib/new_relic/agent/instrumentation/active_storage.rb
|
277
|
+
- lib/new_relic/agent/instrumentation/active_storage_subscriber.rb
|
276
278
|
- lib/new_relic/agent/instrumentation/acts_as_solr.rb
|
277
279
|
- lib/new_relic/agent/instrumentation/authlogic.rb
|
278
280
|
- lib/new_relic/agent/instrumentation/bunny.rb
|