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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +136 -0
  3. data/README.md +0 -7
  4. data/lib/new_relic/agent/agent.rb +9 -4
  5. data/lib/new_relic/agent/configuration/default_source.rb +103 -181
  6. data/lib/new_relic/agent/configuration/environment_source.rb +7 -38
  7. data/lib/new_relic/agent/configuration/manager.rb +141 -59
  8. data/lib/new_relic/agent/configuration/sampler_config_validator.rb +54 -0
  9. data/lib/new_relic/agent/configuration/server_source.rb +0 -1
  10. data/lib/new_relic/agent/connect/response_handler.rb +0 -11
  11. data/lib/new_relic/agent/datastores.rb +13 -17
  12. data/lib/new_relic/agent/distributed_tracing.rb +0 -3
  13. data/lib/new_relic/agent/health_check.rb +1 -0
  14. data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
  15. data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +2 -1
  16. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -4
  17. data/lib/new_relic/agent/instrumentation/active_support.rb +8 -1
  18. data/lib/new_relic/agent/instrumentation/active_support_subscriber.rb +22 -14
  19. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +1 -4
  20. data/lib/new_relic/agent/instrumentation/bunny.rb +0 -1
  21. data/lib/new_relic/agent/instrumentation/curb/chain.rb +2 -2
  22. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +2 -3
  23. data/lib/new_relic/agent/instrumentation/curb.rb +0 -1
  24. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +1 -1
  25. data/lib/new_relic/agent/instrumentation/excon.rb +2 -3
  26. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +1 -2
  27. data/lib/new_relic/agent/instrumentation/httpclient.rb +0 -1
  28. data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
  29. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +0 -2
  30. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +0 -2
  31. data/lib/new_relic/agent/instrumentation/rack/helpers.rb +1 -3
  32. data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
  33. data/lib/new_relic/agent/llm/chat_completion_summary.rb +1 -8
  34. data/lib/new_relic/agent/llm/embedding.rb +1 -8
  35. data/lib/new_relic/agent/messaging.rb +12 -5
  36. data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -2
  37. data/lib/new_relic/agent/monitors/synthetics_monitor.rb +2 -1
  38. data/lib/new_relic/agent/monitors.rb +0 -3
  39. data/lib/new_relic/agent/new_relic_service/encoders.rb +0 -14
  40. data/lib/new_relic/agent/new_relic_service.rb +11 -49
  41. data/lib/new_relic/agent/opentelemetry/trace/span.rb +41 -0
  42. data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +16 -7
  43. data/lib/new_relic/agent/opentelemetry_bridge.rb +9 -5
  44. data/lib/new_relic/agent/serverless_handler.rb +2 -2
  45. data/lib/new_relic/agent/span_event_primitive.rb +1 -1
  46. data/lib/new_relic/agent/sql_sampler.rb +0 -31
  47. data/lib/new_relic/agent/stats_engine.rb +1 -0
  48. data/lib/new_relic/agent/transaction/distributed_tracer.rb +12 -56
  49. data/lib/new_relic/agent/transaction/distributed_tracing.rb +11 -19
  50. data/lib/new_relic/agent/transaction/external_request_segment.rb +1 -131
  51. data/lib/new_relic/agent/transaction/message_broker_segment.rb +0 -2
  52. data/lib/new_relic/agent/transaction/trace_context.rb +33 -11
  53. data/lib/new_relic/agent/transaction.rb +35 -4
  54. data/lib/new_relic/agent/transaction_error_primitive.rb +0 -8
  55. data/lib/new_relic/agent/transaction_event_primitive.rb +0 -14
  56. data/lib/new_relic/agent/utilization/gcp.rb +2 -0
  57. data/lib/new_relic/agent.rb +11 -3
  58. data/lib/new_relic/cli/command.rb +2 -11
  59. data/lib/new_relic/control/instance_methods.rb +2 -15
  60. data/lib/new_relic/control/private_instance_methods.rb +2 -4
  61. data/lib/new_relic/control/server_methods.rb +0 -6
  62. data/lib/new_relic/helper.rb +21 -2
  63. data/lib/new_relic/language_support.rb +3 -34
  64. data/lib/new_relic/supportability_helper.rb +0 -4
  65. data/lib/new_relic/version.rb +2 -2
  66. data/lib/tasks/helpers/newrelicyml.rb +2 -2
  67. data/lib/tasks/helpers/version_bump.rb +1 -2
  68. data/newrelic.yml +25 -28
  69. data/newrelic_rpm.gemspec +10 -9
  70. metadata +27 -26
  71. data/bin/newrelic +0 -8
  72. data/lib/new_relic/agent/configuration/security_policy_source.rb +0 -246
  73. data/lib/new_relic/agent/distributed_tracing/cross_app_payload.rb +0 -44
  74. data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +0 -253
  75. data/lib/new_relic/agent/external.rb +0 -112
  76. data/lib/new_relic/agent/monitors/cross_app_monitor.rb +0 -117
  77. data/lib/new_relic/agent/new_relic_service/security_policy_settings.rb +0 -61
  78. data/lib/new_relic/cli/commands/deployments.rb +0 -206
  79. data/lib/new_relic/recipes/capistrano3.rb +0 -23
  80. data/lib/new_relic/recipes/capistrano_legacy.rb +0 -95
  81. data/lib/new_relic/recipes/helpers/send_deployment.rb +0 -70
  82. data/lib/new_relic/recipes.rb +0 -24
  83. data/recipes/newrelic.rb +0 -10
@@ -1,246 +0,0 @@
1
- # This file is distributed under New Relic's license terms.
2
- # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
- # frozen_string_literal: true
4
-
5
- require 'new_relic/agent/configuration/dotted_hash'
6
-
7
- module NewRelic
8
- module Agent
9
- module Configuration
10
- # The Language Security Policy Source gives customers the ability to
11
- # configure high security mode settings.
12
- class SecurityPolicySource < DottedHash
13
- class << self
14
- def enabled?(option)
15
- Agent.config[option]
16
- end
17
-
18
- def record_sql_enabled?(option)
19
- Agent.config[option] == 'obfuscated' ||
20
- Agent.config[option] == 'raw' ||
21
- false
22
- end
23
-
24
- def not_empty?(option)
25
- !Agent.config[option].empty?
26
- end
27
-
28
- def change_setting(policies, option, new_value)
29
- current_value = Agent.config[option]
30
- unless current_value == new_value
31
- NewRelic::Agent.logger.info( \
32
- "Setting changed: {#{option}: from #{current_value} " \
33
- "to #{new_value}}. Source: SecurityPolicySource"
34
- )
35
- end
36
- policies[option] = new_value
37
- end
38
- end
39
-
40
- # The keys of the security settings map are the names of security
41
- # policies received from the server. They map to multiple configuration
42
- # options in the local config. There is a hash of metadata that
43
- # corresponds to each configuration option with the following keys:
44
- #
45
- # option: the configuration option name
46
- # supported: true if the agent has one or more corresponding
47
- # configuration options
48
- # enabled_fn: a callable that takes the configuration option and returns
49
- # true if the option is enabled, false otherwise
50
- # disabled_value: the value of the configuration option when it is
51
- # disabled
52
- # permitted_fn: a callable, that will be executed if an option is
53
- # permitted by the security policy and is also enabled by the config
54
-
55
- SECURITY_SETTINGS_MAP = {
56
- 'record_sql' => [
57
- {
58
- option: :'transaction_tracer.record_sql',
59
- supported: true,
60
- enabled_fn: method(:record_sql_enabled?),
61
- disabled_value: 'off',
62
- permitted_fn: proc { |policies|
63
- change_setting(policies, :'transaction_tracer.record_sql', 'obfuscated')
64
- }
65
- },
66
- {
67
- option: :'slow_sql.record_sql',
68
- supported: true,
69
- enabled_fn: method(:record_sql_enabled?),
70
- disabled_value: 'off',
71
- permitted_fn: proc { |policies|
72
- change_setting(policies, :'slow_sql.record_sql', 'obfuscated')
73
- }
74
- },
75
- {
76
- option: :'mongo.capture_queries',
77
- supported: true,
78
- enabled_fn: method(:enabled?),
79
- disabled_value: false,
80
- permitted_fn: proc { |policies|
81
- change_setting(policies, :'mongo.obfuscate_queries', true)
82
- }
83
- },
84
- {
85
- option: :'elasticsearch.capture_queries',
86
- supported: true,
87
- enabled_fn: method(:enabled?),
88
- disabled_value: false,
89
- permitted_fn: proc { |policies|
90
- change_setting(policies, :'elasticsearch.obfuscate_queries', true)
91
- }
92
- },
93
- {
94
- option: :'transaction_tracer.record_redis_arguments',
95
- supported: true,
96
- enabled_fn: method(:enabled?),
97
- disabled_value: false,
98
- permitted_fn: nil
99
- }
100
- ],
101
- 'attributes_include' => [
102
- {
103
- option: :'attributes.include',
104
- supported: true,
105
- enabled_fn: method(:not_empty?),
106
- disabled_value: [],
107
- permitted_fn: nil
108
- },
109
- {
110
- option: :'transaction_tracer.attributes.include',
111
- supported: true,
112
- enabled_fn: method(:not_empty?),
113
- disabled_value: [],
114
- permitted_fn: nil
115
- },
116
- {
117
- option: :'transaction_events.attributes.include',
118
- supported: true,
119
- enabled_fn: method(:not_empty?),
120
- disabled_value: [],
121
- permitted_fn: nil
122
- },
123
- {
124
- option: :'error_collector.attributes.include',
125
- supported: true,
126
- enabled_fn: method(:not_empty?),
127
- disabled_value: [],
128
- permitted_fn: nil
129
- },
130
- {
131
- option: :'browser_monitoring.attributes.include',
132
- supported: true,
133
- enabled_fn: method(:not_empty?),
134
- disabled_value: [],
135
- permitted_fn: nil
136
- },
137
- {
138
- option: :'span_events.attributes.include',
139
- supported: true,
140
- enabled_fn: method(:not_empty?),
141
- disabled_value: [],
142
- permitted_fn: nil
143
- },
144
- {
145
- option: :'transaction_segments.attributes.include',
146
- supported: true,
147
- enabled_fn: method(:not_empty?),
148
- disabled_value: [],
149
- permitted_fn: nil
150
- }
151
- ],
152
- 'ai_monitoring' => [
153
- {
154
- option: :'ai_monitoring.enabled',
155
- supported: true,
156
- enabled_fn: method(:enabled?),
157
- disabled_value: false,
158
- permitted_fn: nil
159
- }
160
- ],
161
- 'allow_raw_exception_messages' => [
162
- {
163
- option: :'strip_exception_messages.enabled',
164
- supported: true,
165
- enabled_fn: method(:enabled?),
166
- disabled_value: false,
167
- permitted_fn: nil
168
- }
169
- ],
170
- 'custom_events' => [
171
- {
172
- option: :'custom_insights_events.enabled',
173
- supported: true,
174
- enabled_fn: method(:enabled?),
175
- disabled_value: false,
176
- permitted_fn: nil
177
- }
178
- ],
179
- 'custom_parameters' => [
180
- {
181
- option: :'custom_attributes.enabled',
182
- supported: true,
183
- enabled_fn: method(:enabled?),
184
- disabled_value: false,
185
- permitted_fn: nil
186
- }
187
- ],
188
- 'custom_instrumentation_editor' => [
189
- {
190
- option: nil,
191
- supported: false,
192
- enabled_fn: nil,
193
- disabled_value: nil,
194
- permitted_fn: nil
195
- }
196
- ],
197
- 'message_parameters' => [
198
- {
199
- option: :'message_tracer.segment_parameters.enabled',
200
- supported: true,
201
- enabled_fn: method(:enabled?),
202
- disabled_value: false,
203
- permitted_fn: nil
204
- }
205
- ]
206
- }
207
-
208
- def initialize(security_policies)
209
- super(build_overrides(security_policies))
210
- end
211
-
212
- ENABLED = 'enabled'.freeze
213
- COLON_COLON = '::'.freeze
214
-
215
- def build_overrides(security_policies)
216
- security_policies.inject({}) do |settings, (policy_name, policy_settings)|
217
- SECURITY_SETTINGS_MAP[policy_name].each do |policy|
218
- next unless policy[:supported]
219
-
220
- if policy_settings[ENABLED]
221
- if policy[:enabled_fn].call(policy[:option])
222
- if permitted_fn = policy[:permitted_fn]
223
- permitted_fn.call(settings)
224
- end
225
- else
226
- config_source = Agent.config.source(policy[:option]).class.name.split(COLON_COLON).last
227
- NewRelic::Agent.logger.info( \
228
- "Setting applied: {#{policy[:option]}: #{policy[:disabled_value]}}. " \
229
- "Source: #{config_source}"
230
- )
231
- end
232
- else
233
- settings[policy[:option]] = policy[:disabled_value]
234
- NewRelic::Agent.logger.info( \
235
- "Setting applied: {#{policy[:option]}: #{policy[:disabled_value]}}. " \
236
- 'Source: SecurityPolicySource'
237
- )
238
- end
239
- end
240
- settings
241
- end
242
- end
243
- end
244
- end
245
- end
246
- end
@@ -1,44 +0,0 @@
1
- # This file is distributed under New Relic's license terms.
2
- # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
- # frozen_string_literal: true
4
-
5
- module NewRelic
6
- module Agent
7
- class CrossAppPayload
8
- attr_reader :id, :transaction, :referring_guid, :referring_trip_id, :referring_path_hash
9
-
10
- def initialize(id, transaction, transaction_info)
11
- @id = id
12
- @transaction = transaction
13
-
14
- transaction_info ||= []
15
- @referring_guid = transaction_info[0]
16
- # unused_flag = transaction_info[1]
17
- @referring_trip_id = string_or_false_for(transaction_info[2])
18
- @referring_path_hash = string_or_false_for(transaction_info[3])
19
- end
20
-
21
- def as_json_array(content_length)
22
- queue_time_in_seconds = [transaction.queue_time, 0.0].max
23
- start_time_in_seconds = [transaction.start_time, 0.0].max
24
- app_time_in_seconds = Process.clock_gettime(Process::CLOCK_REALTIME) - start_time_in_seconds
25
-
26
- [
27
- NewRelic::Agent.config[:cross_process_id],
28
- transaction.best_name,
29
- queue_time_in_seconds,
30
- app_time_in_seconds,
31
- content_length,
32
- transaction.guid,
33
- false
34
- ]
35
- end
36
-
37
- private
38
-
39
- def string_or_false_for(value)
40
- value.is_a?(String) && value
41
- end
42
- end
43
- end
44
- end
@@ -1,253 +0,0 @@
1
- # This file is distributed under New Relic's license terms.
2
- # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
- # frozen_string_literal: true
4
-
5
- require 'json'
6
-
7
- module NewRelic
8
- module Agent
9
- module CrossAppTracing
10
- # The cross app response header for "outgoing" calls
11
- NR_APPDATA_HEADER = 'X-NewRelic-App-Data'
12
-
13
- # The cross app id header for "outgoing" calls
14
- NR_ID_HEADER = 'X-NewRelic-ID'
15
-
16
- # The cross app transaction header for "outgoing" calls
17
- NR_TXN_HEADER = 'X-NewRelic-Transaction'
18
-
19
- NR_MESSAGE_BROKER_ID_HEADER = 'NewRelicID'
20
- NR_MESSAGE_BROKER_TXN_HEADER = 'NewRelicTransaction'
21
- NR_MESSAGE_BROKER_SYNTHETICS_HEADER = 'NewRelicSynthetics'
22
-
23
- attr_accessor :is_cross_app_caller, :cross_app_payload, :cat_path_hashes
24
-
25
- def is_cross_app_caller?
26
- @is_cross_app_caller ||= false
27
- end
28
-
29
- def is_cross_app_callee?
30
- !cross_app_payload.nil?
31
- end
32
-
33
- def is_cross_app?
34
- is_cross_app_caller? || is_cross_app_callee?
35
- end
36
-
37
- def cat_trip_id
38
- cross_app_payload&.referring_trip_id || transaction.guid
39
- end
40
-
41
- def cross_app_monitor
42
- NewRelic::Agent.instance.monitors.cross_app_monitor
43
- end
44
-
45
- def cat_path_hash
46
- referring_path_hash = cat_referring_path_hash || '0'
47
- seed = referring_path_hash.to_i(16)
48
- result = cross_app_monitor.path_hash(transaction.best_name, seed)
49
- record_cat_path_hash(result)
50
- result
51
- end
52
-
53
- def insert_cross_app_header(headers)
54
- return unless CrossAppTracing.cross_app_enabled?
55
-
56
- @is_cross_app_caller = true
57
- txn_guid = transaction.guid
58
- trip_id = cat_trip_id
59
- path_hash = cat_path_hash
60
-
61
- insert_request_headers(headers, txn_guid, trip_id, path_hash)
62
- end
63
-
64
- def add_message_cat_headers(headers)
65
- return unless CrossAppTracing.cross_app_enabled?
66
-
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&.id)
77
- app_time_in_seconds = [
78
- Process.clock_gettime(Process::CLOCK_REALTIME) - transaction.start_time,
79
- 0.0
80
- ].max
81
- NewRelic::Agent.record_metric("ClientApplication/#{id}/all", app_time_in_seconds)
82
- end
83
- end
84
-
85
- def assign_cross_app_intrinsics
86
- transaction.attributes.add_intrinsic_attribute(:trip_id, cat_trip_id)
87
- transaction.attributes.add_intrinsic_attribute(:path_hash, cat_path_hash)
88
- end
89
-
90
- private
91
-
92
- def insert_message_headers(headers, txn_guid, trip_id, path_hash, synthetics_header)
93
- headers[NR_MESSAGE_BROKER_ID_HEADER] = obfuscator.obfuscate(Agent.config[:cross_process_id])
94
- headers[NR_MESSAGE_BROKER_TXN_HEADER] = obfuscator.obfuscate(::JSON.dump([txn_guid, false, trip_id, path_hash]))
95
- headers[NR_MESSAGE_BROKER_SYNTHETICS_HEADER] = synthetics_header if synthetics_header
96
- end
97
-
98
- def record_cat_path_hash(hash)
99
- @cat_path_hashes ||= []
100
- if @cat_path_hashes.size < 10 && !@cat_path_hashes.include?(hash)
101
- @cat_path_hashes << hash
102
- end
103
- end
104
-
105
- def cat_referring_path_hash
106
- cross_app_payload&.referring_path_hash
107
- end
108
-
109
- def append_cat_info(payload)
110
- if (referring_guid = cross_app_payload&.referring_guid)
111
- payload[:referring_transaction_guid] = referring_guid
112
- end
113
-
114
- return unless transaction.include_guid?
115
-
116
- payload[:guid] = transaction.guid
117
-
118
- return unless is_cross_app?
119
-
120
- trip_id = cat_trip_id
121
- path_hash = cat_path_hash
122
- referring_path_hash = cat_referring_path_hash
123
-
124
- payload[:cat_trip_id] = trip_id if trip_id
125
- payload[:cat_referring_path_hash] = referring_path_hash if referring_path_hash
126
-
127
- if path_hash
128
- payload[:cat_path_hash] = path_hash
129
-
130
- alternate_path_hashes = cat_path_hashes - [path_hash]
131
- unless alternate_path_hashes.empty?
132
- payload[:cat_alternate_path_hashes] = alternate_path_hashes
133
- end
134
- end
135
- end
136
-
137
- ###############
138
- module_function
139
-
140
- ###############
141
-
142
- def cross_app_enabled?
143
- valid_cross_process_id? &&
144
- valid_encoding_key? &&
145
- cross_application_tracer_enabled?
146
- end
147
-
148
- def valid_cross_process_id?
149
- if Agent.config[:cross_process_id] && Agent.config[:cross_process_id].length > 0
150
- true
151
- else
152
- NewRelic::Agent.logger.debug('No cross_process_id configured')
153
- false
154
- end
155
- end
156
-
157
- def valid_encoding_key?
158
- if Agent.config[:encoding_key] && Agent.config[:encoding_key].length > 0
159
- true
160
- else
161
- NewRelic::Agent.logger.debug('No encoding_key set')
162
- false
163
- end
164
- end
165
-
166
- def cross_application_tracer_enabled?
167
- !NewRelic::Agent.config[:"distributed_tracing.enabled"] &&
168
- NewRelic::Agent.config[:"cross_application_tracer.enabled"]
169
- end
170
-
171
- def obfuscator
172
- @obfuscator ||= NewRelic::Agent::Obfuscator.new(Agent.config[:encoding_key])
173
- end
174
-
175
- def insert_request_headers(request, txn_guid, trip_id, path_hash)
176
- cross_app_id = NewRelic::Agent.config[:cross_process_id]
177
- txn_data = ::JSON.dump([txn_guid, false, trip_id, path_hash])
178
-
179
- request[NR_ID_HEADER] = obfuscator.obfuscate(cross_app_id)
180
- request[NR_TXN_HEADER] = obfuscator.obfuscate(txn_data)
181
- end
182
-
183
- def response_has_crossapp_header?(response)
184
- if !!response[NR_APPDATA_HEADER]
185
- true
186
- else
187
- NewRelic::Agent.logger.debug("No #{NR_APPDATA_HEADER} header")
188
- false
189
- end
190
- end
191
-
192
- # Extract x-process application data from the specified +response+ and return
193
- # it as an array of the form:
194
- #
195
- # [
196
- # <cross app ID>,
197
- # <transaction name>,
198
- # <queue time in seconds>,
199
- # <response time in seconds>,
200
- # <request content length in bytes>,
201
- # <transaction GUID>
202
- # ]
203
- def extract_appdata(response)
204
- appdata = response[NR_APPDATA_HEADER]
205
-
206
- decoded_appdata = obfuscator.deobfuscate(appdata)
207
- decoded_appdata.set_encoding(::Encoding::UTF_8) if
208
- decoded_appdata.respond_to?(:set_encoding)
209
-
210
- ::JSON.parse(decoded_appdata)
211
- end
212
-
213
- def valid_cross_app_id?(xp_id)
214
- !!(xp_id =~ /\A\d+#\d+\z/)
215
- end
216
-
217
- def message_has_crossapp_request_header?(headers)
218
- !!headers[NR_MESSAGE_BROKER_ID_HEADER]
219
- end
220
-
221
- def reject_messaging_cat_headers(headers)
222
- headers.reject { |k, _| k == NR_MESSAGE_BROKER_ID_HEADER || k == NR_MESSAGE_BROKER_TXN_HEADER }
223
- end
224
-
225
- def trusts?(id)
226
- split_id = id.match(/(\d+)#\d+/)
227
- return false if split_id.nil?
228
-
229
- NewRelic::Agent.config[:trusted_account_ids].include?(split_id.captures.first.to_i)
230
- end
231
-
232
- def trusted_valid_cross_app_id?(id)
233
- valid_cross_app_id?(id) && trusts?(id)
234
- end
235
-
236
- # From inbound request headers
237
- def assign_intrinsic_transaction_attributes(state)
238
- # We expect to get the before call to set the id (if we have it) before
239
- # this, and then write our custom parameter when the transaction starts
240
- return unless (txn = state.current_transaction)
241
- return unless (payload = txn.distributed_tracer.cross_app_payload)
242
-
243
- if (cross_app_id = payload.id)
244
- txn.attributes.add_intrinsic_attribute(:client_cross_process_id, cross_app_id)
245
- end
246
-
247
- if (referring_guid = payload.referring_guid)
248
- txn.attributes.add_intrinsic_attribute(:referring_transaction_guid, referring_guid)
249
- end
250
- end
251
- end
252
- end
253
- end
@@ -1,112 +0,0 @@
1
- # This file is distributed under New Relic's license terms.
2
- # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
- # frozen_string_literal: true
4
-
5
- require 'new_relic/agent/transaction/tracing'
6
- require 'new_relic/agent/distributed_tracing/cross_app_tracing'
7
- require 'new_relic/agent/distributed_tracing/cross_app_payload'
8
-
9
- module NewRelic
10
- module Agent
11
- #
12
- # This module contains helper methods to facilitate
13
- # instrumentation of external requests not directly supported by
14
- # the Ruby agent. It is intended to be primarily used by authors
15
- # of 3rd-party instrumentation.
16
- #
17
- # @api public
18
- module External
19
- extend self
20
-
21
- NON_HTTP_CAT_ID_HEADER = 'NewRelicID'.freeze
22
- NON_HTTP_CAT_TXN_HEADER = 'NewRelicTransaction'.freeze
23
- NON_HTTP_CAT_SYNTHETICS_HEADER = 'NewRelicSynthetics'.freeze
24
- NON_HTTP_CAT_CONTENT_LENGTH = -1
25
-
26
- # Process obfuscated +String+ identifying a calling application and transaction that is also running a
27
- # New Relic agent and save information in current transaction for inclusion in a trace. The +String+ is
28
- # generated by +get_request_metadata+ on the calling application.
29
- #
30
- # @param request_metadata [String] received obfuscated request metadata
31
- #
32
- # @!scope class
33
- # @api public
34
- #
35
- def process_request_metadata(request_metadata)
36
- NewRelic::Agent.record_api_supportability_metric(:process_request_metadata)
37
- return unless CrossAppTracing.cross_app_enabled?
38
-
39
- state = NewRelic::Agent::Tracer.state
40
- if transaction = state.current_transaction
41
- rmd = ::JSON.parse(obfuscator.deobfuscate(request_metadata))
42
-
43
- # handle/check ID
44
- #
45
- if id = rmd[NON_HTTP_CAT_ID_HEADER] and CrossAppTracing.trusted_valid_cross_app_id?(id)
46
- # handle transaction info
47
- #
48
- if txn_info = rmd[NON_HTTP_CAT_TXN_HEADER]
49
- payload = CrossAppPayload.new(id, transaction, txn_info)
50
- transaction.distributed_tracer.cross_app_payload = payload
51
-
52
- CrossAppTracing.assign_intrinsic_transaction_attributes(state)
53
- end
54
-
55
- # handle synthetics
56
- #
57
- if synth = rmd[NON_HTTP_CAT_SYNTHETICS_HEADER]
58
- transaction.synthetics_payload = synth
59
- transaction.raw_synthetics_header = obfuscator.obfuscate(::JSON.dump(synth))
60
- end
61
-
62
- else
63
- NewRelic::Agent.logger.error("error processing request metadata: invalid/non-trusted ID: '#{id}'")
64
- end
65
-
66
- nil
67
- end
68
- rescue => e
69
- NewRelic::Agent.logger.error('error during process_request_metadata', e)
70
- end
71
-
72
- # Obtain an obfuscated +String+ suitable for delivery across public networks that carries transaction
73
- # information from this application to a calling application which is also running a New Relic agent.
74
- # This +String+ can be processed by +process_response_metadata+ on the calling application.
75
- #
76
- # @return [String] obfuscated response metadata to send
77
- #
78
- # @!scope class
79
- # @api public
80
- #
81
- def get_response_metadata
82
- NewRelic::Agent.record_api_supportability_metric(:get_response_metadata)
83
- return unless CrossAppTracing.cross_app_enabled?
84
-
85
- return unless (txn = Tracer.current_transaction)
86
- return unless (payload = txn.distributed_tracer.cross_app_payload)
87
-
88
- # must freeze the name since we're responding with it
89
- #
90
- txn.freeze_name_and_execute_if_not_ignored do
91
- # build response payload
92
- #
93
- rmd = {
94
- NewRelicAppData: payload.as_json_array(NON_HTTP_CAT_CONTENT_LENGTH)
95
- }
96
-
97
- # obfuscate the generated response metadata JSON
98
- #
99
- obfuscator.obfuscate(::JSON.dump(rmd))
100
- end
101
- rescue => e
102
- NewRelic::Agent.logger.error('error during get_response_metadata', e)
103
- end
104
-
105
- private
106
-
107
- def obfuscator
108
- CrossAppTracing.obfuscator
109
- end
110
- end
111
- end
112
- end