newrelic_rpm 4.8.0.341 → 5.0.0.342
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +27 -0
- data/CHANGELOG.md +39 -0
- 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 +22 -17
- data/lib/new_relic/agent/configuration/high_security_source.rb +0 -2
- data/lib/new_relic/agent/database.rb +5 -0
- data/lib/new_relic/agent/database/explain_plan_helpers.rb +11 -0
- data/lib/new_relic/agent/distributed_trace_monitor.rb +4 -2
- data/lib/new_relic/agent/distributed_trace_payload.rb +88 -119
- data/lib/new_relic/agent/external.rb +14 -0
- data/lib/new_relic/agent/heap.rb +140 -0
- data/lib/new_relic/agent/instrumentation/bunny.rb +5 -1
- data/lib/new_relic/agent/instrumentation/rails5/action_cable.rb +5 -1
- data/lib/new_relic/agent/messaging.rb +10 -0
- 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.rb +14 -8
- data/lib/new_relic/agent/transaction/distributed_tracing.rb +113 -55
- data/lib/new_relic/agent/transaction/external_request_segment.rb +17 -11
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +12 -4
- 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/recipes/capistrano3.rb +5 -2
- data/lib/new_relic/version.rb +2 -2
- data/newrelic_rpm.gemspec +3 -2
- metadata +38 -9
- data/lib/new_relic/agent/distributed_trace_priority_sampled_buffer.rb +0 -72
@@ -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
|
@@ -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,
|
@@ -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
|
@@ -364,7 +364,17 @@ module NewRelic
|
|
364
364
|
transaction_name
|
365
365
|
end
|
366
366
|
|
367
|
+
NEWRELIC_TRACE_KEY = "NewRelicTrace".freeze
|
368
|
+
RABBITMQ_TRANSPORT_TYPE = "RabbitMQ".freeze
|
369
|
+
|
367
370
|
def consume_message_headers headers, transaction, state
|
371
|
+
if Agent.config[:'distributed_tracing.enabled']
|
372
|
+
payload = headers[NEWRELIC_TRACE_KEY]
|
373
|
+
if transaction.accept_distributed_trace_payload payload
|
374
|
+
transaction.distributed_trace_payload.caller_transport_type = RABBITMQ_TRANSPORT_TYPE
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
368
378
|
if CrossAppTracing.cross_app_enabled? && CrossAppTracing.message_has_crossapp_request_header?(headers)
|
369
379
|
decode_id headers[CrossAppTracing::NR_MESSAGE_BROKER_ID_HEADER], state
|
370
380
|
decode_txn_info headers[CrossAppTracing::NR_MESSAGE_BROKER_TXN_HEADER], state
|
@@ -15,7 +15,8 @@ module NewRelic
|
|
15
15
|
# Specifies the version of the agent's communication protocol with
|
16
16
|
# the NewRelic hosted site.
|
17
17
|
|
18
|
-
PROTOCOL_VERSION =
|
18
|
+
PROTOCOL_VERSION = 15
|
19
|
+
|
19
20
|
# 1f147a42: v10 (tag 3.5.3.17)
|
20
21
|
# cf0d1ff1: v9 (tag 3.5.0)
|
21
22
|
# 14105: v8 (tag 2.10.3)
|
@@ -30,8 +31,8 @@ module NewRelic
|
|
30
31
|
# underlying TCP connection may be in a bad state.
|
31
32
|
CONNECTION_ERRORS = [Timeout::Error, EOFError, SystemCallError, SocketError].freeze
|
32
33
|
|
33
|
-
attr_accessor :request_timeout
|
34
|
-
attr_reader :collector, :marshaller
|
34
|
+
attr_accessor :request_timeout
|
35
|
+
attr_reader :collector, :marshaller, :agent_id
|
35
36
|
|
36
37
|
def initialize(license_key=nil, collector=control.server)
|
37
38
|
@license_key = license_key
|
@@ -41,18 +42,12 @@ module NewRelic
|
|
41
42
|
@in_session = nil
|
42
43
|
@agent_id = nil
|
43
44
|
@shared_tcp_connection = nil
|
45
|
+
reset_remote_method_uris
|
44
46
|
|
45
47
|
@audit_logger = ::NewRelic::Agent::AuditLogger.new
|
46
48
|
Agent.config.register_callback(:'audit_log.enabled') do |enabled|
|
47
49
|
@audit_logger.enabled = enabled
|
48
50
|
end
|
49
|
-
Agent.config.register_callback(:ssl) do |ssl|
|
50
|
-
if !ssl
|
51
|
-
::NewRelic::Agent.logger.warn("Agent is configured not to use SSL when communicating with New Relic's servers")
|
52
|
-
else
|
53
|
-
::NewRelic::Agent.logger.debug("Agent is configured to use SSL")
|
54
|
-
end
|
55
|
-
end
|
56
51
|
|
57
52
|
Agent.config.register_callback(:marshaller) do |marshaller|
|
58
53
|
if marshaller != 'json'
|
@@ -63,17 +58,26 @@ module NewRelic
|
|
63
58
|
end
|
64
59
|
end
|
65
60
|
|
61
|
+
def agent_id=(id)
|
62
|
+
# Remote URIs have the agent run ID in them, so we need to
|
63
|
+
# clear out our cached values whenever the run ID changes.
|
64
|
+
#
|
65
|
+
reset_remote_method_uris
|
66
|
+
|
67
|
+
@agent_id = id
|
68
|
+
end
|
69
|
+
|
66
70
|
def connect(settings={})
|
67
|
-
if host =
|
71
|
+
if host = preconnect
|
68
72
|
@collector = NewRelic::Control.instance.server_from_host(host)
|
69
73
|
end
|
70
74
|
response = invoke_remote(:connect, [settings])
|
71
|
-
|
75
|
+
self.agent_id = response['agent_run_id']
|
72
76
|
response
|
73
77
|
end
|
74
78
|
|
75
|
-
def
|
76
|
-
invoke_remote(:
|
79
|
+
def preconnect
|
80
|
+
invoke_remote(:preconnect)
|
77
81
|
end
|
78
82
|
|
79
83
|
def shutdown(time)
|
@@ -261,8 +265,7 @@ module NewRelic
|
|
261
265
|
conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
262
266
|
conn.cert_store = ssl_cert_store
|
263
267
|
rescue StandardError, LoadError
|
264
|
-
msg = "
|
265
|
-
msg << "Either disable SSL in the agent configuration, or install SSL support."
|
268
|
+
msg = "SSL is not available in the environment; please install SSL support."
|
266
269
|
raise UnrecoverableAgentException.new(msg)
|
267
270
|
end
|
268
271
|
|
@@ -296,7 +299,7 @@ module NewRelic
|
|
296
299
|
conn = Net::HTTP.new(@collector.name, @collector.port)
|
297
300
|
end
|
298
301
|
|
299
|
-
setup_connection_for_ssl(conn)
|
302
|
+
setup_connection_for_ssl(conn)
|
300
303
|
setup_connection_timeouts(conn)
|
301
304
|
|
302
305
|
::NewRelic::Agent.logger.debug("Created net/http handle to #{conn.address}:#{conn.port}")
|
@@ -335,11 +338,28 @@ module NewRelic
|
|
335
338
|
NewRelic::Control.instance
|
336
339
|
end
|
337
340
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
341
|
+
def remote_method_uri(method)
|
342
|
+
@remote_method_uris[method]
|
343
|
+
end
|
344
|
+
|
345
|
+
def reset_remote_method_uris
|
346
|
+
@remote_method_uris = Hash.new do |hash, remote_method|
|
347
|
+
hash[remote_method] = generate_remote_method_uri(remote_method)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def generate_remote_method_uri(method)
|
352
|
+
params = {
|
353
|
+
'protocol_version' => PROTOCOL_VERSION,
|
354
|
+
'license_key' => license_key,
|
355
|
+
'run_id' => @agent_id,
|
356
|
+
'method' => method,
|
357
|
+
'marshal_format' => 'json', # Other formats are explicitly
|
358
|
+
# ruled out; see the initializer
|
359
|
+
}
|
360
|
+
|
361
|
+
uri = "/agent_listener/invoke_raw_method?"
|
362
|
+
uri << params.map do |k,v|
|
343
363
|
next unless v
|
344
364
|
"#{k}=#{v}"
|
345
365
|
end.compact.join('&')
|
@@ -368,7 +388,7 @@ module NewRelic
|
|
368
388
|
data, encoding = compress_request_if_needed(data)
|
369
389
|
size = data.size
|
370
390
|
|
371
|
-
uri = remote_method_uri(method
|
391
|
+
uri = remote_method_uri(method)
|
372
392
|
full_uri = "#{@collector}#{uri}"
|
373
393
|
|
374
394
|
@audit_logger.log_request(full_uri, payload, @marshaller)
|
@@ -0,0 +1,68 @@
|
|
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/heap'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
class PrioritySampledBuffer < SampledBuffer
|
10
|
+
PRIORITY_KEY = "priority".freeze
|
11
|
+
|
12
|
+
attr_reader :seen_lifetime, :captured_lifetime
|
13
|
+
|
14
|
+
def initialize(capacity)
|
15
|
+
super
|
16
|
+
@captured_lifetime = 0
|
17
|
+
@seen_lifetime = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
# expects priority and a block, or an event as a hash with a `priority` key.
|
21
|
+
def append(priority: nil, event: nil, &blk)
|
22
|
+
increment_seen
|
23
|
+
|
24
|
+
if @seen == @capacity
|
25
|
+
@items = Heap.new(@items) { |x| priority_for(x) }
|
26
|
+
end
|
27
|
+
|
28
|
+
if full?
|
29
|
+
priority ||= priority_for(event)
|
30
|
+
if priority_for(@items[0]) < priority
|
31
|
+
@items[0] = event || blk.call
|
32
|
+
@items.fix(0)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
@items << (event || blk.call)
|
36
|
+
@captured_lifetime += 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :append_event, :append
|
41
|
+
|
42
|
+
def capacity=(new_capacity)
|
43
|
+
@capacity = new_capacity
|
44
|
+
old_items = @items.to_a
|
45
|
+
old_seen = @seen
|
46
|
+
reset!
|
47
|
+
old_items.each { |i| append(event: i) }
|
48
|
+
@seen = old_seen
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_a
|
52
|
+
@items.to_a.dup
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def increment_seen
|
58
|
+
@seen += 1
|
59
|
+
@seen_lifetime += 1
|
60
|
+
end
|
61
|
+
|
62
|
+
def priority_for(event)
|
63
|
+
event[0][PRIORITY_KEY]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -11,7 +11,7 @@ module NewRelic
|
|
11
11
|
{
|
12
12
|
:type => :ruby,
|
13
13
|
:name => "MRI",
|
14
|
-
:supported => ["2.0.0", "~>2.1.0", "~>2.2.0", "~>2.3.0", "~>2.4.0"],
|
14
|
+
:supported => ["2.0.0", "~>2.1.0", "~>2.2.0", "~>2.3.0", "~>2.4.0", "~>2.5.0"],
|
15
15
|
:deprecated => ["1.8.6", "1.8.7", "1.9.2", "1.9.3"],
|
16
16
|
:url => "https://www.ruby-lang.org",
|
17
17
|
:feed => "https://www.ruby-lang.org/en/feeds/news.rss",
|
@@ -58,7 +58,8 @@ module NewRelic
|
|
58
58
|
:http_response_code,
|
59
59
|
:response_content_length,
|
60
60
|
:response_content_type,
|
61
|
-
:sampled
|
61
|
+
:sampled,
|
62
|
+
:priority
|
62
63
|
|
63
64
|
attr_reader :guid,
|
64
65
|
:metrics,
|
@@ -283,11 +284,15 @@ module NewRelic
|
|
283
284
|
@ignore_trace = false
|
284
285
|
|
285
286
|
if Agent.config[:'distributed_tracing.enabled']
|
286
|
-
@sampled = NewRelic::Agent.instance.
|
287
|
+
@sampled = NewRelic::Agent.instance.adaptive_sampler.sampled?
|
287
288
|
else
|
288
289
|
@sampled = nil
|
289
290
|
end
|
290
291
|
|
292
|
+
# we will eventually add this behavior into the AdaptiveSampler (ThroughputMontor)
|
293
|
+
@priority = rand
|
294
|
+
@priority +=1 if @sampled
|
295
|
+
|
291
296
|
@attributes = Attributes.new(NewRelic::Agent.instance.attribute_filter)
|
292
297
|
|
293
298
|
merge_request_parameters(@filtered_params)
|
@@ -596,7 +601,7 @@ module NewRelic
|
|
596
601
|
end
|
597
602
|
|
598
603
|
def assign_intrinsics(state)
|
599
|
-
attributes.add_intrinsic_attribute :'
|
604
|
+
attributes.add_intrinsic_attribute :'sampled', sampled?
|
600
605
|
|
601
606
|
if gc_time = calculate_gc_time
|
602
607
|
attributes.add_intrinsic_attribute(:gc_time, gc_time)
|
@@ -612,8 +617,8 @@ module NewRelic
|
|
612
617
|
attributes.add_intrinsic_attribute(:synthetics_monitor_id, synthetics_monitor_id)
|
613
618
|
end
|
614
619
|
|
615
|
-
if distributed_trace_payload ||
|
616
|
-
|
620
|
+
if distributed_trace_payload || distributed_trace_payload_created?
|
621
|
+
assign_distributed_trace_intrinsics
|
617
622
|
elsif state.is_cross_app?
|
618
623
|
attributes.add_intrinsic_attribute(:trip_id, cat_trip_id)
|
619
624
|
attributes.add_intrinsic_attribute(:path_hash, cat_path_hash)
|
@@ -648,13 +653,14 @@ module NewRelic
|
|
648
653
|
:duration => duration,
|
649
654
|
:metrics => @metrics,
|
650
655
|
:attributes => @attributes,
|
651
|
-
:error => false
|
656
|
+
:error => false,
|
657
|
+
:priority => @priority
|
652
658
|
}
|
653
659
|
|
654
|
-
@payload[:'
|
660
|
+
@payload[:'sampled'] = sampled? if Agent.config[:'distributed_tracing.enabled']
|
655
661
|
|
656
662
|
append_cat_info(state, duration, @payload)
|
657
|
-
|
663
|
+
append_distributed_trace_info(@payload)
|
658
664
|
append_apdex_perf_zone(duration, @payload)
|
659
665
|
append_synthetics_to(state, @payload)
|
660
666
|
append_referring_transaction_guid_to(state, @payload)
|