newrelic_rpm 4.8.0.341 → 5.1.0.344
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +27 -0
- data/CHANGELOG.md +93 -0
- data/README.md +0 -3
- data/config.dot +0 -3
- data/lib/new_relic/agent/{throughput_monitor.rb → adaptive_sampler.rb} +22 -13
- data/lib/new_relic/agent/agent.rb +3 -4
- data/lib/new_relic/agent/configuration/default_source.rb +41 -19
- data/lib/new_relic/agent/configuration/high_security_source.rb +0 -2
- data/lib/new_relic/agent/database/explain_plan_helpers.rb +11 -0
- data/lib/new_relic/agent/database.rb +5 -0
- data/lib/new_relic/agent/distributed_trace_monitor.rb +4 -2
- data/lib/new_relic/agent/distributed_trace_payload.rb +85 -119
- data/lib/new_relic/agent/error_collector.rb +17 -1
- data/lib/new_relic/agent/external.rb +14 -0
- data/lib/new_relic/agent/heap.rb +140 -0
- data/lib/new_relic/agent/instrumentation/active_record_5.rb +5 -0
- data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +14 -1
- data/lib/new_relic/agent/instrumentation/bunny.rb +5 -1
- data/lib/new_relic/agent/instrumentation/grape.rb +33 -29
- data/lib/new_relic/agent/instrumentation/rails5/action_cable.rb +5 -1
- data/lib/new_relic/agent/instrumentation/resque.rb +17 -36
- data/lib/new_relic/agent/instrumentation/sequel.rb +0 -1
- data/lib/new_relic/agent/javascript_instrumentor.rb +2 -2
- data/lib/new_relic/agent/messaging.rb +10 -0
- data/lib/new_relic/agent/method_tracer.rb +23 -18
- data/lib/new_relic/agent/new_relic_service.rb +43 -23
- data/lib/new_relic/agent/priority_sampled_buffer.rb +68 -0
- data/lib/new_relic/agent/supported_versions.rb +1 -1
- data/lib/new_relic/agent/transaction/attributes.rb +1 -0
- data/lib/new_relic/agent/transaction/distributed_tracing.rb +173 -55
- data/lib/new_relic/agent/transaction/external_request_segment.rb +14 -64
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +12 -4
- data/lib/new_relic/agent/transaction.rb +15 -8
- data/lib/new_relic/agent/transaction_error_primitive.rb +2 -8
- data/lib/new_relic/agent/transaction_event_aggregator.rb +16 -13
- data/lib/new_relic/agent/transaction_event_primitive.rb +5 -3
- data/lib/new_relic/agent/transaction_event_recorder.rb +3 -11
- data/lib/new_relic/agent.rb +27 -0
- data/lib/new_relic/build.rb +2 -2
- data/lib/new_relic/recipes/capistrano3.rb +5 -2
- data/lib/new_relic/version.rb +2 -2
- data/newrelic_rpm.gemspec +3 -2
- metadata +39 -9
- data/lib/new_relic/agent/distributed_trace_priority_sampled_buffer.rb +0 -72
@@ -7,73 +7,66 @@ require 'base64'
|
|
7
7
|
module NewRelic
|
8
8
|
module Agent
|
9
9
|
class DistributedTracePayload
|
10
|
-
VERSION =[0,
|
11
|
-
|
10
|
+
VERSION =[0, 1].freeze
|
11
|
+
PARENT_TYPE = "App".freeze
|
12
12
|
POUND = '#'.freeze
|
13
13
|
|
14
14
|
# Key names for serialization
|
15
|
-
VERSION_KEY
|
16
|
-
DATA_KEY
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
ID_KEY
|
21
|
-
|
22
|
-
SAMPLED_KEY
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
TIMESTAMP_KEY = 'ti'.freeze
|
27
|
-
HOST_KEY = 'ho'.freeze
|
28
|
-
SYNTHETICS_KEY = 'sy'.freeze
|
29
|
-
SYNTHETICS_RESOURCE_KEY = 'r'.freeze
|
30
|
-
SYNTHETICS_JOB_KEY = 'j'.freeze
|
31
|
-
SYNTHETICS_MONITOR_KEY = 'm'.freeze
|
15
|
+
VERSION_KEY = 'v'.freeze
|
16
|
+
DATA_KEY = 'd'.freeze
|
17
|
+
PARENT_TYPE_KEY = 'ty'.freeze
|
18
|
+
PARENT_ACCOUNT_ID_KEY = 'ac'.freeze
|
19
|
+
PARENT_APP_KEY = 'ap'.freeze
|
20
|
+
ID_KEY = 'id'.freeze
|
21
|
+
TRACE_ID_KEY = 'tr'.freeze
|
22
|
+
SAMPLED_KEY = 'sa'.freeze
|
23
|
+
PARENT_ID_KEY = 'pa'.freeze
|
24
|
+
TIMESTAMP_KEY = 'ti'.freeze
|
25
|
+
PRIORITY_KEY = 'pr'.freeze
|
32
26
|
|
33
27
|
# Intrinsic Keys
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
ORDER_INTRINSIC_KEY = "nr.order".freeze
|
42
|
-
GUID_INTRINSIC_KEY = "nr.guid".freeze
|
43
|
-
REFERRING_TRANSACTION_GUID_INTRINSIC_KEY = "nr.referringTransactionGuid".freeze
|
28
|
+
PARENT_TYPE_INTRINSIC_KEY = "parent.type".freeze
|
29
|
+
PARENT_APP_INTRINSIC_KEY = "parent.app".freeze
|
30
|
+
PARENT_ACCOUNT_ID_INTRINSIC_KEY = "parent.account".freeze
|
31
|
+
PARENT_TRANSPORT_TYPE_INTRINSIC_KEY = "parent.transportType".freeze
|
32
|
+
PARENT_TRANSPORT_DURATION_INTRINSIC_KEY = "parent.transportDuration".freeze
|
33
|
+
GUID_INTRINSIC_KEY = "guid".freeze
|
34
|
+
TRACE_ID_INTRINSIC_KEY = "traceId".freeze
|
44
35
|
TRIP_ID_INTRINSIC_KEY = "nr.tripId".freeze
|
45
|
-
|
36
|
+
PARENT_ID_INTRINSIC_KEY = "parentId".freeze
|
37
|
+
GRANDPARENT_ID_INTRINSIC_KEY = "grandparentId".freeze
|
46
38
|
COMMA = ",".freeze
|
47
39
|
|
48
40
|
INTRINSIC_KEYS = [
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
CALLER_HOST_INTRINSIC_KEY,
|
55
|
-
DEPTH_INTRINSIC_KEY,
|
56
|
-
ORDER_INTRINSIC_KEY,
|
41
|
+
PARENT_TYPE_INTRINSIC_KEY,
|
42
|
+
PARENT_APP_INTRINSIC_KEY,
|
43
|
+
PARENT_ACCOUNT_ID_INTRINSIC_KEY,
|
44
|
+
PARENT_TRANSPORT_TYPE_INTRINSIC_KEY,
|
45
|
+
PARENT_TRANSPORT_DURATION_INTRINSIC_KEY,
|
57
46
|
GUID_INTRINSIC_KEY,
|
58
|
-
|
47
|
+
TRACE_ID_INTRINSIC_KEY,
|
59
48
|
TRIP_ID_INTRINSIC_KEY,
|
60
|
-
|
49
|
+
PARENT_ID_INTRINSIC_KEY,
|
50
|
+
GRANDPARENT_ID_INTRINSIC_KEY
|
61
51
|
].freeze
|
62
52
|
|
53
|
+
# Intrinsic Values
|
54
|
+
PARENT_TRANSPORT_TYPE_UNKNOWN = 'unknown'.freeze
|
55
|
+
|
63
56
|
class << self
|
64
|
-
def for_transaction transaction
|
57
|
+
def for_transaction transaction
|
65
58
|
payload = new
|
66
59
|
return payload unless connected?
|
67
60
|
|
68
61
|
payload.version = VERSION
|
69
|
-
payload.
|
62
|
+
payload.parent_type = PARENT_TYPE
|
70
63
|
|
71
64
|
# We should not rely on the xp_id being formulated this way, but we have
|
72
65
|
# seen nil account ids coming down in staging for some accounts
|
73
66
|
account_id, fallback_app_id = Agent.config[:cross_process_id].split(POUND)
|
74
|
-
payload.
|
67
|
+
payload.parent_account_id = account_id
|
75
68
|
|
76
|
-
payload.
|
69
|
+
payload.parent_app_id = if Agent.config[:application_id].empty?
|
77
70
|
fallback_app_id
|
78
71
|
else
|
79
72
|
Agent.config[:application_id]
|
@@ -81,18 +74,10 @@ module NewRelic
|
|
81
74
|
|
82
75
|
payload.timestamp = (Time.now.to_f * 1000).round
|
83
76
|
payload.id = transaction.guid
|
84
|
-
payload.
|
77
|
+
payload.trace_id = transaction.trace_id
|
85
78
|
payload.sampled = transaction.sampled?
|
86
|
-
payload.
|
87
|
-
payload.
|
88
|
-
payload.order = transaction.order
|
89
|
-
payload.host = uri.host if uri
|
90
|
-
|
91
|
-
if transaction.synthetics_payload
|
92
|
-
payload.synthetics_resource = transaction.synthetics_payload[2]
|
93
|
-
payload.synthetics_job = transaction.synthetics_payload[3]
|
94
|
-
payload.synthetics_monitor = transaction.synthetics_payload[4]
|
95
|
-
end
|
79
|
+
payload.priority = transaction.priority
|
80
|
+
payload.parent_id = transaction.parent_id
|
96
81
|
|
97
82
|
payload
|
98
83
|
end
|
@@ -103,23 +88,15 @@ module NewRelic
|
|
103
88
|
|
104
89
|
payload = new
|
105
90
|
payload.version = raw_payload[VERSION_KEY]
|
106
|
-
payload.
|
107
|
-
payload.
|
108
|
-
payload.
|
91
|
+
payload.parent_type = payload_data[PARENT_TYPE_KEY]
|
92
|
+
payload.parent_account_id = payload_data[PARENT_ACCOUNT_ID_KEY]
|
93
|
+
payload.parent_app_id = payload_data[PARENT_APP_KEY]
|
109
94
|
payload.timestamp = payload_data[TIMESTAMP_KEY]
|
110
95
|
payload.id = payload_data[ID_KEY]
|
111
|
-
payload.
|
96
|
+
payload.trace_id = payload_data[TRACE_ID_KEY]
|
112
97
|
payload.sampled = payload_data[SAMPLED_KEY]
|
113
|
-
payload.
|
114
|
-
payload.
|
115
|
-
payload.order = payload_data[ORDER_KEY]
|
116
|
-
payload.host = payload_data[HOST_KEY]
|
117
|
-
|
118
|
-
if payload_synthetics = payload_data[SYNTHETICS_KEY]
|
119
|
-
payload.synthetics_resource = payload_synthetics[SYNTHETICS_RESOURCE_KEY]
|
120
|
-
payload.synthetics_job = payload_synthetics[SYNTHETICS_JOB_KEY]
|
121
|
-
payload.synthetics_monitor = payload_synthetics[SYNTHETICS_MONITOR_KEY]
|
122
|
-
end
|
98
|
+
payload.priority = payload_data[PRIORITY_KEY]
|
99
|
+
payload.parent_id = payload_data[PARENT_ID_KEY]
|
123
100
|
|
124
101
|
payload
|
125
102
|
end
|
@@ -129,11 +106,15 @@ module NewRelic
|
|
129
106
|
from_json decoded_payload
|
130
107
|
end
|
131
108
|
|
132
|
-
#
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
109
|
+
# Assigns intrinsics for the first distributed trace in a trip
|
110
|
+
def assign_intrinsics_for_first_trace transaction, transaction_payload
|
111
|
+
transaction_payload[GUID_INTRINSIC_KEY] = transaction.guid
|
112
|
+
transaction_payload[TRACE_ID_INTRINSIC_KEY] = transaction.trace_id
|
113
|
+
transaction_payload[TRIP_ID_INTRINSIC_KEY] = transaction.trace_id
|
114
|
+
end
|
115
|
+
|
116
|
+
def major_version_matches?(payload)
|
117
|
+
payload.version[0] == VERSION[0]
|
137
118
|
end
|
138
119
|
|
139
120
|
private
|
@@ -146,26 +127,21 @@ module NewRelic
|
|
146
127
|
end
|
147
128
|
|
148
129
|
attr_accessor :version,
|
149
|
-
:
|
130
|
+
:parent_type,
|
150
131
|
:caller_transport_type,
|
151
|
-
:
|
152
|
-
:
|
132
|
+
:parent_account_id,
|
133
|
+
:parent_app_id,
|
153
134
|
:id,
|
154
|
-
:
|
135
|
+
:trace_id,
|
155
136
|
:sampled,
|
156
|
-
:
|
157
|
-
:
|
158
|
-
:
|
159
|
-
:synthetics_monitor,
|
160
|
-
:order,
|
161
|
-
:depth,
|
162
|
-
:timestamp,
|
163
|
-
:host
|
137
|
+
:priority,
|
138
|
+
:parent_id,
|
139
|
+
:timestamp
|
164
140
|
|
165
141
|
alias_method :sampled?, :sampled
|
166
142
|
|
167
|
-
def
|
168
|
-
|
143
|
+
def initialize
|
144
|
+
@caller_transport_type = PARENT_TRANSPORT_TYPE_UNKNOWN
|
169
145
|
end
|
170
146
|
|
171
147
|
def to_json
|
@@ -174,27 +150,19 @@ module NewRelic
|
|
174
150
|
}
|
175
151
|
|
176
152
|
result[DATA_KEY] = {
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
ID_KEY
|
181
|
-
|
182
|
-
SAMPLED_KEY
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
153
|
+
PARENT_TYPE_KEY => parent_type,
|
154
|
+
PARENT_ACCOUNT_ID_KEY => parent_account_id,
|
155
|
+
PARENT_APP_KEY => parent_app_id,
|
156
|
+
ID_KEY => id,
|
157
|
+
TRACE_ID_KEY => trace_id,
|
158
|
+
SAMPLED_KEY => sampled,
|
159
|
+
PRIORITY_KEY => priority,
|
160
|
+
PARENT_ID_KEY => parent_id,
|
161
|
+
# GRANDPARENT_ID_KEY does not go into the outbound JSON payload;
|
162
|
+
# the callee will take our parent ID as its grandparent ID
|
187
163
|
TIMESTAMP_KEY => timestamp,
|
188
164
|
}
|
189
165
|
|
190
|
-
if synthetics?
|
191
|
-
result[DATA_KEY][SYNTHETICS_KEY] = {
|
192
|
-
SYNTHETICS_RESOURCE_KEY => synthetics_resource,
|
193
|
-
SYNTHETICS_JOB_KEY => synthetics_job,
|
194
|
-
SYNTHETICS_MONITOR_KEY => synthetics_monitor
|
195
|
-
}
|
196
|
-
end
|
197
|
-
|
198
166
|
JSON.dump(result)
|
199
167
|
end
|
200
168
|
|
@@ -204,19 +172,17 @@ module NewRelic
|
|
204
172
|
Base64.strict_encode64 to_json
|
205
173
|
end
|
206
174
|
|
207
|
-
def assign_intrinsics transaction,
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
payload[TRIP_ID_INTRINSIC_KEY] = trip_id
|
219
|
-
payload[PARENT_IDS_INTRINSIC_KEY] = parent_ids.join COMMA if parent_ids
|
175
|
+
def assign_intrinsics transaction, transaction_payload
|
176
|
+
transaction_payload[PARENT_TYPE_INTRINSIC_KEY] = parent_type
|
177
|
+
transaction_payload[PARENT_APP_INTRINSIC_KEY] = parent_app_id
|
178
|
+
transaction_payload[PARENT_ACCOUNT_ID_INTRINSIC_KEY] = parent_account_id
|
179
|
+
transaction_payload[PARENT_TRANSPORT_TYPE_INTRINSIC_KEY] = caller_transport_type
|
180
|
+
transaction_payload[PARENT_TRANSPORT_DURATION_INTRINSIC_KEY] = transaction.transport_duration
|
181
|
+
transaction_payload[GUID_INTRINSIC_KEY] = transaction.guid
|
182
|
+
transaction_payload[TRACE_ID_INTRINSIC_KEY] = trace_id
|
183
|
+
transaction_payload[TRIP_ID_INTRINSIC_KEY] = trace_id
|
184
|
+
transaction_payload[PARENT_ID_INTRINSIC_KEY] = transaction.parent_id if transaction.parent_id
|
185
|
+
transaction_payload[GRANDPARENT_ID_INTRINSIC_KEY] = transaction.grandparent_id if transaction.grandparent_id
|
220
186
|
end
|
221
187
|
end
|
222
188
|
end
|
@@ -13,6 +13,9 @@ 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
|
16
19
|
EXCEPTION_TAG_IVAR = :'@__nr_seen_exception'
|
17
20
|
|
18
21
|
attr_reader :error_trace_aggregator, :error_event_aggregator
|
@@ -213,6 +216,19 @@ module NewRelic
|
|
213
216
|
nil
|
214
217
|
end
|
215
218
|
|
219
|
+
def truncate_trace(trace, keep_frames=MAX_BACKTRACE_FRAMES)
|
220
|
+
return trace if trace.length < keep_frames || trace.length == 0
|
221
|
+
|
222
|
+
# If keep_frames is odd, we will split things up favoring the top of the trace
|
223
|
+
keep_top = (keep_frames / 2.0).ceil
|
224
|
+
keep_bottom = (keep_frames / 2.0).floor
|
225
|
+
|
226
|
+
truncate_frames = trace.length - keep_frames
|
227
|
+
|
228
|
+
truncated_trace = trace[0...keep_top].concat(["<truncated #{truncate_frames.to_s} additional frames>"]).concat(trace[-keep_bottom..-1])
|
229
|
+
truncated_trace
|
230
|
+
end
|
231
|
+
|
216
232
|
EMPTY_STRING = ''.freeze
|
217
233
|
|
218
234
|
def create_noticed_error(exception, options)
|
@@ -225,7 +241,7 @@ module NewRelic
|
|
225
241
|
|
226
242
|
noticed_error.file_name = sense_method(exception, :file_name)
|
227
243
|
noticed_error.line_number = sense_method(exception, :line_number)
|
228
|
-
noticed_error.stack_trace = extract_stack_trace(exception)
|
244
|
+
noticed_error.stack_trace = truncate_trace(extract_stack_trace(exception))
|
229
245
|
|
230
246
|
noticed_error.expected = !! options.delete(:expected)
|
231
247
|
|
@@ -53,6 +53,15 @@ module NewRelic
|
|
53
53
|
#
|
54
54
|
def process_request_metadata request_metadata
|
55
55
|
NewRelic::Agent.record_api_supportability_metric(:process_request_metadata)
|
56
|
+
|
57
|
+
if NewRelic::Agent.config[:'distributed_tracing.enabled']
|
58
|
+
NewRelic::Agent.logger.log_once(
|
59
|
+
:warn,
|
60
|
+
:process_request_metadata_noop,
|
61
|
+
'Skipping process_request_metadata because distributed tracing is enabled')
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
56
65
|
return unless CrossAppTracing.cross_app_enabled?
|
57
66
|
|
58
67
|
state = NewRelic::Agent::TransactionState.tl_get
|
@@ -100,6 +109,11 @@ module NewRelic
|
|
100
109
|
NewRelic::Agent.record_api_supportability_metric(:get_response_metadata)
|
101
110
|
return unless CrossAppTracing.cross_app_enabled?
|
102
111
|
|
112
|
+
if NewRelic::Agent.config[:'distributed_tracing.enabled']
|
113
|
+
::NewRelic::Agent.logger.warn('Skipping get_response_metadata because distributed tracing is enabled')
|
114
|
+
return
|
115
|
+
end
|
116
|
+
|
103
117
|
state = NewRelic::Agent::TransactionState.tl_get
|
104
118
|
if transaction = state.current_transaction and state.client_cross_app_id
|
105
119
|
|
@@ -0,0 +1,140 @@
|
|
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
|
+
# This class implements a min Heap. The first element is always the one with the
|
8
|
+
# lowest priority. It is a tree structure that is represented as an array. The
|
9
|
+
# relationship between between nodes in the tree and indices in the array are as
|
10
|
+
# follows:
|
11
|
+
#
|
12
|
+
# parent_index = (child_index - 1) / 2
|
13
|
+
# left_child_index = parent_index * 2 + 1
|
14
|
+
# right_child_index = parent_index * 2 + 2
|
15
|
+
#
|
16
|
+
# the root node is at index 0
|
17
|
+
# a node is a leaf node when its index >= length / 2
|
18
|
+
#
|
19
|
+
|
20
|
+
class Heap
|
21
|
+
|
22
|
+
# @param [Array] items an optional array of items to intialize the heap
|
23
|
+
#
|
24
|
+
# @param [Callable] priority_fn an optional priority function used to
|
25
|
+
# to compute the priority for an item. If it's not supplied priority
|
26
|
+
# will be computed using Comparable.
|
27
|
+
def initialize(items = nil, &priority_fn)
|
28
|
+
@items = []
|
29
|
+
@priority_fn = priority_fn || ->(x) { x }
|
30
|
+
items.each{ |item| push(item) } if items
|
31
|
+
end
|
32
|
+
|
33
|
+
def [](index)
|
34
|
+
@items[index]
|
35
|
+
end
|
36
|
+
|
37
|
+
def []=(index, value)
|
38
|
+
@items[index] = value
|
39
|
+
end
|
40
|
+
|
41
|
+
def fix(index)
|
42
|
+
parent_index = parent_index_for(index)
|
43
|
+
|
44
|
+
if in_range?(parent_index) && priority(parent_index) > priority(index)
|
45
|
+
heapify_up(index)
|
46
|
+
else
|
47
|
+
child_index = left_child_index_for(index)
|
48
|
+
|
49
|
+
return unless in_range?(child_index)
|
50
|
+
|
51
|
+
if right_sibling_smaller?(child_index)
|
52
|
+
child_index += 1
|
53
|
+
end
|
54
|
+
|
55
|
+
if priority(child_index) < priority(index)
|
56
|
+
heapify_down(index)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def push(item)
|
62
|
+
@items << item
|
63
|
+
heapify_up(size - 1)
|
64
|
+
end
|
65
|
+
|
66
|
+
alias_method :<<, :push
|
67
|
+
|
68
|
+
def pop
|
69
|
+
swap(0, size - 1)
|
70
|
+
item = @items.pop
|
71
|
+
heapify_down(0)
|
72
|
+
item
|
73
|
+
end
|
74
|
+
|
75
|
+
def size
|
76
|
+
@items.size
|
77
|
+
end
|
78
|
+
|
79
|
+
def empty?
|
80
|
+
@items.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_a
|
84
|
+
@items
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def priority(index)
|
90
|
+
@priority_fn.call(@items[index])
|
91
|
+
end
|
92
|
+
|
93
|
+
def parent_index_for child_index
|
94
|
+
(child_index - 1) / 2
|
95
|
+
end
|
96
|
+
|
97
|
+
def left_child_index_for parent_index
|
98
|
+
2 * parent_index + 1
|
99
|
+
end
|
100
|
+
|
101
|
+
def right_sibling_smaller?(lchild_index)
|
102
|
+
in_range?(lchild_index + 1) && priority(lchild_index) > priority(lchild_index + 1)
|
103
|
+
end
|
104
|
+
|
105
|
+
def in_range?(index)
|
106
|
+
index >= 0 && index < size
|
107
|
+
end
|
108
|
+
|
109
|
+
def heapify_up(child_index)
|
110
|
+
return if child_index == 0
|
111
|
+
|
112
|
+
parent_index = parent_index_for(child_index)
|
113
|
+
|
114
|
+
if priority(child_index) < priority(parent_index)
|
115
|
+
swap(child_index, parent_index)
|
116
|
+
heapify_up(parent_index)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def heapify_down(parent_index)
|
121
|
+
child_index = left_child_index_for(parent_index)
|
122
|
+
return unless in_range?(child_index)
|
123
|
+
|
124
|
+
if right_sibling_smaller?(child_index)
|
125
|
+
child_index += 1
|
126
|
+
end
|
127
|
+
|
128
|
+
if priority(child_index) < priority(parent_index)
|
129
|
+
swap(parent_index, child_index)
|
130
|
+
heapify_down(child_index)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def swap(i, j)
|
135
|
+
@items[i], @items[j] = @items[j], @items[i]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
@@ -31,6 +31,11 @@ DependencyDetection.defer do
|
|
31
31
|
::NewRelic::Agent::PrependSupportability.record_metrics_for(::ActiveRecord::Base, ::ActiveRecord::Relation)
|
32
32
|
::ActiveRecord::Base.prepend ::NewRelic::Agent::Instrumentation::ActiveRecordPrepend::BaseExtensions
|
33
33
|
::ActiveRecord::Relation.prepend ::NewRelic::Agent::Instrumentation::ActiveRecordPrepend::RelationExtensions
|
34
|
+
|
35
|
+
if ::ActiveRecord::VERSION::MINOR.to_i == 1 &&
|
36
|
+
::ActiveRecord::VERSION::TINY.to_i >= 6
|
37
|
+
::ActiveRecord::Base.prepend ::NewRelic::Agent::Instrumentation::ActiveRecordPrepend::BaseExtensions516
|
38
|
+
end
|
34
39
|
end
|
35
40
|
end
|
36
41
|
end
|
@@ -24,6 +24,19 @@ module NewRelic
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
module BaseExtensions516
|
28
|
+
# In ActiveRecord v5.0.0 through v5.1.5, touch() will call
|
29
|
+
# update_all() and cause us to record a transaction.
|
30
|
+
# Starting in v5.1.6, this call no longer happens. We'll
|
31
|
+
# have to set the database metrics explicitly now.
|
32
|
+
#
|
33
|
+
def touch(*args, &blk)
|
34
|
+
::NewRelic::Agent.with_database_metric_name(self.class.name, nil, ACTIVE_RECORD) do
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
27
40
|
module RelationExtensions
|
28
41
|
def update_all(*args, &blk)
|
29
42
|
::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
|
@@ -58,4 +71,4 @@ module NewRelic
|
|
58
71
|
end
|
59
72
|
end
|
60
73
|
end
|
61
|
-
end
|
74
|
+
end
|
@@ -24,7 +24,11 @@ DependencyDetection.defer do
|
|
24
24
|
def publish payload, opts = {}
|
25
25
|
begin
|
26
26
|
destination = NewRelic::Agent::Instrumentation::Bunny.exchange_name(name)
|
27
|
-
|
27
|
+
|
28
|
+
tracing_enabled =
|
29
|
+
NewRelic::Agent::CrossAppTracing.cross_app_enabled? ||
|
30
|
+
NewRelic::Agent.config[:'distributed_tracing.enabled']
|
31
|
+
opts[:headers] ||= {} if tracing_enabled
|
28
32
|
|
29
33
|
segment = NewRelic::Agent::Messaging.start_amqp_publish_segment(
|
30
34
|
library: NewRelic::Agent::Instrumentation::Bunny::LIBRARY,
|
@@ -30,35 +30,33 @@ module NewRelic
|
|
30
30
|
Transaction.set_default_transaction_name(txn_name, :grape, node_name)
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
"#{class_name}#{action_name} (#{method_name})"
|
48
|
-
end
|
33
|
+
def name_for_transaction(route, class_name, version)
|
34
|
+
action_name = route.path.sub(FORMAT_REGEX, EMPTY_STRING)
|
35
|
+
method_name = route.request_method
|
36
|
+
version ||= route.version
|
37
|
+
|
38
|
+
# defaulting does not set rack.env['api.version'] and route.version may return Array
|
39
|
+
#
|
40
|
+
version = version.join(PIPE_STRING) if Array === version
|
41
|
+
|
42
|
+
if version
|
43
|
+
action_name = action_name.sub(VERSION_REGEX, EMPTY_STRING)
|
44
|
+
"#{class_name}-#{version}#{action_name} (#{method_name})"
|
45
|
+
else
|
46
|
+
"#{class_name}#{action_name} (#{method_name})"
|
49
47
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
48
|
+
end
|
49
|
+
|
50
|
+
def name_for_transaction_deprecated(route, class_name, version)
|
51
|
+
action_name = route.route_path.sub(FORMAT_REGEX, EMPTY_STRING)
|
52
|
+
method_name = route.route_method
|
53
|
+
version ||= route.route_version
|
54
|
+
|
55
|
+
if version
|
56
|
+
action_name = action_name.sub(VERSION_REGEX, EMPTY_STRING)
|
57
|
+
"#{class_name}-#{version}#{action_name} (#{method_name})"
|
58
|
+
else
|
59
|
+
"#{class_name}#{action_name} (#{method_name})"
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
@@ -109,6 +107,13 @@ DependencyDetection.defer do
|
|
109
107
|
end
|
110
108
|
|
111
109
|
def instrument_call
|
110
|
+
if defined?(Grape::VERSION) && Gem::Version.new(::Grape::VERSION) >= Gem::Version.new("0.16.0")
|
111
|
+
::NewRelic::Agent::Instrumentation::GrapeInstrumentation.send :remove_method, :name_for_transaction_deprecated
|
112
|
+
else
|
113
|
+
::NewRelic::Agent::Instrumentation::GrapeInstrumentation.send :remove_method, :name_for_transaction
|
114
|
+
::NewRelic::Agent::Instrumentation::GrapeInstrumentation.send :alias_method, :name_for_transaction, :name_for_transaction_deprecated
|
115
|
+
end
|
116
|
+
|
112
117
|
::Grape::API.class_eval do
|
113
118
|
def call_with_new_relic(env)
|
114
119
|
begin
|
@@ -130,5 +135,4 @@ DependencyDetection.defer do
|
|
130
135
|
alias_method :call, :call_with_new_relic
|
131
136
|
end
|
132
137
|
end
|
133
|
-
|
134
138
|
end
|
@@ -27,6 +27,10 @@ DependencyDetection.defer do
|
|
27
27
|
ActiveSupport::Notifications.subscribe(/(perform_action|transmit)\.action_cable/,
|
28
28
|
NewRelic::Agent::Instrumentation::ActionCableSubscriber.new)
|
29
29
|
|
30
|
-
|
30
|
+
ActiveSupport.on_load(:action_cable) do
|
31
|
+
::NewRelic::Agent::PrependSupportability.record_metrics_for(
|
32
|
+
::ActionCable::Engine,
|
33
|
+
::ActionCable::RemoteConnections)
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|