newrelic_rpm 9.17.0 → 9.21.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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/.build_ignore +1 -0
  3. data/CHANGELOG.md +105 -1
  4. data/lib/new_relic/agent/agent.rb +2 -0
  5. data/lib/new_relic/agent/agent_helpers/connect.rb +3 -3
  6. data/lib/new_relic/agent/agent_helpers/harvest.rb +3 -3
  7. data/lib/new_relic/agent/agent_helpers/shutdown.rb +1 -1
  8. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +1 -1
  9. data/lib/new_relic/agent/agent_helpers/startup.rb +4 -4
  10. data/lib/new_relic/agent/configuration/default_source.rb +145 -120
  11. data/lib/new_relic/agent/configuration/manager.rb +5 -2
  12. data/lib/new_relic/agent/configuration/yaml_source.rb +4 -4
  13. data/lib/new_relic/agent/database.rb +1 -1
  14. data/lib/new_relic/agent/database_adapter.rb +1 -1
  15. data/lib/new_relic/agent/datastores/redis.rb +1 -1
  16. data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -1
  17. data/lib/new_relic/agent/distributed_tracing.rb +2 -0
  18. data/lib/new_relic/agent/external.rb +2 -0
  19. data/lib/new_relic/agent/http_clients/uri_util.rb +1 -1
  20. data/lib/new_relic/agent/instrumentation/action_dispatch.rb +1 -1
  21. data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +1 -1
  22. data/lib/new_relic/agent/instrumentation/action_mailbox.rb +1 -1
  23. data/lib/new_relic/agent/instrumentation/action_mailer.rb +1 -1
  24. data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
  25. data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +6 -2
  26. data/lib/new_relic/agent/instrumentation/active_record.rb +6 -4
  27. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +2 -2
  28. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +11 -9
  29. data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +2 -2
  30. data/lib/new_relic/agent/instrumentation/async_http.rb +1 -1
  31. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/instrumentation.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +1 -1
  33. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +4 -0
  34. data/lib/new_relic/agent/instrumentation/curb.rb +1 -1
  35. data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +1 -2
  36. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +1 -0
  37. data/lib/new_relic/agent/instrumentation/elasticsearch.rb +1 -1
  38. data/lib/new_relic/agent/instrumentation/ethon.rb +1 -1
  39. data/lib/new_relic/agent/instrumentation/excon.rb +1 -1
  40. data/lib/new_relic/agent/instrumentation/fiber/chain.rb +1 -1
  41. data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +1 -1
  42. data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -4
  43. data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +1 -1
  44. data/lib/new_relic/agent/instrumentation/httpx.rb +1 -1
  45. data/lib/new_relic/agent/instrumentation/logstasher.rb +1 -1
  46. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +1 -1
  47. data/lib/new_relic/agent/instrumentation/memcache/helper.rb +2 -2
  48. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +1 -1
  49. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +1 -1
  50. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +1 -1
  51. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +3 -3
  52. data/lib/new_relic/agent/instrumentation/net_http.rb +2 -1
  53. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +0 -2
  54. data/lib/new_relic/agent/instrumentation/rake.rb +1 -1
  55. data/lib/new_relic/agent/instrumentation/rdkafka/chain.rb +2 -2
  56. data/lib/new_relic/agent/instrumentation/rdkafka/prepend.rb +2 -2
  57. data/lib/new_relic/agent/instrumentation/redis/constants.rb +2 -2
  58. data/lib/new_relic/agent/instrumentation/resque.rb +2 -2
  59. data/lib/new_relic/agent/instrumentation/roda.rb +1 -1
  60. data/lib/new_relic/agent/instrumentation/ruby_kafka/prepend.rb +1 -1
  61. data/lib/new_relic/agent/instrumentation/ruby_openai.rb +2 -2
  62. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delay_extensions.rb +24 -0
  63. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +1 -1
  64. data/lib/new_relic/agent/instrumentation/sidekiq.rb +9 -1
  65. data/lib/new_relic/agent/instrumentation/stripe.rb +1 -1
  66. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +2 -2
  67. data/lib/new_relic/agent/llm/chat_completion_summary.rb +1 -1
  68. data/lib/new_relic/agent/llm/embedding.rb +1 -1
  69. data/lib/new_relic/agent/local_log_decorator.rb +1 -1
  70. data/lib/new_relic/agent/logging.rb +1 -1
  71. data/lib/new_relic/agent/messaging.rb +5 -0
  72. data/lib/new_relic/agent/method_tracer.rb +3 -0
  73. data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
  74. data/lib/new_relic/agent/monitors/synthetics_monitor.rb +1 -1
  75. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +2 -2
  76. data/lib/new_relic/agent/new_relic_service.rb +2 -2
  77. data/lib/new_relic/agent/opentelemetry/context/propagation/trace_propagator.rb +66 -0
  78. data/lib/new_relic/agent/opentelemetry/context/propagation.rb +15 -0
  79. data/lib/{tasks/instrumentation_generator/templates/Envfile.tt → new_relic/agent/opentelemetry/context.rb} +9 -5
  80. data/lib/new_relic/agent/opentelemetry/trace/span.rb +31 -0
  81. data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +129 -0
  82. data/lib/new_relic/agent/opentelemetry/trace/tracer_provider.rb +18 -0
  83. data/lib/new_relic/agent/opentelemetry/trace.rb +15 -0
  84. data/lib/new_relic/agent/opentelemetry/transaction_patch.rb +69 -0
  85. data/lib/new_relic/agent/opentelemetry_bridge.rb +32 -0
  86. data/lib/new_relic/agent/parameter_filtering.rb +1 -1
  87. data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
  88. data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
  89. data/lib/new_relic/agent/serverless_handler.rb +7 -1
  90. data/lib/new_relic/agent/span_event_primitive.rb +8 -1
  91. data/lib/new_relic/agent/tracer.rb +1 -1
  92. data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -1
  93. data/lib/new_relic/agent/transaction/datastore_segment.rb +1 -1
  94. data/lib/new_relic/agent/transaction/distributed_tracer.rb +3 -3
  95. data/lib/new_relic/agent/transaction/message_broker_segment.rb +1 -1
  96. data/lib/new_relic/agent/transaction/request_attributes.rb +1 -6
  97. data/lib/new_relic/agent/transaction/trace_context.rb +33 -4
  98. data/lib/new_relic/agent/transaction/tracing.rb +3 -3
  99. data/lib/new_relic/agent/transaction.rb +2 -1
  100. data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -1
  101. data/lib/new_relic/agent/utilization/ecs.rb +22 -0
  102. data/lib/new_relic/agent/utilization/ecs_v4.rb +22 -0
  103. data/lib/new_relic/agent/utilization_data.rb +40 -5
  104. data/lib/new_relic/agent/vm/c_ruby_vm.rb +3 -3
  105. data/lib/new_relic/agent.rb +28 -0
  106. data/lib/new_relic/constants.rb +1 -0
  107. data/lib/new_relic/control/instance_methods.rb +5 -0
  108. data/lib/new_relic/control/instrumentation.rb +1 -1
  109. data/lib/new_relic/dependency_detection.rb +0 -1
  110. data/lib/new_relic/helper.rb +7 -0
  111. data/lib/new_relic/version.rb +1 -1
  112. data/lib/sequel/extensions/new_relic_instrumentation.rb +1 -1
  113. data/lib/tasks/helpers/newrelicyml.rb +6 -2
  114. data/newrelic.yml +80 -43
  115. data/newrelic_rpm.gemspec +1 -1
  116. metadata +17 -19
  117. data/lib/tasks/instrumentation_generator/README.md +0 -63
  118. data/lib/tasks/instrumentation_generator/TODO.md +0 -33
  119. data/lib/tasks/instrumentation_generator/instrumentation.thor +0 -130
  120. data/lib/tasks/instrumentation_generator/templates/chain.tt +0 -21
  121. data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -7
  122. data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +0 -32
  123. data/lib/tasks/instrumentation_generator/templates/instrumentation.tt +0 -13
  124. data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +0 -3
  125. data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +0 -19
  126. data/lib/tasks/instrumentation_generator/templates/prepend.tt +0 -13
  127. data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +0 -3
  128. data/lib/tasks/instrumentation_generator/templates/test.tt +0 -15
@@ -8,7 +8,7 @@ module NewRelic
8
8
  module Agent
9
9
  module Instrumentation
10
10
  class ActiveJobSubscriber < NotificationsSubscriber
11
- PAYLOAD_KEYS = %i[adapter db_runtime error job wait]
11
+ PAYLOAD_KEYS = %i[adapter db_runtime error job wait jobs]
12
12
 
13
13
  def add_segment_params(segment, payload)
14
14
  PAYLOAD_KEYS.each do |key|
@@ -16,8 +16,12 @@ module NewRelic
16
16
  end
17
17
  end
18
18
 
19
+ # NOTE: For `enqueue_all.active_job`, only the first job is used to determine the queue.
20
+ # Therefore, this assumes all jobs given as arguments for perform_all_later share the same queue.
19
21
  def metric_name(name, payload)
20
- queue = payload[:job].queue_name
22
+ job = payload[:job] || payload[:jobs].first
23
+
24
+ queue = job.queue_name
21
25
  method = method_from_name(name)
22
26
  "Ruby/ActiveJob/#{queue}/#{method}"
23
27
  end
@@ -13,7 +13,8 @@ module NewRelic
13
13
  end
14
14
 
15
15
  def self.insert_instrumentation
16
- if defined?(::ActiveRecord::VERSION::MAJOR) && ::ActiveRecord::VERSION::MAJOR.to_i >= 3
16
+ if defined?(::ActiveRecord::VERSION::MAJOR) &&
17
+ NewRelic::Helper.version_satisfied?(::ActiveRecord::VERSION::MAJOR, '>=', 3)
17
18
  if ::NewRelic::Agent.config[:prepend_active_record_instrumentation]
18
19
  ::ActiveRecord::Base.prepend(::NewRelic::Agent::Instrumentation::ActiveRecordPrepend::BaseExtensions)
19
20
  ::ActiveRecord::Relation.prepend(::NewRelic::Agent::Instrumentation::ActiveRecordPrepend::RelationExtensions)
@@ -37,7 +38,7 @@ module NewRelic
37
38
  end
38
39
  end
39
40
 
40
- if RUBY_VERSION < '2.7.0'
41
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
41
42
  def log_with_newrelic_instrumentation(*args, &block)
42
43
  state = NewRelic::Agent::Tracer.state
43
44
 
@@ -137,7 +138,7 @@ DependencyDetection.defer do
137
138
  depends_on do
138
139
  defined?(ActiveRecord) && defined?(ActiveRecord::Base) &&
139
140
  (!defined?(ActiveRecord::VERSION) ||
140
- ActiveRecord::VERSION::MAJOR.to_i <= 3)
141
+ NewRelic::Helper.version_satisfied?(ActiveRecord::VERSION::MAJOR, '<=', 3))
141
142
  end
142
143
 
143
144
  depends_on do
@@ -151,7 +152,8 @@ DependencyDetection.defer do
151
152
  executes do
152
153
  require 'new_relic/agent/instrumentation/active_record_helper'
153
154
 
154
- if defined?(Rails::VERSION::MAJOR) && Rails::VERSION::MAJOR.to_i == 3
155
+ if defined?(Rails::VERSION::MAJOR) &&
156
+ NewRelic::Helper.version_satisfied?(Rails::VERSION::MAJOR, '==', 3)
155
157
  ActiveSupport.on_load(:active_record) do
156
158
  NewRelic::Agent::Instrumentation::ActiveRecord.insert_instrumentation
157
159
  end
@@ -49,7 +49,7 @@ module NewRelic
49
49
 
50
50
  alias_method(:delete_all_without_newrelic, :delete_all)
51
51
 
52
- if RUBY_VERSION < '2.7.0'
52
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
53
53
  def delete_all(*args, &blk)
54
54
  ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
55
55
  delete_all_without_newrelic(*args, &blk)
@@ -235,7 +235,7 @@ module NewRelic
235
235
  }.freeze
236
236
 
237
237
  DEFAULT = 'default'.freeze
238
- UNKNOWN = 'unknown'.freeze
238
+ UNKNOWN = NewRelic::UNKNOWN_LOWER
239
239
  LOCALHOST = 'localhost'.freeze
240
240
 
241
241
  def adapter_from_config(config)
@@ -28,7 +28,7 @@ module NewRelic
28
28
  ) { yield }
29
29
  rescue => e
30
30
  # The translate_exception_class method got introduced in 4.1
31
- if ::ActiveRecord::VERSION::MINOR == 0
31
+ if NewRelic::Helper.version_satisfied?(::ActiveRecord::VERSION::MINOR, '==', 0)
32
32
  raise translate_exception(e, sql)
33
33
  else
34
34
  raise translate_exception_class(e, sql)
@@ -86,7 +86,7 @@ DependencyDetection.defer do
86
86
  depends_on do
87
87
  defined?(ActiveRecord) && defined?(ActiveRecord::Base) &&
88
88
  defined?(ActiveRecord::VERSION) &&
89
- ActiveRecord::VERSION::MAJOR.to_i >= 4
89
+ NewRelic::Helper.version_satisfied?(ActiveRecord::VERSION::MAJOR, '>=', 4)
90
90
  end
91
91
 
92
92
  depends_on do
@@ -113,7 +113,7 @@ DependencyDetection.defer do
113
113
 
114
114
  # Default to .prepending, unless the ActiveRecord version is <=4
115
115
  # **AND** the :prepend_active_record_instrumentation config is false
116
- if ActiveRecord::VERSION::MAJOR > 4 \
116
+ if NewRelic::Helper.version_satisfied?(ActiveRecord::VERSION::MAJOR, '>', 4) \
117
117
  || NewRelic::Agent.config[:prepend_active_record_instrumentation]
118
118
 
119
119
  ActiveRecord::Base.send(:prepend,
@@ -131,11 +131,13 @@ DependencyDetection.defer do
131
131
  major_version = ActiveRecord::VERSION::MAJOR.to_i
132
132
  minor_version = ActiveRecord::VERSION::MINOR.to_i
133
133
 
134
- activerecord_extension = if major_version == 4
134
+ activerecord_extension = if NewRelic::Helper.version_satisfied?(major_version, '==', 4)
135
135
  NewRelic::Agent::Instrumentation::ActiveRecordNotifications::BaseExtensions4x
136
- elsif major_version == 5 && minor_version == 0
136
+ elsif NewRelic::Helper.version_satisfied?(major_version, '==', 5) &&
137
+ NewRelic::Helper.version_satisfied?(minor_version, '==', 0)
137
138
  NewRelic::Agent::Instrumentation::ActiveRecordNotifications::BaseExtensions50
138
- elsif major_version == 5 && minor_version == 1
139
+ elsif NewRelic::Helper.version_satisfied?(major_version, '==', 5) &&
140
+ NewRelic::Helper.version_satisfied?(minor_version, '==', 1)
139
141
  NewRelic::Agent::Instrumentation::ActiveRecordNotifications::BaseExtensions51
140
142
  end
141
143
 
@@ -146,9 +148,9 @@ DependencyDetection.defer do
146
148
  end
147
149
 
148
150
  executes do
149
- if ActiveRecord::VERSION::MAJOR == 5 \
150
- && ActiveRecord::VERSION::MINOR.to_i == 1 \
151
- && ActiveRecord::VERSION::TINY.to_i >= 6
151
+ if NewRelic::Helper.version_satisfied?(ActiveRecord::VERSION::MAJOR, '==', 5) \
152
+ && NewRelic::Helper.version_satisfied?(ActiveRecord::VERSION::MINOR, '==', 1) \
153
+ && NewRelic::Helper.version_satisfied?(ActiveRecord::VERSION::TINY, '>=', 6)
152
154
 
153
155
  ActiveRecord::Base.prepend(NewRelic::Agent::Instrumentation::ActiveRecordPrepend::BaseExtensions516)
154
156
  end
@@ -11,7 +11,7 @@ module NewRelic
11
11
  ACTIVE_RECORD = 'ActiveRecord'.freeze
12
12
 
13
13
  module BaseExtensions
14
- if RUBY_VERSION < '2.7.0'
14
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
15
15
  def save(*args, &blk)
16
16
  ::NewRelic::Agent.with_database_metric_name(self.class.name, nil, ACTIVE_RECORD) do
17
17
  super
@@ -46,7 +46,7 @@ module NewRelic
46
46
  # Starting in v5.1.6, this call no longer happens. We'll
47
47
  # have to set the database metrics explicitly now.
48
48
  #
49
- if RUBY_VERSION < '2.7.0'
49
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
50
50
  def touch(*args, **kwargs, &blk)
51
51
  ::NewRelic::Agent.with_database_metric_name(self.class.name, nil, ACTIVE_RECORD) do
52
52
  super
@@ -11,7 +11,7 @@ DependencyDetection.defer do
11
11
 
12
12
  depends_on do
13
13
  defined?(Async::HTTP) &&
14
- Gem::Version.new(Async::HTTP::VERSION) >= Gem::Version.new('0.59.0') &&
14
+ NewRelic::Helper.version_satisfied?(Async::HTTP::VERSION, '>=', '0.59.0') &&
15
15
  !defined?(Traces::Backend::NewRelic) # defined in the traces-backend-newrelic gem
16
16
  end
17
17
 
@@ -69,7 +69,7 @@ module NewRelic::Agent::Instrumentation
69
69
  end
70
70
 
71
71
  def get_stream_name(params, arn)
72
- params&.dig(:stream_name) || arn.split('/').last || 'unknown'
72
+ params&.dig(:stream_name) || arn.split('/').last || NewRelic::UNKNOWN_LOWER
73
73
  rescue => e
74
74
  NewRelic::Agent.logger.warn("Failed to get stream name: #{e}")
75
75
  end
@@ -12,7 +12,7 @@ DependencyDetection.defer do
12
12
  depends_on do
13
13
  defined?(Concurrent) &&
14
14
  defined?(Concurrent::VERSION) &&
15
- Gem::Version.new(Concurrent::VERSION) >= Gem::Version.new('1.1.5')
15
+ NewRelic::Helper.version_satisfied?(Concurrent::VERSION, '>=', '1.1.5')
16
16
  end
17
17
 
18
18
  executes do
@@ -54,6 +54,7 @@ module NewRelic
54
54
  # Have NewRelic ignore actions in this controller. Specify the actions as hash options
55
55
  # using :except and :only. If no actions are specified, all actions are ignored.
56
56
  #
57
+ # @!scope class
57
58
  # @api public
58
59
  #
59
60
  def newrelic_ignore(specifiers = {})
@@ -65,6 +66,7 @@ module NewRelic
65
66
  # actions that are not user facing or that skew your overall apdex measurement.
66
67
  # Accepts :except and :only options, as with #newrelic_ignore.
67
68
  #
69
+ # @!scope class
68
70
  # @api public
69
71
  #
70
72
  def newrelic_ignore_apdex(specifiers = {})
@@ -72,6 +74,7 @@ module NewRelic
72
74
  newrelic_ignore_aspect(NR_IGNORE_APDEX_KEY, specifiers)
73
75
  end
74
76
 
77
+ # @!scope class
75
78
  # @api public
76
79
  def newrelic_ignore_enduser(specifiers = {})
77
80
  NewRelic::Agent.record_api_supportability_metric(:newrelic_ignore_enduser)
@@ -159,6 +162,7 @@ module NewRelic
159
162
  # See NewRelic::Agent::Instrumentation::ControllerInstrumentation#perform_action_with_newrelic_trace
160
163
  # for the full list of available options.
161
164
  #
165
+ # @!scope class
162
166
  # @api public
163
167
  #
164
168
  def add_transaction_tracer(method, options = {})
@@ -12,7 +12,7 @@ DependencyDetection.defer do
12
12
 
13
13
  depends_on do
14
14
  defined?(Curl) && defined?(Curl::CURB_VERSION) &&
15
- Gem::Version.new(Curl::CURB_VERSION) >= CURB_MIN_VERSION
15
+ NewRelic::Helper.version_satisfied?(Curl::CURB_VERSION, '>=', CURB_MIN_VERSION)
16
16
  end
17
17
 
18
18
  executes do
@@ -5,8 +5,7 @@
5
5
  module NewRelic::Agent::Instrumentation
6
6
  module Elasticsearch::Chain
7
7
  def self.instrument!
8
- to_instrument = if ::Gem::Version.create(::Elasticsearch::VERSION) <
9
- ::Gem::Version.create('8.0.0')
8
+ to_instrument = if NewRelic::Helper.version_satisfied?(::Elasticsearch::VERSION, '<', '8.0.0')
10
9
  ::Elasticsearch::Transport::Client
11
10
  else
12
11
  ::Elastic::Transport::Client
@@ -102,6 +102,7 @@ module NewRelic::Agent::Instrumentation
102
102
  end
103
103
 
104
104
  def nr_cluster_name
105
+ return unless NewRelic::Agent.config[:'elasticsearch.capture_cluster_name']
105
106
  return @nr_cluster_name if defined?(@nr_cluster_name)
106
107
  return if nr_hosts.empty?
107
108
 
@@ -14,7 +14,7 @@ DependencyDetection.defer do
14
14
  end
15
15
 
16
16
  executes do
17
- to_instrument = if Gem::Version.create(Elasticsearch::VERSION) < Gem::Version.create('8.0.0')
17
+ to_instrument = if NewRelic::Helper.version_satisfied?(Elasticsearch::VERSION, '<', '8.0.0')
18
18
  Elasticsearch::Transport::Client
19
19
  else
20
20
  Elastic::Transport::Client
@@ -18,7 +18,7 @@ DependencyDetection.defer do
18
18
  end
19
19
 
20
20
  depends_on do
21
- defined?(Ethon) && Gem::Version.new(Ethon::VERSION) >= Gem::Version.new('0.12.0')
21
+ defined?(Ethon) && NewRelic::Helper.version_satisfied?(Ethon::VERSION, '>=', '0.12.0')
22
22
  end
23
23
 
24
24
  executes do
@@ -26,7 +26,7 @@ DependencyDetection.defer do
26
26
 
27
27
  executes do
28
28
  excon_version = Gem::Version.new(Excon::VERSION)
29
- if excon_version >= EXCON_MIN_VERSION
29
+ if NewRelic::Helper.version_satisfied?(excon_version, '>=', EXCON_MIN_VERSION)
30
30
  install_excon_instrumentation(excon_version)
31
31
  else
32
32
  NewRelic::Agent.logger.warn("Excon instrumentation requires at least version #{EXCON_MIN_VERSION}")
@@ -10,7 +10,7 @@ module NewRelic::Agent::Instrumentation
10
10
 
11
11
  alias_method(:initialize_without_new_relic, :initialize)
12
12
 
13
- if RUBY_VERSION < '2.7.0'
13
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
14
14
  def initialize(*_args, &block)
15
15
  traced_block = add_thread_tracing(&block)
16
16
  initialize_with_newrelic_tracing { initialize_without_new_relic(&traced_block) }
@@ -9,7 +9,7 @@ module NewRelic::Agent::Instrumentation
9
9
  module Prepend
10
10
  include NewRelic::Agent::Instrumentation::MonitoredFiber
11
11
 
12
- if RUBY_VERSION < '2.7.0'
12
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
13
13
  def initialize(*_args, &block)
14
14
  traced_block = add_thread_tracing(&block)
15
15
  initialize_with_newrelic_tracing { super(&traced_block) }
@@ -16,10 +16,7 @@ DependencyDetection.defer do
16
16
  end
17
17
 
18
18
  depends_on do
19
- minimum_supported_version = Gem::Version.new(HTTPCLIENT_MIN_VERSION)
20
- current_version = Gem::Version.new(HTTPClient::VERSION)
21
-
22
- current_version >= minimum_supported_version
19
+ NewRelic::Helper.version_satisfied?(HTTPClient::VERSION, '>=', HTTPCLIENT_MIN_VERSION)
23
20
  end
24
21
 
25
22
  executes do
@@ -30,7 +30,7 @@ module NewRelic::Agent::Instrumentation::HTTPX
30
30
 
31
31
  def nr_finish_segment
32
32
  proc do |request, segment|
33
- response = @responses[request]
33
+ response = request.response if request
34
34
 
35
35
  unless response
36
36
  NewRelic::Agent.logger.debug('Processed an on-response callback for HTTPX but could not find the response!')
@@ -10,7 +10,7 @@ DependencyDetection.defer do
10
10
  named :httpx
11
11
 
12
12
  depends_on do
13
- defined?(HTTPX) && Gem::Version.new(HTTPX::VERSION) >= Gem::Version.new('1.0.0')
13
+ defined?(HTTPX) && NewRelic::Helper.version_satisfied?(HTTPX::VERSION, '>=', '1.0.0')
14
14
  end
15
15
 
16
16
  executes do
@@ -11,7 +11,7 @@ DependencyDetection.defer do
11
11
 
12
12
  depends_on do
13
13
  defined?(LogStasher) &&
14
- Gem::Version.new(LogStasher::VERSION) >= Gem::Version.new('1.0.0') &&
14
+ NewRelic::Helper.version_satisfied?(LogStasher::VERSION, '>=', '1.0.0') &&
15
15
  NewRelic::Agent.config[:'application_logging.enabled']
16
16
  end
17
17
 
@@ -61,7 +61,7 @@ module NewRelic
61
61
  # TODO: MAJOR VERSION
62
62
  # Dalli - 3.1.0 renamed send_multiget to pipelined_get, but the method is otherwise the same
63
63
  # Once we no longer support Dalli < 3.1.0, remove this conditional logic
64
- if Gem::Version.new(::Dalli::VERSION) >= Gem::Version.new('3.1.0')
64
+ if NewRelic::Helper.version_satisfied?(::Dalli::VERSION, '>=', '3.1.0')
65
65
  alias_method(:pipelined_get_without_newrelic_trace, :pipelined_get)
66
66
  def pipelined_get(keys)
67
67
  send_multiget_with_newrelic_tracing(keys) { pipelined_get_without_newrelic_trace(keys) }
@@ -9,11 +9,11 @@ module NewRelic::Agent::Instrumentation
9
9
  BINARY_PROTOCOL_SUPPORTED_VERSION = Gem::Version.new('3.0.2')
10
10
 
11
11
  def supports_datastore_instances?
12
- DATASTORE_INSTANCES_SUPPORTED_VERSION <= Gem::Version.new(::Dalli::VERSION)
12
+ NewRelic::Helper.version_satisfied?(DATASTORE_INSTANCES_SUPPORTED_VERSION, '<=', ::Dalli::VERSION)
13
13
  end
14
14
 
15
15
  def supports_binary_protocol?
16
- BINARY_PROTOCOL_SUPPORTED_VERSION <= Gem::Version.new(::Dalli::VERSION)
16
+ NewRelic::Helper.version_satisfied?(BINARY_PROTOCOL_SUPPORTED_VERSION, '<=', ::Dalli::VERSION)
17
17
  end
18
18
 
19
19
  def client_methods
@@ -6,7 +6,7 @@ module NewRelic::Agent::Instrumentation
6
6
  module Memcache
7
7
  module Tracer
8
8
  SLASH = '/'
9
- UNKNOWN = 'unknown'
9
+ UNKNOWN = NewRelic::UNKNOWN_LOWER
10
10
  LOCALHOST = 'localhost'
11
11
  MULTIGET_METRIC_NAME = 'get_multi_request'
12
12
  MEMCACHED = 'Memcached'
@@ -87,7 +87,7 @@ module NewRelic::Agent::Instrumentation
87
87
  # TODO: MAJOR VERSION
88
88
  # Dalli - 3.1.0 renamed send_multiget to pipelined_get, but the method is otherwise the same
89
89
  # Once we no longer support Dalli < 3.1.0, remove this conditional logic
90
- if Gem::Version.new(::Dalli::VERSION) >= Gem::Version.new('3.1.0')
90
+ if NewRelic::Helper.version_satisfied?(::Dalli::VERSION, '>=', '3.1.0')
91
91
  def pipelined_get(keys)
92
92
  send_multiget_with_newrelic_tracing(keys) { super }
93
93
  end
@@ -106,7 +106,7 @@ module NewRelic
106
106
  )
107
107
  end
108
108
 
109
- UNKNOWN = 'unknown'.freeze
109
+ UNKNOWN = NewRelic::UNKNOWN_LOWER
110
110
  LOCALHOST = 'localhost'.freeze
111
111
 
112
112
  def host_from_address(address)
@@ -21,7 +21,7 @@ module NewRelic
21
21
 
22
22
  begin
23
23
  response = nil
24
- segment.add_request_headers(wrapped_request)
24
+ segment&.add_request_headers(wrapped_request)
25
25
 
26
26
  # RUBY-1244 Disable further tracing in request to avoid double
27
27
  # counting if connection wasn't started (which calls request again).
@@ -34,10 +34,10 @@ module NewRelic
34
34
  wrapped_response = NewRelic::Agent::HTTPClients::NetHTTPResponse.new(response)
35
35
 
36
36
  if NewRelic::Agent::LLM.openai_parent?(segment)
37
- NewRelic::Agent::LLM.populate_openai_response_headers(wrapped_response, segment.parent)
37
+ NewRelic::Agent::LLM.populate_openai_response_headers(wrapped_response, segment&.parent)
38
38
  end
39
39
 
40
- segment.process_response_headers(wrapped_response)
40
+ segment&.process_response_headers(wrapped_response)
41
41
 
42
42
  response
43
43
  ensure
@@ -19,7 +19,8 @@ DependencyDetection.defer do
19
19
 
20
20
  # Airbrake uses method chaining on Net::HTTP in versions < 10.0.2 (10.0.2 updated to prepend for Net:HTTP)
21
21
  conflicts_with_prepend do
22
- defined?(Airbrake) && defined?(Airbrake::AIRBRAKE_VERSION) && Gem::Version.create(Airbrake::AIRBRAKE_VERSION) < Gem::Version.create('10.0.2')
22
+ defined?(Airbrake) && defined?(Airbrake::AIRBRAKE_VERSION) &&
23
+ NewRelic::Helper.version_satisfied?(Airbrake::AIRBRAKE_VERSION, '<', '10.0.2')
23
24
  end
24
25
 
25
26
  conflicts_with_prepend do
@@ -16,8 +16,6 @@ module NewRelic
16
16
  end
17
17
 
18
18
  def self.find_all_subscribers
19
- # TODO: need to talk to Rails core about an API for this,
20
- # rather than digging through Listener ivars
21
19
  instance_variable_names = [:@subscribers, :@string_subscribers, :@other_subscribers]
22
20
  all_subscribers = []
23
21
 
@@ -12,7 +12,7 @@ DependencyDetection.defer do
12
12
  configure_with :rake
13
13
 
14
14
  depends_on { defined?(Rake) && defined?(Rake::VERSION) }
15
- depends_on { Gem::Version.new(Rake::VERSION) >= Gem::Version.new('10.0.0') }
15
+ depends_on { NewRelic::Helper.version_satisfied?(Rake::VERSION, '>=', '10.0.0') }
16
16
  depends_on { NewRelic::Agent.config[:'rake.tasks'].any? }
17
17
  depends_on { NewRelic::Agent::Instrumentation::Rake.safe_from_third_party_gem? }
18
18
 
@@ -40,8 +40,8 @@ module NewRelic::Agent::Instrumentation
40
40
  alias_method(:producer_without_new_relic, :producer)
41
41
  alias_method(:consumer_without_new_relic, :consumer)
42
42
 
43
- if Gem::Version.new(::Rdkafka::VERSION) >= Gem::Version.new('0.16.0') ||
44
- (Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0'))
43
+ if NewRelic::Helper.version_satisfied?(::Rdkafka::VERSION, '>=', '0.16.0') ||
44
+ NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '2.7.0')
45
45
  def producer(**kwargs)
46
46
  producer_without_new_relic(**kwargs).tap do |producer|
47
47
  set_nr_config(producer)
@@ -36,8 +36,8 @@ module NewRelic::Agent::Instrumentation
36
36
  module Prepend
37
37
  include NewRelic::Agent::Instrumentation::RdkafkaConfig
38
38
 
39
- if (defined?(::Rdkafka) && Gem::Version.new(::Rdkafka::VERSION) >= Gem::Version.new('0.16.0')) ||
40
- (Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0'))
39
+ if (defined?(::Rdkafka) && NewRelic::Helper.version_satisfied?(::Rdkafka::VERSION, '>=', '0.16.0')) ||
40
+ NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '2.7.0')
41
41
  def producer(**kwargs)
42
42
  super.tap do |producer|
43
43
  set_nr_config(producer)
@@ -6,12 +6,12 @@ module NewRelic::Agent::Instrumentation::Redis
6
6
  class Constants
7
7
  PRODUCT_NAME = 'Redis'
8
8
  CONNECT = 'connect'
9
- UNKNOWN = 'unknown'
9
+ UNKNOWN = NewRelic::UNKNOWN_LOWER
10
10
  LOCALHOST = 'localhost'
11
11
  MULTI_OPERATION = 'multi'
12
12
  PIPELINE_OPERATION = 'pipeline'
13
13
  HAS_REDIS_CLIENT = defined?(::Redis) &&
14
- Gem::Version.new(::Redis::VERSION) >= Gem::Version.new('5.0.0') &&
14
+ NewRelic::Helper.version_satisfied?(::Redis::VERSION, '>=', '5.0.0') &&
15
15
  !defined?(::RedisClient).nil?
16
16
  end
17
17
  end
@@ -15,7 +15,7 @@ DependencyDetection.defer do
15
15
 
16
16
  # Airbrake uses method chaining on Resque::Job on versions < 11.0.3
17
17
  conflicts_with_prepend do
18
- defined?(Airbrake) && defined?(Airbrake::AIRBRAKE_VERSION) && Gem::Version.create(Airbrake::AIRBRAKE_VERSION) < Gem::Version.create('11.0.3')
18
+ defined?(Airbrake) && defined?(Airbrake::AIRBRAKE_VERSION) && NewRelic::Helper.version_satisfied?(Airbrake::AIRBRAKE_VERSION, '<', '11.0.3')
19
19
  end
20
20
 
21
21
  executes do
@@ -25,7 +25,7 @@ DependencyDetection.defer do
25
25
  # we don't believe this lib is still necessary for Ruby 3.4 users.
26
26
  # however, if we receive customer feedback to the contrary, we can find
27
27
  # an alternate approach.
28
- Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.4')
28
+ NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '3.4')
29
29
  NewRelic::Agent.logger.info('Requiring resolv-replace')
30
30
  require 'resolv'
31
31
  require 'resolv-replace'
@@ -11,7 +11,7 @@ DependencyDetection.defer do
11
11
 
12
12
  depends_on do
13
13
  defined?(Roda) &&
14
- Gem::Version.new(Roda::RodaVersion) >= Gem::Version.new('3.19.0') &&
14
+ NewRelic::Helper.version_satisfied?(Roda::RodaVersion, '>=', '3.19.0') &&
15
15
  Roda::RodaPlugins::Base::ClassMethods.private_method_defined?(:build_rack_app) &&
16
16
  Roda::RodaPlugins::Base::InstanceMethods.method_defined?(:_roda_handle_main_route)
17
17
  end
@@ -20,7 +20,7 @@ module NewRelic::Agent::Instrumentation
20
20
  module Prepend
21
21
  include NewRelic::Agent::Instrumentation::RubyKafka
22
22
 
23
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3')
23
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '3')
24
24
  def each_message(**args)
25
25
  super do |message|
26
26
  each_message_with_new_relic(message) do
@@ -12,13 +12,13 @@ DependencyDetection.defer do
12
12
  depends_on do
13
13
  NewRelic::Agent.config[:'ai_monitoring.enabled'] &&
14
14
  defined?(OpenAI) && defined?(OpenAI::Client) &&
15
- Gem::Version.new(OpenAI::VERSION) >= Gem::Version.new('3.4.0')
15
+ NewRelic::Helper.version_satisfied?(OpenAI::VERSION, '>=', '3.4.0')
16
16
  end
17
17
 
18
18
  executes do
19
19
  if use_prepend?
20
20
  # TODO: Remove condition when we drop support for versions below 5.0.0
21
- if Gem::Version.new(OpenAI::VERSION) >= Gem::Version.new('5.0.0')
21
+ if NewRelic::Helper.version_satisfied?(OpenAI::VERSION, '>=', '5.0.0')
22
22
  prepend_instrument OpenAI::Client,
23
23
  NewRelic::Agent::Instrumentation::OpenAI::Prepend,
24
24
  NewRelic::Agent::Instrumentation::OpenAI::VENDOR
@@ -0,0 +1,24 @@
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
+ if defined?(Sidekiq::DelayExtensions)
6
+ class Sidekiq::DelayExtensions::GenericJob
7
+ def newrelic_trace_args(msg, queue)
8
+ (target, method_name, *) = ::Sidekiq::DelayExtensions::YAML.unsafe_load(msg['args'][0])
9
+
10
+ if target.is_a?(String)
11
+ target = target.constantize
12
+ end
13
+
14
+ {
15
+ :name => method_name,
16
+ :class_name => target.class.name,
17
+ :category => 'OtherTransaction/SidekiqJob'
18
+ }
19
+ rescue => e
20
+ NewRelic::Agent.logger.error('Failure during deserializing YAML for Sidekiq::DelayExtensions::GenericJob', e)
21
+ NewRelic::Agent::Instrumentation::Sidekiq::Server.default_trace_args(msg)
22
+ end
23
+ end
24
+ end
@@ -8,7 +8,7 @@
8
8
  #
9
9
  # see https://github.com/sidekiq/sidekiq/issues/5076 for the discussion
10
10
  # of the removal, which includes mentions of alternatives
11
- if defined?(Sidekiq::VERSION) && Sidekiq::VERSION < '7.0.0'
11
+ if defined?(Sidekiq::VERSION) && NewRelic::Helper.version_satisfied?(Sidekiq::VERSION, '<', '7.0.0')
12
12
  class Sidekiq::Extensions::DelayedClass
13
13
  def newrelic_trace_args(msg, queue)
14
14
  (target, method_name, _args) = if YAML.respond_to?(:unsafe_load)
@@ -5,6 +5,7 @@
5
5
  require_relative 'sidekiq/client'
6
6
  require_relative 'sidekiq/server'
7
7
  require_relative 'sidekiq/extensions/delayed_class'
8
+ require_relative 'sidekiq/extensions/delay_extensions'
8
9
 
9
10
  DependencyDetection.defer do
10
11
  @name = :sidekiq
@@ -29,7 +30,14 @@ DependencyDetection.defer do
29
30
  chain.add(NewRelic::Agent::Instrumentation::Sidekiq::Client)
30
31
  end
31
32
  config.server_middleware do |chain|
32
- chain.add(NewRelic::Agent::Instrumentation::Sidekiq::Server)
33
+ # We started prepending v chaining NR middleware in 9.18.0 in response to:
34
+ # https://github.com/newrelic/newrelic-ruby-agent/issues/3037
35
+ # This way, exceptions resolved by Sidekiq's own middleware are not reported in the agent
36
+ if chain.respond_to?(:prepend)
37
+ chain.prepend(NewRelic::Agent::Instrumentation::Sidekiq::Server)
38
+ else
39
+ chain.add(NewRelic::Agent::Instrumentation::Sidekiq::Server)
40
+ end
33
41
  end
34
42
 
35
43
  if config.respond_to?(:error_handlers)
@@ -13,7 +13,7 @@ DependencyDetection.defer do
13
13
 
14
14
  depends_on do
15
15
  defined?(Stripe) &&
16
- Gem::Version.new(Stripe::VERSION) >= Gem::Version.new('5.38.0')
16
+ NewRelic::Helper.version_satisfied?(Stripe::VERSION, '>=', '5.38.0')
17
17
  end
18
18
 
19
19
  executes do