newrelic_rpm 9.4.1 → 9.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -4
  3. data/lib/new_relic/agent/attribute_pre_filtering.rb +109 -0
  4. data/lib/new_relic/agent/configuration/default_source.rb +74 -1
  5. data/lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb +4 -0
  6. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +9 -0
  7. data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +2 -2
  8. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +4 -0
  9. data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +3 -0
  10. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +4 -1
  11. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +3 -0
  12. data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +4 -0
  13. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +4 -0
  14. data/lib/new_relic/agent/instrumentation/grpc/server/instrumentation.rb +4 -0
  15. data/lib/new_relic/agent/instrumentation/grpc_client.rb +1 -1
  16. data/lib/new_relic/agent/instrumentation/grpc_server.rb +1 -1
  17. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +4 -0
  18. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +4 -0
  19. data/lib/new_relic/agent/instrumentation/logger/instrumentation.rb +3 -0
  20. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +9 -0
  21. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +4 -0
  22. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +4 -0
  23. data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +4 -0
  24. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +6 -0
  25. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +4 -0
  26. data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +4 -0
  27. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +4 -0
  28. data/lib/new_relic/agent/instrumentation/resque/instrumentation.rb +4 -0
  29. data/lib/new_relic/agent/instrumentation/roda/instrumentation.rb +4 -0
  30. data/lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb +1 -1
  31. data/lib/new_relic/agent/instrumentation/roda.rb +1 -0
  32. data/lib/new_relic/agent/instrumentation/sidekiq/client.rb +4 -0
  33. data/lib/new_relic/agent/instrumentation/sidekiq/server.rb +26 -3
  34. data/lib/new_relic/agent/instrumentation/sidekiq.rb +2 -2
  35. data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +4 -0
  36. data/lib/new_relic/agent/instrumentation/stripe.rb +28 -0
  37. data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +77 -0
  38. data/lib/new_relic/agent/instrumentation/tilt/instrumentation.rb +4 -0
  39. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +5 -1
  40. data/lib/new_relic/agent/transaction/abstract_segment.rb +52 -0
  41. data/lib/new_relic/agent.rb +12 -0
  42. data/lib/new_relic/rack/agent_hooks.rb +1 -1
  43. data/lib/new_relic/rack/agent_middleware.rb +0 -16
  44. data/lib/new_relic/supportability_helper.rb +1 -0
  45. data/lib/new_relic/version.rb +2 -2
  46. data/newrelic.yml +45 -0
  47. metadata +5 -2
@@ -6,6 +6,8 @@ module NewRelic
6
6
  module Agent
7
7
  module Instrumentation
8
8
  module RackBuilder
9
+ INSTRUMENTATION_NAME = 'Rack'
10
+
9
11
  def self.track_deferred_detection(builder_class)
10
12
  class << builder_class
11
13
  attr_accessor :_nr_deferred_detection_ran
@@ -51,6 +53,8 @@ module NewRelic
51
53
  def run_with_tracing(app)
52
54
  return yield(app) unless middleware_instrumentation_enabled?
53
55
 
56
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
57
+
54
58
  yield(::NewRelic::Agent::Instrumentation::MiddlewareProxy.wrap(app, true))
55
59
  end
56
60
 
@@ -58,6 +62,8 @@ module NewRelic
58
62
  return if middleware_class.nil?
59
63
  return yield(middleware_class) unless middleware_instrumentation_enabled?
60
64
 
65
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
66
+
61
67
  yield(::NewRelic::Agent::Instrumentation::MiddlewareProxy.for_class(middleware_class))
62
68
  end
63
69
  end
@@ -9,6 +9,8 @@ module NewRelic
9
9
  module Instrumentation
10
10
  module Rails3
11
11
  module ActionController
12
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
13
+
12
14
  # determine the path that is used in the metric name for
13
15
  # the called controller action
14
16
  def newrelic_metric_path(action_name_override = nil)
@@ -21,6 +23,8 @@ module NewRelic
21
23
  end
22
24
 
23
25
  def process_action(*args) # THREAD_LOCAL_ACCESS
26
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
27
+
24
28
  munged_params = NewRelic::Agent::ParameterFiltering.filter_rails_request_parameters(request.filtered_parameters)
25
29
  perform_action_with_newrelic_trace(:category => :controller,
26
30
  :name => self.action_name,
@@ -7,11 +7,15 @@ module NewRelic
7
7
  module Instrumentation
8
8
  module Rake
9
9
  module Tracer
10
+ INSTRUMENTATION_NAME = 'Rake'
11
+
10
12
  def invoke_with_newrelic_tracing(*args)
11
13
  unless NewRelic::Agent::Instrumentation::Rake.should_trace?(name)
12
14
  return yield
13
15
  end
14
16
 
17
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
18
+
15
19
  begin
16
20
  timeout = NewRelic::Agent.config[:'rake.connect_timeout']
17
21
  NewRelic::Agent.instance.wait_on_connect(timeout)
@@ -6,6 +6,8 @@ require_relative 'constants'
6
6
 
7
7
  module NewRelic::Agent::Instrumentation
8
8
  module Redis
9
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
10
+
9
11
  def connect_with_tracing
10
12
  with_tracing(Constants::CONNECT, database: db) { yield }
11
13
  end
@@ -43,6 +45,8 @@ module NewRelic::Agent::Instrumentation
43
45
  private
44
46
 
45
47
  def with_tracing(operation, statement: nil, database: nil)
48
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
49
+
46
50
  segment = NewRelic::Agent::Tracer.start_datastore_segment(
47
51
  product: Constants::PRODUCT_NAME,
48
52
  operation: operation,
@@ -6,7 +6,11 @@ module NewRelic::Agent::Instrumentation
6
6
  module Resque
7
7
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
8
8
 
9
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
10
+
9
11
  def with_tracing
12
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
13
+
10
14
  begin
11
15
  perform_action_with_newrelic_trace(
12
16
  :name => 'perform',
@@ -7,6 +7,8 @@ module NewRelic::Agent::Instrumentation
7
7
  module Tracer
8
8
  include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
9
9
 
10
+ INSTRUMENTATION_NAME = 'Roda'
11
+
10
12
  def self.included(clazz)
11
13
  clazz.extend(self)
12
14
  end
@@ -39,6 +41,8 @@ module NewRelic::Agent::Instrumentation
39
41
  end
40
42
 
41
43
  def _roda_handle_main_route_with_tracing(*args)
44
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
45
+
42
46
  perform_action_with_newrelic_trace(
43
47
  category: :roda,
44
48
  name: ::NewRelic::Agent::Instrumentation::Roda::TransactionNamer.transaction_name(request),
@@ -10,7 +10,7 @@ module NewRelic
10
10
  extend self
11
11
 
12
12
  ROOT = '/'.freeze
13
- REGEX_MULTIPLE_SLASHES = %r{^[/^\A]*(.*?)[/$?\z]*$}.freeze
13
+ REGEX_MULTIPLE_SLASHES = %r{^[/^]*(.*?)[/$?]*$}.freeze
14
14
 
15
15
  def transaction_name(request)
16
16
  path = request.path || ::NewRelic::Agent::UNKNOWN_METRIC
@@ -3,6 +3,7 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  require_relative 'roda/instrumentation'
6
+ require_relative 'roda/roda_transaction_namer'
6
7
 
7
8
  DependencyDetection.defer do
8
9
  named :roda
@@ -6,7 +6,11 @@ module NewRelic::Agent::Instrumentation::Sidekiq
6
6
  class Client
7
7
  include Sidekiq::ClientMiddleware if defined?(Sidekiq::ClientMiddleware)
8
8
 
9
+ INSTRUMENTATION_NAME = 'SidekiqClient'
10
+
9
11
  def call(_worker_class, job, *_)
12
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
13
+
10
14
  job[NewRelic::NEWRELIC_KEY] ||= distributed_tracing_headers if ::NewRelic::Agent.config[:'distributed_tracing.enabled']
11
15
  yield
12
16
  end
@@ -7,9 +7,16 @@ module NewRelic::Agent::Instrumentation::Sidekiq
7
7
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
8
8
  include Sidekiq::ServerMiddleware if defined?(Sidekiq::ServerMiddleware)
9
9
 
10
+ ATTRIBUTE_BASE_NAMESPACE = 'sidekiq.args'
11
+ ATTRIBUTE_FILTER_TYPES = %i[include exclude].freeze
12
+ ATTRIBUTE_JOB_NAMESPACE = :"job.#{ATTRIBUTE_BASE_NAMESPACE}"
13
+ INSTRUMENTATION_NAME = 'SidekiqServer'
14
+
10
15
  # Client middleware has additional parameters, and our tests use the
11
16
  # middleware client-side to work inline.
12
17
  def call(worker, msg, queue, *_)
18
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
19
+
13
20
  trace_args = if worker.respond_to?(:newrelic_trace_args)
14
21
  worker.newrelic_trace_args(msg, queue)
15
22
  else
@@ -18,10 +25,16 @@ module NewRelic::Agent::Instrumentation::Sidekiq
18
25
  trace_headers = msg.delete(NewRelic::NEWRELIC_KEY)
19
26
 
20
27
  perform_action_with_newrelic_trace(trace_args) do
21
- NewRelic::Agent::Transaction.merge_untrusted_agent_attributes(msg['args'], :'job.sidekiq.args',
22
- NewRelic::Agent::AttributeFilter::DST_NONE)
28
+ NewRelic::Agent::Transaction.merge_untrusted_agent_attributes(
29
+ NewRelic::Agent::AttributePreFiltering.pre_filter(msg['args'], self.class.nr_attribute_options),
30
+ ATTRIBUTE_JOB_NAMESPACE,
31
+ NewRelic::Agent::AttributeFilter::DST_NONE
32
+ )
33
+
34
+ if ::NewRelic::Agent.config[:'distributed_tracing.enabled'] && trace_headers&.any?
35
+ ::NewRelic::Agent::DistributedTracing::accept_distributed_trace_headers(trace_headers, 'Other')
36
+ end
23
37
 
24
- ::NewRelic::Agent::DistributedTracing::accept_distributed_trace_headers(trace_headers, 'Other') if ::NewRelic::Agent.config[:'distributed_tracing.enabled'] && trace_headers&.any?
25
38
  yield
26
39
  end
27
40
  end
@@ -33,5 +46,15 @@ module NewRelic::Agent::Instrumentation::Sidekiq
33
46
  :category => 'OtherTransaction/SidekiqJob'
34
47
  }
35
48
  end
49
+
50
+ def self.nr_attribute_options
51
+ @nr_attribute_options ||= begin
52
+ ATTRIBUTE_FILTER_TYPES.each_with_object({}) do |type, opts|
53
+ pattern =
54
+ NewRelic::Agent::AttributePreFiltering.formulate_regexp_union(:"#{ATTRIBUTE_BASE_NAMESPACE}.#{type}")
55
+ opts[type] = pattern if pattern
56
+ end.merge(attribute_namespace: ATTRIBUTE_JOB_NAMESPACE)
57
+ end
58
+ end
36
59
  end
37
60
  end
@@ -43,8 +43,8 @@ DependencyDetection.defer do
43
43
  executes do
44
44
  next unless Gem::Version.new(Sidekiq::VERSION) < Gem::Version.new('5.0.0')
45
45
 
46
- deprecation_msg = 'Instrumentation for Sidekiq versions below 5.0.0 is deprecated.' \
47
- 'They will stop being monitored in version 9.0.0. ' \
46
+ deprecation_msg = 'Instrumentation for Sidekiq versions below 5.0.0 is deprecated ' \
47
+ 'and will be dropped entirely in a future major New Relic Ruby agent release.' \
48
48
  'Please upgrade your Sidekiq version to continue receiving full support. '
49
49
 
50
50
  NewRelic::Agent.logger.log_once(
@@ -13,6 +13,8 @@ module NewRelic::Agent::Instrumentation
13
13
  module Tracer
14
14
  include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
15
15
 
16
+ INSTRUMENTATION_NAME = 'Sinatra'
17
+
16
18
  def self.included(clazz)
17
19
  clazz.extend(self)
18
20
  end
@@ -90,6 +92,8 @@ module NewRelic::Agent::Instrumentation
90
92
  end
91
93
 
92
94
  def dispatch_with_tracing
95
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
96
+
93
97
  request_params = get_request_params
94
98
  filtered_params = ::NewRelic::Agent::ParameterFiltering::apply_filters(request.env, request_params || {})
95
99
 
@@ -0,0 +1,28 @@
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/instrumentation/stripe_subscriber'
6
+
7
+ DependencyDetection.defer do
8
+ named :stripe
9
+
10
+ depends_on do
11
+ NewRelic::Agent.config[:'instrumentation.stripe'] == 'enabled'
12
+ end
13
+
14
+ depends_on do
15
+ defined?(Stripe) &&
16
+ Gem::Version.new(Stripe::VERSION) >= Gem::Version.new('5.38.0')
17
+ end
18
+
19
+ executes do
20
+ NewRelic::Agent.logger.info('Installing Stripe instrumentation')
21
+ end
22
+
23
+ executes do
24
+ newrelic_subscriber = NewRelic::Agent::Instrumentation::StripeSubscriber.new
25
+ Stripe::Instrumentation.subscribe(:request_begin) { |event| newrelic_subscriber.start_segment(event) }
26
+ Stripe::Instrumentation.subscribe(:request_end) { |event| newrelic_subscriber.finish_segment(event) }
27
+ end
28
+ end
@@ -0,0 +1,77 @@
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 Instrumentation
8
+ class StripeSubscriber
9
+ DEFAULT_DESTINATIONS = AttributeFilter::DST_SPAN_EVENTS
10
+ EVENT_ATTRIBUTES = %i[http_status method num_retries path request_id].freeze
11
+ ATTRIBUTE_NAMESPACE = 'stripe.user_data'
12
+ ATTRIBUTE_FILTER_TYPES = %i[include exclude].freeze
13
+
14
+ def start_segment(event)
15
+ return unless is_execution_traced?
16
+
17
+ segment = NewRelic::Agent::Tracer.start_segment(name: metric_name(event))
18
+ event.user_data[:newrelic_segment] = segment
19
+ rescue => e
20
+ NewRelic::Agent.logger.error("Error starting New Relic Stripe segment: #{e}")
21
+ end
22
+
23
+ def finish_segment(event)
24
+ return unless is_execution_traced?
25
+
26
+ segment = remove_and_return_nr_segment(event)
27
+ add_stripe_attributes(segment, event)
28
+ add_custom_attributes(segment, event)
29
+ rescue => e
30
+ NewRelic::Agent.logger.error("Error finishing New Relic Stripe segment: #{e}")
31
+ ensure
32
+ segment&.finish
33
+ end
34
+
35
+ private
36
+
37
+ def is_execution_traced?
38
+ NewRelic::Agent::Tracer.state.is_execution_traced?
39
+ end
40
+
41
+ def metric_name(event)
42
+ "Stripe#{event.path}/#{event.method}"
43
+ end
44
+
45
+ def add_stripe_attributes(segment, event)
46
+ EVENT_ATTRIBUTES.each do |attribute|
47
+ segment.add_agent_attribute("stripe_#{attribute}", event.send(attribute), DEFAULT_DESTINATIONS)
48
+ end
49
+ end
50
+
51
+ def add_custom_attributes(segment, event)
52
+ return if NewRelic::Agent.config[:'stripe.user_data.include'].empty?
53
+
54
+ filtered_attributes = NewRelic::Agent::AttributePreFiltering.pre_filter_hash(event.user_data, nr_attribute_options)
55
+ filtered_attributes.each do |key, value|
56
+ segment.add_agent_attribute("stripe_user_data_#{key}", value, DEFAULT_DESTINATIONS)
57
+ end
58
+ end
59
+
60
+ def nr_attribute_options
61
+ ATTRIBUTE_FILTER_TYPES.each_with_object({}) do |type, opts|
62
+ pattern =
63
+ NewRelic::Agent::AttributePreFiltering.formulate_regexp_union(:"#{ATTRIBUTE_NAMESPACE}.#{type}")
64
+ opts[type] = pattern if pattern
65
+ end
66
+ end
67
+
68
+ def remove_and_return_nr_segment(event)
69
+ segment = event.user_data[:newrelic_segment]
70
+ event.user_data.delete(:newrelic_segment)
71
+
72
+ segment
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -6,6 +6,8 @@ module NewRelic
6
6
  module Agent
7
7
  module Instrumentation
8
8
  module Tilt
9
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
10
+
9
11
  def metric_name(klass, file)
10
12
  "View/#{klass}/#{file}/Rendering"
11
13
  end
@@ -21,6 +23,8 @@ module NewRelic
21
23
  end
22
24
 
23
25
  def render_with_tracing(*args, &block)
26
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
27
+
24
28
  begin
25
29
  finishable = Tracer.start_segment(
26
30
  name: metric_name(self.class, create_filename_for_metric(self.file))
@@ -8,8 +8,8 @@ module NewRelic
8
8
  module Typhoeus
9
9
  HYDRA_SEGMENT_NAME = 'External/Multiple/Typhoeus::Hydra/run'
10
10
  NOTICEABLE_ERROR_CLASS = 'Typhoeus::Errors::TyphoeusError'
11
-
12
11
  EARLIEST_VERSION = Gem::Version.new('0.5.3')
12
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
13
13
 
14
14
  def self.is_supported_version?
15
15
  Gem::Version.new(::Typhoeus::VERSION) >= EARLIEST_VERSION
@@ -31,6 +31,8 @@ module NewRelic
31
31
  end
32
32
 
33
33
  def with_tracing
34
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
35
+
34
36
  segment = NewRelic::Agent::Tracer.start_segment(name: HYDRA_SEGMENT_NAME)
35
37
  instance_variable_set(:@__newrelic_hydra_segment, segment)
36
38
  begin
@@ -41,6 +43,8 @@ module NewRelic
41
43
  end
42
44
 
43
45
  def self.trace(request)
46
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
47
+
44
48
  state = NewRelic::Agent::Tracer.state
45
49
  return unless state.is_execution_traced?
46
50
 
@@ -24,6 +24,9 @@ module NewRelic
24
24
  attr_writer :record_metrics, :record_scoped_metric, :record_on_finish
25
25
  attr_reader :noticed_error
26
26
 
27
+ CALLBACK = :@callback
28
+ SEGMENT = 'segment'
29
+
27
30
  def initialize(name = nil, start_time = nil)
28
31
  @name = name
29
32
  @starting_segment_key = NewRelic::Agent::Tracer.current_segment_key
@@ -49,6 +52,7 @@ module NewRelic
49
52
  @code_function = nil
50
53
  @code_lineno = nil
51
54
  @code_namespace = nil
55
+ invoke_callback
52
56
  end
53
57
 
54
58
  def start
@@ -327,6 +331,54 @@ module NewRelic
327
331
  Tracer.state
328
332
  end
329
333
  end
334
+
335
+ # for segment callback usage info, see self.set_segment_callback
336
+ def invoke_callback
337
+ return unless self.class.instance_variable_defined?(CALLBACK)
338
+
339
+ NewRelic::Agent.logger.debug("Invoking callback for #{self.class.name}...")
340
+ self.class.instance_variable_get(CALLBACK).call
341
+ end
342
+
343
+ # Setting and invoking a segment callback
344
+ # =======================================
345
+ # Each individual segment class such as `ExternalRequestSegment` allows
346
+ # for exactly one instance of a `Proc` (meaning a proc or lambda) to be
347
+ # set as a callback. A callback can be set on a segment class by calling
348
+ # `.set_segment_callback` with a proc or lambda as the only argument.
349
+ # If set, the callback will be invoked with `#call` at segment class
350
+ # initialization time.
351
+ #
352
+ # Example usage:
353
+ # callback = -> { puts 'Hello, World! }
354
+ # ExternalRequestSegment.set_segment_callback(callback)
355
+ # ExternalRequestSegment.new(library, uri, procedure)
356
+ #
357
+ # A callback set on a segment class will only be called when that
358
+ # specific segment class is initialized. Other segment classes will not
359
+ # be impacted.
360
+ #
361
+ # Great caution should be taken in the defining of the callback block
362
+ # to not have the block perform anything too time consuming or resource
363
+ # intensive in order to keep the New Relic Ruby agent operating
364
+ # normally.
365
+ #
366
+ # Given that callbacks are user defined, they must be set entirely at
367
+ # the user's own risk. It is recommended that each callback use
368
+ # conditional logic that only performs work for certain qualified
369
+ # segments. It is recommended that each callback be thoroughly tested
370
+ # in non-production environments before being introduced to production
371
+ # environments.
372
+ def self.set_segment_callback(callback_proc)
373
+ unless callback_proc.is_a?(Proc)
374
+ NewRelic::Agent.logger.error("#{self}.#{__method__}: expected an argument of type Proc, " \
375
+ "got #{callback_proc.class}")
376
+ return
377
+ end
378
+
379
+ NewRelic::Agent.record_api_supportability_metric(:set_segment_callback)
380
+ instance_variable_set(CALLBACK, callback_proc)
381
+ end
330
382
  end
331
383
  end
332
384
  end
@@ -58,6 +58,7 @@ module NewRelic
58
58
  require 'new_relic/agent/deprecator'
59
59
  require 'new_relic/agent/logging'
60
60
  require 'new_relic/agent/distributed_tracing'
61
+ require 'new_relic/agent/attribute_pre_filtering'
61
62
  require 'new_relic/agent/attribute_processing'
62
63
  require 'new_relic/agent/linking_metadata'
63
64
  require 'new_relic/agent/local_log_decorator'
@@ -213,6 +214,17 @@ module NewRelic
213
214
  record_metric(metric_name, value)
214
215
  end
215
216
 
217
+ def record_instrumentation_invocation(library)
218
+ record_metric_once("Supportability/#{library}/Invoked")
219
+ end
220
+
221
+ # see ActiveSupport::Inflector.demodulize
222
+ def base_name(klass_name)
223
+ return klass_name unless ridx = klass_name.rindex('::')
224
+
225
+ klass_name[(ridx + 2), klass_name.length]
226
+ end
227
+
216
228
  SUPPORTABILITY_INCREMENT_METRIC = 'Supportability/API/increment_metric'.freeze
217
229
 
218
230
  # Increment a simple counter metric.
@@ -23,7 +23,7 @@ module NewRelic::Rack
23
23
  #
24
24
  class AgentHooks < AgentMiddleware
25
25
  def self.needed?
26
- !NewRelic::Agent.config[:disable_middleware_instrumentation]
26
+ NewRelic::Agent.config[:disable_middleware_instrumentation]
27
27
  end
28
28
 
29
29
  def traced_call(env)
@@ -26,22 +26,6 @@ module NewRelic
26
26
  prefix = ::NewRelic::Agent::Instrumentation::ControllerInstrumentation::TransactionNamer.prefix_for_category(nil, @category)
27
27
  "#{prefix}#{self.class.name}/call"
28
28
  end
29
-
30
- # If middleware tracing is disabled, we'll still inject our agent-specific
31
- # middlewares, and still trace those, but we don't want to capture HTTP
32
- # response codes, since middleware that's outside of ours might change the
33
- # response code before it goes back to the client.
34
- def capture_http_response_code(state, result)
35
- return if NewRelic::Agent.config[:disable_middleware_instrumentation]
36
-
37
- super
38
- end
39
-
40
- def capture_response_content_type(state, result)
41
- return if NewRelic::Agent.config[:disable_middleware_instrumentation]
42
-
43
- super
44
- end
45
29
  end
46
30
  end
47
31
  end
@@ -46,6 +46,7 @@ module NewRelic
46
46
  :recording_web_transaction?,
47
47
  :require_test_helper,
48
48
  :set_error_group_callback,
49
+ :set_segment_callback,
49
50
  :set_sql_obfuscator,
50
51
  :set_transaction_name,
51
52
  :set_user_id,
@@ -6,8 +6,8 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 9
9
- MINOR = 4
10
- TINY = 1
9
+ MINOR = 5
10
+ TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
13
13
  end
data/newrelic.yml CHANGED
@@ -223,6 +223,9 @@ common: &default_settings
223
223
 
224
224
  # If true, the agent won't wrap third-party middlewares in instrumentation
225
225
  # (regardless of whether they are installed via Rack::Builder or Rails).
226
+ # When middleware instrumentation is disabled, if an application is using
227
+ # middleware that could alter the response code, the HTTP status code reported on
228
+ # the transaction may not reflect the altered value.
226
229
  # disable_middleware_instrumentation: false
227
230
 
228
231
  # If true, disables agent middleware for Roda. This middleware is responsible for
@@ -494,6 +497,10 @@ common: &default_settings
494
497
  # prepend, chain, disabled.
495
498
  # instrumentation.sinatra: auto
496
499
 
500
+ # Controls auto-instrumentation of Stripe at startup. May be one of: enabled,
501
+ # disabled.
502
+ # instrumentation.stripe: enabled
503
+
497
504
  # Controls auto-instrumentation of the Thread class at start up to allow the agent
498
505
  # to correctly nest spans inside of an asynchronous transaction. This does not
499
506
  # enable the agent to automatically trace all threads created (see
@@ -585,6 +592,26 @@ common: &default_settings
585
592
  # before shutting down.
586
593
  # send_data_on_exit: true
587
594
 
595
+ # An array of strings that will collectively serve as a denylist for filtering
596
+ # which Sidekiq job arguments get reported to New Relic. To capture any Sidekiq
597
+ # arguments, 'job.sidekiq.args.*' must be added to the separate
598
+ # :'attributes.include' configuration option. Each string in this array will be
599
+ # turned into a regular expression via Regexp.new to permit advanced matching. For
600
+ # job argument hashes, if either a key or value matches the pair will be excluded.
601
+ # All matching job argument array elements and job argument scalars will be
602
+ # excluded.
603
+ # sidekiq.args.exclude: []
604
+
605
+ # An array of strings that will collectively serve as an allowlist for filtering
606
+ # which Sidekiq job arguments get reported to New Relic. To capture any Sidekiq
607
+ # arguments, 'job.sidekiq.args.*' must be added to the separate
608
+ # :'attributes.include' configuration option. Each string in this array will be
609
+ # turned into a regular expression via Regexp.new to permit advanced matching. For
610
+ # job argument hashes, if either a key or value matches the pair will be included.
611
+ # All matching job argument array elements and job argument scalars will be
612
+ # included.
613
+ # sidekiq.args.include: []
614
+
588
615
  # If true, the agent collects slow SQL queries.
589
616
  # slow_sql.enabled: true
590
617
 
@@ -634,6 +661,24 @@ common: &default_settings
634
661
  # allowlist. Enabled automatically in high security mode.
635
662
  # strip_exception_messages.enabled: false
636
663
 
664
+ # An array of strings to specify which keys and/or values inside a Stripe event's
665
+ # user_data hash should
666
+ # not be reported to New Relic. Each string in this array will be turned into a
667
+ # regular expression via
668
+ # Regexp.new to permit advanced matching. For each hash pair, if either the key or
669
+ # value is matched the
670
+ # pair will not be reported. By default, no user_data is reported, so this option
671
+ # should only be used if
672
+ # the stripe.user_data.include option is being used.
673
+ # stripe.user_data.exclude: []
674
+
675
+ # An array of strings to specify which keys inside a Stripe event's user_data hash
676
+ # should be reported
677
+ # to New Relic. Each string in this array will be turned into a regular expression
678
+ # via Regexp.new to
679
+ # permit advanced matching. Setting the value to ["."] will report all user_data.
680
+ # stripe.user_data.include: []
681
+
637
682
  # When set to true, forces a synchronous connection to the New Relic collector
638
683
  # during application startup. For very short-lived processes, this helps ensure
639
684
  # the New Relic agent has time to report.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_rpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.4.1
4
+ version: 9.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanna McClure
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-08-16 00:00:00.000000000 Z
14
+ date: 2023-09-12 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -255,6 +255,7 @@ files:
255
255
  - lib/new_relic/agent/agent_helpers/transmit.rb
256
256
  - lib/new_relic/agent/agent_logger.rb
257
257
  - lib/new_relic/agent/attribute_filter.rb
258
+ - lib/new_relic/agent/attribute_pre_filtering.rb
258
259
  - lib/new_relic/agent/attribute_processing.rb
259
260
  - lib/new_relic/agent/attributes.rb
260
261
  - lib/new_relic/agent/audit_logger.rb
@@ -471,6 +472,8 @@ files:
471
472
  - lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb
472
473
  - lib/new_relic/agent/instrumentation/sinatra/prepend.rb
473
474
  - lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb
475
+ - lib/new_relic/agent/instrumentation/stripe.rb
476
+ - lib/new_relic/agent/instrumentation/stripe_subscriber.rb
474
477
  - lib/new_relic/agent/instrumentation/thread.rb
475
478
  - lib/new_relic/agent/instrumentation/thread/chain.rb
476
479
  - lib/new_relic/agent/instrumentation/thread/instrumentation.rb