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.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +27 -0
  3. data/CHANGELOG.md +93 -0
  4. data/README.md +0 -3
  5. data/config.dot +0 -3
  6. data/lib/new_relic/agent/{throughput_monitor.rb → adaptive_sampler.rb} +22 -13
  7. data/lib/new_relic/agent/agent.rb +3 -4
  8. data/lib/new_relic/agent/configuration/default_source.rb +41 -19
  9. data/lib/new_relic/agent/configuration/high_security_source.rb +0 -2
  10. data/lib/new_relic/agent/database/explain_plan_helpers.rb +11 -0
  11. data/lib/new_relic/agent/database.rb +5 -0
  12. data/lib/new_relic/agent/distributed_trace_monitor.rb +4 -2
  13. data/lib/new_relic/agent/distributed_trace_payload.rb +85 -119
  14. data/lib/new_relic/agent/error_collector.rb +17 -1
  15. data/lib/new_relic/agent/external.rb +14 -0
  16. data/lib/new_relic/agent/heap.rb +140 -0
  17. data/lib/new_relic/agent/instrumentation/active_record_5.rb +5 -0
  18. data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +14 -1
  19. data/lib/new_relic/agent/instrumentation/bunny.rb +5 -1
  20. data/lib/new_relic/agent/instrumentation/grape.rb +33 -29
  21. data/lib/new_relic/agent/instrumentation/rails5/action_cable.rb +5 -1
  22. data/lib/new_relic/agent/instrumentation/resque.rb +17 -36
  23. data/lib/new_relic/agent/instrumentation/sequel.rb +0 -1
  24. data/lib/new_relic/agent/javascript_instrumentor.rb +2 -2
  25. data/lib/new_relic/agent/messaging.rb +10 -0
  26. data/lib/new_relic/agent/method_tracer.rb +23 -18
  27. data/lib/new_relic/agent/new_relic_service.rb +43 -23
  28. data/lib/new_relic/agent/priority_sampled_buffer.rb +68 -0
  29. data/lib/new_relic/agent/supported_versions.rb +1 -1
  30. data/lib/new_relic/agent/transaction/attributes.rb +1 -0
  31. data/lib/new_relic/agent/transaction/distributed_tracing.rb +173 -55
  32. data/lib/new_relic/agent/transaction/external_request_segment.rb +14 -64
  33. data/lib/new_relic/agent/transaction/message_broker_segment.rb +12 -4
  34. data/lib/new_relic/agent/transaction.rb +15 -8
  35. data/lib/new_relic/agent/transaction_error_primitive.rb +2 -8
  36. data/lib/new_relic/agent/transaction_event_aggregator.rb +16 -13
  37. data/lib/new_relic/agent/transaction_event_primitive.rb +5 -3
  38. data/lib/new_relic/agent/transaction_event_recorder.rb +3 -11
  39. data/lib/new_relic/agent.rb +27 -0
  40. data/lib/new_relic/build.rb +2 -2
  41. data/lib/new_relic/recipes/capistrano3.rb +5 -2
  42. data/lib/new_relic/version.rb +2 -2
  43. data/newrelic_rpm.gemspec +3 -2
  44. metadata +39 -9
  45. 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, 0].freeze
11
- CALLER_TYPE = "App".freeze
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 = 'v'.freeze
16
- DATA_KEY = 'd'.freeze
17
- CALLER_TYPE_KEY = 'ty'.freeze
18
- CALLER_ACCOUNT_KEY = 'ac'.freeze
19
- CALLER_APP_KEY = 'ap'.freeze
20
- ID_KEY = 'id'.freeze
21
- TRIP_ID_KEY = 'tr'.freeze
22
- SAMPLED_KEY = 'sa'.freeze
23
- PARENT_IDS_KEY = 'pa'.freeze
24
- DEPTH_KEY = 'de'.freeze
25
- ORDER_KEY = 'or'.freeze
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
- CALLER_TYPE_INTRINSIC_KEY = "caller.type".freeze
35
- CALLER_APP_INTRINSIC_KEY = "caller.app".freeze
36
- CALLER_ACCOUNT_ID_INTRINSIC_KEY = "caller.account".freeze
37
- CALLER_TRANSPORT_TYPE_INTRINSIC_KEY = "caller.transportType".freeze
38
- CALLER_TRANSPORT_DURATION_INTRINSIC_KEY = "caller.transportDuration".freeze
39
- CALLER_HOST_INTRINSIC_KEY = "caller.host".freeze
40
- DEPTH_INTRINSIC_KEY = "nr.depth".freeze
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
- PARENT_IDS_INTRINSIC_KEY = "nr.parentIds".freeze
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
- CALLER_TYPE_INTRINSIC_KEY,
50
- CALLER_APP_INTRINSIC_KEY,
51
- CALLER_ACCOUNT_ID_INTRINSIC_KEY,
52
- CALLER_TRANSPORT_TYPE_INTRINSIC_KEY,
53
- CALLER_TRANSPORT_DURATION_INTRINSIC_KEY,
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
- REFERRING_TRANSACTION_GUID_INTRINSIC_KEY,
47
+ TRACE_ID_INTRINSIC_KEY,
59
48
  TRIP_ID_INTRINSIC_KEY,
60
- PARENT_IDS_INTRINSIC_KEY
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, uri=nil
57
+ def for_transaction transaction
65
58
  payload = new
66
59
  return payload unless connected?
67
60
 
68
61
  payload.version = VERSION
69
- payload.caller_type = CALLER_TYPE
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.caller_account_id = account_id
67
+ payload.parent_account_id = account_id
75
68
 
76
- payload.caller_app_id = if Agent.config[:application_id].empty?
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.trip_id = transaction.distributed_tracing_trip_id
77
+ payload.trace_id = transaction.trace_id
85
78
  payload.sampled = transaction.sampled?
86
- payload.parent_ids = transaction.parent_ids
87
- payload.depth = transaction.depth + 1
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.caller_type = payload_data[CALLER_TYPE_KEY]
107
- payload.caller_account_id = payload_data[CALLER_ACCOUNT_KEY]
108
- payload.caller_app_id = payload_data[CALLER_APP_KEY]
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.trip_id = payload_data[TRIP_ID_KEY]
96
+ payload.trace_id = payload_data[TRACE_ID_KEY]
112
97
  payload.sampled = payload_data[SAMPLED_KEY]
113
- payload.parent_ids = payload_data[PARENT_IDS_KEY]
114
- payload.depth = payload_data[DEPTH_KEY]
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
- #assigns intrinsics for the first distributed trace in a trip
133
- def assign_initial_intrinsics transaction, payload
134
- payload[TRIP_ID_INTRINSIC_KEY] = transaction.distributed_tracing_trip_id
135
- payload[DEPTH_INTRINSIC_KEY] = transaction.depth
136
- payload[PARENT_IDS_INTRINSIC_KEY] = transaction.parent_ids
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
- :caller_type,
130
+ :parent_type,
150
131
  :caller_transport_type,
151
- :caller_account_id,
152
- :caller_app_id,
132
+ :parent_account_id,
133
+ :parent_app_id,
153
134
  :id,
154
- :trip_id,
135
+ :trace_id,
155
136
  :sampled,
156
- :parent_ids,
157
- :synthetics_resource,
158
- :synthetics_job,
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 synthetics?
168
- !!(synthetics_resource || synthetics_job || synthetics_monitor)
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
- CALLER_TYPE_KEY => caller_type,
178
- CALLER_ACCOUNT_KEY => caller_account_id,
179
- CALLER_APP_KEY => caller_app_id,
180
- ID_KEY => id,
181
- TRIP_ID_KEY => trip_id,
182
- SAMPLED_KEY => sampled,
183
- PARENT_IDS_KEY => parent_ids,
184
- DEPTH_KEY => depth,
185
- ORDER_KEY => order,
186
- HOST_KEY => host,
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, payload
208
- payload[CALLER_TYPE_INTRINSIC_KEY] = caller_type
209
- payload[CALLER_APP_INTRINSIC_KEY] = caller_app_id
210
- payload[CALLER_ACCOUNT_ID_INTRINSIC_KEY] = caller_account_id
211
- payload[CALLER_TRANSPORT_TYPE_INTRINSIC_KEY] = caller_transport_type
212
- payload[CALLER_TRANSPORT_DURATION_INTRINSIC_KEY] = transaction.transport_duration
213
- payload[CALLER_HOST_INTRINSIC_KEY] = host
214
- payload[DEPTH_INTRINSIC_KEY] = depth
215
- payload[ORDER_INTRINSIC_KEY] = order
216
- payload[GUID_INTRINSIC_KEY] = transaction.guid
217
- payload[REFERRING_TRANSACTION_GUID_INTRINSIC_KEY] = id
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
- opts[:headers] ||= {} if NewRelic::Agent::CrossAppTracing.cross_app_enabled?
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
- if defined?(Grape::VERSION) && Gem::Version.new(::Grape::VERSION) >= Gem::Version.new("0.16.0")
34
- def name_for_transaction(route, class_name, version)
35
- action_name = route.path.sub(FORMAT_REGEX, EMPTY_STRING)
36
- method_name = route.request_method
37
- version ||= route.version
38
-
39
- # defaulting does not set rack.env['api.version'] and route.version may return Array
40
- #
41
- version = version.join(PIPE_STRING) if Array === version
42
-
43
- if version
44
- action_name = action_name.sub(VERSION_REGEX, EMPTY_STRING)
45
- "#{class_name}-#{version}#{action_name} (#{method_name})"
46
- else
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
- else
51
- def name_for_transaction(route, class_name, version)
52
- action_name = route.route_path.sub(FORMAT_REGEX, EMPTY_STRING)
53
- method_name = route.route_method
54
- version ||= route.route_version
55
-
56
- if version
57
- action_name = action_name.sub(VERSION_REGEX, EMPTY_STRING)
58
- "#{class_name}-#{version}#{action_name} (#{method_name})"
59
- else
60
- "#{class_name}#{action_name} (#{method_name})"
61
- end
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
- ::NewRelic::Agent::PrependSupportability.record_metrics_for(::ActionCable::Engine, ::ActionCable::RemoteConnections)
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