newrelic_rpm 9.9.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.
- checksums.yaml +4 -4
- data/.build_ignore +1 -0
- data/CHANGELOG.md +463 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +16 -17
- data/Rakefile +1 -1
- data/lib/boot/strap.rb +102 -0
- data/lib/new_relic/agent/agent.rb +6 -0
- data/lib/new_relic/agent/agent_helpers/connect.rb +3 -0
- data/lib/new_relic/agent/agent_helpers/harvest.rb +3 -0
- data/lib/new_relic/agent/agent_helpers/shutdown.rb +3 -0
- data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +1 -0
- data/lib/new_relic/agent/agent_helpers/startup.rb +7 -0
- data/lib/new_relic/agent/agent_logger.rb +1 -0
- data/lib/new_relic/agent/aws.rb +68 -0
- data/lib/new_relic/agent/configuration/default_source.rb +603 -105
- data/lib/new_relic/agent/configuration/environment_source.rb +5 -1
- data/lib/new_relic/agent/configuration/manager.rb +28 -2
- data/lib/new_relic/agent/configuration/yaml_source.rb +7 -2
- data/lib/new_relic/agent/database/obfuscation_helpers.rb +11 -11
- data/lib/new_relic/agent/database/obfuscator.rb +1 -0
- data/lib/new_relic/agent/database.rb +41 -1
- data/lib/new_relic/agent/database_adapter.rb +1 -1
- data/lib/new_relic/agent/datastores/redis.rb +1 -1
- data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -1
- data/lib/new_relic/agent/distributed_tracing.rb +4 -2
- data/lib/new_relic/agent/error_collector.rb +37 -10
- data/lib/new_relic/agent/external.rb +2 -0
- data/lib/new_relic/agent/health_check.rb +136 -0
- data/lib/new_relic/agent/http_clients/uri_util.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_dispatch.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_mailbox.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_mailer.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +6 -2
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +0 -13
- data/lib/new_relic/agent/instrumentation/active_record.rb +7 -12
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +7 -3
- data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +11 -9
- data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +2 -2
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +9 -16
- data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger.rb +0 -2
- data/lib/new_relic/agent/instrumentation/active_support_logger.rb +0 -2
- data/lib/new_relic/agent/instrumentation/async_http.rb +2 -3
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/instrumentation.rb +66 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose.rb +22 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/instrumentation.rb +91 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis.rb +22 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/chain.rb +33 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/instrumentation.rb +93 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/prepend.rb +23 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda.rb +23 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs/chain.rb +37 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs/instrumentation.rb +67 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs/prepend.rb +21 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs.rb +23 -0
- data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +14 -0
- data/lib/new_relic/agent/instrumentation/bunny.rb +3 -4
- data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +1 -3
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/curb.rb +4 -5
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +0 -23
- data/lib/new_relic/agent/instrumentation/dynamodb/chain.rb +27 -0
- data/lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb +64 -0
- data/lib/new_relic/agent/instrumentation/dynamodb/prepend.rb +19 -0
- data/lib/new_relic/agent/instrumentation/dynamodb.rb +23 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +1 -2
- data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +53 -7
- data/lib/new_relic/agent/instrumentation/elasticsearch.rb +1 -3
- data/lib/new_relic/agent/instrumentation/ethon.rb +1 -5
- data/lib/new_relic/agent/instrumentation/excon.rb +1 -17
- data/lib/new_relic/agent/instrumentation/fiber/chain.rb +1 -1
- data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +1 -1
- data/lib/new_relic/agent/instrumentation/fiber.rb +0 -2
- data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +0 -3
- data/lib/new_relic/agent/instrumentation/grape.rb +1 -1
- data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -5
- data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/httpx.rb +1 -5
- data/lib/new_relic/agent/instrumentation/logger.rb +1 -3
- data/lib/new_relic/agent/instrumentation/logstasher/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/logstasher/instrumentation.rb +24 -0
- data/lib/new_relic/agent/instrumentation/logstasher/prepend.rb +13 -0
- data/lib/new_relic/agent/instrumentation/logstasher.rb +25 -0
- data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache/helper.rb +2 -2
- data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache.rb +0 -1
- data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +3 -3
- data/lib/new_relic/agent/instrumentation/net_http.rb +2 -1
- data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +0 -2
- data/lib/new_relic/agent/instrumentation/opensearch/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/opensearch/instrumentation.rb +66 -0
- data/lib/{tasks/instrumentation_generator/templates/instrumentation.tt → new_relic/agent/instrumentation/opensearch/prepend.rb} +4 -4
- data/lib/new_relic/agent/instrumentation/opensearch.rb +23 -0
- data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
- data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +3 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +9 -5
- data/lib/new_relic/agent/instrumentation/rake.rb +1 -2
- data/lib/new_relic/agent/instrumentation/rdkafka/chain.rb +72 -0
- data/lib/new_relic/agent/instrumentation/rdkafka/instrumentation.rb +70 -0
- data/lib/new_relic/agent/instrumentation/rdkafka/prepend.rb +67 -0
- data/lib/new_relic/agent/instrumentation/rdkafka.rb +25 -0
- data/lib/new_relic/agent/instrumentation/redis/cluster_middleware.rb +26 -0
- data/lib/new_relic/agent/instrumentation/redis/constants.rb +2 -2
- data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +14 -11
- data/lib/new_relic/agent/instrumentation/redis/middleware.rb +3 -0
- data/lib/new_relic/agent/instrumentation/redis.rb +11 -5
- data/lib/new_relic/agent/instrumentation/resque.rb +8 -6
- data/lib/new_relic/agent/instrumentation/roda.rb +5 -5
- data/lib/new_relic/agent/instrumentation/ruby_kafka/chain.rb +55 -0
- data/lib/new_relic/agent/instrumentation/ruby_kafka/instrumentation.rb +67 -0
- data/lib/new_relic/agent/instrumentation/ruby_kafka/prepend.rb +60 -0
- data/lib/new_relic/agent/instrumentation/ruby_kafka.rb +25 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai.rb +2 -2
- data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delay_extensions.rb +24 -0
- data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +2 -2
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +9 -15
- data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -19
- data/lib/new_relic/agent/instrumentation/stripe.rb +1 -1
- data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +22 -1
- data/lib/new_relic/agent/instrumentation/thread.rb +0 -2
- data/lib/new_relic/agent/instrumentation/tilt.rb +0 -4
- data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +2 -2
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
- data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +11 -5
- data/lib/new_relic/agent/instrumentation/view_component.rb +0 -2
- data/lib/new_relic/agent/javascript_instrumentor.rb +2 -3
- data/lib/new_relic/agent/llm/chat_completion_summary.rb +1 -1
- data/lib/new_relic/agent/llm/embedding.rb +1 -1
- data/lib/new_relic/agent/local_log_decorator.rb +20 -3
- data/lib/new_relic/agent/log_event_aggregator.rb +119 -28
- data/lib/new_relic/agent/logging.rb +1 -1
- data/lib/new_relic/agent/messaging.rb +16 -5
- data/lib/new_relic/agent/method_tracer.rb +3 -0
- data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
- data/lib/new_relic/agent/monitors/synthetics_monitor.rb +1 -1
- data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +2 -2
- data/lib/new_relic/agent/new_relic_service.rb +8 -2
- data/lib/new_relic/agent/opentelemetry/context/propagation/trace_propagator.rb +66 -0
- data/lib/new_relic/agent/opentelemetry/context/propagation.rb +15 -0
- data/lib/{tasks/instrumentation_generator/templates/Envfile.tt → new_relic/agent/opentelemetry/context.rb} +9 -5
- data/lib/new_relic/agent/opentelemetry/trace/span.rb +31 -0
- data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +129 -0
- data/lib/new_relic/agent/opentelemetry/trace/tracer_provider.rb +18 -0
- data/lib/new_relic/agent/opentelemetry/trace.rb +15 -0
- data/lib/new_relic/agent/opentelemetry/transaction_patch.rb +69 -0
- data/lib/new_relic/agent/opentelemetry_bridge.rb +32 -0
- data/lib/new_relic/agent/parameter_filtering.rb +1 -1
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
- data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
- data/lib/new_relic/agent/serverless_handler.rb +247 -12
- data/lib/new_relic/agent/serverless_handler_event_sources.json +155 -0
- data/lib/new_relic/agent/serverless_handler_event_sources.rb +49 -0
- data/lib/new_relic/agent/span_event_primitive.rb +16 -11
- data/lib/new_relic/agent/system_info.rb +14 -0
- data/lib/new_relic/agent/threading/backtrace_node.rb +10 -1
- data/lib/new_relic/agent/tracer.rb +1 -1
- data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -1
- data/lib/new_relic/agent/transaction/datastore_segment.rb +1 -1
- data/lib/new_relic/agent/transaction/distributed_tracer.rb +3 -3
- data/lib/new_relic/agent/transaction/external_request_segment.rb +0 -10
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +4 -1
- data/lib/new_relic/agent/transaction/request_attributes.rb +14 -7
- data/lib/new_relic/agent/transaction/trace_context.rb +34 -5
- data/lib/new_relic/agent/transaction/tracing.rb +3 -3
- data/lib/new_relic/agent/transaction.rb +4 -7
- data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -1
- data/lib/new_relic/agent/utilization/ecs.rb +22 -0
- data/lib/new_relic/agent/utilization/ecs_v4.rb +22 -0
- data/lib/new_relic/agent/utilization_data.rb +40 -5
- data/lib/new_relic/agent/vm/c_ruby_vm.rb +3 -3
- data/lib/new_relic/agent.rb +124 -2
- data/lib/new_relic/constants.rb +1 -0
- data/lib/new_relic/control/frameworks/grape.rb +14 -0
- data/lib/new_relic/control/frameworks/padrino.rb +14 -0
- data/lib/new_relic/control/frameworks/rails4.rb +1 -3
- data/lib/new_relic/control/instance_methods.rb +6 -0
- data/lib/new_relic/control/instrumentation.rb +1 -1
- data/lib/new_relic/control/private_instance_methods.rb +4 -0
- data/lib/new_relic/control/security_interface.rb +57 -0
- data/lib/new_relic/control.rb +1 -1
- data/lib/new_relic/dependency_detection.rb +11 -14
- data/lib/new_relic/environment_report.rb +2 -2
- data/lib/new_relic/helper.rb +22 -0
- data/lib/new_relic/language_support.rb +3 -1
- data/lib/new_relic/local_environment.rb +1 -4
- data/lib/new_relic/rack/browser_monitoring.rb +20 -8
- data/lib/new_relic/version.rb +1 -1
- data/lib/sequel/extensions/new_relic_instrumentation.rb +3 -2
- data/lib/tasks/config.rake +7 -3
- data/lib/tasks/gha.rake +31 -0
- data/lib/tasks/helpers/config.html.erb +3 -2
- data/lib/tasks/helpers/format.rb +1 -1
- data/lib/tasks/helpers/newrelicyml.rb +80 -13
- data/newrelic.yml +425 -162
- data/newrelic_rpm.gemspec +3 -1
- data/test/agent_helper.rb +24 -2
- metadata +91 -22
- data/lib/tasks/instrumentation_generator/README.md +0 -63
- data/lib/tasks/instrumentation_generator/TODO.md +0 -33
- data/lib/tasks/instrumentation_generator/instrumentation.thor +0 -121
- data/lib/tasks/instrumentation_generator/templates/chain.tt +0 -21
- data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -7
- data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +0 -29
- data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +0 -3
- data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +0 -19
- data/lib/tasks/instrumentation_generator/templates/prepend.tt +0 -13
- data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +0 -3
- data/lib/tasks/instrumentation_generator/templates/test.tt +0 -15
data/lib/new_relic/agent.rb
CHANGED
@@ -64,6 +64,7 @@ module NewRelic
|
|
64
64
|
require 'new_relic/agent/linking_metadata'
|
65
65
|
require 'new_relic/agent/local_log_decorator'
|
66
66
|
require 'new_relic/agent/llm'
|
67
|
+
require 'new_relic/agent/aws'
|
67
68
|
|
68
69
|
require 'new_relic/agent/instrumentation/controller_instrumentation'
|
69
70
|
|
@@ -84,6 +85,10 @@ module NewRelic
|
|
84
85
|
# An exception that forces an agent to stop reporting until its mongrel is restarted.
|
85
86
|
class ForceDisconnectException < StandardError; end
|
86
87
|
|
88
|
+
# Error handling for the automated custom instrumentation tracer logic
|
89
|
+
class AutomaticTracerParseException < StandardError; end
|
90
|
+
class AutomaticTracerTraceException < StandardError; end
|
91
|
+
|
87
92
|
# An exception that forces an agent to restart.
|
88
93
|
class ForceRestartException < StandardError
|
89
94
|
def message
|
@@ -108,6 +113,9 @@ module NewRelic
|
|
108
113
|
# placeholder name used when we cannot determine a transaction's name
|
109
114
|
UNKNOWN_METRIC = '(unknown)'.freeze
|
110
115
|
LLM_FEEDBACK_MESSAGE = 'LlmFeedbackMessage'
|
116
|
+
# give the observed app time to load the code that automatic tracers have
|
117
|
+
# been configured for
|
118
|
+
AUTOMATIC_TRACER_MAX_ATTEMPTS = 60 # 60 = try about twice a second for 30 seconds
|
111
119
|
|
112
120
|
attr_reader :error_group_callback
|
113
121
|
attr_reader :llm_token_count_callback
|
@@ -124,8 +132,8 @@ module NewRelic
|
|
124
132
|
def agent # :nodoc:
|
125
133
|
return @agent if @agent
|
126
134
|
|
127
|
-
NewRelic::Agent.logger.
|
128
|
-
NewRelic::Agent.logger.
|
135
|
+
NewRelic::Agent.logger.debug("Agent unavailable as it hasn't been started.")
|
136
|
+
NewRelic::Agent.logger.debug(caller.join("\n"))
|
129
137
|
nil
|
130
138
|
end
|
131
139
|
|
@@ -162,6 +170,92 @@ module NewRelic
|
|
162
170
|
end
|
163
171
|
end
|
164
172
|
|
173
|
+
# @api private
|
174
|
+
def self.add_automatic_method_tracers(arr)
|
175
|
+
return unless arr
|
176
|
+
return arr if arr.respond_to?(:empty?) && arr.empty?
|
177
|
+
|
178
|
+
arr = arr.split(/\s*,\s*/) if arr.is_a?(String)
|
179
|
+
|
180
|
+
add_tracers_once_methods_are_defined(arr.dup)
|
181
|
+
|
182
|
+
arr
|
183
|
+
end
|
184
|
+
|
185
|
+
# spawn a thread that will attempt to establish a tracer for each of the
|
186
|
+
# configured methods. the thread will continue to keep trying with each
|
187
|
+
# tracer until one of the following happens:
|
188
|
+
# - the tracer is successfully established
|
189
|
+
# - the configured method string couldn't be parsed
|
190
|
+
# - establishing a tracer for a successfully parsed string failed
|
191
|
+
# - the maximum number of attempts has been reached
|
192
|
+
# the thread will only be spawned once per agent initialization, to account
|
193
|
+
# for configuration reloading scenarios.
|
194
|
+
#
|
195
|
+
# @api private
|
196
|
+
def self.add_tracers_once_methods_are_defined(notations)
|
197
|
+
# this class method can be invoked multiple times at agent startup, so
|
198
|
+
# we return asap here instead of using a traditional memoization of
|
199
|
+
# waiting for the method's body to finish being executed
|
200
|
+
if defined?(@add_tracers_once_methods_are_defined)
|
201
|
+
return
|
202
|
+
else
|
203
|
+
@add_tracers_once_methods_are_defined = true
|
204
|
+
end
|
205
|
+
|
206
|
+
Thread.new do
|
207
|
+
AUTOMATIC_TRACER_MAX_ATTEMPTS.times do
|
208
|
+
notations.delete_if { |notation| prep_tracer_for(notation) }
|
209
|
+
|
210
|
+
break if notations.empty?
|
211
|
+
|
212
|
+
sleep 0.5
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# returns `true` if the notation string has either been successfully
|
218
|
+
# processed or raised an error during processing. returns `false` if the
|
219
|
+
# string seems good but the (customer) code to be traced has not yet been
|
220
|
+
# loaded into the Ruby VM
|
221
|
+
#
|
222
|
+
# @api private
|
223
|
+
def self.prep_tracer_for(fully_qualified_method_notation)
|
224
|
+
delimiters = fully_qualified_method_notation.scan(/\.|#/)
|
225
|
+
raise AutomaticTracerParseException.new("Expected exactly one '.' or '#' delimiter.") unless delimiters.size == 1
|
226
|
+
|
227
|
+
delimiter = delimiters.first
|
228
|
+
namespace, method_name = fully_qualified_method_notation.split(delimiter)
|
229
|
+
unless namespace && !namespace.empty?
|
230
|
+
raise AutomaticTracerParseException.new("Nothing found to the left of the #{delimiter} delimiter.")
|
231
|
+
end
|
232
|
+
unless method_name && !method_name.empty?
|
233
|
+
raise AutomaticTracerParseException.new("Nothing found to the right of the #{delimiter} delimiter.")
|
234
|
+
end
|
235
|
+
|
236
|
+
begin
|
237
|
+
klass = ::NewRelic::LanguageSupport.constantize(namespace)
|
238
|
+
return false unless klass
|
239
|
+
|
240
|
+
klass_to_trace = delimiter.eql?('.') ? klass.singleton_class : klass
|
241
|
+
add_or_defer_method_tracer(klass_to_trace, method_name, nil, {})
|
242
|
+
rescue StandardError => e
|
243
|
+
raise AutomaticTracerTraceException.new("#{e.class} - #{e.message}")
|
244
|
+
end
|
245
|
+
|
246
|
+
true
|
247
|
+
rescue AutomaticTracerParseException => e
|
248
|
+
NewRelic::Agent.logger.error('Unable to parse out a usable method name to trace. Expected a valid, fully ' \
|
249
|
+
"qualified method notation. Got: '#{fully_qualified_method_notation}'. " \
|
250
|
+
"Error: #{e.message}")
|
251
|
+
true
|
252
|
+
rescue AutomaticTracerTraceException => e
|
253
|
+
NewRelic::Agent.logger.error('Unable to automatically apply a tracer to method ' \
|
254
|
+
"'#{fully_qualified_method_notation}'. Error: #{e.message}")
|
255
|
+
true
|
256
|
+
end
|
257
|
+
|
258
|
+
# @api private
|
165
259
|
def add_deferred_method_tracers_now
|
166
260
|
@tracer_lock.synchronize do
|
167
261
|
@tracer_queue.each do |receiver, method_name, metric_name, options|
|
@@ -199,6 +293,7 @@ module NewRelic
|
|
199
293
|
#
|
200
294
|
# This method is safe to use from any thread.
|
201
295
|
#
|
296
|
+
# @!scope class
|
202
297
|
# @api public
|
203
298
|
def record_metric(metric_name, value) # THREAD_LOCAL_ACCESS
|
204
299
|
record_api_supportability_metric(:record_metric)
|
@@ -239,6 +334,7 @@ module NewRelic
|
|
239
334
|
#
|
240
335
|
# This method is safe to use from any thread.
|
241
336
|
#
|
337
|
+
# @!scope class
|
242
338
|
# @api public
|
243
339
|
#
|
244
340
|
def increment_metric(metric_name, amount = 1) # THREAD_LOCAL_ACCESS
|
@@ -266,6 +362,7 @@ module NewRelic
|
|
266
362
|
#
|
267
363
|
# Return the new block or the existing filter Proc if no block is passed.
|
268
364
|
#
|
365
|
+
# @!scope class
|
269
366
|
# @api public
|
270
367
|
#
|
271
368
|
def ignore_error_filter(&block)
|
@@ -304,6 +401,7 @@ module NewRelic
|
|
304
401
|
# them if you are calling <code>notice_error</code> outside a
|
305
402
|
# transaction.
|
306
403
|
#
|
404
|
+
# @!scope class
|
307
405
|
# @api public
|
308
406
|
#
|
309
407
|
def notice_error(exception, options = {})
|
@@ -341,6 +439,7 @@ module NewRelic
|
|
341
439
|
# :'error.expected' => Whether (true) or not (false) the error was expected
|
342
440
|
# :options => The options hash passed to `NewRelic::Agent.notice_error`
|
343
441
|
#
|
442
|
+
# @!scope class
|
344
443
|
# @api public
|
345
444
|
#
|
346
445
|
def set_error_group_callback(callback_proc)
|
@@ -380,6 +479,7 @@ module NewRelic
|
|
380
479
|
# may be strings, symbols, numeric values or
|
381
480
|
# booleans.
|
382
481
|
#
|
482
|
+
# @!scope class
|
383
483
|
# @api public
|
384
484
|
#
|
385
485
|
def record_custom_event(event_type, event_attrs)
|
@@ -412,6 +512,7 @@ module NewRelic
|
|
412
512
|
# @param [optional, Hash] Set of key-value pairs to store any other
|
413
513
|
# desired data to submit with the feedback event.
|
414
514
|
#
|
515
|
+
# @!scope class
|
415
516
|
# @api public
|
416
517
|
#
|
417
518
|
def record_llm_feedback_event(trace_id:,
|
@@ -465,6 +566,7 @@ module NewRelic
|
|
465
566
|
# :model => [String] The name of the LLM model
|
466
567
|
# :content => [String] The message content or prompt
|
467
568
|
#
|
569
|
+
# @!scope class
|
468
570
|
# @api public
|
469
571
|
#
|
470
572
|
def set_llm_token_count_callback(callback_proc)
|
@@ -497,6 +599,7 @@ module NewRelic
|
|
497
599
|
# file logger. The setting for the newrelic.yml section to use
|
498
600
|
# (ie, RAILS_ENV) can be overridden with an :env argument.
|
499
601
|
#
|
602
|
+
# @!scope class
|
500
603
|
# @api public
|
501
604
|
#
|
502
605
|
def manual_start(options = {})
|
@@ -529,6 +632,7 @@ module NewRelic
|
|
529
632
|
# connection, this tells me to only try it once so this method returns
|
530
633
|
# quickly if there is some kind of latency with the server.
|
531
634
|
#
|
635
|
+
# @!scope class
|
532
636
|
# @api public
|
533
637
|
#
|
534
638
|
def after_fork(options = {})
|
@@ -542,6 +646,7 @@ module NewRelic
|
|
542
646
|
#
|
543
647
|
# @param options [Hash] Unused options Hash, for back compatibility only
|
544
648
|
#
|
649
|
+
# @!scope class
|
545
650
|
# @api public
|
546
651
|
#
|
547
652
|
def shutdown(options = {})
|
@@ -552,6 +657,7 @@ module NewRelic
|
|
552
657
|
# Clear out any data the agent has buffered but has not yet transmitted
|
553
658
|
# to the collector.
|
554
659
|
#
|
660
|
+
# @!scope class
|
555
661
|
# @api public
|
556
662
|
def drop_buffered_data
|
557
663
|
# the following line needs else branch coverage
|
@@ -566,6 +672,7 @@ module NewRelic
|
|
566
672
|
# register instrumentation than just loading the files directly,
|
567
673
|
# although that probably also works.
|
568
674
|
#
|
675
|
+
# @!scope class
|
569
676
|
# @api public
|
570
677
|
#
|
571
678
|
def add_instrumentation(file_pattern)
|
@@ -575,6 +682,7 @@ module NewRelic
|
|
575
682
|
|
576
683
|
# Require agent testing helper methods
|
577
684
|
#
|
685
|
+
# @!scope class
|
578
686
|
# @api public
|
579
687
|
def require_test_helper
|
580
688
|
record_api_supportability_metric(:require_test_helper)
|
@@ -595,6 +703,7 @@ module NewRelic
|
|
595
703
|
# my_obfuscator(sql)
|
596
704
|
# end
|
597
705
|
#
|
706
|
+
# @!scope class
|
598
707
|
# @api public
|
599
708
|
#
|
600
709
|
def set_sql_obfuscator(type = :replace, &block)
|
@@ -610,6 +719,7 @@ module NewRelic
|
|
610
719
|
# traced errors, transaction traces, Insights events, slow SQL traces,
|
611
720
|
# or RUM injection will happen for this transaction.
|
612
721
|
#
|
722
|
+
# @!scope class
|
613
723
|
# @api public
|
614
724
|
#
|
615
725
|
def ignore_transaction
|
@@ -620,6 +730,7 @@ module NewRelic
|
|
620
730
|
# This method disables the recording of Apdex metrics in the current
|
621
731
|
# transaction.
|
622
732
|
#
|
733
|
+
# @!scope class
|
623
734
|
# @api public
|
624
735
|
#
|
625
736
|
def ignore_apdex
|
@@ -630,6 +741,7 @@ module NewRelic
|
|
630
741
|
# This method disables browser monitoring javascript injection in the
|
631
742
|
# current transaction.
|
632
743
|
#
|
744
|
+
# @!scope class
|
633
745
|
# @api public
|
634
746
|
#
|
635
747
|
def ignore_enduser
|
@@ -642,6 +754,7 @@ module NewRelic
|
|
642
754
|
# track of the first entry point and turn on tracing again after
|
643
755
|
# leaving that block. This uses the thread local Tracer::State.
|
644
756
|
#
|
757
|
+
# @!scope class
|
645
758
|
# @api public
|
646
759
|
#
|
647
760
|
def disable_all_tracing
|
@@ -666,6 +779,7 @@ module NewRelic
|
|
666
779
|
# ...
|
667
780
|
# end
|
668
781
|
#
|
782
|
+
# @!scope class
|
669
783
|
# @api public
|
670
784
|
#
|
671
785
|
def disable_sql_recording
|
@@ -704,6 +818,7 @@ module NewRelic
|
|
704
818
|
# may be strings, symbols, numeric values or
|
705
819
|
# booleans.
|
706
820
|
#
|
821
|
+
# @!scope class
|
707
822
|
# @api public
|
708
823
|
#
|
709
824
|
def add_custom_attributes(params) # THREAD_LOCAL_ACCESS
|
@@ -744,6 +859,7 @@ module NewRelic
|
|
744
859
|
# booleans.
|
745
860
|
#
|
746
861
|
# @see https://docs.newrelic.com/docs/using-new-relic/welcome-new-relic/get-started/glossary#span
|
862
|
+
# @!scope class
|
747
863
|
# @api public
|
748
864
|
def add_custom_span_attributes(params)
|
749
865
|
record_api_supportability_metric(:add_custom_span_attributes)
|
@@ -785,6 +901,7 @@ module NewRelic
|
|
785
901
|
#
|
786
902
|
# Attribute pairs with empty or nil contents
|
787
903
|
# will be dropped.
|
904
|
+
# @!scope class
|
788
905
|
# @api public
|
789
906
|
def add_custom_log_attributes(params)
|
790
907
|
record_api_supportability_metric(:add_custom_log_attributes)
|
@@ -800,6 +917,7 @@ module NewRelic
|
|
800
917
|
#
|
801
918
|
# @param [String] user_id The user id to add to the current transaction attributes
|
802
919
|
#
|
920
|
+
# @!scope class
|
803
921
|
# @api public
|
804
922
|
def set_user_id(user_id)
|
805
923
|
record_api_supportability_metric(:set_user_id)
|
@@ -843,6 +961,7 @@ module NewRelic
|
|
843
961
|
#
|
844
962
|
# The default category is the same as the running transaction.
|
845
963
|
#
|
964
|
+
# @!scope class
|
846
965
|
# @api public
|
847
966
|
#
|
848
967
|
def set_transaction_name(name, options = {})
|
@@ -853,6 +972,7 @@ module NewRelic
|
|
853
972
|
# Get the name of the current running transaction. This is useful if you
|
854
973
|
# want to modify the default name.
|
855
974
|
#
|
975
|
+
# @!scope class
|
856
976
|
# @api public
|
857
977
|
#
|
858
978
|
def get_transaction_name # THREAD_LOCAL_ACCESS
|
@@ -924,6 +1044,7 @@ module NewRelic
|
|
924
1044
|
# * entity.guid - The guid of the current entity.
|
925
1045
|
# * hostname - The fully qualified hostname.
|
926
1046
|
#
|
1047
|
+
# @!scope class
|
927
1048
|
# @api public
|
928
1049
|
def linking_metadata
|
929
1050
|
metadata = Hash.new
|
@@ -950,6 +1071,7 @@ module NewRelic
|
|
950
1071
|
#
|
951
1072
|
# @param [String] nonce The nonce to use in the javascript tag for browser instrumentation
|
952
1073
|
#
|
1074
|
+
# @!scope class
|
953
1075
|
# @api public
|
954
1076
|
#
|
955
1077
|
def browser_timing_header(nonce = nil)
|
data/lib/new_relic/constants.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
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/control/frameworks/ruby'
|
6
|
+
module NewRelic
|
7
|
+
class Control
|
8
|
+
module Frameworks
|
9
|
+
# Contains basic control logic for Grape
|
10
|
+
class Grape < NewRelic::Control::Frameworks::Ruby
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
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/control/frameworks/sinatra'
|
6
|
+
module NewRelic
|
7
|
+
class Control
|
8
|
+
module Frameworks
|
9
|
+
# Contains basic control logic for Padrino
|
10
|
+
class Padrino < NewRelic::Control::Frameworks::Sinatra
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -9,9 +9,7 @@ module NewRelic
|
|
9
9
|
module Frameworks
|
10
10
|
class Rails4 < NewRelic::Control::Frameworks::Rails3
|
11
11
|
def rails_gem_list
|
12
|
-
|
13
|
-
"#{gem.name} (#{gem.version})"
|
14
|
-
end
|
12
|
+
NewRelic::Helper.rubygems_specs.map { |gem| "#{gem.name} (#{gem.version})" }
|
15
13
|
end
|
16
14
|
|
17
15
|
def append_plugin_list
|
@@ -73,6 +73,8 @@ module NewRelic
|
|
73
73
|
init_config(options)
|
74
74
|
NewRelic::Agent.agent = NewRelic::Agent::Agent.instance
|
75
75
|
init_instrumentation
|
76
|
+
init_security_agent
|
77
|
+
report_agent_version_metric
|
76
78
|
end
|
77
79
|
|
78
80
|
def determine_env(options)
|
@@ -170,6 +172,10 @@ module NewRelic
|
|
170
172
|
def stdout
|
171
173
|
STDOUT
|
172
174
|
end
|
175
|
+
|
176
|
+
def report_agent_version_metric
|
177
|
+
NewRelic::Agent.record_metric_once("Supportability/AgentVersion/newrelic_rpm/#{NewRelic::VERSION::STRING}")
|
178
|
+
end
|
173
179
|
end
|
174
180
|
include InstanceMethods
|
175
181
|
end
|
@@ -68,7 +68,7 @@ module NewRelic
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def rails_32_deprecation
|
71
|
-
return unless defined?(Rails::VERSION) &&
|
71
|
+
return unless defined?(Rails::VERSION) && NewRelic::Helper.version_satisfied?(Rails::VERSION::STRING, '<=', '3.2')
|
72
72
|
|
73
73
|
deprecation_msg = 'The Ruby agent is dropping support for Rails 3.2 ' \
|
74
74
|
'in a future major release. Please upgrade your Rails version to continue receiving support. ' \
|
@@ -0,0 +1,57 @@
|
|
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 'singleton'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
class Control
|
9
|
+
class SecurityInterface
|
10
|
+
include Singleton
|
11
|
+
|
12
|
+
attr_accessor :wait
|
13
|
+
|
14
|
+
SUPPORTABILITY_PREFIX_SECURITY = 'Supportability/Ruby/SecurityAgent/Enabled/'
|
15
|
+
SUPPORTABILITY_PREFIX_SECURITY_AGENT = 'Supportability/Ruby/SecurityAgent/Agent/Enabled/'
|
16
|
+
ENABLED = 'enabled'
|
17
|
+
DISABLED = 'disabled'
|
18
|
+
|
19
|
+
def agent_started?
|
20
|
+
(@agent_started ||= false) == true
|
21
|
+
end
|
22
|
+
|
23
|
+
def waiting?
|
24
|
+
(@wait ||= false) == true
|
25
|
+
end
|
26
|
+
|
27
|
+
def init_agent
|
28
|
+
return if agent_started? || waiting?
|
29
|
+
|
30
|
+
record_supportability_metrics
|
31
|
+
|
32
|
+
if Agent.config[:'security.agent.enabled'] && !Agent.config[:high_security]
|
33
|
+
Agent.logger.info('Invoking New Relic security module')
|
34
|
+
require 'newrelic_security'
|
35
|
+
|
36
|
+
@agent_started = true
|
37
|
+
else
|
38
|
+
Agent.logger.info('New Relic Security is completely disabled by one of the user-provided configurations: `security.agent.enabled` or `high_security`. Not loading security capabilities.')
|
39
|
+
Agent.logger.info("high_security = #{Agent.config[:high_security]}")
|
40
|
+
Agent.logger.info("security.agent.enabled = #{Agent.config[:'security.agent.enabled']}")
|
41
|
+
end
|
42
|
+
rescue LoadError
|
43
|
+
Agent.logger.info('New Relic security agent not found - skipping')
|
44
|
+
rescue StandardError => exception
|
45
|
+
Agent.logger.error("Exception in New Relic security module loading: #{exception} #{exception.backtrace}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def record_supportability_metrics
|
49
|
+
Agent.config[:'security.agent.enabled'] ? security_agent_metric(ENABLED) : security_agent_metric(DISABLED)
|
50
|
+
end
|
51
|
+
|
52
|
+
def security_agent_metric(setting)
|
53
|
+
NewRelic::Agent.record_metric_once(SUPPORTABILITY_PREFIX_SECURITY_AGENT + setting)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/new_relic/control.rb
CHANGED
@@ -8,7 +8,6 @@ require 'new_relic/local_environment'
|
|
8
8
|
require 'new_relic/language_support'
|
9
9
|
require 'new_relic/helper'
|
10
10
|
|
11
|
-
require 'singleton'
|
12
11
|
require 'erb'
|
13
12
|
require 'socket'
|
14
13
|
require 'net/https'
|
@@ -18,6 +17,7 @@ require 'new_relic/control/server_methods'
|
|
18
17
|
require 'new_relic/control/instrumentation'
|
19
18
|
require 'new_relic/control/class_methods'
|
20
19
|
require 'new_relic/control/instance_methods'
|
20
|
+
require 'new_relic/control/security_interface'
|
21
21
|
|
22
22
|
require 'new_relic/agent'
|
23
23
|
require 'new_relic/delayed_job_injection'
|
@@ -25,11 +25,9 @@ module DependencyDetection
|
|
25
25
|
|
26
26
|
def detect!
|
27
27
|
@items.each do |item|
|
28
|
-
if item.
|
29
|
-
|
30
|
-
|
31
|
-
item.configure_as_unsatisfied unless item.disabled_configured?
|
32
|
-
end
|
28
|
+
next if item.executed || item.disabled_configured?
|
29
|
+
|
30
|
+
item.dependencies_satisfied? ? item.execute : item.configure_as_unsatisfied
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -65,6 +63,13 @@ module DependencyDetection
|
|
65
63
|
end
|
66
64
|
|
67
65
|
def configure_as_unsatisfied
|
66
|
+
# TODO: currently using :unsatisfied for Padrino will clobber the value
|
67
|
+
# already set for Sinatra, so skip Padrino and circle back with a
|
68
|
+
# new Padrino specific solution in the future.
|
69
|
+
#
|
70
|
+
# https://github.com/newrelic/newrelic-ruby-agent/issues/2912
|
71
|
+
return if name == :padrino
|
72
|
+
|
68
73
|
NewRelic::Agent.config.instance_variable_get(:@cache)[config_key] = :unsatisfied
|
69
74
|
end
|
70
75
|
|
@@ -139,8 +144,6 @@ module DependencyDetection
|
|
139
144
|
!(disabled_configured? || deprecated_disabled_configured?)
|
140
145
|
end
|
141
146
|
|
142
|
-
# TODO: MAJOR VERSION
|
143
|
-
# will only return true if a disabled key is found and is truthy
|
144
147
|
def deprecated_disabled_configured?
|
145
148
|
return false if self.name.nil?
|
146
149
|
|
@@ -148,12 +151,7 @@ module DependencyDetection
|
|
148
151
|
return false unless ::NewRelic::Agent.config[key] == true
|
149
152
|
|
150
153
|
::NewRelic::Agent.logger.debug("Not installing #{self.name} instrumentation because of configuration #{key}")
|
151
|
-
|
152
|
-
"[DEPRECATED] configuration #{key} for #{self.name} will be removed in the next major release. " \
|
153
|
-
"Use `#{config_key}` with one of `#{VALID_CONFIG_VALUES.map(&:to_s).inspect}`"
|
154
|
-
)
|
155
|
-
|
156
|
-
return true
|
154
|
+
true
|
157
155
|
end
|
158
156
|
|
159
157
|
def config_key
|
@@ -181,7 +179,6 @@ module DependencyDetection
|
|
181
179
|
# logs the resolved value during debug mode.
|
182
180
|
def fetch_config_value(key)
|
183
181
|
valid_value = valid_config_value(::NewRelic::Agent.config[key].to_s.to_sym)
|
184
|
-
::NewRelic::Agent.logger.debug("Using #{valid_value} configuration value for #{self.name} to configure instrumentation")
|
185
182
|
return valid_value
|
186
183
|
end
|
187
184
|
|
@@ -44,7 +44,7 @@ module NewRelic
|
|
44
44
|
####################################
|
45
45
|
report_on('Gems') do
|
46
46
|
begin
|
47
|
-
|
47
|
+
NewRelic::Helper.rubygems_specs.map { |gem| "#{gem.name}(#{gem.version})" }
|
48
48
|
rescue
|
49
49
|
# There are certain rubygem, bundler, rails combinations (e.g. gem
|
50
50
|
# 1.6.2, rails 2.3, bundler 1.2.3) where the code above throws an error
|
@@ -67,7 +67,7 @@ module NewRelic
|
|
67
67
|
report_on('Physical Cores') { ::NewRelic::Agent::SystemInfo.num_physical_cores }
|
68
68
|
report_on('Arch') { ::NewRelic::Agent::SystemInfo.processor_arch }
|
69
69
|
report_on('OS version') { ::NewRelic::Agent::SystemInfo.os_version }
|
70
|
-
report_on('OS') { ::NewRelic::Agent::SystemInfo.
|
70
|
+
report_on('OS') { ::NewRelic::Agent::SystemInfo.os_distribution }
|
71
71
|
report_on('Database adapter') { ::NewRelic::Agent::DatabaseAdapter.value }
|
72
72
|
report_on('Framework') { Agent.config[:framework].to_s }
|
73
73
|
report_on('Dispatcher') { Agent.config[:dispatcher].to_s }
|
data/lib/new_relic/helper.rb
CHANGED
@@ -82,5 +82,27 @@ module NewRelic
|
|
82
82
|
File.exist?(executable_path) && File.file?(executable_path) && File.executable?(executable_path)
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
def version_satisfied?(left, operator, right)
|
87
|
+
left = Gem::Version.new(left) unless left.is_a?(Gem::Version)
|
88
|
+
right = Gem::Version.new(right) unless right.is_a?(Gem::Version)
|
89
|
+
|
90
|
+
left.public_send(operator, right)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Bundler version 2.5.12 deprecated all_specs and added installed_specs.
|
94
|
+
# To support newer Bundler versions, try to use installed_specs first,
|
95
|
+
# then fall back to all_specs.
|
96
|
+
# All callers expect this to be an array, so return an array if Bundler isn't defined
|
97
|
+
# @api private
|
98
|
+
def rubygems_specs
|
99
|
+
return [] unless defined?(Bundler)
|
100
|
+
|
101
|
+
if Bundler.rubygems.respond_to?(:installed_specs)
|
102
|
+
Bundler.rubygems.installed_specs
|
103
|
+
else
|
104
|
+
Bundler.rubygems.all_specs
|
105
|
+
end
|
106
|
+
end
|
85
107
|
end
|
86
108
|
end
|
@@ -88,7 +88,9 @@ module NewRelic
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def bundled_gem?(gem_name)
|
91
|
-
defined?(Bundler)
|
91
|
+
return false unless defined?(Bundler)
|
92
|
+
|
93
|
+
NewRelic::Helper.rubygems_specs.map(&:name).include?(gem_name)
|
92
94
|
rescue => e
|
93
95
|
::NewRelic::Agent.logger.info("Could not determine if third party #{gem_name} gem is installed", e)
|
94
96
|
false
|
@@ -142,10 +142,7 @@ module NewRelic
|
|
142
142
|
end
|
143
143
|
|
144
144
|
def check_for_falcon
|
145
|
-
|
146
|
-
NewRelic::LanguageSupport.object_space_usable?
|
147
|
-
|
148
|
-
@discovered_dispatcher = :falcon if find_class_in_object_space(::Falcon::Server)
|
145
|
+
@discovered_dispatcher = :falcon if defined?(::Falcon::Server) && File.basename($PROGRAM_NAME) == 'falcon'
|
149
146
|
end
|
150
147
|
|
151
148
|
def check_for_delayed_job
|