newrelic_rpm 9.23.0 → 10.0.0
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 +4 -4
- data/CHANGELOG.md +136 -0
- data/README.md +0 -7
- data/lib/new_relic/agent/agent.rb +9 -4
- data/lib/new_relic/agent/configuration/default_source.rb +103 -181
- data/lib/new_relic/agent/configuration/environment_source.rb +7 -38
- data/lib/new_relic/agent/configuration/manager.rb +141 -59
- data/lib/new_relic/agent/configuration/sampler_config_validator.rb +54 -0
- data/lib/new_relic/agent/configuration/server_source.rb +0 -1
- data/lib/new_relic/agent/connect/response_handler.rb +0 -11
- data/lib/new_relic/agent/datastores.rb +13 -17
- data/lib/new_relic/agent/distributed_tracing.rb +0 -3
- data/lib/new_relic/agent/health_check.rb +1 -0
- data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +2 -1
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -4
- data/lib/new_relic/agent/instrumentation/active_support.rb +8 -1
- data/lib/new_relic/agent/instrumentation/active_support_subscriber.rb +22 -14
- data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +1 -4
- data/lib/new_relic/agent/instrumentation/bunny.rb +0 -1
- data/lib/new_relic/agent/instrumentation/curb/chain.rb +2 -2
- data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +2 -3
- data/lib/new_relic/agent/instrumentation/curb.rb +0 -1
- data/lib/new_relic/agent/instrumentation/excon/middleware.rb +1 -1
- data/lib/new_relic/agent/instrumentation/excon.rb +2 -3
- data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +1 -2
- data/lib/new_relic/agent/instrumentation/httpclient.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
- data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +0 -2
- data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +0 -2
- data/lib/new_relic/agent/instrumentation/rack/helpers.rb +1 -3
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
- data/lib/new_relic/agent/llm/chat_completion_summary.rb +1 -8
- data/lib/new_relic/agent/llm/embedding.rb +1 -8
- data/lib/new_relic/agent/messaging.rb +12 -5
- data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -2
- data/lib/new_relic/agent/monitors/synthetics_monitor.rb +2 -1
- data/lib/new_relic/agent/monitors.rb +0 -3
- data/lib/new_relic/agent/new_relic_service/encoders.rb +0 -14
- data/lib/new_relic/agent/new_relic_service.rb +11 -49
- data/lib/new_relic/agent/opentelemetry/trace/span.rb +41 -0
- data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +16 -7
- data/lib/new_relic/agent/opentelemetry_bridge.rb +9 -5
- data/lib/new_relic/agent/serverless_handler.rb +2 -2
- data/lib/new_relic/agent/span_event_primitive.rb +1 -1
- data/lib/new_relic/agent/sql_sampler.rb +0 -31
- data/lib/new_relic/agent/stats_engine.rb +1 -0
- data/lib/new_relic/agent/transaction/distributed_tracer.rb +12 -56
- data/lib/new_relic/agent/transaction/distributed_tracing.rb +11 -19
- data/lib/new_relic/agent/transaction/external_request_segment.rb +1 -131
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +0 -2
- data/lib/new_relic/agent/transaction/trace_context.rb +33 -11
- data/lib/new_relic/agent/transaction.rb +35 -4
- data/lib/new_relic/agent/transaction_error_primitive.rb +0 -8
- data/lib/new_relic/agent/transaction_event_primitive.rb +0 -14
- data/lib/new_relic/agent/utilization/gcp.rb +2 -0
- data/lib/new_relic/agent.rb +11 -3
- data/lib/new_relic/cli/command.rb +2 -11
- data/lib/new_relic/control/instance_methods.rb +2 -15
- data/lib/new_relic/control/private_instance_methods.rb +2 -4
- data/lib/new_relic/control/server_methods.rb +0 -6
- data/lib/new_relic/helper.rb +21 -2
- data/lib/new_relic/language_support.rb +3 -34
- data/lib/new_relic/supportability_helper.rb +0 -4
- data/lib/new_relic/version.rb +2 -2
- data/lib/tasks/helpers/newrelicyml.rb +2 -2
- data/lib/tasks/helpers/version_bump.rb +1 -2
- data/newrelic.yml +25 -28
- data/newrelic_rpm.gemspec +10 -9
- metadata +27 -26
- data/bin/newrelic +0 -8
- data/lib/new_relic/agent/configuration/security_policy_source.rb +0 -246
- data/lib/new_relic/agent/distributed_tracing/cross_app_payload.rb +0 -44
- data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +0 -253
- data/lib/new_relic/agent/external.rb +0 -112
- data/lib/new_relic/agent/monitors/cross_app_monitor.rb +0 -117
- data/lib/new_relic/agent/new_relic_service/security_policy_settings.rb +0 -61
- data/lib/new_relic/cli/commands/deployments.rb +0 -206
- data/lib/new_relic/recipes/capistrano3.rb +0 -23
- data/lib/new_relic/recipes/capistrano_legacy.rb +0 -95
- data/lib/new_relic/recipes/helpers/send_deployment.rb +0 -70
- data/lib/new_relic/recipes.rb +0 -24
- data/recipes/newrelic.rb +0 -10
|
@@ -144,7 +144,7 @@ module NewRelic
|
|
|
144
144
|
def payload_v1 # New Relic serverless payload v1
|
|
145
145
|
payload_hash = {'metadata' => metadata, 'data' => @payloads}
|
|
146
146
|
json = NewRelic::Agent.agent.service.marshaller.dump(payload_hash)
|
|
147
|
-
gzipped =
|
|
147
|
+
gzipped = Zlib.gzip(json)
|
|
148
148
|
base64_encoded = NewRelic::Base64.strict_encode64(gzipped)
|
|
149
149
|
array = [PAYLOAD_VERSION, LAMBDA_MARKER, base64_encoded]
|
|
150
150
|
::JSON.dump(array)
|
|
@@ -152,7 +152,7 @@ module NewRelic
|
|
|
152
152
|
|
|
153
153
|
def payload_v2 # New Relic serverless payload v2
|
|
154
154
|
json = NewRelic::Agent.agent.service.marshaller.dump(@payloads)
|
|
155
|
-
gzipped =
|
|
155
|
+
gzipped = Zlib.gzip(json)
|
|
156
156
|
base64_encoded = NewRelic::Base64.strict_encode64(gzipped)
|
|
157
157
|
array = [PAYLOAD_VERSION, LAMBDA_MARKER, metadata, base64_encoded]
|
|
158
158
|
::JSON.dump(array)
|
|
@@ -92,7 +92,7 @@ module NewRelic
|
|
|
92
92
|
[intrinsics, custom_attributes(segment), agent_attributes.merge(agent_attributes(segment))]
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
-
def for_datastore_segment(segment)
|
|
95
|
+
def for_datastore_segment(segment)
|
|
96
96
|
intrinsics = intrinsics_for(segment)
|
|
97
97
|
|
|
98
98
|
intrinsics[COMPONENT_KEY] = segment.product
|
|
@@ -122,37 +122,6 @@ module NewRelic
|
|
|
122
122
|
@sql_traces.delete(shortest_key)
|
|
123
123
|
end
|
|
124
124
|
|
|
125
|
-
# Records an SQL query, potentially creating a new slow SQL trace, or
|
|
126
|
-
# aggregating the query into an existing slow SQL trace.
|
|
127
|
-
#
|
|
128
|
-
# This method should be used only by gem authors wishing to extend
|
|
129
|
-
# the Ruby agent to instrument new database interfaces - it should
|
|
130
|
-
# generally not be called directly from application code.
|
|
131
|
-
#
|
|
132
|
-
# @param sql [String] the SQL query being recorded
|
|
133
|
-
# @param metric_name [String] is the metric name under which this query will be recorded
|
|
134
|
-
# @param config [Object] is the driver configuration for the connection
|
|
135
|
-
# @param duration [Float] number of seconds the query took to execute
|
|
136
|
-
# @param explainer [Proc] for internal use only - 3rd-party clients must
|
|
137
|
-
# not pass this parameter.
|
|
138
|
-
#
|
|
139
|
-
# @api public
|
|
140
|
-
# @deprecated Use {Datastores.notice_sql} instead.
|
|
141
|
-
#
|
|
142
|
-
def notice_sql(sql, metric_name, config, duration, state = nil, explainer = nil, binds = nil, name = nil) # THREAD_LOCAL_ACCESS sometimes
|
|
143
|
-
state ||= Tracer.state
|
|
144
|
-
data = state.sql_sampler_transaction_data
|
|
145
|
-
return unless data
|
|
146
|
-
|
|
147
|
-
if state.is_sql_recorded?
|
|
148
|
-
if duration > Agent.config[:'slow_sql.explain_threshold']
|
|
149
|
-
backtrace = caller.join("\n")
|
|
150
|
-
statement = Database::Statement.new(sql, config, explainer, binds, name)
|
|
151
|
-
data.sql_data << SlowSql.new(statement, metric_name, duration, backtrace)
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
125
|
PRIORITY = 'priority'.freeze
|
|
157
126
|
|
|
158
127
|
def distributed_trace_attributes(state)
|
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
require 'new_relic/agent/transaction/trace_context'
|
|
6
6
|
require 'new_relic/agent/transaction/distributed_tracing'
|
|
7
|
-
require 'new_relic/agent/distributed_tracing/cross_app_tracing'
|
|
8
7
|
|
|
9
8
|
module NewRelic
|
|
10
9
|
module Agent
|
|
11
10
|
class Transaction
|
|
12
11
|
class DistributedTracer
|
|
13
|
-
include NewRelic::Agent::CrossAppTracing
|
|
14
12
|
include DistributedTracing
|
|
15
13
|
include TraceContext
|
|
16
14
|
|
|
@@ -55,12 +53,10 @@ module NewRelic
|
|
|
55
53
|
end
|
|
56
54
|
|
|
57
55
|
def record_metrics
|
|
58
|
-
record_cross_app_metrics
|
|
59
56
|
DistributedTraceMetrics.record_metrics_for_transaction(transaction)
|
|
60
57
|
end
|
|
61
58
|
|
|
62
59
|
def append_payload(payload)
|
|
63
|
-
append_cat_info(payload)
|
|
64
60
|
DistributedTraceAttributes.copy_from_transaction( \
|
|
65
61
|
transaction,
|
|
66
62
|
trace_state_payload || distributed_trace_payload,
|
|
@@ -78,14 +74,12 @@ module NewRelic
|
|
|
78
74
|
|
|
79
75
|
insert_trace_context_header(headers)
|
|
80
76
|
insert_distributed_trace_header(headers)
|
|
81
|
-
insert_cross_app_header(headers)
|
|
82
77
|
log_request_headers(headers)
|
|
83
78
|
end
|
|
84
79
|
|
|
85
80
|
def consume_message_headers(headers, tracer_state, transport_type)
|
|
86
81
|
log_request_headers(headers, 'INCOMING')
|
|
87
82
|
consume_message_distributed_tracing_headers(headers, transport_type)
|
|
88
|
-
consume_message_cross_app_tracing_headers(headers, tracer_state)
|
|
89
83
|
consume_message_synthetics_headers(headers)
|
|
90
84
|
rescue => e
|
|
91
85
|
NewRelic::Agent.logger.error('Error in consume_message_headers', e)
|
|
@@ -94,8 +88,6 @@ module NewRelic
|
|
|
94
88
|
def assign_intrinsics
|
|
95
89
|
if dt_enabled?
|
|
96
90
|
DistributedTraceAttributes.copy_to_attributes(transaction.payload, transaction.attributes)
|
|
97
|
-
elsif is_cross_app?
|
|
98
|
-
assign_cross_app_intrinsics
|
|
99
91
|
end
|
|
100
92
|
end
|
|
101
93
|
|
|
@@ -107,17 +99,6 @@ module NewRelic
|
|
|
107
99
|
headers[NewRelic::NEWRELIC_KEY] = payload.http_safe if payload
|
|
108
100
|
end
|
|
109
101
|
|
|
110
|
-
def insert_cat_headers(headers)
|
|
111
|
-
return unless CrossAppTracing.cross_app_enabled?
|
|
112
|
-
|
|
113
|
-
@is_cross_app_caller = true
|
|
114
|
-
insert_message_headers(headers,
|
|
115
|
-
transaction.guid,
|
|
116
|
-
cat_trip_id,
|
|
117
|
-
cat_path_hash,
|
|
118
|
-
transaction.raw_synthetics_header)
|
|
119
|
-
end
|
|
120
|
-
|
|
121
102
|
private
|
|
122
103
|
|
|
123
104
|
def dt_enabled?
|
|
@@ -125,15 +106,18 @@ module NewRelic
|
|
|
125
106
|
end
|
|
126
107
|
|
|
127
108
|
def consume_message_synthetics_headers(headers)
|
|
128
|
-
synthetics_header = headers[
|
|
129
|
-
if synthetics_header
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
109
|
+
synthetics_header = headers[SyntheticsMonitor::NON_HTTP_SYNTHETICS_HEADER_KEY]
|
|
110
|
+
if synthetics_header
|
|
111
|
+
require 'new_relic/agent/obfuscator'
|
|
112
|
+
obfuscator = ::NewRelic::Agent::Obfuscator.new(Agent.config[:encoding_key])
|
|
113
|
+
incoming_payload = ::JSON.parse(obfuscator.deobfuscate(synthetics_header))
|
|
114
|
+
if SyntheticsMonitor.is_valid_payload?(incoming_payload) &&
|
|
115
|
+
SyntheticsMonitor.is_supported_version?(incoming_payload) &&
|
|
116
|
+
SyntheticsMonitor.is_trusted?(incoming_payload)
|
|
117
|
+
|
|
118
|
+
transaction.raw_synthetics_header = synthetics_header
|
|
119
|
+
transaction.synthetics_payload = incoming_payload
|
|
120
|
+
end
|
|
137
121
|
end
|
|
138
122
|
rescue => e
|
|
139
123
|
NewRelic::Agent.logger.error('Error in consume_message_synthetics_header', e)
|
|
@@ -151,34 +135,6 @@ module NewRelic
|
|
|
151
135
|
|
|
152
136
|
accept_distributed_trace_payload(payload)
|
|
153
137
|
end
|
|
154
|
-
|
|
155
|
-
def consume_message_cross_app_tracing_headers(headers, tracer_state)
|
|
156
|
-
return unless CrossAppTracing.cross_app_enabled?
|
|
157
|
-
return unless CrossAppTracing.message_has_crossapp_request_header?(headers)
|
|
158
|
-
|
|
159
|
-
accept_cross_app_payload(headers, tracer_state)
|
|
160
|
-
CrossAppTracing.assign_intrinsic_transaction_attributes(tracer_state)
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
def accept_cross_app_payload(headers, tracer_state)
|
|
164
|
-
encoded_id = headers[CrossAppTracing::NR_MESSAGE_BROKER_ID_HEADER]
|
|
165
|
-
decoded_id = encoded_id.nil? ? EMPTY_STRING : deobfuscate(encoded_id)
|
|
166
|
-
|
|
167
|
-
return unless CrossAppTracing.trusted_valid_cross_app_id?(decoded_id)
|
|
168
|
-
|
|
169
|
-
txn_header = headers[CrossAppTracing::NR_MESSAGE_BROKER_TXN_HEADER]
|
|
170
|
-
txn_info = ::JSON.parse(deobfuscate(txn_header))
|
|
171
|
-
payload = CrossAppPayload.new(decoded_id, transaction, txn_info)
|
|
172
|
-
|
|
173
|
-
@cross_app_payload = payload
|
|
174
|
-
rescue => e
|
|
175
|
-
NewRelic::Agent.logger.debug("Failure deserializing encoded header in #{self.class}, #{e.class}, #{e.message}")
|
|
176
|
-
nil
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
def deobfuscate(message)
|
|
180
|
-
CrossAppTracing.obfuscator.deobfuscate(message)
|
|
181
|
-
end
|
|
182
138
|
end
|
|
183
139
|
end
|
|
184
140
|
end
|
|
@@ -161,29 +161,21 @@ module NewRelic
|
|
|
161
161
|
transaction.parent_span_id = payload.id
|
|
162
162
|
|
|
163
163
|
unless payload.sampled.nil?
|
|
164
|
-
if payload.sampled
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
if payload.sampled
|
|
165
|
+
set_priority_and_sampled(
|
|
166
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled'],
|
|
167
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled.trace_id_ratio_based.ratio'],
|
|
168
|
+
payload
|
|
169
|
+
)
|
|
168
170
|
else
|
|
169
|
-
|
|
170
|
-
|
|
171
|
+
set_priority_and_sampled(
|
|
172
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled'],
|
|
173
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled.trace_id_ratio_based.ratio'],
|
|
174
|
+
payload
|
|
175
|
+
)
|
|
171
176
|
end
|
|
172
177
|
end
|
|
173
178
|
end
|
|
174
|
-
|
|
175
|
-
def set_priority_and_sampled_newrelic_header(config, payload)
|
|
176
|
-
if config == 'always_on'
|
|
177
|
-
transaction.sampled = true
|
|
178
|
-
transaction.priority = 2.0
|
|
179
|
-
elsif config == 'always_off'
|
|
180
|
-
transaction.sampled = false
|
|
181
|
-
transaction.priority = 0
|
|
182
|
-
else # case for 'default' value
|
|
183
|
-
transaction.sampled = payload.sampled
|
|
184
|
-
transaction.priority = payload.priority if payload.priority
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
179
|
end
|
|
188
180
|
end
|
|
189
181
|
end
|
|
@@ -64,119 +64,6 @@ module NewRelic
|
|
|
64
64
|
NewRelic::Agent.logger.error('Error in add_request_headers', e)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
# This method extracts app data from an external response if present. If
|
|
68
|
-
# a valid cross-app ID is found, the name of the segment is updated to
|
|
69
|
-
# reflect the cross-process ID and transaction name.
|
|
70
|
-
#
|
|
71
|
-
# @param [Hash] response a hash of response headers
|
|
72
|
-
#
|
|
73
|
-
# @api public
|
|
74
|
-
def read_response_headers(response)
|
|
75
|
-
return unless record_metrics? && CrossAppTracing.cross_app_enabled?
|
|
76
|
-
return unless CrossAppTracing.response_has_crossapp_header?(response)
|
|
77
|
-
|
|
78
|
-
unless data = CrossAppTracing.extract_appdata(response)
|
|
79
|
-
NewRelic::Agent.logger.debug("Couldn't extract_appdata from external segment response")
|
|
80
|
-
return
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
if CrossAppTracing.valid_cross_app_id?(data[0])
|
|
84
|
-
@app_data = data
|
|
85
|
-
update_segment_name
|
|
86
|
-
else
|
|
87
|
-
NewRelic::Agent.logger.debug('External segment response has invalid cross_app_id')
|
|
88
|
-
end
|
|
89
|
-
rescue => e
|
|
90
|
-
NewRelic::Agent.logger.error('Error in read_response_headers', e)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def cross_app_request? # :nodoc:
|
|
94
|
-
!!@app_data
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def cross_process_id # :nodoc:
|
|
98
|
-
@app_data && @app_data[0]
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def transaction_guid # :nodoc:
|
|
102
|
-
@app_data && @app_data[5]
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def cross_process_transaction_name # :nodoc:
|
|
106
|
-
@app_data && @app_data[1]
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Obtain an obfuscated +String+ suitable for delivery across public networks that identifies this application
|
|
110
|
-
# and transaction to another application which is also running a New Relic agent. This +String+ can be processed
|
|
111
|
-
# by +process_request_metadata+ on the receiving application.
|
|
112
|
-
#
|
|
113
|
-
# @return [String] obfuscated request metadata to send
|
|
114
|
-
#
|
|
115
|
-
# @api public
|
|
116
|
-
#
|
|
117
|
-
def get_request_metadata
|
|
118
|
-
NewRelic::Agent.record_api_supportability_metric(:get_request_metadata)
|
|
119
|
-
return unless CrossAppTracing.cross_app_enabled?
|
|
120
|
-
|
|
121
|
-
if transaction
|
|
122
|
-
|
|
123
|
-
# build hash of CAT metadata
|
|
124
|
-
#
|
|
125
|
-
rmd = {
|
|
126
|
-
NewRelicID: NewRelic::Agent.config[:cross_process_id],
|
|
127
|
-
NewRelicTransaction: [
|
|
128
|
-
transaction.guid,
|
|
129
|
-
false,
|
|
130
|
-
transaction.distributed_tracer.cat_trip_id,
|
|
131
|
-
transaction.distributed_tracer.cat_path_hash
|
|
132
|
-
]
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
# flag cross app in the state so transaction knows to add bits to payload
|
|
136
|
-
#
|
|
137
|
-
transaction.distributed_tracer.is_cross_app_caller = true
|
|
138
|
-
|
|
139
|
-
# add Synthetics header if we have it
|
|
140
|
-
#
|
|
141
|
-
rmd[:NewRelicSynthetics] = transaction.raw_synthetics_header if transaction.raw_synthetics_header
|
|
142
|
-
|
|
143
|
-
# obfuscate the generated request metadata JSON
|
|
144
|
-
#
|
|
145
|
-
obfuscator.obfuscate(::JSON.dump(rmd))
|
|
146
|
-
|
|
147
|
-
end
|
|
148
|
-
rescue => e
|
|
149
|
-
NewRelic::Agent.logger.error('error during get_request_metadata', e)
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
# Process obfuscated +String+ sent from a called application that is also running a New Relic agent and
|
|
153
|
-
# save information in current transaction for inclusion in a trace. This +String+ is generated by
|
|
154
|
-
# +get_response_metadata+ on the receiving application.
|
|
155
|
-
#
|
|
156
|
-
# @param response_metadata [String] received obfuscated response metadata
|
|
157
|
-
#
|
|
158
|
-
# @api public
|
|
159
|
-
#
|
|
160
|
-
def process_response_metadata(response_metadata)
|
|
161
|
-
NewRelic::Agent.record_api_supportability_metric(:process_response_metadata)
|
|
162
|
-
if transaction
|
|
163
|
-
app_data = ::JSON.parse(obfuscator.deobfuscate(response_metadata))[APP_DATA_KEY]
|
|
164
|
-
|
|
165
|
-
# validate cross app id
|
|
166
|
-
#
|
|
167
|
-
if Array === app_data and CrossAppTracing.trusted_valid_cross_app_id?(app_data[0])
|
|
168
|
-
@app_data = app_data
|
|
169
|
-
update_segment_name
|
|
170
|
-
else
|
|
171
|
-
NewRelic::Agent.logger.error('error processing response metadata: invalid/non-trusted ID')
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
nil
|
|
176
|
-
rescue => e
|
|
177
|
-
NewRelic::Agent.logger.error('error during process_response_metadata', e)
|
|
178
|
-
end
|
|
179
|
-
|
|
180
67
|
def record_metrics
|
|
181
68
|
add_unscoped_metrics
|
|
182
69
|
super
|
|
@@ -184,7 +71,6 @@ module NewRelic
|
|
|
184
71
|
|
|
185
72
|
def process_response_headers(response) # :nodoc:
|
|
186
73
|
set_http_status_code(response)
|
|
187
|
-
read_response_headers(response)
|
|
188
74
|
end
|
|
189
75
|
|
|
190
76
|
private
|
|
@@ -206,10 +92,6 @@ module NewRelic
|
|
|
206
92
|
|
|
207
93
|
def segment_complete
|
|
208
94
|
params[:uri] = uri.to_s
|
|
209
|
-
if cross_app_request?
|
|
210
|
-
params[:transaction_guid] = transaction_guid
|
|
211
|
-
end
|
|
212
|
-
|
|
213
95
|
super
|
|
214
96
|
end
|
|
215
97
|
|
|
@@ -223,10 +105,6 @@ module NewRelic
|
|
|
223
105
|
@unscoped_metrics = [EXTERNAL_ALL,
|
|
224
106
|
"External/#{host}/all",
|
|
225
107
|
suffixed_rollup_metric]
|
|
226
|
-
|
|
227
|
-
if cross_app_request?
|
|
228
|
-
@unscoped_metrics << "ExternalApp/#{host}/#{cross_process_id}/all"
|
|
229
|
-
end
|
|
230
108
|
end
|
|
231
109
|
|
|
232
110
|
def suffixed_rollup_metric
|
|
@@ -238,15 +116,7 @@ module NewRelic
|
|
|
238
116
|
end
|
|
239
117
|
|
|
240
118
|
def update_segment_name
|
|
241
|
-
|
|
242
|
-
@name = "ExternalTransaction/#{host}/#{cross_process_id}/#{cross_process_transaction_name}"
|
|
243
|
-
else
|
|
244
|
-
@name = "External/#{host}/#{library}/#{procedure}"
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
def obfuscator
|
|
249
|
-
CrossAppTracing.obfuscator
|
|
119
|
+
@name = "External/#{host}/#{library}/#{procedure}"
|
|
250
120
|
end
|
|
251
121
|
|
|
252
122
|
def record_span_event
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# frozen_string_literal: true
|
|
4
4
|
|
|
5
5
|
require 'new_relic/agent/transaction/segment'
|
|
6
|
-
require 'new_relic/agent/distributed_tracing/cross_app_tracing'
|
|
7
6
|
|
|
8
7
|
module NewRelic
|
|
9
8
|
module Agent
|
|
@@ -89,7 +88,6 @@ module NewRelic
|
|
|
89
88
|
def transaction_assigned
|
|
90
89
|
if headers && transaction && action == :produce && record_metrics?
|
|
91
90
|
transaction.distributed_tracer.insert_distributed_trace_header(headers)
|
|
92
|
-
transaction.distributed_tracer.insert_cat_headers(headers)
|
|
93
91
|
transaction.distributed_tracer.log_request_headers(headers)
|
|
94
92
|
end
|
|
95
93
|
rescue => e
|
|
@@ -154,32 +154,54 @@ module NewRelic
|
|
|
154
154
|
|
|
155
155
|
def determine_sampling_decision(payload, trace_flags)
|
|
156
156
|
if trace_flags == '01'
|
|
157
|
-
set_priority_and_sampled(
|
|
157
|
+
set_priority_and_sampled(
|
|
158
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled'],
|
|
159
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled.trace_id_ratio_based.ratio'],
|
|
160
|
+
payload,
|
|
161
|
+
trace_flags
|
|
162
|
+
)
|
|
158
163
|
elsif trace_flags == '00'
|
|
159
|
-
set_priority_and_sampled(
|
|
164
|
+
set_priority_and_sampled(
|
|
165
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled'],
|
|
166
|
+
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled.trace_id_ratio_based.ratio'],
|
|
167
|
+
payload,
|
|
168
|
+
trace_flags
|
|
169
|
+
)
|
|
160
170
|
else
|
|
161
|
-
use_nr_tracestate_sampled(payload)
|
|
171
|
+
use_nr_tracestate_sampled(payload, trace_flags)
|
|
162
172
|
end
|
|
163
173
|
rescue
|
|
164
|
-
use_nr_tracestate_sampled(payload)
|
|
174
|
+
use_nr_tracestate_sampled(payload, trace_flags)
|
|
165
175
|
end
|
|
166
176
|
|
|
167
|
-
def use_nr_tracestate_sampled(payload)
|
|
168
|
-
|
|
177
|
+
def use_nr_tracestate_sampled(payload, trace_flags)
|
|
178
|
+
if payload.sampled.nil?
|
|
179
|
+
if trace_flags == '01'
|
|
180
|
+
transaction.sampled = NewRelic::Agent.instance.adaptive_sampler_remote_parent_sampled.sampled?
|
|
181
|
+
elsif trace_flags == '00'
|
|
182
|
+
transaction.sampled = NewRelic::Agent.instance.adaptive_sampler_remote_parent_not_sampled.sampled?
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
transaction.priority = transaction.default_priority
|
|
186
|
+
else
|
|
169
187
|
transaction.sampled = payload.sampled
|
|
170
188
|
transaction.priority = payload.priority if payload.priority
|
|
171
189
|
end
|
|
172
190
|
end
|
|
173
191
|
|
|
174
|
-
def set_priority_and_sampled(
|
|
175
|
-
|
|
192
|
+
def set_priority_and_sampled(sampler, ratio, payload, trace_flags = nil)
|
|
193
|
+
case sampler
|
|
194
|
+
when 'adaptive'
|
|
195
|
+
use_nr_tracestate_sampled(payload, trace_flags)
|
|
196
|
+
when 'always_on'
|
|
176
197
|
transaction.sampled = true
|
|
177
198
|
transaction.priority = 2.0
|
|
178
|
-
|
|
199
|
+
when 'always_off'
|
|
179
200
|
transaction.sampled = false
|
|
180
201
|
transaction.priority = 0
|
|
181
|
-
|
|
182
|
-
|
|
202
|
+
when 'trace_id_ratio_based'
|
|
203
|
+
transaction.sampled = transaction.trace_ratio_sampled?(ratio)
|
|
204
|
+
transaction.priority = transaction.default_priority
|
|
183
205
|
end
|
|
184
206
|
end
|
|
185
207
|
|
|
@@ -211,7 +211,7 @@ module NewRelic
|
|
|
211
211
|
end
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
-
def initialize(category, options)
|
|
214
|
+
def initialize(category, options)
|
|
215
215
|
@nesting_max_depth = 0
|
|
216
216
|
@current_segment_by_thread = {}
|
|
217
217
|
@current_segment_lock = Mutex.new
|
|
@@ -294,11 +294,31 @@ module NewRelic
|
|
|
294
294
|
return false unless Agent.config[:'distributed_tracing.enabled']
|
|
295
295
|
|
|
296
296
|
if @sampled.nil?
|
|
297
|
-
@sampled = NewRelic::Agent.
|
|
297
|
+
@sampled = case NewRelic::Agent.config[:'distributed_tracing.sampler.root']
|
|
298
|
+
when 'adaptive'
|
|
299
|
+
NewRelic::Agent.instance.adaptive_sampler.sampled?
|
|
300
|
+
when 'always_on'
|
|
301
|
+
true
|
|
302
|
+
when 'always_off'
|
|
303
|
+
false
|
|
304
|
+
when 'trace_id_ratio_based'
|
|
305
|
+
trace_ratio_sampled?(NewRelic::Agent.config[:'distributed_tracing.sampler.root.trace_id_ratio_based.ratio'])
|
|
306
|
+
end
|
|
298
307
|
end
|
|
299
308
|
@sampled
|
|
300
309
|
end
|
|
301
310
|
|
|
311
|
+
def trace_ratio_sampled?(ratio)
|
|
312
|
+
# In the opentelemetry-sdk TraceIdRatioBased sampler, the algorithm
|
|
313
|
+
# looks like this:
|
|
314
|
+
# ratio == 1.0 || trace_id[8, 8].unpack1('Q>') < (ratio * (2**64 - 1)).ceil
|
|
315
|
+
# OTel stores their trace ids as binary strings
|
|
316
|
+
# ex. Array(trace_id).pack('H*')
|
|
317
|
+
# Since we don't store our trace ids as binary strings, this way is
|
|
318
|
+
# faster, but still gets the same result.
|
|
319
|
+
ratio == 1.0 || Integer(trace_id[16, 16], 16) < (ratio * (2**64 - 1)).ceil
|
|
320
|
+
end
|
|
321
|
+
|
|
302
322
|
def trace_id
|
|
303
323
|
@trace_id ||= NewRelic::Agent::GuidGenerator.generate_guid(32)
|
|
304
324
|
end
|
|
@@ -307,8 +327,19 @@ module NewRelic
|
|
|
307
327
|
@trace_id = value
|
|
308
328
|
end
|
|
309
329
|
|
|
330
|
+
def default_priority
|
|
331
|
+
(sampled? ? rand + 1.0 : rand).round(NewRelic::PRIORITY_PRECISION)
|
|
332
|
+
end
|
|
333
|
+
|
|
310
334
|
def priority
|
|
311
|
-
@priority ||=
|
|
335
|
+
@priority ||= case NewRelic::Agent.config[:'distributed_tracing.sampler.root']
|
|
336
|
+
when 'adaptive', 'trace_id_ratio_based'
|
|
337
|
+
default_priority
|
|
338
|
+
when 'always_on'
|
|
339
|
+
2.0
|
|
340
|
+
when 'always_off'
|
|
341
|
+
0
|
|
342
|
+
end
|
|
312
343
|
end
|
|
313
344
|
|
|
314
345
|
def referer
|
|
@@ -689,7 +720,7 @@ module NewRelic
|
|
|
689
720
|
end
|
|
690
721
|
|
|
691
722
|
def include_guid?
|
|
692
|
-
|
|
723
|
+
is_synthetics_request?
|
|
693
724
|
end
|
|
694
725
|
|
|
695
726
|
def is_synthetics_request?
|
|
@@ -26,8 +26,6 @@ module NewRelic
|
|
|
26
26
|
NAME_KEY = 'transactionName'
|
|
27
27
|
DURATION_KEY = 'duration'
|
|
28
28
|
SAMPLED_KEY = 'sampled'
|
|
29
|
-
CAT_GUID_KEY = 'nr.transactionGuid'
|
|
30
|
-
CAT_REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'
|
|
31
29
|
SYNTHETICS_RESOURCE_ID_KEY = 'nr.syntheticsResourceId'
|
|
32
30
|
SYNTHETICS_JOB_ID_KEY = 'nr.syntheticsJobId'
|
|
33
31
|
SYNTHETICS_MONITOR_ID_KEY = 'nr.syntheticsMonitorId'
|
|
@@ -69,7 +67,6 @@ module NewRelic
|
|
|
69
67
|
attrs[SAMPLED_KEY] = payload[:sampled] if payload.key?(:sampled)
|
|
70
68
|
attrs[PRIORITY_KEY] = payload[:priority]
|
|
71
69
|
append_synthetics(payload, attrs)
|
|
72
|
-
append_cat(payload, attrs)
|
|
73
70
|
DistributedTraceAttributes.copy_to_hash(payload, attrs)
|
|
74
71
|
PayloadMetricMapping.append_mapped_metrics(payload[:metrics], attrs)
|
|
75
72
|
else
|
|
@@ -95,11 +92,6 @@ module NewRelic
|
|
|
95
92
|
sample[new_key] = v
|
|
96
93
|
end
|
|
97
94
|
end
|
|
98
|
-
|
|
99
|
-
def append_cat(payload, sample)
|
|
100
|
-
sample[CAT_GUID_KEY] = payload[:guid] if payload[:guid]
|
|
101
|
-
sample[CAT_REFERRING_TRANSACTION_GUID_KEY] = payload[:referring_transaction_guid] if payload[:referring_transaction_guid]
|
|
102
|
-
end
|
|
103
95
|
end
|
|
104
96
|
end
|
|
105
97
|
end
|
|
@@ -30,10 +30,6 @@ module NewRelic
|
|
|
30
30
|
SAMPLED_KEY = 'sampled'
|
|
31
31
|
PRIORITY_KEY = 'priority'
|
|
32
32
|
GUID_KEY = 'nr.guid'
|
|
33
|
-
REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'
|
|
34
|
-
CAT_PATH_HASH_KEY = 'nr.pathHash'
|
|
35
|
-
CAT_REFERRING_PATH_HASH_KEY = 'nr.referringPathHash'
|
|
36
|
-
CAT_ALTERNATE_PATH_HASHES_KEY = 'nr.alternatePathHashes'
|
|
37
33
|
APDEX_PERF_ZONE_KEY = 'nr.apdexPerfZone'
|
|
38
34
|
SYNTHETICS_RESOURCE_ID_KEY = 'nr.syntheticsResourceId'
|
|
39
35
|
SYNTHETICS_JOB_ID_KEY = 'nr.syntheticsJobId'
|
|
@@ -69,9 +65,6 @@ module NewRelic
|
|
|
69
65
|
|
|
70
66
|
def append_optional_attributes(sample, payload)
|
|
71
67
|
optionally_append(GUID_KEY, :guid, sample, payload)
|
|
72
|
-
optionally_append(REFERRING_TRANSACTION_GUID_KEY, :referring_transaction_guid, sample, payload)
|
|
73
|
-
optionally_append(CAT_PATH_HASH_KEY, :cat_path_hash, sample, payload)
|
|
74
|
-
optionally_append(CAT_REFERRING_PATH_HASH_KEY, :cat_referring_path_hash, sample, payload)
|
|
75
68
|
optionally_append(APDEX_PERF_ZONE_KEY, :apdex_perf_zone, sample, payload)
|
|
76
69
|
optionally_append(SYNTHETICS_RESOURCE_ID_KEY, :synthetics_resource_id, sample, payload)
|
|
77
70
|
optionally_append(SYNTHETICS_JOB_ID_KEY, :synthetics_job_id, sample, payload)
|
|
@@ -79,7 +72,6 @@ module NewRelic
|
|
|
79
72
|
optionally_append(SYNTHETICS_TYPE_KEY, :synthetics_type, sample, payload)
|
|
80
73
|
optionally_append(SYNTHETICS_INITIATOR_KEY, :synthetics_initiator, sample, payload)
|
|
81
74
|
append_synthetics_info_attributes(sample, payload)
|
|
82
|
-
append_cat_alternate_path_hashes(sample, payload)
|
|
83
75
|
end
|
|
84
76
|
|
|
85
77
|
def append_synthetics_info_attributes(sample, payload)
|
|
@@ -93,12 +85,6 @@ module NewRelic
|
|
|
93
85
|
end
|
|
94
86
|
end
|
|
95
87
|
|
|
96
|
-
def append_cat_alternate_path_hashes(sample, payload)
|
|
97
|
-
if payload.include?(:cat_alternate_path_hashes)
|
|
98
|
-
sample[CAT_ALTERNATE_PATH_HASHES_KEY] = payload[:cat_alternate_path_hashes].sort.join(COMMA)
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
88
|
def optionally_append(sample_key, payload_key, sample, payload)
|
|
103
89
|
if payload.include?(payload_key)
|
|
104
90
|
sample[sample_key] = string(payload[payload_key])
|