newrelic_rpm 6.8.0.360 → 6.9.0.363
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +16 -16
- data/CHANGELOG.md +64 -0
- data/lib/new_relic/agent.rb +6 -5
- data/lib/new_relic/agent/agent.rb +43 -36
- data/lib/new_relic/agent/attributes.rb +2 -4
- data/lib/new_relic/agent/configuration/default_source.rb +23 -22
- data/lib/new_relic/agent/configuration/server_source.rb +1 -1
- data/lib/new_relic/agent/configuration/yaml_source.rb +1 -1
- data/lib/new_relic/agent/database.rb +1 -2
- data/lib/new_relic/agent/distributed_tracing.rb +155 -6
- data/lib/new_relic/agent/{cross_app_payload.rb → distributed_tracing/cross_app_payload.rb} +0 -0
- data/lib/new_relic/agent/{cross_app_tracing.rb → distributed_tracing/cross_app_tracing.rb} +60 -45
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_intrinsics.rb +80 -0
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_metrics.rb +75 -0
- data/lib/new_relic/agent/{distributed_trace_payload.rb → distributed_tracing/distributed_trace_payload.rb} +19 -28
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_transport_type.rb +39 -0
- data/lib/new_relic/agent/distributed_tracing/trace_context.rb +246 -0
- data/lib/new_relic/agent/{trace_context_payload.rb → distributed_tracing/trace_context_payload.rb} +3 -11
- data/lib/new_relic/agent/error_collector.rb +3 -5
- data/lib/new_relic/agent/error_event_aggregator.rb +3 -1
- data/lib/new_relic/agent/external.rb +7 -7
- data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +1 -2
- data/lib/new_relic/agent/instrumentation/bunny.rb +1 -1
- data/lib/new_relic/agent/instrumentation/curb.rb +1 -1
- data/lib/new_relic/agent/instrumentation/excon.rb +1 -1
- data/lib/new_relic/agent/instrumentation/grape.rb +5 -10
- data/lib/new_relic/agent/instrumentation/http.rb +1 -1
- data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -1
- data/lib/new_relic/agent/instrumentation/net.rb +1 -1
- data/lib/new_relic/agent/instrumentation/resque.rb +3 -0
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +1 -1
- data/lib/new_relic/agent/logging.rb +13 -3
- data/lib/new_relic/agent/messaging.rb +5 -73
- data/lib/new_relic/agent/method_tracer.rb +3 -2
- data/lib/new_relic/agent/method_tracer_helpers.rb +1 -1
- data/lib/new_relic/agent/monitors.rb +27 -0
- data/lib/new_relic/agent/monitors/cross_app_monitor.rb +110 -0
- data/lib/new_relic/agent/monitors/distributed_tracing_monitor.rb +27 -0
- data/lib/new_relic/agent/{inbound_request_monitor.rb → monitors/inbound_request_monitor.rb} +1 -1
- data/lib/new_relic/agent/{synthetics_monitor.rb → monitors/synthetics_monitor.rb} +2 -4
- data/lib/new_relic/agent/span_event_primitive.rb +25 -29
- data/lib/new_relic/agent/sql_sampler.rb +2 -2
- data/lib/new_relic/agent/supported_versions.rb +2 -2
- data/lib/new_relic/agent/tracer.rb +3 -3
- data/lib/new_relic/agent/transaction.rb +21 -28
- data/lib/new_relic/agent/transaction/distributed_tracer.rb +171 -0
- data/lib/new_relic/agent/transaction/distributed_tracing.rb +61 -69
- data/lib/new_relic/agent/transaction/external_request_segment.rb +8 -44
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +3 -11
- data/lib/new_relic/agent/transaction/trace.rb +2 -4
- data/lib/new_relic/agent/transaction/trace_context.rb +88 -79
- data/lib/new_relic/agent/transaction/trace_node.rb +2 -5
- data/lib/new_relic/agent/transaction_error_primitive.rb +2 -2
- data/lib/new_relic/agent/transaction_event_primitive.rb +26 -29
- data/lib/new_relic/coerce.rb +5 -3
- data/lib/new_relic/constants.rb +34 -0
- data/lib/new_relic/noticed_error.rb +2 -4
- data/lib/new_relic/rack/browser_monitoring.rb +4 -0
- data/lib/new_relic/supportability_helper.rb +14 -0
- data/lib/new_relic/version.rb +1 -1
- data/lib/tasks/tests.rake +6 -1
- data/newrelic_rpm.gemspec +4 -2
- data/test/agent_helper.rb +21 -1
- metadata +49 -19
- data/lib/new_relic/agent/cross_app_monitor.rb +0 -110
- data/lib/new_relic/agent/distributed_trace_intrinsics.rb +0 -90
- data/lib/new_relic/agent/distributed_trace_metrics.rb +0 -74
- data/lib/new_relic/agent/distributed_trace_monitor.rb +0 -30
- data/lib/new_relic/agent/distributed_trace_transport_type.rb +0 -43
- data/lib/new_relic/agent/trace_context.rb +0 -244
- data/lib/new_relic/agent/trace_context_request_monitor.rb +0 -42
@@ -70,7 +70,7 @@ module NewRelic
|
|
70
70
|
|
71
71
|
def fix_transaction_threshold(merged_settings)
|
72
72
|
# when value is "apdex_f" remove the config and defer to default
|
73
|
-
if merged_settings['transaction_tracer.transaction_threshold'] =~ /apdex_f/i
|
73
|
+
if merged_settings['transaction_tracer.transaction_threshold'].to_s =~ /apdex_f/i
|
74
74
|
merged_settings.delete('transaction_tracer.transaction_threshold')
|
75
75
|
end
|
76
76
|
end
|
@@ -112,7 +112,7 @@ module NewRelic
|
|
112
112
|
|
113
113
|
def substitute_transaction_threshold(config)
|
114
114
|
if config['transaction_tracer'] &&
|
115
|
-
config['transaction_tracer']['transaction_threshold'] =~ /apdex_f/i
|
115
|
+
config['transaction_tracer']['transaction_threshold'].to_s =~ /apdex_f/i
|
116
116
|
# when value is "apdex_f" remove the config and defer to default
|
117
117
|
config['transaction_tracer'].delete('transaction_threshold')
|
118
118
|
end
|
@@ -133,10 +133,9 @@ module NewRelic
|
|
133
133
|
]
|
134
134
|
|
135
135
|
SQL_COMMENT_REGEX = Regexp.new('/\*.*?\*/', Regexp::MULTILINE).freeze
|
136
|
-
EMPTY_STRING = ''.freeze
|
137
136
|
|
138
137
|
def parse_operation_from_query(sql)
|
139
|
-
sql = Helper.correctly_encoded(sql).gsub(SQL_COMMENT_REGEX,
|
138
|
+
sql = Helper.correctly_encoded(sql).gsub(SQL_COMMENT_REGEX, NewRelic::EMPTY_STR)
|
140
139
|
if sql =~ /(\w+)/
|
141
140
|
op = $1.downcase
|
142
141
|
return op if KNOWN_OPERATIONS.include?(op)
|
@@ -1,8 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# This file is distributed under New Relic's license terms.
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
+
# frozen_string_literal: true
|
4
5
|
|
5
|
-
|
6
|
+
require_relative 'distributed_tracing/cross_app_payload'
|
7
|
+
require_relative 'distributed_tracing/cross_app_tracing'
|
8
|
+
|
9
|
+
require_relative 'distributed_tracing/distributed_trace_transport_type'
|
10
|
+
require_relative 'distributed_tracing/distributed_trace_payload'
|
11
|
+
|
12
|
+
require_relative 'distributed_tracing/trace_context'
|
6
13
|
|
7
14
|
module NewRelic
|
8
15
|
module Agent
|
@@ -14,8 +21,9 @@ module NewRelic
|
|
14
21
|
#
|
15
22
|
# @api public
|
16
23
|
module DistributedTracing
|
24
|
+
extend NewRelic::SupportabilityHelper
|
17
25
|
extend self
|
18
|
-
|
26
|
+
|
19
27
|
# Create a payload object containing the current transaction's
|
20
28
|
# tracing properties (e.g., duration, priority). You can use
|
21
29
|
# this object to generate headers to inject into a network
|
@@ -27,10 +35,19 @@ module NewRelic
|
|
27
35
|
# could not create the payload
|
28
36
|
#
|
29
37
|
# @api public
|
38
|
+
#
|
39
|
+
# @deprecated See {#create_distributed_trace_headers} instead.
|
40
|
+
#
|
30
41
|
def create_distributed_trace_payload
|
31
|
-
|
32
|
-
|
42
|
+
Deprecator.deprecate :create_distributed_trace_payload, :create_distributed_trace_headers
|
43
|
+
|
44
|
+
unless Agent.config[:'distributed_tracing.enabled']
|
45
|
+
NewRelic::Agent.logger.warn "Not configured to create New Relic distributed trace payload"
|
46
|
+
return nil
|
33
47
|
end
|
48
|
+
|
49
|
+
return unless transaction = Transaction.tl_current
|
50
|
+
transaction.distributed_tracer.create_distributed_trace_payload
|
34
51
|
rescue => e
|
35
52
|
NewRelic::Agent.logger.error 'error during create_distributed_trace_payload', e
|
36
53
|
nil
|
@@ -53,15 +70,147 @@ module NewRelic
|
|
53
70
|
# @return nil
|
54
71
|
#
|
55
72
|
# @api public
|
73
|
+
#
|
74
|
+
# @deprecated See {#accept_distributed_trace_headers} instead
|
75
|
+
#
|
56
76
|
def accept_distributed_trace_payload payload
|
57
|
-
|
58
|
-
|
77
|
+
Deprecator.deprecate :accept_distributed_trace_payload, :accept_distributed_trace_headers
|
78
|
+
|
79
|
+
unless Agent.config[:'distributed_tracing.enabled']
|
80
|
+
NewRelic::Agent.logger.warn "Not configured to accept New Relic distributed trace payload"
|
81
|
+
return nil
|
59
82
|
end
|
83
|
+
|
84
|
+
return unless transaction = Transaction.tl_current
|
85
|
+
transaction.distributed_tracer.accept_distributed_trace_payload(payload)
|
60
86
|
nil
|
61
87
|
rescue => e
|
62
88
|
NewRelic::Agent.logger.error 'error during accept_distributed_trace_payload', e
|
63
89
|
nil
|
64
90
|
end
|
91
|
+
|
92
|
+
|
93
|
+
# Adds the Distributed Trace headers so that the downstream service can participate in a
|
94
|
+
# distributed trace. This method should be called every time an outbound call is made
|
95
|
+
# since the header payload contains a timestamp.
|
96
|
+
#
|
97
|
+
# Distributed Tracing must be enabled to use this method.
|
98
|
+
#
|
99
|
+
# +insert_distributed_trace_headers+ always inserts W3C trace context headers and inserts
|
100
|
+
# New Relic distributed tracing header by default. New Relic headers may be suppressed by
|
101
|
+
# setting +exclude_new_relic_header+ to +true+ in your configuration file.
|
102
|
+
#
|
103
|
+
# @param headers [Hash] Is a Hash to which the distributed trace headers
|
104
|
+
# will be inserted.
|
105
|
+
#
|
106
|
+
# @return {Transaction} The transaction the headers were inserted from,
|
107
|
+
# or +nil+ if headers were not inserted.
|
108
|
+
#
|
109
|
+
# @api public
|
110
|
+
#
|
111
|
+
def insert_distributed_trace_headers headers={}
|
112
|
+
record_api_supportability_metric(:insert_distributed_trace_headers)
|
113
|
+
|
114
|
+
unless Agent.config[:'distributed_tracing.enabled']
|
115
|
+
NewRelic::Agent.logger.warn "Not configured to insert distributed trace headers"
|
116
|
+
return nil
|
117
|
+
end
|
118
|
+
|
119
|
+
return unless valid_api_argument_class? headers, "headers", Hash
|
120
|
+
|
121
|
+
return unless transaction = Transaction.tl_current
|
122
|
+
|
123
|
+
transaction.distributed_tracer.insert_headers headers
|
124
|
+
transaction
|
125
|
+
rescue => e
|
126
|
+
NewRelic::Agent.logger.error 'error during insert_distributed_trace_headers', e
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
# Accepts distributed tracing headers from any source that has been packaged
|
131
|
+
# as a Ruby Hash, thereby allowing the user to manually inject distributed
|
132
|
+
# tracing headers. It is optimized to process +HTTP_TRACEPARENT+, +HTTP_TRACESTATE+,
|
133
|
+
# and +HTTP_NEWRELIC+ as the given Hash keys. which is the most common scenario
|
134
|
+
# from Rack middleware in most Ruby applications. However, the Hash keys are
|
135
|
+
# case-insensitive and the "HTTP_" prefixes may also be omitted.
|
136
|
+
#
|
137
|
+
# Calling this method is not necessary in a typical HTTP trace as
|
138
|
+
# distributed tracing is already handled by the agent.
|
139
|
+
#
|
140
|
+
# When used, invoke this method as early as possible in a transaction's life-cycle
|
141
|
+
# as calling after the headers are already created will have no effect.
|
142
|
+
#
|
143
|
+
# This method accepts both W3C trace context and New Relic distributed tracing headers.
|
144
|
+
# When both are present, only the W3C headers are utilized. When W3C trace context
|
145
|
+
# headers are present, New Relic headers are ignored regardless if W3C trace context
|
146
|
+
# headers are valid and parsable.
|
147
|
+
#
|
148
|
+
# @param headers [Hash] Incoming distributed trace headers as a Ruby
|
149
|
+
# Hash object. Hash keys are expected to be one of
|
150
|
+
# +TRACEPARENT+, +TRACESTATE+, +NEWRELIC+ and are
|
151
|
+
# case-insensitive, with or without "HTTP_" prefixes.
|
152
|
+
#
|
153
|
+
# either as a JSON string or as a
|
154
|
+
# header-friendly string returned from
|
155
|
+
# {DistributedTracePayload#http_safe}
|
156
|
+
#
|
157
|
+
# @param transport_Type [String] May be one of: +HTTP+, +HTTPS+, +Kafka+, +JMS+,
|
158
|
+
# +IronMQ+, +AMQP+, +Queue+, +Other+. Values are
|
159
|
+
# case sensitive. All other values result in +Unknown+
|
160
|
+
#
|
161
|
+
# @return {Transaction} if successful, +nil+ otherwise
|
162
|
+
#
|
163
|
+
# @api public
|
164
|
+
#
|
165
|
+
def accept_distributed_trace_headers headers, transport_type = NewRelic::HTTP
|
166
|
+
record_api_supportability_metric(:accept_distributed_trace_headers)
|
167
|
+
|
168
|
+
unless Agent.config[:'distributed_tracing.enabled']
|
169
|
+
NewRelic::Agent.logger.warn "Not configured to accept distributed trace headers"
|
170
|
+
return nil
|
171
|
+
end
|
172
|
+
|
173
|
+
return unless valid_api_argument_class? headers, "headers", Hash
|
174
|
+
return unless valid_api_argument_class? transport_type, "transport_type", String
|
175
|
+
|
176
|
+
return unless transaction = Transaction.tl_current
|
177
|
+
|
178
|
+
# assume we have Rack conforming keys when transport_type is HTTP(S)
|
179
|
+
# otherwise, fish for key/value pairs regardless of prefix and case-sensitivity.
|
180
|
+
hdr = if transport_type.start_with? NewRelic::HTTP
|
181
|
+
headers
|
182
|
+
else
|
183
|
+
# start with the most common case first
|
184
|
+
hdr = {
|
185
|
+
NewRelic::HTTP_TRACEPARENT_KEY => headers[NewRelic::TRACEPARENT_KEY],
|
186
|
+
NewRelic::HTTP_TRACESTATE_KEY => headers[NewRelic::TRACESTATE_KEY],
|
187
|
+
NewRelic::HTTP_NEWRELIC_KEY => headers[NewRelic::NEWRELIC_KEY]
|
188
|
+
}
|
189
|
+
|
190
|
+
# when not found, search for any casing for trace context headers, ignoring potential prefixes
|
191
|
+
hdr[NewRelic::HTTP_TRACEPARENT_KEY] ||= variant_key_value headers, NewRelic::TRACEPARENT_KEY
|
192
|
+
hdr[NewRelic::HTTP_TRACESTATE_KEY] ||= variant_key_value headers, NewRelic::TRACESTATE_KEY
|
193
|
+
hdr[NewRelic::HTTP_NEWRELIC_KEY] ||= variant_key_value headers, NewRelic::CANDIDATE_NEWRELIC_KEYS
|
194
|
+
hdr
|
195
|
+
end
|
196
|
+
|
197
|
+
transaction.distributed_tracer.accept_incoming_request hdr, transport_type
|
198
|
+
transaction
|
199
|
+
rescue => e
|
200
|
+
NewRelic::Agent.logger.error 'error during accept_distributed_trace_headers', e
|
201
|
+
nil
|
202
|
+
end
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
def has_variant_key? key, variants
|
207
|
+
key.to_s.downcase.end_with?(*Array(variants))
|
208
|
+
end
|
209
|
+
|
210
|
+
def variant_key_value headers, variants
|
211
|
+
(headers.detect{|k, v| has_variant_key?(k, variants)} || NewRelic::EMPTY_ARRAY)[1]
|
212
|
+
end
|
213
|
+
|
65
214
|
end
|
66
215
|
end
|
67
216
|
end
|
File without changes
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# encoding: utf-8
|
3
3
|
# This file is distributed under New Relic's license terms.
|
4
4
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
5
|
+
# frozen_string_literal: true
|
5
6
|
|
6
7
|
require 'json'
|
7
8
|
|
@@ -9,23 +10,22 @@ module NewRelic
|
|
9
10
|
module Agent
|
10
11
|
module CrossAppTracing
|
11
12
|
# The cross app response header for "outgoing" calls
|
12
|
-
NR_APPDATA_HEADER = 'X-NewRelic-App-Data'
|
13
|
+
NR_APPDATA_HEADER = 'X-NewRelic-App-Data'
|
13
14
|
|
14
15
|
# The cross app id header for "outgoing" calls
|
15
|
-
NR_ID_HEADER = 'X-NewRelic-ID'
|
16
|
+
NR_ID_HEADER = 'X-NewRelic-ID'
|
16
17
|
|
17
18
|
# The cross app transaction header for "outgoing" calls
|
18
|
-
NR_TXN_HEADER = 'X-NewRelic-Transaction'
|
19
|
+
NR_TXN_HEADER = 'X-NewRelic-Transaction'
|
19
20
|
|
20
|
-
NR_MESSAGE_BROKER_ID_HEADER = 'NewRelicID'
|
21
|
-
NR_MESSAGE_BROKER_TXN_HEADER = 'NewRelicTransaction'
|
22
|
-
NR_MESSAGE_BROKER_SYNTHETICS_HEADER = 'NewRelicSynthetics'
|
21
|
+
NR_MESSAGE_BROKER_ID_HEADER = 'NewRelicID'
|
22
|
+
NR_MESSAGE_BROKER_TXN_HEADER = 'NewRelicTransaction'
|
23
|
+
NR_MESSAGE_BROKER_SYNTHETICS_HEADER = 'NewRelicSynthetics'
|
23
24
|
|
24
25
|
attr_accessor :is_cross_app_caller, :cross_app_payload, :cat_path_hashes
|
25
26
|
|
26
27
|
def is_cross_app_caller?
|
27
|
-
@is_cross_app_caller
|
28
|
-
@is_cross_app_caller
|
28
|
+
@is_cross_app_caller ||= false
|
29
29
|
end
|
30
30
|
|
31
31
|
def is_cross_app_callee?
|
@@ -37,28 +37,61 @@ module NewRelic
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def cat_trip_id
|
40
|
-
cross_app_payload && cross_app_payload.referring_trip_id || guid
|
40
|
+
cross_app_payload && cross_app_payload.referring_trip_id || transaction.guid
|
41
|
+
end
|
42
|
+
|
43
|
+
def cross_app_monitor
|
44
|
+
NewRelic::Agent.instance.monitors.cross_app_monitor
|
41
45
|
end
|
42
46
|
|
43
47
|
def cat_path_hash
|
44
48
|
referring_path_hash = cat_referring_path_hash || '0'
|
45
49
|
seed = referring_path_hash.to_i(16)
|
46
|
-
result =
|
50
|
+
result = cross_app_monitor.path_hash(transaction.best_name, seed)
|
47
51
|
record_cat_path_hash(result)
|
48
52
|
result
|
49
53
|
end
|
50
54
|
|
55
|
+
def insert_cross_app_header request
|
56
|
+
return unless CrossAppTracing.cross_app_enabled?
|
57
|
+
@is_cross_app_caller = true
|
58
|
+
txn_guid = transaction.guid
|
59
|
+
trip_id = cat_trip_id
|
60
|
+
path_hash = cat_path_hash
|
61
|
+
|
62
|
+
insert_request_headers request, txn_guid, trip_id, path_hash
|
63
|
+
end
|
64
|
+
|
51
65
|
def add_message_cat_headers headers
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
66
|
+
return unless CrossAppTracing.cross_app_enabled?
|
67
|
+
@is_cross_app_caller = true
|
68
|
+
insert_message_headers headers,
|
69
|
+
transaction.guid,
|
70
|
+
cat_trip_id,
|
71
|
+
cat_path_hash,
|
72
|
+
transaction.raw_synthetics_header
|
73
|
+
end
|
74
|
+
|
75
|
+
def record_cross_app_metrics
|
76
|
+
if (id = cross_app_payload && cross_app_payload.id)
|
77
|
+
app_time_in_seconds = [Time.now.to_f - transaction.start_time.to_f, 0.0].max
|
78
|
+
NewRelic::Agent.record_metric "ClientApplication/#{id}/all", app_time_in_seconds
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def assign_cross_app_intrinsics
|
83
|
+
transaction.attributes.add_intrinsic_attribute(:trip_id, cat_trip_id)
|
84
|
+
transaction.attributes.add_intrinsic_attribute(:path_hash, cat_path_hash)
|
58
85
|
end
|
59
86
|
|
60
87
|
private
|
61
88
|
|
89
|
+
def insert_message_headers headers, txn_guid, trip_id, path_hash, synthetics_header
|
90
|
+
headers[NR_MESSAGE_BROKER_ID_HEADER] = obfuscator.obfuscate(Agent.config[:cross_process_id])
|
91
|
+
headers[NR_MESSAGE_BROKER_TXN_HEADER] = obfuscator.obfuscate(::JSON.dump([txn_guid, false, trip_id, path_hash]))
|
92
|
+
headers[NR_MESSAGE_BROKER_SYNTHETICS_HEADER] = synthetics_header if synthetics_header
|
93
|
+
end
|
94
|
+
|
62
95
|
def record_cat_path_hash(hash)
|
63
96
|
@cat_path_hashes ||= []
|
64
97
|
if @cat_path_hashes.size < 10 && !@cat_path_hashes.include?(hash)
|
@@ -75,8 +108,8 @@ module NewRelic
|
|
75
108
|
payload[:referring_transaction_guid] = referring_guid
|
76
109
|
end
|
77
110
|
|
78
|
-
return unless include_guid?
|
79
|
-
payload[:guid] = guid
|
111
|
+
return unless transaction.include_guid?
|
112
|
+
payload[:guid] = transaction.guid
|
80
113
|
|
81
114
|
return unless is_cross_app?
|
82
115
|
trip_id = cat_trip_id
|
@@ -96,18 +129,6 @@ module NewRelic
|
|
96
129
|
end
|
97
130
|
end
|
98
131
|
|
99
|
-
def assign_cross_app_intrinsics
|
100
|
-
attributes.add_intrinsic_attribute(:trip_id, cat_trip_id)
|
101
|
-
attributes.add_intrinsic_attribute(:path_hash, cat_path_hash)
|
102
|
-
end
|
103
|
-
|
104
|
-
def record_cross_app_metrics
|
105
|
-
if (id = cross_app_payload && cross_app_payload.id)
|
106
|
-
app_time_in_seconds = [Time.now.to_f - @start_time.to_f, 0.0].max
|
107
|
-
NewRelic::Agent.record_metric "ClientApplication/#{id}/all", app_time_in_seconds
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
132
|
###############
|
112
133
|
module_function
|
113
134
|
###############
|
@@ -119,7 +140,7 @@ module NewRelic
|
|
119
140
|
end
|
120
141
|
|
121
142
|
def valid_cross_process_id?
|
122
|
-
if
|
143
|
+
if Agent.config[:cross_process_id] && Agent.config[:cross_process_id].length > 0
|
123
144
|
true
|
124
145
|
else
|
125
146
|
NewRelic::Agent.logger.debug "No cross_process_id configured"
|
@@ -128,7 +149,7 @@ module NewRelic
|
|
128
149
|
end
|
129
150
|
|
130
151
|
def valid_encoding_key?
|
131
|
-
if
|
152
|
+
if Agent.config[:encoding_key] && Agent.config[:encoding_key].length > 0
|
132
153
|
true
|
133
154
|
else
|
134
155
|
NewRelic::Agent.logger.debug "No encoding_key set"
|
@@ -143,7 +164,7 @@ module NewRelic
|
|
143
164
|
end
|
144
165
|
|
145
166
|
def obfuscator
|
146
|
-
@obfuscator ||= NewRelic::Agent::Obfuscator.new(
|
167
|
+
@obfuscator ||= NewRelic::Agent::Obfuscator.new(Agent.config[:encoding_key])
|
147
168
|
end
|
148
169
|
|
149
170
|
def insert_request_headers request, txn_guid, trip_id, path_hash
|
@@ -188,12 +209,6 @@ module NewRelic
|
|
188
209
|
!!(xp_id =~ /\A\d+#\d+\z/)
|
189
210
|
end
|
190
211
|
|
191
|
-
def insert_message_headers headers, txn_guid, trip_id, path_hash, synthetics_header
|
192
|
-
headers[NR_MESSAGE_BROKER_ID_HEADER] = obfuscator.obfuscate(NewRelic::Agent.config[:cross_process_id])
|
193
|
-
headers[NR_MESSAGE_BROKER_TXN_HEADER] = obfuscator.obfuscate(::JSON.dump([txn_guid, false, trip_id, path_hash]))
|
194
|
-
headers[NR_MESSAGE_BROKER_SYNTHETICS_HEADER] = synthetics_header if synthetics_header
|
195
|
-
end
|
196
|
-
|
197
212
|
def message_has_crossapp_request_header? headers
|
198
213
|
!!headers[NR_MESSAGE_BROKER_ID_HEADER]
|
199
214
|
end
|
@@ -217,15 +232,15 @@ module NewRelic
|
|
217
232
|
def assign_intrinsic_transaction_attributes state
|
218
233
|
# We expect to get the before call to set the id (if we have it) before
|
219
234
|
# this, and then write our custom parameter when the transaction starts
|
220
|
-
return unless (
|
221
|
-
return unless (
|
235
|
+
return unless (txn = state.current_transaction)
|
236
|
+
return unless (payload = txn.distributed_tracer.cross_app_payload)
|
222
237
|
|
223
|
-
if (cross_app_id =
|
224
|
-
|
238
|
+
if (cross_app_id = payload.id)
|
239
|
+
txn.attributes.add_intrinsic_attribute(:client_cross_process_id, cross_app_id)
|
225
240
|
end
|
226
241
|
|
227
|
-
if (referring_guid =
|
228
|
-
|
242
|
+
if (referring_guid = payload.referring_guid)
|
243
|
+
txn.attributes.add_intrinsic_attribute(:referring_transaction_guid, referring_guid)
|
229
244
|
end
|
230
245
|
end
|
231
246
|
end
|
@@ -0,0 +1,80 @@
|
|
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
|
+
# frozen_string_literal: true
|
5
|
+
|
6
|
+
module NewRelic
|
7
|
+
module Agent
|
8
|
+
module DistributedTraceIntrinsics
|
9
|
+
extend self
|
10
|
+
|
11
|
+
# Intrinsic Keys
|
12
|
+
INTRINSIC_KEYS = [
|
13
|
+
PARENT_TYPE_KEY = "parent.type",
|
14
|
+
PARENT_APP_KEY = "parent.app",
|
15
|
+
PARENT_ACCOUNT_ID_KEY = "parent.account",
|
16
|
+
PARENT_TRANSPORT_TYPE_KEY = "parent.transportType",
|
17
|
+
PARENT_TRANSPORT_DURATION_KEY = "parent.transportDuration",
|
18
|
+
GUID_KEY = "guid",
|
19
|
+
TRACE_ID_KEY = "traceId",
|
20
|
+
PARENT_TRANSACTION_ID_KEY = "parentId",
|
21
|
+
PARENT_SPAN_ID_KEY = "parentSpanId",
|
22
|
+
SAMPLED_KEY = "sampled",
|
23
|
+
].freeze
|
24
|
+
|
25
|
+
# This method extracts intrinsics from the transaction_payload and
|
26
|
+
# inserts them into the specified destination.
|
27
|
+
def copy_to_hash transaction_payload, destination
|
28
|
+
return unless enabled?
|
29
|
+
INTRINSIC_KEYS.each do |key|
|
30
|
+
value = transaction_payload[key]
|
31
|
+
destination[key] = value unless value.nil?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# This method extracts intrinsics from the transaction_payload and
|
36
|
+
# inserts them as intrinsics in the specified transaction_attributes
|
37
|
+
def copy_to_attributes transaction_payload, destination
|
38
|
+
return unless enabled?
|
39
|
+
INTRINSIC_KEYS.each do |key|
|
40
|
+
next unless transaction_payload.key? key
|
41
|
+
destination.add_intrinsic_attribute key, transaction_payload[key]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# This method takes all distributed tracing intrinsics from the transaction
|
46
|
+
# and the trace_payload, and populates them into the destination
|
47
|
+
def copy_from_transaction transaction, trace_payload, destination
|
48
|
+
transport_type = transaction.distributed_tracer.caller_transport_type
|
49
|
+
destination[PARENT_TRANSPORT_TYPE_KEY] = DistributedTraceTransportType.from transport_type
|
50
|
+
|
51
|
+
destination[GUID_KEY] = transaction.guid
|
52
|
+
destination[SAMPLED_KEY] = transaction.sampled?
|
53
|
+
destination[TRACE_ID_KEY] = transaction.trace_id
|
54
|
+
|
55
|
+
if transaction.parent_span_id
|
56
|
+
destination[PARENT_SPAN_ID_KEY] = transaction.parent_span_id
|
57
|
+
end
|
58
|
+
|
59
|
+
if trace_payload
|
60
|
+
destination[PARENT_TYPE_KEY] = trace_payload.parent_type
|
61
|
+
destination[PARENT_APP_KEY] = trace_payload.parent_app_id
|
62
|
+
destination[PARENT_ACCOUNT_ID_KEY] = trace_payload.parent_account_id
|
63
|
+
|
64
|
+
destination[PARENT_TRANSPORT_DURATION_KEY] = transaction.calculate_transport_duration trace_payload
|
65
|
+
|
66
|
+
if parent_transaction_id = transaction.distributed_tracer.parent_transaction_id
|
67
|
+
destination[PARENT_TRANSACTION_ID_KEY] = parent_transaction_id
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def enabled?
|
75
|
+
return Agent.config[:'distributed_tracing.enabled']
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|