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
@@ -13,17 +13,15 @@ module NewRelic
13
13
  /^NEW_RELIC_METADATA_/ # read by NewRelic::Agent::Connect::RequestBuilder
14
14
  ]
15
15
 
16
- attr_accessor :alias_map, :type_map
16
+ attr_accessor :alias_map
17
17
 
18
18
  def initialize
19
19
  set_log_file
20
20
  set_config_file
21
21
 
22
22
  @alias_map = {}
23
- @type_map = {}
24
23
 
25
24
  DEFAULTS.each do |config_setting, value|
26
- self.type_map[config_setting] = value[:type]
27
25
  set_aliases(config_setting, value)
28
26
  end
29
27
 
@@ -70,43 +68,14 @@ module NewRelic
70
68
  nr_env_var_keys.each do |key|
71
69
  next if SPECIAL_CASE_KEYS.any? { |pattern| pattern === key.upcase }
72
70
 
73
- set_value_from_environment_variable(key)
74
- end
75
- end
76
-
77
- def set_value_from_environment_variable(key)
78
- config_key = convert_environment_key_to_config_key(key)
79
- set_key_by_type(config_key, key)
80
- end
71
+ config_key = convert_environment_key_to_config_key(key)
81
72
 
82
- def set_key_by_type(config_key, environment_key)
83
- value = ENV[environment_key]
84
- type = self.type_map[config_key]
85
-
86
- if type == String
87
- self[config_key] = value
88
- elsif type == Integer
89
- self[config_key] = value.to_i
90
- elsif type == Float
91
- self[config_key] = value.to_f
92
- elsif type == Symbol
93
- self[config_key] = value.to_sym
94
- elsif type == Array
95
- self[config_key] = if DEFAULTS[config_key].key?(:transform)
96
- DEFAULTS[config_key][:transform].call(value)
97
- else
98
- value.split(/\s*,\s*/)
99
- end
100
- elsif type == NewRelic::Agent::Configuration::Boolean
101
- if /false|off|no/i.match?(value)
102
- self[config_key] = false
103
- elsif !value.nil?
104
- self[config_key] = true
73
+ unless DEFAULTS.key?(config_key) || serverless?
74
+ ::NewRelic::Agent.logger.info("#{key} does not have a corresponding configuration setting (#{config_key} does not exist).")
75
+ ::NewRelic::Agent.logger.info('Run `rake newrelic:config:docs` or visit https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration to see a list of available configuration settings.')
105
76
  end
106
- elsif !serverless?
107
- ::NewRelic::Agent.logger.info("#{environment_key} does not have a corresponding configuration setting (#{config_key} does not exist).")
108
- ::NewRelic::Agent.logger.info('Run `rake newrelic:config:docs` or visit https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration to see a list of available configuration settings.')
109
- self[config_key] = value
77
+
78
+ self[config_key] = ENV[key]
110
79
  end
111
80
  end
112
81
 
@@ -9,7 +9,6 @@ require 'new_relic/agent/configuration/default_source'
9
9
  require 'new_relic/agent/configuration/server_source'
10
10
  require 'new_relic/agent/configuration/environment_source'
11
11
  require 'new_relic/agent/configuration/high_security_source'
12
- require 'new_relic/agent/configuration/security_policy_source'
13
12
 
14
13
  module NewRelic
15
14
  module Agent
@@ -17,6 +16,28 @@ module NewRelic
17
16
  class Manager
18
17
  DEPENDENCY_DETECTION_VALUES = %i[prepend chain unsatisfied].freeze
19
18
 
19
+ BOOLEAN_MAP = {
20
+ 'true' => true,
21
+ 'yes' => true,
22
+ 'on' => true,
23
+ 'false' => false,
24
+ 'no' => false,
25
+ 'off' => false
26
+ }.freeze
27
+
28
+ INSTRUMENTATION_VALUES = %w[chain prepend unsatisfied]
29
+ NUMERIC_TYPES = [Integer, Float]
30
+ STRINGLIKE_TYPES = [String, Symbol]
31
+
32
+ TYPE_COERCIONS = {Integer => {pattern: /^\d+$/, proc: proc { |s| s.to_i }},
33
+ Float => {pattern: /^\d+\.\d+$/, proc: proc { |s| s.to_f }},
34
+ Array => {proc: proc { |s| s.split(/\s*,\s*/) }},
35
+ Hash => {proc: proc { |s| s.split(/\s*,\s*/).each_with_object({}) { |i, h| k, v = i.split(/\s*=\s*/); h[k] = v } }},
36
+ NewRelic::Agent::Configuration::Boolean => {pattern: /^(?:#{BOOLEAN_MAP.keys.join('|')})$/,
37
+ proc: proc { |s| BOOLEAN_MAP[s] }}}.freeze
38
+
39
+ USER_CONFIG_CLASSES = [NewRelic::Agent::Configuration::EnvironmentSource, NewRelic::Agent::Configuration::YamlSource]
40
+
20
41
  # Defining these explicitly saves object allocations that we incur
21
42
  # if we use Forwardable and def_delegators.
22
43
  def [](key)
@@ -48,7 +69,6 @@ module NewRelic
48
69
 
49
70
  def remove_config_type(sym)
50
71
  source = case sym
51
- when :security_policy then @security_policy_source
52
72
  when :high_security then @high_security_source
53
73
  when :environment then @environment_source
54
74
  when :server then @server_source
@@ -62,7 +82,6 @@ module NewRelic
62
82
 
63
83
  def remove_config(source)
64
84
  case source
65
- when SecurityPolicySource then @security_policy_source = nil
66
85
  when HighSecuritySource then @high_security_source = nil
67
86
  when EnvironmentSource then @environment_source = nil
68
87
  when ServerSource then @server_source = nil
@@ -85,7 +104,6 @@ module NewRelic
85
104
  invoke_callbacks(:add, source)
86
105
 
87
106
  case source
88
- when SecurityPolicySource then @security_policy_source = source
89
107
  when HighSecuritySource then @high_security_source = source
90
108
  when EnvironmentSource then @environment_source = source
91
109
  when ServerSource then @server_source = source
@@ -116,74 +134,139 @@ module NewRelic
116
134
  next unless config
117
135
 
118
136
  accessor = key.to_sym
137
+ next unless config.has_key?(accessor)
119
138
 
120
- if config.has_key?(accessor)
121
- begin
122
- return evaluate_and_apply_transformations(accessor, config[accessor])
123
- rescue
124
- next
125
- end
139
+ begin
140
+ return evaluate_and_apply_transformations(accessor, config[accessor], config_category(config.class))
141
+ rescue
142
+ next
126
143
  end
127
144
  end
128
145
 
129
146
  nil
130
147
  end
131
148
 
132
- def evaluate_procs(value)
133
- if value.respond_to?(:call)
134
- instance_eval(&value)
135
- else
136
- value
137
- end
138
- end
149
+ def config_category(klass)
150
+ return :user if USER_CONFIG_CLASSES.include?(klass)
151
+ return :test if [DottedHash, Hash].include?(klass)
152
+ return :manual if klass == ManualSource
139
153
 
140
- def evaluate_and_apply_transformations(key, value)
141
- evaluated = evaluate_procs(value)
142
- default = enforce_allowlist(key, evaluated)
143
- return default if default
154
+ return :nr
155
+ end
144
156
 
145
- boolean = enforce_boolean(key, value)
146
- evaluated = boolean if [true, false].include?(boolean)
157
+ def evaluate_and_apply_transformations(key, value, category)
158
+ evaluated = value.respond_to?(:call) ? instance_eval(&value) : value
159
+ evaluated = type_coerce(key, evaluated, category)
160
+ evaluated = enforce_allowlist(key, evaluated)
147
161
 
148
162
  apply_transformations(key, evaluated)
149
163
  end
150
164
 
151
- def apply_transformations(key, value)
152
- if transform = transform_from_default(key)
153
- begin
154
- transform.call(value)
155
- rescue => e
156
- NewRelic::Agent.logger.error("Error applying transformation for #{key}, pre-transform value was: #{value}.", e)
157
- raise e
158
- end
159
- else
160
- value
165
+ def boolean?(type, value)
166
+ return false unless type == NewRelic::Agent::Configuration::Boolean
167
+
168
+ value.class == TrueClass || value.class == FalseClass
169
+ end
170
+
171
+ # auto-instrumentation configuration params can be symbols or strings
172
+ # and unless we want to refactor the configuration hash to support both
173
+ # types, we handle the special case here
174
+ def instrumentation?(type, value)
175
+ return false unless type == String || type == Symbol
176
+ return true if INSTRUMENTATION_VALUES.include?(value.to_s)
177
+
178
+ false
179
+ end
180
+
181
+ def handle_nil_type(key, value, category)
182
+ return value if %i[manual test].include?(category)
183
+
184
+ # TODO: identify all config params such as :web_transactions_apdex
185
+ # that can exist in the @config hash without having an entry
186
+ # in the DEFAULTS hash. then warn here when a key is in play
187
+ # that is not on that allowlist. for now, just permit any key
188
+ # and return the value.
189
+ # https://github.com/newrelic/newrelic-ruby-agent/issues/3340
190
+ default_without_warning(key) || value
191
+ end
192
+
193
+ # permit an int to be supplied for a float based param and vice versa
194
+ def numeric_conversion(value)
195
+ value.is_a?(Integer) ? value.to_f : value.round
196
+ end
197
+
198
+ # permit a symbol to be supplied for a string based param and vice versa
199
+ def string_conversion(value)
200
+ value.is_a?(Symbol) ? value.to_s : value.to_sym
201
+ end
202
+
203
+ def type_coerce(key, value, category)
204
+ return validate_nil(key, category) if value.nil?
205
+
206
+ type = DEFAULTS.dig(key, :type)
207
+ return handle_nil_type(key, value, category) unless type
208
+ return value if value.is_a?(type) || boolean?(type, value) || instrumentation?(type, value)
209
+ return numeric_conversion(value) if NUMERIC_TYPES.include?(type) && NUMERIC_TYPES.include?(value.class)
210
+ return string_conversion(value) if STRINGLIKE_TYPES.include?(type) && STRINGLIKE_TYPES.include?(value.class)
211
+
212
+ # convert bool to string for regex usage and bool hash lookup
213
+ value = value.to_s if type == Boolean
214
+ if value.class != String
215
+ return value if category == :test || likely_transformed_already?(key, value)
216
+
217
+ return default_with_warning(key, value, "Expected to receive a value of type #{type} but " \
218
+ "received #{value.class}.")
219
+ end
220
+
221
+ pattern = TYPE_COERCIONS.dig(type, :pattern)
222
+ if pattern && value !~ pattern
223
+ return default_with_warning(key, value, "Expected to receive a value of type #{type} matching " \
224
+ "pattern '#{pattern}'.")
161
225
  end
226
+
227
+ procedure = TYPE_COERCIONS.dig(type, :proc)
228
+ return value unless procedure
229
+
230
+ procedure.call(value)
162
231
  end
163
232
 
164
- def enforce_allowlist(key, value)
165
- return unless allowlist = default_source.allowlist_for(key)
166
- return if allowlist.include?(value)
233
+ def likely_transformed_already?(key, value)
234
+ DEFAULTS.dig(key, :transformed_type) == value.class
235
+ end
167
236
 
168
- default = default_source.default_for(key)
169
- NewRelic::Agent.logger.warn "Invalid value '#{value}' for #{key}, applying default value of '#{default}'"
237
+ def default_with_warning(key, value, msg)
238
+ default = default_without_warning(key)
239
+ NewRelic::Agent.logger.warn "Received an invalid '#{value}' value for the '#{key}' configuration " \
240
+ "parameter! #{msg} Using the default value of '#{default}'."
170
241
  default
171
242
  end
172
243
 
173
- def enforce_boolean(key, value)
174
- type = default_source.value_from_defaults(key, :type)
175
- return unless type == Boolean
244
+ def default_without_warning(key)
245
+ default = DEFAULTS.dig(key, :default)
246
+ default.respond_to?(:call) ? default.call : default
247
+ end
176
248
 
177
- bool_value = default_source.boolean_for(key, value)
178
- return bool_value unless bool_value.nil?
249
+ def validate_nil(key, category)
250
+ return if DEFAULTS.dig(key, :allow_nil) || category == :test # tests are free to specify nil
251
+ return default_without_warning(key) unless category == :user # only user supplied config raises a warning
179
252
 
180
- default = default_source.default_for(key)
181
- NewRelic::Agent.logger.warn "Invalid value '#{value}' for #{key}, applying default value of '#{default}'"
182
- default
253
+ default_with_warning(key, nil, 'Nil values are not permitted for the parameter.')
183
254
  end
184
255
 
185
- def transform_from_default(key)
186
- default_source.transform_for(key)
256
+ def apply_transformations(key, value)
257
+ return value unless transform = default_source.transform_for(key)
258
+
259
+ transform.call(value)
260
+ rescue => e
261
+ default_with_warning(key, value, "Error encountered while applying transformation: >>#{e}<<")
262
+ end
263
+
264
+ def enforce_allowlist(key, value)
265
+ return value unless allowlist = default_source.allowlist_for(key)
266
+ return value if allowlist.include?(value)
267
+
268
+ default_with_warning(key, value, 'Expected to receive a value found on the following list: ' \
269
+ ">>#{allowlist}<<, but received '#{value}'.")
187
270
  end
188
271
 
189
272
  def default_source
@@ -197,17 +280,19 @@ module NewRelic
197
280
 
198
281
  def invoke_callbacks(direction, source)
199
282
  return unless source
283
+ return if source.respond_to?(:empty?) && source.empty?
200
284
 
201
285
  source.keys.each do |key|
286
+ next unless @callbacks.key?(key)
287
+
202
288
  begin
203
- # we need to evaluate and apply transformations for the value to deal with procs as values
204
- # this is usually done by the fetch method when accessing config, however the callbacks bypass that
205
- evaluated_cache = evaluate_and_apply_transformations(key, @cache[key])
206
- evaluated_source = evaluate_and_apply_transformations(key, source[key])
207
- rescue
289
+ evaluated_source = evaluate_and_apply_transformations(key, source[key], config_category(source.class))
290
+ rescue => e
291
+ NewRelic::Agent.logger.warn("Error evaluating callback for direction '#{direction}' with key '#{key}': #{e}")
208
292
  next
209
293
  end
210
294
 
295
+ evaluated_cache = @cache[key]
211
296
  if evaluated_cache != evaluated_source
212
297
  @callbacks[key].each do |proc|
213
298
  if direction == :add
@@ -256,8 +341,8 @@ module NewRelic
256
341
  end
257
342
 
258
343
  def apply_mask(hash)
259
- MASK_DEFAULTS \
260
- .select { |_, proc| proc.call } \
344
+ MASK_DEFAULTS
345
+ .select { |_, proc| proc.call }
261
346
  .each { |key, _| hash.delete(key) }
262
347
  hash
263
348
  end
@@ -379,7 +464,6 @@ module NewRelic
379
464
 
380
465
  # Generally only useful during initial construction and tests
381
466
  def reset_to_defaults
382
- @security_policy_source = nil
383
467
  @high_security_source = nil
384
468
  @environment_source = EnvironmentSource.new
385
469
  log_config(:add, @environment_source) # this is the only place the EnvironmentSource is ever created, so we should log it
@@ -433,7 +517,6 @@ module NewRelic
433
517
  end
434
518
 
435
519
  def delete_all_configs_for_testing
436
- @security_policy_source = nil
437
520
  @high_security_source = nil
438
521
  @environment_source = nil
439
522
  @server_source = nil
@@ -454,8 +537,7 @@ module NewRelic
454
537
  private
455
538
 
456
539
  def config_stack
457
- stack = [@security_policy_source,
458
- @high_security_source,
540
+ stack = [@high_security_source,
459
541
  @environment_source,
460
542
  @server_source,
461
543
  @manual_source,
@@ -0,0 +1,54 @@
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
+ module Configuration
8
+ # Handles validation for the `distributed_tracing.sampler.*` configs
9
+ # Focuses on validating the trace id ratio based ratios
10
+ module SamplerConfigValidator
11
+ @sampler_strategy_warnings = {}
12
+
13
+ class << self
14
+ def validate_sampling_ratio(ratio)
15
+ return nil if ratio.nil?
16
+ return nil unless valid_ratio?(ratio)
17
+
18
+ ratio
19
+ end
20
+
21
+ def validate_sampler_strategy_with_ratio(strategy_key, ratio_key)
22
+ proc do |strategy|
23
+ next strategy unless strategy == 'trace_id_ratio_based'
24
+
25
+ ratio = NewRelic::Agent.config[ratio_key]
26
+
27
+ next strategy if valid_ratio?(ratio)
28
+
29
+ unless @sampler_strategy_warnings[strategy_key]
30
+ NewRelic::Agent.logger.warn(
31
+ "Invalid or missing ratio for #{ratio_key} (value: #{ratio.inspect}). " \
32
+ "Falling back to 'adaptive' for #{strategy_key}."
33
+ )
34
+
35
+ @sampler_strategy_warnings[strategy_key] = true
36
+ end
37
+
38
+ 'adaptive'
39
+ end
40
+ end
41
+
42
+ def valid_ratio?(ratio)
43
+ ratio.is_a?(Float) && (0.0..1.0).cover?(ratio)
44
+ end
45
+
46
+ # used for testing
47
+ def reset_warnings!
48
+ @sampler_strategy_warnings = {}
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -18,7 +18,6 @@ module NewRelic
18
18
  'browser_monitoring.debug',
19
19
  'browser_monitoring.loader',
20
20
  'browser_monitoring.loader_version',
21
- 'cross_process_id',
22
21
  'data_report_period',
23
22
  'encoding_key',
24
23
  'entity_guid',
@@ -23,10 +23,7 @@ module NewRelic
23
23
 
24
24
  @agent.agent_id = config_data['agent_run_id']
25
25
 
26
- security_policies = config_data.delete('security_policies')
27
-
28
26
  add_server_side_config(config_data)
29
- add_security_policy_config(security_policies) if security_policies
30
27
 
31
28
  @agent.transaction_rules = RulesEngine.create_transaction_rules(config_data)
32
29
  @agent.stats_engine.metric_rules = RulesEngine.create_metric_rules(config_data)
@@ -44,14 +41,6 @@ module NewRelic
44
41
  server_config = NewRelic::Agent::Configuration::ServerSource.new(config_data, @config)
45
42
  @config.replace_or_add_config(server_config)
46
43
  end
47
-
48
- def add_security_policy_config(security_policies)
49
- ::NewRelic::Agent.logger.info('Installing security policies')
50
- security_policy_source = NewRelic::Agent::Configuration::SecurityPolicySource.new(security_policies)
51
- @config.replace_or_add_config(security_policy_source)
52
- # drop data collected before applying security policies
53
- @agent.drop_buffered_data
54
- end
55
44
  end
56
45
  end
57
46
  end
@@ -85,13 +85,12 @@ module NewRelic
85
85
  # statement-level metrics (i.e. table or model name)
86
86
  #
87
87
  # @param [Proc,#call] callback proc or other callable to invoke after
88
- # running the datastore block. Receives three arguments: result of the
89
- # yield, the most specific (scoped) metric name, and elapsed time of the
90
- # call. An example use is attaching SQL to Transaction Traces at the end
88
+ # running the datastore block. Receives one argument: result of the
89
+ # yield. An example use is attaching SQL to Transaction Traces at the end
91
90
  # of a wrapped datastore call.
92
91
  #
93
- # callback = Proc.new do |result, metrics, elapsed|
94
- # NewRelic::Agent::Datastores.notice_sql(query, metrics, elapsed)
92
+ # callback = Proc.new do |result|
93
+ # NewRelic::Agent::Datastores.notice_sql(query)
95
94
  # end
96
95
  #
97
96
  # NewRelic::Agent::Datastores.wrap("FauxDB", "find", "items", callback) do
@@ -107,6 +106,11 @@ module NewRelic
107
106
  # @api public
108
107
  #
109
108
  def self.wrap(product, operation, collection = nil, callback = nil)
109
+ NewRelic::Agent.logger.warn('The NewRelic::Agent::Datastores.wrap method is changing. ' \
110
+ 'In a future major version, proc will only accept a single argument, the result of the yield. ' \
111
+ 'The scoped metric name and elapsed arguments will be removed, as they are being removed from the ' \
112
+ 'Datastores.notice_sql method. The scoped metric name and elapsed values are derived from the ' \
113
+ 'current segment when the wrap yields.')
110
114
  NewRelic::Agent.record_api_supportability_metric(:wrap)
111
115
 
112
116
  return yield unless operation
@@ -138,19 +142,13 @@ module NewRelic
138
142
  # If you are recording non-SQL data, please use {notice_statement}
139
143
  # instead.
140
144
  #
141
- # NewRelic::Agent::Datastores.notice_sql(query, metrics, elapsed)
145
+ # NewRelic::Agent::Datastores.notice_sql(query)
142
146
  #
143
147
  # @param [String] query the SQL text to be captured. Note that depending
144
148
  # on user settings, this string will be run through obfuscation, but
145
149
  # some dialects of SQL (or non-SQL queries) are not guaranteed to be
146
150
  # properly obfuscated by these routines!
147
151
  #
148
- # @param [String] scoped_metric The most specific metric relating to this
149
- # query. Typically the result of
150
- # NewRelic::Agent::Datastores::MetricHelper#metrics_for
151
- #
152
- # @param [Float] elapsed the elapsed time during query execution
153
- #
154
152
  # @note THERE ARE SECURITY CONCERNS WHEN CAPTURING QUERY TEXT!
155
153
  # New Relic's Transaction Tracing and Slow SQL features will
156
154
  # attempt to apply obfuscation to the passed queries, but it is possible
@@ -159,7 +157,7 @@ module NewRelic
159
157
  #
160
158
  # @api public
161
159
  #
162
- def self.notice_sql(query, scoped_metric, elapsed)
160
+ def self.notice_sql(query)
163
161
  NewRelic::Agent.record_api_supportability_metric(:notice_sql)
164
162
 
165
163
  if (txn = Tracer.current_transaction) && (segment = txn.current_segment) && segment.respond_to?(:notice_sql)
@@ -176,12 +174,10 @@ module NewRelic
176
174
  # ensure that user information is obfuscated if the agent setting
177
175
  # `transaction_tracer.record_sql` is set to `obfuscated`
178
176
  #
179
- # NewRelic::Agent::Datastores.notice_statement("key", elapsed)
177
+ # NewRelic::Agent::Datastores.notice_statement("key")
180
178
  #
181
179
  # @param [String] statement text of the statement to capture.
182
180
  #
183
- # @param [Float] elapsed the elapsed time during query execution
184
- #
185
181
  # @note THERE ARE SECURITY CONCERNS WHEN CAPTURING STATEMENTS!
186
182
  # This method will properly ignore statements when the user has turned
187
183
  # off capturing queries, but it is not able to obfuscate arbitrary data!
@@ -191,7 +187,7 @@ module NewRelic
191
187
  #
192
188
  # @api public
193
189
  #
194
- def self.notice_statement(statement, elapsed)
190
+ def self.notice_statement(statement)
195
191
  NewRelic::Agent.record_api_supportability_metric(:notice_statement)
196
192
 
197
193
  # Settings may change eventually, but for now we follow the same
@@ -2,9 +2,6 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- require_relative 'distributed_tracing/cross_app_payload'
6
- require_relative 'distributed_tracing/cross_app_tracing'
7
-
8
5
  require_relative 'distributed_tracing/distributed_trace_transport_type'
9
6
  require_relative 'distributed_tracing/distributed_trace_payload'
10
7
 
@@ -93,6 +93,7 @@ module NewRelic
93
93
 
94
94
  def contents
95
95
  <<~CONTENTS
96
+ entity_guid: #{NewRelic::Agent.config[:entity_guid]}
96
97
  healthy: #{@status[:healthy]}
97
98
  status: #{@status[:message]}#{last_error}
98
99
  start_time_unix_nano: #{@start_time}
@@ -71,7 +71,7 @@ module NewRelic
71
71
  end
72
72
 
73
73
  def self.run_in_trace(job, block, event)
74
- trace_execution_scoped("ActiveJob/#{adapter.sub(/^ActiveJob::/, '')}/Queue/#{event}/Named/#{job.queue_name}",
74
+ trace_execution_scoped("ActiveJob/#{adapter.sub(/^ActiveJob::/, '')}/Queue/#{event}/Named/#{job.queue_name}/#{job.class}",
75
75
  code_information: code_information_for_job(job)) do
76
76
  block.call
77
77
  end
@@ -22,8 +22,9 @@ module NewRelic
22
22
  job = payload[:job] || payload[:jobs].first
23
23
 
24
24
  queue = job.queue_name
25
+ job_class = job.class.name.include?('::') ? job.class.name[job.class.name.rindex('::') + 2..-1] : job.class.name
25
26
  method = method_from_name(name)
26
- "Ruby/ActiveJob/#{queue}/#{method}"
27
+ "Ruby/ActiveJob/#{queue}/#{job_class}/#{method}"
27
28
  end
28
29
 
29
30
  PATTERN = /\A([^\.]+)\.active_job\z/
@@ -99,10 +99,7 @@ module NewRelic
99
99
  # convert vendor (makara, etc.) wrapper names to their bare names
100
100
  # ex: postgresql_makara -> postgresql
101
101
  def bare_adapter_name(adapter_name)
102
- # TODO: OLD RUBIES - RUBY_VERSION < 2.5
103
- # With Ruby 2.5+ we could use #delete_suffix instead of #chomp for a
104
- # potential speed boost
105
- return adapter_name.chomp(MAKARA_SUFFIX) if adapter_name&.end_with?(MAKARA_SUFFIX)
102
+ return adapter_name.delete_suffix(MAKARA_SUFFIX) if adapter_name&.end_with?(MAKARA_SUFFIX)
106
103
 
107
104
  adapter_name
108
105
  end
@@ -7,6 +7,8 @@ require 'new_relic/agent/instrumentation/active_support_subscriber'
7
7
  DependencyDetection.defer do
8
8
  named :active_support
9
9
 
10
+ EVENT_NAMES_PARAMETER = :'instrumentation.active_support_notifications.active_support_events'
11
+
10
12
  depends_on do
11
13
  !NewRelic::Agent.config[:disable_active_support]
12
14
  end
@@ -16,12 +18,17 @@ DependencyDetection.defer do
16
18
  !NewRelic::Agent::Instrumentation::ActiveSupportSubscriber.subscribed?
17
19
  end
18
20
 
21
+ depends_on do
22
+ !NewRelic::Agent.config[EVENT_NAMES_PARAMETER].empty?
23
+ end
24
+
19
25
  executes do
20
26
  NewRelic::Agent.logger.info('Installing ActiveSupport instrumentation')
21
27
  end
22
28
 
23
29
  executes do
24
- ActiveSupport::Notifications.subscribe(/\.active_support$/,
30
+ event_names = NewRelic::Agent.config[EVENT_NAMES_PARAMETER].map { |n| Regexp.escape(n) }.join('|')
31
+ ActiveSupport::Notifications.subscribe(/\A(?:#{event_names})\z/,
25
32
  NewRelic::Agent::Instrumentation::ActiveSupportSubscriber.new)
26
33
  end
27
34
  end