newrelic_rpm 9.7.0 → 9.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +376 -2
- data/README.md +17 -18
- data/Rakefile +1 -1
- data/lib/boot/strap.rb +101 -0
- data/lib/new_relic/agent/agent.rb +4 -1
- data/lib/new_relic/agent/agent_helpers/connect.rb +10 -8
- data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +1 -1
- data/lib/new_relic/agent/agent_helpers/startup.rb +2 -1
- data/lib/new_relic/agent/agent_logger.rb +3 -1
- data/lib/new_relic/agent/aws.rb +68 -0
- data/lib/new_relic/agent/configuration/default_source.rb +519 -23
- data/lib/new_relic/agent/configuration/environment_source.rb +14 -2
- data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
- data/lib/new_relic/agent/configuration/manager.rb +51 -8
- data/lib/new_relic/agent/configuration/security_policy_source.rb +11 -0
- data/lib/new_relic/agent/configuration/yaml_source.rb +2 -0
- data/lib/new_relic/agent/connect/request_builder.rb +1 -1
- data/lib/new_relic/agent/custom_event_aggregator.rb +27 -1
- 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 +39 -0
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_payload.rb +1 -5
- data/lib/new_relic/agent/error_collector.rb +39 -10
- data/lib/new_relic/agent/harvester.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +0 -13
- data/lib/new_relic/agent/instrumentation/active_record.rb +1 -8
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +3 -0
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +1 -12
- data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/instrumentation.rb +7 -3
- 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 +4 -3
- 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 -2
- data/lib/new_relic/agent/instrumentation/curb.rb +3 -4
- 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/instrumentation.rb +58 -8
- data/lib/new_relic/agent/instrumentation/elasticsearch.rb +0 -2
- data/lib/new_relic/agent/instrumentation/ethon.rb +0 -4
- data/lib/new_relic/agent/instrumentation/excon.rb +0 -16
- data/lib/new_relic/agent/instrumentation/fiber.rb +0 -2
- 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/grpc_server.rb +1 -1
- data/lib/new_relic/agent/instrumentation/httpclient.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httpx.rb +0 -4
- 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.rb +0 -1
- data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +6 -0
- data/lib/new_relic/agent/instrumentation/opensearch/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/opensearch/instrumentation.rb +66 -0
- data/lib/new_relic/agent/instrumentation/opensearch/prepend.rb +13 -0
- 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 +0 -1
- 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/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 +0 -4
- data/lib/new_relic/agent/instrumentation/roda.rb +4 -4
- 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/chain.rb +36 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai/instrumentation.rb +196 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai/prepend.rb +20 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai.rb +35 -0
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +0 -14
- data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -19
- 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.rb +0 -1
- data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +13 -6
- 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_message.rb +25 -0
- data/lib/new_relic/agent/llm/chat_completion_summary.rb +66 -0
- data/lib/new_relic/agent/llm/embedding.rb +60 -0
- data/lib/new_relic/agent/llm/llm_event.rb +95 -0
- data/lib/new_relic/agent/llm/response_headers.rb +80 -0
- data/lib/new_relic/agent/llm.rb +49 -0
- data/lib/new_relic/agent/local_log_decorator.rb +8 -1
- data/lib/new_relic/agent/log_event_aggregator.rb +120 -44
- data/lib/new_relic/agent/messaging.rb +11 -5
- data/lib/new_relic/agent/new_relic_service.rb +12 -2
- data/lib/new_relic/agent/serverless_handler.rb +400 -0
- 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 +8 -10
- data/lib/new_relic/agent/system_info.rb +14 -0
- data/lib/new_relic/agent/threading/agent_thread.rb +1 -2
- data/lib/new_relic/agent/tracer.rb +5 -5
- data/lib/new_relic/agent/transaction/abstract_segment.rb +1 -1
- data/lib/new_relic/agent/transaction/external_request_segment.rb +0 -10
- data/lib/new_relic/agent/transaction/request_attributes.rb +13 -1
- data/lib/new_relic/agent/transaction/trace_context.rb +1 -1
- data/lib/new_relic/agent/transaction/tracing.rb +2 -2
- data/lib/new_relic/agent/transaction.rb +2 -6
- data/lib/new_relic/agent/transaction_error_primitive.rb +23 -19
- data/lib/new_relic/agent.rb +198 -10
- data/lib/new_relic/constants.rb +2 -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 +8 -0
- 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 +10 -5
- data/lib/new_relic/environment_report.rb +2 -2
- data/lib/new_relic/helper.rb +15 -0
- data/lib/new_relic/language_support.rb +3 -1
- data/lib/new_relic/local_environment.rb +14 -10
- data/lib/new_relic/rack/browser_monitoring.rb +28 -12
- data/lib/new_relic/supportability_helper.rb +2 -0
- data/lib/new_relic/thread_local_storage.rb +31 -0
- data/lib/new_relic/version.rb +2 -2
- data/lib/sequel/extensions/new_relic_instrumentation.rb +3 -2
- data/lib/tasks/config.rake +8 -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 +76 -13
- data/lib/tasks/instrumentation_generator/instrumentation.thor +31 -22
- data/lib/tasks/instrumentation_generator/templates/chain.tt +0 -1
- data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -1
- data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +11 -8
- data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +1 -1
- data/newrelic.yml +387 -143
- data/newrelic_rpm.gemspec +2 -0
- data/test/agent_helper.rb +17 -2
- metadata +80 -3
@@ -33,22 +33,6 @@ DependencyDetection.defer do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
executes do
|
37
|
-
next unless Gem::Version.new(Excon::VERSION) < Gem::Version.new('0.56.0')
|
38
|
-
|
39
|
-
deprecation_msg = 'Instrumentation for Excon versions below 0.56.0 is deprecated.' \
|
40
|
-
'They will stop being monitored in version 9.0.0. ' \
|
41
|
-
'Please upgrade your Excon version to continue receiving full support. '
|
42
|
-
|
43
|
-
NewRelic::Agent.logger.log_once(
|
44
|
-
:warn,
|
45
|
-
:deprecated_excon_version,
|
46
|
-
deprecation_msg
|
47
|
-
)
|
48
|
-
|
49
|
-
NewRelic::Agent.record_metric('Supportability/Deprecated/Excon', 1)
|
50
|
-
end
|
51
|
-
|
52
36
|
def install_excon_instrumentation(excon_version)
|
53
37
|
require 'new_relic/agent/distributed_tracing/cross_app_tracing'
|
54
38
|
require 'new_relic/agent/http_clients/excon_wrappers'
|
@@ -19,7 +19,7 @@ DependencyDetection.defer do
|
|
19
19
|
|
20
20
|
depends_on do
|
21
21
|
begin
|
22
|
-
if
|
22
|
+
if NewRelic::Helper.rubygems_specs.map(&:name).include?('newrelic-grape')
|
23
23
|
NewRelic::Agent.logger.info('Not installing New Relic supported Grape instrumentation because the third party newrelic-grape gem is present')
|
24
24
|
false
|
25
25
|
else
|
@@ -14,7 +14,7 @@ DependencyDetection.defer do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
executes do
|
17
|
-
supportability_name = NewRelic::Agent::Instrumentation::GRPC::
|
17
|
+
supportability_name = NewRelic::Agent::Instrumentation::GRPC::Server::INSTRUMENTATION_NAME
|
18
18
|
if use_prepend?
|
19
19
|
prepend_instrument GRPC::RpcServer, NewRelic::Agent::Instrumentation::GRPC::Server::RpcServerPrepend, supportability_name
|
20
20
|
prepend_instrument GRPC::RpcDesc, NewRelic::Agent::Instrumentation::GRPC::Server::RpcDescPrepend, supportability_name
|
@@ -13,10 +13,6 @@ DependencyDetection.defer do
|
|
13
13
|
defined?(HTTPX) && Gem::Version.new(HTTPX::VERSION) >= Gem::Version.new('1.0.0')
|
14
14
|
end
|
15
15
|
|
16
|
-
executes do
|
17
|
-
NewRelic::Agent.logger.info('Installing httpx instrumentation')
|
18
|
-
end
|
19
|
-
|
20
16
|
executes do
|
21
17
|
if use_prepend?
|
22
18
|
prepend_instrument HTTPX::Session, NewRelic::Agent::Instrumentation::HTTPX::Prepend
|
@@ -15,12 +15,10 @@ DependencyDetection.defer do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
executes do
|
18
|
-
NewRelic::Agent.logger.info('Installing Logger instrumentation')
|
19
|
-
|
20
18
|
if use_prepend?
|
21
19
|
prepend_instrument Logger, NewRelic::Agent::Instrumentation::Logger::Prepend
|
22
20
|
else
|
23
|
-
chain_instrument NewRelic::Agent::Instrumentation::Logger
|
21
|
+
chain_instrument NewRelic::Agent::Instrumentation::Logger, NewRelic::Agent::Instrumentation::Logger::INSTRUMENTATION_NAME
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
@@ -0,0 +1,21 @@
|
|
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::Agent::Instrumentation
|
6
|
+
module LogStasher::Chain
|
7
|
+
def self.instrument!
|
8
|
+
::LogStasher.singleton_class.class_eval do
|
9
|
+
include NewRelic::Agent::Instrumentation::LogStasher
|
10
|
+
|
11
|
+
alias_method(:build_logstash_event_without_new_relic, :build_logstash_event)
|
12
|
+
|
13
|
+
def build_logstash_event(*args)
|
14
|
+
build_logstash_event_with_new_relic(*args) do
|
15
|
+
build_logstash_event_without_new_relic(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -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
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module LogStasher
|
7
|
+
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
|
8
|
+
|
9
|
+
def self.enabled?
|
10
|
+
NewRelic::Agent.config[:'instrumentation.logstasher'] != 'disabled'
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_logstash_event_with_new_relic(*args)
|
14
|
+
logstasher_event = yield
|
15
|
+
log = logstasher_event.instance_variable_get(:@data)
|
16
|
+
|
17
|
+
::NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
|
18
|
+
::NewRelic::Agent.agent.log_event_aggregator.record_logstasher_event(log)
|
19
|
+
::NewRelic::Agent::LocalLogDecorator.decorate(log)
|
20
|
+
|
21
|
+
logstasher_event
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
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::Agent::Instrumentation
|
6
|
+
module LogStasher::Prepend
|
7
|
+
include NewRelic::Agent::Instrumentation::LogStasher
|
8
|
+
|
9
|
+
def build_logstash_event(*args)
|
10
|
+
build_logstash_event_with_new_relic(*args) { super }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
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_relative 'logstasher/instrumentation'
|
6
|
+
require_relative 'logstasher/chain'
|
7
|
+
require_relative 'logstasher/prepend'
|
8
|
+
|
9
|
+
DependencyDetection.defer do
|
10
|
+
named :logstasher
|
11
|
+
|
12
|
+
depends_on do
|
13
|
+
defined?(LogStasher) &&
|
14
|
+
Gem::Version.new(LogStasher::VERSION) >= Gem::Version.new('1.0.0') &&
|
15
|
+
NewRelic::Agent.config[:'application_logging.enabled']
|
16
|
+
end
|
17
|
+
|
18
|
+
executes do
|
19
|
+
if use_prepend?
|
20
|
+
prepend_instrument LogStasher.singleton_class, NewRelic::Agent::Instrumentation::LogStasher::Prepend
|
21
|
+
else
|
22
|
+
chain_instrument NewRelic::Agent::Instrumentation::LogStasher::Chain
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -74,7 +74,6 @@ DependencyDetection.defer do
|
|
74
74
|
depends_on { NewRelic::Agent::Instrumentation::Memcache::DalliCAS.should_instrument? }
|
75
75
|
|
76
76
|
executes do
|
77
|
-
NewRelic::Agent.logger.info('Installing Dalli CAS Client Memcache instrumentation')
|
78
77
|
if use_prepend?
|
79
78
|
prepend_module = NewRelic::Agent::Instrumentation::Memcache::Prepend
|
80
79
|
prepend_module.dalli_cas_prependers do |client_class, instrumenting_module|
|
@@ -32,7 +32,13 @@ module NewRelic
|
|
32
32
|
end
|
33
33
|
|
34
34
|
wrapped_response = NewRelic::Agent::HTTPClients::NetHTTPResponse.new(response)
|
35
|
+
|
36
|
+
if NewRelic::Agent::LLM.openai_parent?(segment)
|
37
|
+
NewRelic::Agent::LLM.populate_openai_response_headers(wrapped_response, segment.parent)
|
38
|
+
end
|
39
|
+
|
35
40
|
segment.process_response_headers(wrapped_response)
|
41
|
+
|
36
42
|
response
|
37
43
|
ensure
|
38
44
|
segment&.finish
|
@@ -0,0 +1,21 @@
|
|
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::Agent::Instrumentation
|
6
|
+
module OpenSearch::Chain
|
7
|
+
def self.instrument!
|
8
|
+
::OpenSearch::Transport::Client.class_eval do
|
9
|
+
include NewRelic::Agent::Instrumentation::OpenSearch
|
10
|
+
|
11
|
+
alias_method(:perform_request_without_tracing, :perform_request)
|
12
|
+
|
13
|
+
def perform_request(*args)
|
14
|
+
perform_request_with_tracing(*args) do
|
15
|
+
perform_request_without_tracing(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,66 @@
|
|
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::Agent::Instrumentation
|
6
|
+
module OpenSearch
|
7
|
+
PRODUCT_NAME = 'OpenSearch'
|
8
|
+
OPERATION = 'perform_request'
|
9
|
+
OPERATION_PATTERN = %r{/lib/opensearch/api/(?!.+#{OPERATION})}
|
10
|
+
INSTANCE_METHOD_PATTERN = /:in (?:`|')(?:.+#)?([^']+)'\z/
|
11
|
+
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
|
12
|
+
|
13
|
+
def perform_request_with_tracing(_method, _path, params = NewRelic::EMPTY_HASH, body = nil, _headers = nil, _opts = nil, &_block)
|
14
|
+
return yield unless NewRelic::Agent::Tracer.tracing_enabled?
|
15
|
+
|
16
|
+
segment = NewRelic::Agent::Tracer.start_datastore_segment(
|
17
|
+
product: PRODUCT_NAME,
|
18
|
+
operation: nr_operation || OPERATION,
|
19
|
+
host: nr_hosts[:host],
|
20
|
+
port_path_or_id: nr_hosts[:port],
|
21
|
+
database_name: nr_cluster_name
|
22
|
+
)
|
23
|
+
begin
|
24
|
+
NewRelic::Agent::Tracer.capture_segment_error(segment) { yield }
|
25
|
+
ensure
|
26
|
+
if segment
|
27
|
+
segment.notice_nosql_statement(nr_reported_query(body || params))
|
28
|
+
segment.finish
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# See Elasticsearch instrumentation for explanation on Ruby 3.4 changes to match instance method
|
36
|
+
def nr_operation
|
37
|
+
location = caller_locations.detect { |loc| loc.to_s.match?(OPERATION_PATTERN) }
|
38
|
+
return unless location && location.to_s =~ INSTANCE_METHOD_PATTERN
|
39
|
+
|
40
|
+
Regexp.last_match(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
def nr_reported_query(query)
|
44
|
+
return unless NewRelic::Agent.config[:'opensearch.capture_queries']
|
45
|
+
return query unless NewRelic::Agent.config[:'opensearch.obfuscate_queries']
|
46
|
+
|
47
|
+
NewRelic::Agent::Datastores::NosqlObfuscator.obfuscate_statement(query)
|
48
|
+
end
|
49
|
+
|
50
|
+
def nr_cluster_name
|
51
|
+
return @nr_cluster_name if defined?(@nr_cluster_name)
|
52
|
+
return if nr_hosts.empty?
|
53
|
+
|
54
|
+
NewRelic::Agent.disable_all_tracing do
|
55
|
+
@nr_cluster_name ||= perform_request('GET', '/').body['cluster_name']
|
56
|
+
end
|
57
|
+
rescue StandardError => e
|
58
|
+
NewRelic::Agent.logger.error('Failed to get cluster name for OpenSearch', e)
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def nr_hosts
|
63
|
+
@nr_hosts ||= (transport.hosts.first || NewRelic::EMPTY_HASH)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,13 @@
|
|
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::Agent::Instrumentation
|
6
|
+
module OpenSearch::Prepend
|
7
|
+
include NewRelic::Agent::Instrumentation::OpenSearch
|
8
|
+
|
9
|
+
def perform_request(*args)
|
10
|
+
perform_request_with_tracing(*args) { super }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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_relative 'opensearch/instrumentation'
|
6
|
+
require_relative 'opensearch/chain'
|
7
|
+
require_relative 'opensearch/prepend'
|
8
|
+
|
9
|
+
DependencyDetection.defer do
|
10
|
+
named :opensearch
|
11
|
+
|
12
|
+
depends_on do
|
13
|
+
defined?(OpenSearch)
|
14
|
+
end
|
15
|
+
|
16
|
+
executes do
|
17
|
+
if use_prepend?
|
18
|
+
prepend_instrument OpenSearch::Transport::Client, NewRelic::Agent::Instrumentation::OpenSearch::Prepend
|
19
|
+
else
|
20
|
+
chain_instrument NewRelic::Agent::Instrumentation::OpenSearch::Chain
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -22,11 +22,11 @@ DependencyDetection.defer do
|
|
22
22
|
depends_on { defined?(Padrino) && defined?(Padrino::Routing::InstanceMethods) }
|
23
23
|
|
24
24
|
executes do
|
25
|
-
NewRelic::Agent
|
25
|
+
supportability_name = NewRelic::Agent::Instrumentation::Padrino::INSTRUMENTATION_NAME
|
26
26
|
if use_prepend?
|
27
|
-
prepend_instrument Padrino::Application, NewRelic::Agent::Instrumentation::PadrinoTracer::Prepend
|
27
|
+
prepend_instrument Padrino::Application, NewRelic::Agent::Instrumentation::PadrinoTracer::Prepend, supportability_name
|
28
28
|
else
|
29
|
-
chain_instrument NewRelic::Agent::Instrumentation::PadrinoTracer::Chain
|
29
|
+
chain_instrument NewRelic::Agent::Instrumentation::PadrinoTracer::Chain, supportability_name
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -13,6 +13,7 @@ module NewRelic
|
|
13
13
|
attr_accessor :_nr_deferred_detection_ran
|
14
14
|
end
|
15
15
|
builder_class._nr_deferred_detection_ran = false
|
16
|
+
NewRelic::Control::SecurityInterface.instance.wait = true
|
16
17
|
end
|
17
18
|
|
18
19
|
def deferred_dependency_check
|
@@ -21,6 +22,8 @@ module NewRelic
|
|
21
22
|
NewRelic::Agent.logger.info('Doing deferred dependency-detection before Rack startup')
|
22
23
|
DependencyDetection.detect!
|
23
24
|
self.class._nr_deferred_detection_ran = true
|
25
|
+
NewRelic::Control::SecurityInterface.instance.wait = false
|
26
|
+
NewRelic::Control::SecurityInterface.instance.init_agent
|
24
27
|
end
|
25
28
|
|
26
29
|
def check_for_late_instrumentation(app)
|
@@ -32,15 +32,19 @@ DependencyDetection.defer do
|
|
32
32
|
NewRelic::Agent::Instrumentation::ActionControllerSubscriber \
|
33
33
|
.subscribe(/^process_action.action_controller$/)
|
34
34
|
|
35
|
-
subs = %w[
|
35
|
+
subs = %w[exist_fragment?
|
36
|
+
expire_fragment
|
37
|
+
halted_callback
|
38
|
+
read_fragment
|
39
|
+
redirect_to
|
36
40
|
send_data
|
41
|
+
send_file
|
37
42
|
send_stream
|
38
|
-
|
39
|
-
|
40
|
-
unpermitted_parameters]
|
43
|
+
write_fragment
|
44
|
+
unpermitted_parameters].map { |s| Regexp.escape(s) }
|
41
45
|
|
42
46
|
# have to double escape period because its going from string -> regex
|
43
47
|
NewRelic::Agent::Instrumentation::ActionControllerOtherSubscriber \
|
44
|
-
.subscribe(Regexp.new("^(
|
48
|
+
.subscribe(Regexp.new("^(?:#{subs.join('|')})\\.action_controller$"))
|
45
49
|
end
|
46
50
|
end
|
@@ -17,7 +17,6 @@ DependencyDetection.defer do
|
|
17
17
|
depends_on { NewRelic::Agent::Instrumentation::Rake.safe_from_third_party_gem? }
|
18
18
|
|
19
19
|
executes do
|
20
|
-
NewRelic::Agent.logger.info('Installing Rake instrumentation')
|
21
20
|
NewRelic::Agent.logger.debug("Instrumenting Rake tasks: #{NewRelic::Agent.config[:'rake.tasks']}")
|
22
21
|
end
|
23
22
|
|
@@ -0,0 +1,72 @@
|
|
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_relative 'instrumentation'
|
6
|
+
|
7
|
+
module NewRelic::Agent::Instrumentation
|
8
|
+
module Rdkafka::Chain
|
9
|
+
def self.instrument!
|
10
|
+
::Rdkafka::Producer.class_eval do
|
11
|
+
include NewRelic::Agent::Instrumentation::Rdkafka
|
12
|
+
|
13
|
+
alias_method(:produce_without_new_relic, :produce)
|
14
|
+
|
15
|
+
def produce(**kwargs)
|
16
|
+
produce_with_new_relic(kwargs) do |headers|
|
17
|
+
kwargs[:headers] = headers
|
18
|
+
produce_without_new_relic(**kwargs)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
::Rdkafka::Consumer.class_eval do
|
24
|
+
include NewRelic::Agent::Instrumentation::Rdkafka
|
25
|
+
|
26
|
+
alias_method(:each_without_new_relic, :each)
|
27
|
+
|
28
|
+
def each(**kwargs)
|
29
|
+
each_without_new_relic(**kwargs) do |message|
|
30
|
+
each_with_new_relic(message) do
|
31
|
+
yield(message)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
::Rdkafka::Config.class_eval do
|
38
|
+
include NewRelic::Agent::Instrumentation::RdkafkaConfig
|
39
|
+
|
40
|
+
alias_method(:producer_without_new_relic, :producer)
|
41
|
+
alias_method(:consumer_without_new_relic, :consumer)
|
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'))
|
45
|
+
def producer(**kwargs)
|
46
|
+
producer_without_new_relic(**kwargs).tap do |producer|
|
47
|
+
set_nr_config(producer)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def consumer(**kwargs)
|
52
|
+
consumer_without_new_relic(**kwargs).tap do |consumer|
|
53
|
+
set_nr_config(consumer)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
else
|
57
|
+
def producer
|
58
|
+
producer_without_new_relic.tap do |producer|
|
59
|
+
set_nr_config(producer)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def consumer
|
64
|
+
consumer_without_new_relic.tap do |consumer|
|
65
|
+
set_nr_config(consumer)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,70 @@
|
|
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/messaging'
|
6
|
+
|
7
|
+
module NewRelic::Agent::Instrumentation
|
8
|
+
module Rdkafka
|
9
|
+
MESSAGING_LIBRARY = 'Kafka'
|
10
|
+
PRODUCE = 'Produce'
|
11
|
+
CONSUME = 'Consume'
|
12
|
+
|
13
|
+
INSTRUMENTATION_NAME = 'Rdkafka'
|
14
|
+
|
15
|
+
def produce_with_new_relic(*args)
|
16
|
+
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
|
17
|
+
|
18
|
+
topic_name = args[0][:topic]
|
19
|
+
segment = NewRelic::Agent::Tracer.start_message_broker_segment(
|
20
|
+
action: :produce,
|
21
|
+
library: MESSAGING_LIBRARY,
|
22
|
+
destination_type: :topic,
|
23
|
+
destination_name: topic_name
|
24
|
+
)
|
25
|
+
create_kafka_metrics(action: PRODUCE, topic: topic_name)
|
26
|
+
|
27
|
+
headers = args[0][:headers] || {}
|
28
|
+
::NewRelic::Agent::DistributedTracing.insert_distributed_trace_headers(headers)
|
29
|
+
|
30
|
+
NewRelic::Agent::Tracer.capture_segment_error(segment) { yield(headers) }
|
31
|
+
ensure
|
32
|
+
segment&.finish
|
33
|
+
end
|
34
|
+
|
35
|
+
def each_with_new_relic(message)
|
36
|
+
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
|
37
|
+
|
38
|
+
headers = message&.headers || {}
|
39
|
+
topic_name = message&.topic
|
40
|
+
|
41
|
+
NewRelic::Agent::Messaging.wrap_message_broker_consume_transaction(
|
42
|
+
library: MESSAGING_LIBRARY,
|
43
|
+
destination_type: :topic,
|
44
|
+
destination_name: topic_name,
|
45
|
+
headers: headers,
|
46
|
+
action: :consume
|
47
|
+
) do
|
48
|
+
create_kafka_metrics(action: CONSUME, topic: topic_name)
|
49
|
+
yield
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_kafka_metrics(action:, topic:)
|
54
|
+
hosts = []
|
55
|
+
# both 'bootstrap.servers' and 'metadata.broker.list' are valid ways to specify the Kafka server
|
56
|
+
hosts << @nr_config[:'bootstrap.servers'] if @nr_config[:'bootstrap.servers']
|
57
|
+
hosts << @nr_config[:'metadata.broker.list'] if @nr_config[:'metadata.broker.list']
|
58
|
+
hosts.each do |host|
|
59
|
+
NewRelic::Agent.record_metric("MessageBroker/Kafka/Nodes/#{host}/#{action}/#{topic}", 1)
|
60
|
+
NewRelic::Agent.record_metric("MessageBroker/Kafka/Nodes/#{host}", 1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module RdkafkaConfig
|
66
|
+
def set_nr_config(producer_or_consumer)
|
67
|
+
producer_or_consumer.instance_variable_set(:@nr_config, self)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,67 @@
|
|
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_relative 'instrumentation'
|
6
|
+
|
7
|
+
module NewRelic::Agent::Instrumentation
|
8
|
+
module RdkafkaProducer
|
9
|
+
module Prepend
|
10
|
+
include NewRelic::Agent::Instrumentation::Rdkafka
|
11
|
+
|
12
|
+
def produce(**kwargs)
|
13
|
+
produce_with_new_relic(kwargs) do |headers|
|
14
|
+
kwargs[:headers] = headers
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module RdkafkaConsumer
|
22
|
+
module Prepend
|
23
|
+
include NewRelic::Agent::Instrumentation::Rdkafka
|
24
|
+
|
25
|
+
def each
|
26
|
+
super do |message|
|
27
|
+
each_with_new_relic(message) do
|
28
|
+
yield(message)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module RdkafkaConfig
|
36
|
+
module Prepend
|
37
|
+
include NewRelic::Agent::Instrumentation::RdkafkaConfig
|
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'))
|
41
|
+
def producer(**kwargs)
|
42
|
+
super.tap do |producer|
|
43
|
+
set_nr_config(producer)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def consumer(**kwargs)
|
48
|
+
super.tap do |consumer|
|
49
|
+
set_nr_config(consumer)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
else # older versions
|
53
|
+
def producer
|
54
|
+
super.tap do |producer|
|
55
|
+
set_nr_config(producer)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def consumer
|
60
|
+
super.tap do |consumer|
|
61
|
+
set_nr_config(consumer)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,25 @@
|
|
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
|
+
DependencyDetection.defer do
|
6
|
+
named :rdkafka
|
7
|
+
|
8
|
+
depends_on do
|
9
|
+
defined?(Rdkafka)
|
10
|
+
end
|
11
|
+
|
12
|
+
executes do
|
13
|
+
require_relative 'rdkafka/instrumentation'
|
14
|
+
require_relative 'rdkafka/chain'
|
15
|
+
require_relative 'rdkafka/prepend'
|
16
|
+
|
17
|
+
if use_prepend?
|
18
|
+
prepend_instrument Rdkafka::Config, NewRelic::Agent::Instrumentation::RdkafkaConfig::Prepend
|
19
|
+
prepend_instrument Rdkafka::Producer, NewRelic::Agent::Instrumentation::RdkafkaProducer::Prepend
|
20
|
+
prepend_instrument Rdkafka::Consumer, NewRelic::Agent::Instrumentation::RdkafkaConsumer::Prepend
|
21
|
+
else
|
22
|
+
chain_instrument NewRelic::Agent::Instrumentation::Rdkafka::Chain
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|