newrelic_rpm 8.15.0 → 9.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -28
- data/.rubocop_todo.yml +41 -3
- data/CHANGELOG.md +191 -38
- data/CONTRIBUTING.md +1 -1
- data/README.md +3 -1
- data/bin/nrdebug +16 -16
- data/lib/new_relic/agent/agent_helpers/connect.rb +1 -1
- data/lib/new_relic/agent/agent_helpers/special_startup.rb +1 -2
- data/lib/new_relic/agent/attribute_filter.rb +0 -2
- data/lib/new_relic/agent/commands/thread_profiler_session.rb +3 -3
- data/lib/new_relic/agent/configuration/default_source.rb +139 -476
- data/lib/new_relic/agent/configuration/high_security_source.rb +0 -2
- data/lib/new_relic/agent/configuration/security_policy_source.rb +0 -16
- data/lib/new_relic/agent/database.rb +0 -14
- data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -2
- data/lib/new_relic/agent/error_collector.rb +1 -1
- data/lib/new_relic/agent/error_filter.rb +3 -3
- data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +6 -19
- data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +39 -0
- data/lib/new_relic/agent/instrumentation/action_dispatch.rb +31 -0
- data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +64 -0
- data/lib/new_relic/agent/instrumentation/action_mailbox.rb +30 -0
- data/lib/new_relic/agent/instrumentation/action_mailbox_subscriber.rb +33 -0
- data/lib/new_relic/agent/instrumentation/action_mailer.rb +30 -0
- data/lib/new_relic/agent/instrumentation/action_mailer_subscriber.rb +85 -0
- data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +7 -7
- data/lib/new_relic/agent/instrumentation/active_job.rb +15 -2
- data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +41 -0
- data/lib/new_relic/agent/instrumentation/active_storage.rb +4 -0
- data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +2 -30
- data/lib/new_relic/agent/instrumentation/active_support.rb +21 -6
- data/lib/new_relic/agent/instrumentation/active_support_subscriber.rb +41 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/custom_events.rb +12 -0
- data/lib/new_relic/agent/instrumentation/fiber/chain.rb +20 -0
- data/lib/new_relic/agent/instrumentation/fiber/instrumentation.rb +24 -0
- data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +18 -0
- data/lib/new_relic/agent/instrumentation/fiber.rb +25 -0
- data/lib/new_relic/agent/instrumentation/grape.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache.rb +2 -2
- data/lib/new_relic/agent/instrumentation/net_http.rb +1 -1
- data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +41 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +4 -4
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +13 -1
- data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +1 -8
- data/lib/new_relic/agent/instrumentation/rake.rb +1 -1
- data/lib/new_relic/agent/instrumentation/redis.rb +1 -1
- data/lib/new_relic/agent/instrumentation/resque.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sequel.rb +4 -5
- data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +3 -7
- data/lib/new_relic/agent/monitors/cross_app_monitor.rb +0 -1
- data/lib/new_relic/agent/new_relic_service/security_policy_settings.rb +0 -1
- data/lib/new_relic/agent/new_relic_service.rb +1 -1
- data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +0 -1
- data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +1 -1
- data/lib/new_relic/agent/tracer.rb +10 -1
- data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -2
- data/lib/new_relic/agent/transaction/tracing.rb +2 -2
- data/lib/new_relic/agent/transaction.rb +17 -16
- data/lib/new_relic/agent.rb +1 -19
- data/lib/new_relic/cli/commands/install.rb +9 -9
- data/lib/new_relic/control/instance_methods.rb +1 -1
- data/lib/new_relic/local_environment.rb +0 -10
- data/lib/new_relic/supportability_helper.rb +0 -1
- data/lib/new_relic/version.rb +2 -2
- data/lib/newrelic_rpm.rb +1 -1
- data/lib/sequel/extensions/{newrelic_instrumentation.rb → new_relic_instrumentation.rb} +3 -3
- data/lib/sequel/plugins/{newrelic_instrumentation.rb → new_relic_instrumentation.rb} +3 -3
- data/lib/tasks/helpers/format.rb +1 -1
- data/lib/tasks/instrumentation_generator/instrumentation.thor +7 -10
- data/lib/tasks/instrumentation_generator/templates/Envfile.tt +1 -1
- data/newrelic.yml +15 -9
- data/newrelic_rpm.gemspec +17 -13
- data/test/agent_helper.rb +1 -1
- metadata +37 -14
- data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +0 -83
- data/lib/new_relic/agent/instrumentation/authlogic.rb +0 -33
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +0 -215
- data/lib/new_relic/agent/instrumentation/rainbows_instrumentation.rb +0 -36
- data/lib/new_relic/agent/instrumentation/sunspot.rb +0 -41
@@ -11,8 +11,6 @@ module NewRelic
|
|
11
11
|
def initialize(local_settings)
|
12
12
|
super({
|
13
13
|
:capture_params => false,
|
14
|
-
:'resque.capture_params' => false,
|
15
|
-
:'sidekiq.capture_params' => false,
|
16
14
|
:'attributes.include' => [],
|
17
15
|
|
18
16
|
:'transaction_tracer.record_sql' => record_sql_setting(local_settings, :'transaction_tracer.record_sql'),
|
@@ -191,22 +191,6 @@ module NewRelic
|
|
191
191
|
disabled_value: false,
|
192
192
|
permitted_fn: nil
|
193
193
|
}
|
194
|
-
],
|
195
|
-
"job_arguments" => [
|
196
|
-
{
|
197
|
-
option: :'resque.capture_params',
|
198
|
-
supported: true,
|
199
|
-
enabled_fn: method(:enabled?),
|
200
|
-
disabled_value: false,
|
201
|
-
permitted_fn: nil
|
202
|
-
},
|
203
|
-
{
|
204
|
-
option: :'sidekiq.capture_params',
|
205
|
-
supported: true,
|
206
|
-
enabled_fn: method(:enabled?),
|
207
|
-
disabled_value: false,
|
208
|
-
permitted_fn: nil
|
209
|
-
}
|
210
194
|
]
|
211
195
|
}
|
212
196
|
|
@@ -7,20 +7,6 @@ require 'new_relic/agent/database/explain_plan_helpers'
|
|
7
7
|
require 'new_relic/agent/database/obfuscator'
|
8
8
|
|
9
9
|
module NewRelic
|
10
|
-
# columns for a mysql explain plan
|
11
|
-
MYSQL_EXPLAIN_COLUMNS = [
|
12
|
-
"Id",
|
13
|
-
"Select Type",
|
14
|
-
"Table",
|
15
|
-
"Type",
|
16
|
-
"Possible Keys",
|
17
|
-
"Key",
|
18
|
-
"Key Length",
|
19
|
-
"Ref",
|
20
|
-
"Rows",
|
21
|
-
"Extra"
|
22
|
-
].freeze
|
23
|
-
|
24
10
|
module Agent
|
25
11
|
module Database
|
26
12
|
MAX_QUERY_LENGTH = 16384
|
@@ -166,8 +166,7 @@ module NewRelic
|
|
166
166
|
|
167
167
|
def cross_application_tracer_enabled?
|
168
168
|
!NewRelic::Agent.config[:"distributed_tracing.enabled"] &&
|
169
|
-
|
170
|
-
NewRelic::Agent.config[:cross_application_tracing])
|
169
|
+
NewRelic::Agent.config[:"cross_application_tracer.enabled"]
|
171
170
|
end
|
172
171
|
|
173
172
|
def obfuscator
|
@@ -26,7 +26,7 @@ module NewRelic
|
|
26
26
|
@error_filter = NewRelic::Agent::ErrorFilter.new
|
27
27
|
|
28
28
|
%w[
|
29
|
-
|
29
|
+
ignore_classes ignore_messages ignore_status_codes
|
30
30
|
expected_classes expected_messages expected_status_codes
|
31
31
|
].each do |w|
|
32
32
|
Agent.config.register_callback(:"error_collector.#{w}") do |value|
|
@@ -19,7 +19,7 @@ module NewRelic
|
|
19
19
|
|
20
20
|
def load_all
|
21
21
|
%i[
|
22
|
-
|
22
|
+
ignore_classes ignore_messages ignore_status_codes
|
23
23
|
expected_classes expected_messages expected_status_codes
|
24
24
|
].each { |setting| load_from_config(setting) }
|
25
25
|
end
|
@@ -31,7 +31,7 @@ module NewRelic
|
|
31
31
|
return if new_value.nil? || (new_value.respond_to?(:empty?) && new_value.empty?)
|
32
32
|
|
33
33
|
case setting.to_sym
|
34
|
-
when :
|
34
|
+
when :ignore_classes
|
35
35
|
new_value = new_value.split(',').map!(&:strip) if new_value.is_a?(String)
|
36
36
|
errors = @ignore_classes = new_value
|
37
37
|
when :ignore_messages
|
@@ -120,7 +120,7 @@ module NewRelic
|
|
120
120
|
|
121
121
|
def log_filter(setting, errors)
|
122
122
|
case setting
|
123
|
-
when :
|
123
|
+
when :ignore_classes
|
124
124
|
errors.each do |error|
|
125
125
|
::NewRelic::Agent.logger.debug("Ignoring errors of type '#{error}'")
|
126
126
|
end
|
@@ -10,9 +10,7 @@ module NewRelic
|
|
10
10
|
class ActionCableSubscriber < NotificationsSubscriber
|
11
11
|
PERFORM_ACTION = 'perform_action.action_cable'.freeze
|
12
12
|
|
13
|
-
def
|
14
|
-
return unless state.is_execution_traced?
|
15
|
-
|
13
|
+
def start_segment(name, id, payload) # THREAD_LOCAL_ACCESS
|
16
14
|
finishable = if name == PERFORM_ACTION
|
17
15
|
Tracer.start_transaction_or_segment(
|
18
16
|
name: transaction_name_from_payload(payload),
|
@@ -22,21 +20,6 @@ module NewRelic
|
|
22
20
|
Tracer.start_segment(name: metric_name_from_payload(name, payload))
|
23
21
|
end
|
24
22
|
push_segment(id, finishable)
|
25
|
-
rescue => e
|
26
|
-
log_notification_error(e, name, 'start')
|
27
|
-
end
|
28
|
-
|
29
|
-
def finish(name, id, payload) # THREAD_LOCAL_ACCESS
|
30
|
-
return unless state.is_execution_traced?
|
31
|
-
|
32
|
-
if exception = exception_object(payload)
|
33
|
-
NewRelic::Agent.notice_error(exception)
|
34
|
-
end
|
35
|
-
|
36
|
-
finishable = pop_segment(id)
|
37
|
-
finishable.finish if finishable
|
38
|
-
rescue => e
|
39
|
-
log_notification_error(e, name, 'finish')
|
40
23
|
end
|
41
24
|
|
42
25
|
private
|
@@ -46,7 +29,11 @@ module NewRelic
|
|
46
29
|
end
|
47
30
|
|
48
31
|
def metric_name_from_payload(name, payload)
|
49
|
-
"Ruby/ActionCable/#{payload
|
32
|
+
"Ruby/ActionCable/#{metric_name(payload)}/#{action_name(name)}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def metric_name(payload)
|
36
|
+
payload[:broadcasting] || payload[:channel_class]
|
50
37
|
end
|
51
38
|
|
52
39
|
DOT_ACTION_CABLE = '.action_cable'.freeze
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/notifications_subscriber'
|
6
|
+
require 'new_relic/agent/instrumentation/ignore_actions'
|
7
|
+
require 'new_relic/agent/parameter_filtering'
|
8
|
+
|
9
|
+
module NewRelic
|
10
|
+
module Agent
|
11
|
+
module Instrumentation
|
12
|
+
class ActionControllerOtherSubscriber < NotificationsSubscriber
|
13
|
+
def add_segment_params(segment, payload)
|
14
|
+
segment.params[:filter] = payload[:filter] if payload[:filter]
|
15
|
+
segment.params[:keys] = payload[:keys] if payload[:keys]
|
16
|
+
segment.params[:original_path] = payload[:request].original_fullpath if payload[:request]
|
17
|
+
|
18
|
+
if payload[:context]
|
19
|
+
segment.params[:action] = payload[:context][:action]
|
20
|
+
segment.params[:controller] = payload[:context][:controller]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def metric_name(name, payload)
|
25
|
+
controller_name = controller_name_for_metric(payload)
|
26
|
+
"Ruby/ActionController#{"/#{controller_name}" if controller_name}/#{name.gsub(/\.action_controller/, '')}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def controller_name_for_metric(payload)
|
30
|
+
# redirect_to
|
31
|
+
return payload[:request].controller_class.controller_path if payload[:request] && payload[:request].controller_class
|
32
|
+
|
33
|
+
# unpermitted_parameters
|
34
|
+
::NewRelic::LanguageSupport.constantize(payload[:context][:controller]).controller_path if payload[:context] && payload[:context][:controller]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/action_dispatch_subscriber'
|
6
|
+
|
7
|
+
DependencyDetection.defer do
|
8
|
+
named :action_dispatch
|
9
|
+
|
10
|
+
depends_on do
|
11
|
+
!NewRelic::Agent.config[:disable_action_dispatch]
|
12
|
+
end
|
13
|
+
|
14
|
+
depends_on do
|
15
|
+
defined?(ActiveSupport) &&
|
16
|
+
defined?(ActionDispatch) &&
|
17
|
+
defined?(ActionPack) &&
|
18
|
+
ActionPack.respond_to?(:gem_version) &&
|
19
|
+
ActionPack.gem_version >= Gem::Version.new('6.0.0') && # notifications for dispatch added in Rails 6
|
20
|
+
!NewRelic::Agent::Instrumentation::ActionDispatchSubscriber.subscribed?
|
21
|
+
end
|
22
|
+
|
23
|
+
executes do
|
24
|
+
NewRelic::Agent.logger.info('Installing ActionDispatch instrumentation')
|
25
|
+
end
|
26
|
+
|
27
|
+
executes do
|
28
|
+
ActiveSupport::Notifications.subscribe(/\A[^\.]+\.action_dispatch\z/,
|
29
|
+
NewRelic::Agent::Instrumentation::ActionDispatchSubscriber.new)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/notifications_subscriber'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Instrumentation
|
10
|
+
class ActionDispatchSubscriber < NotificationsSubscriber
|
11
|
+
def start(name, id, payload)
|
12
|
+
return unless state.is_execution_traced?
|
13
|
+
|
14
|
+
start_segment(name, id, payload)
|
15
|
+
rescue => e
|
16
|
+
log_notification_error(e, name, 'start')
|
17
|
+
end
|
18
|
+
|
19
|
+
def finish(name, id, payload)
|
20
|
+
return unless state.is_execution_traced?
|
21
|
+
|
22
|
+
finish_segment(id, payload)
|
23
|
+
rescue => e
|
24
|
+
log_notification_error(e, name, 'finish')
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_segment(name, id, payload)
|
28
|
+
segment = Tracer.start_segment(name: metric_name(name, payload))
|
29
|
+
push_segment(id, segment)
|
30
|
+
end
|
31
|
+
|
32
|
+
def finish_segment(id, payload)
|
33
|
+
if segment = pop_segment(id)
|
34
|
+
if exception = exception_object(payload)
|
35
|
+
segment.notice_error(exception)
|
36
|
+
end
|
37
|
+
segment.finish
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def metric_name(name, payload)
|
42
|
+
middleware = payload[:middleware]
|
43
|
+
method = method_from_name(name)
|
44
|
+
"Ruby/ActionDispatch/#{middleware}/#{method}"
|
45
|
+
end
|
46
|
+
|
47
|
+
PATTERN = /\A([^\.]+)\.action_dispatch\z/
|
48
|
+
UNKNOWN = 'unknown'.freeze
|
49
|
+
|
50
|
+
METHOD_NAME_MAPPING = Hash.new do |h, k|
|
51
|
+
if PATTERN =~ k
|
52
|
+
h[k] = $1
|
53
|
+
else
|
54
|
+
h[k] = UNKNOWN
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_from_name(name)
|
59
|
+
METHOD_NAME_MAPPING[name]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/action_mailbox_subscriber'
|
6
|
+
|
7
|
+
DependencyDetection.defer do
|
8
|
+
named :action_mailbox
|
9
|
+
|
10
|
+
depends_on do
|
11
|
+
!NewRelic::Agent.config[:disable_action_mailbox]
|
12
|
+
end
|
13
|
+
|
14
|
+
depends_on do
|
15
|
+
defined?(ActiveSupport) &&
|
16
|
+
defined?(ActionMailbox) &&
|
17
|
+
ActionMailbox.respond_to?(:gem_version) && # 'require "action_mailbox"' doesn't require version...
|
18
|
+
ActionMailbox.gem_version >= Gem::Version.new('7.1.0.alpha') && # notifications added in Rails 7.1
|
19
|
+
!NewRelic::Agent::Instrumentation::ActionMailboxSubscriber.subscribed?
|
20
|
+
end
|
21
|
+
|
22
|
+
executes do
|
23
|
+
NewRelic::Agent.logger.info('Installing ActionMailbox instrumentation')
|
24
|
+
end
|
25
|
+
|
26
|
+
executes do
|
27
|
+
ActiveSupport::Notifications.subscribe(/\A[^\.]+\.action_mailbox\z/,
|
28
|
+
NewRelic::Agent::Instrumentation::ActionMailboxSubscriber.new)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/notifications_subscriber'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Instrumentation
|
10
|
+
class ActionMailboxSubscriber < NotificationsSubscriber
|
11
|
+
def metric_name(name, payload)
|
12
|
+
mailbox = payload[:mailbox].class.name
|
13
|
+
method = method_from_name(name)
|
14
|
+
"Ruby/ActionMailbox/#{mailbox}/#{method}"
|
15
|
+
end
|
16
|
+
|
17
|
+
PATTERN = /\A([^\.]*)\.action_mailbox\z/
|
18
|
+
|
19
|
+
METHOD_NAME_MAPPING = Hash.new do |h, k|
|
20
|
+
if PATTERN =~ k
|
21
|
+
h[k] = $1
|
22
|
+
else
|
23
|
+
h[k] = NewRelic::UNKNOWN
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_from_name(name)
|
28
|
+
METHOD_NAME_MAPPING[name]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/action_mailer_subscriber'
|
6
|
+
|
7
|
+
DependencyDetection.defer do
|
8
|
+
named :action_mailer
|
9
|
+
|
10
|
+
depends_on do
|
11
|
+
!NewRelic::Agent.config[:disable_action_mailer]
|
12
|
+
end
|
13
|
+
|
14
|
+
depends_on do
|
15
|
+
defined?(ActiveSupport) &&
|
16
|
+
defined?(ActionMailer) &&
|
17
|
+
ActionMailer.respond_to?(:gem_version) &&
|
18
|
+
ActionMailer.gem_version >= Gem::Version.new('5.0') &&
|
19
|
+
!NewRelic::Agent::Instrumentation::ActionMailerSubscriber.subscribed?
|
20
|
+
end
|
21
|
+
|
22
|
+
executes do
|
23
|
+
NewRelic::Agent.logger.info('Installing ActionMailer instrumentation')
|
24
|
+
end
|
25
|
+
|
26
|
+
executes do
|
27
|
+
ActiveSupport::Notifications.subscribe(/\A(?:[^\.]+)\.action_mailer\z/,
|
28
|
+
NewRelic::Agent::Instrumentation::ActionMailerSubscriber.new)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/notifications_subscriber'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Instrumentation
|
10
|
+
# NOTE: as of v7.1.0.0.alpha, deliver.action_mailer will provide
|
11
|
+
# an empty payload hash ({}) to #start, so in this subscriber class
|
12
|
+
# we defer params population until #finish and start the segment with
|
13
|
+
# a temporary name that is later replaced
|
14
|
+
class ActionMailerSubscriber < NotificationsSubscriber
|
15
|
+
BASE_NAME = 'Ruby/ActionMailer'
|
16
|
+
PAYLOAD_KEYS = %i[action data key mailer message_id perform_deliveries subject]
|
17
|
+
PATTERN = /\A([^\.]+)\.action_mailer\z/
|
18
|
+
UNKNOWN_MAILER = %r{^#{BASE_NAME}/#{UNKNOWN}/}
|
19
|
+
|
20
|
+
METHOD_NAME_MAPPING = Hash.new do |h, k|
|
21
|
+
if PATTERN =~ k
|
22
|
+
h[k] = $1
|
23
|
+
else
|
24
|
+
h[k] = NewRelic::UNKNOWN
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def start(name, id, payload)
|
29
|
+
return unless state.is_execution_traced?
|
30
|
+
|
31
|
+
start_segment(name, id, payload)
|
32
|
+
rescue => e
|
33
|
+
log_notification_error(e, name, 'start')
|
34
|
+
end
|
35
|
+
|
36
|
+
def finish(name, id, payload)
|
37
|
+
return unless state.is_execution_traced?
|
38
|
+
|
39
|
+
finish_segment(id, payload)
|
40
|
+
rescue => e
|
41
|
+
log_notification_error(e, name, 'finish')
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def start_segment(name, id, payload)
|
47
|
+
segment = Tracer.start_segment(name: metric_name(name, payload))
|
48
|
+
push_segment(id, segment)
|
49
|
+
end
|
50
|
+
|
51
|
+
def finish_segment(id, payload)
|
52
|
+
segment = pop_segment(id)
|
53
|
+
return unless segment
|
54
|
+
|
55
|
+
if segment.name.match?(UNKNOWN_MAILER) && payload.key?(:mailer)
|
56
|
+
segment.name = segment.name.sub(UNKNOWN_MAILER, "#{BASE_NAME}/#{payload[:mailer]}/")
|
57
|
+
end
|
58
|
+
|
59
|
+
PAYLOAD_KEYS.each do |key|
|
60
|
+
segment.params[key] = payload[key] if payload.key?(key)
|
61
|
+
end
|
62
|
+
|
63
|
+
notice_exception(segment, payload)
|
64
|
+
segment.finish
|
65
|
+
end
|
66
|
+
|
67
|
+
def notice_exception(segment, payload)
|
68
|
+
if exception = exception_object(payload)
|
69
|
+
segment.notice_error(exception)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def metric_name(name, payload)
|
74
|
+
mailer = payload[:mailer] || UNKNOWN
|
75
|
+
method = method_from_name(name)
|
76
|
+
"#{BASE_NAME}/#{mailer}/#{method}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def method_from_name(name)
|
80
|
+
METHOD_NAME_MAPPING[name]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -10,28 +10,25 @@ module NewRelic
|
|
10
10
|
module Agent
|
11
11
|
module Instrumentation
|
12
12
|
class ActionViewSubscriber < NotificationsSubscriber
|
13
|
-
def
|
13
|
+
def start_segment(name, id, payload)
|
14
14
|
parent = segment_stack[id].last
|
15
15
|
metric_name = format_metric_name(name, payload, parent)
|
16
16
|
|
17
17
|
event = ActionViewEvent.new(metric_name, payload[:identifier])
|
18
|
-
|
18
|
+
|
19
|
+
if recordable?(name, metric_name)
|
19
20
|
event.finishable = Tracer.start_segment(name: metric_name)
|
20
21
|
end
|
21
22
|
push_segment(id, event)
|
22
|
-
rescue => e
|
23
|
-
log_notification_error(e, name, 'start')
|
24
23
|
end
|
25
24
|
|
26
|
-
def
|
25
|
+
def finish_segment(id, payload)
|
27
26
|
if segment = pop_segment(id)
|
28
27
|
if exception = exception_object(payload)
|
29
28
|
segment.notice_error(exception)
|
30
29
|
end
|
31
30
|
segment.finish
|
32
31
|
end
|
33
|
-
rescue => e
|
34
|
-
log_notification_error(e, name, 'finish')
|
35
32
|
end
|
36
33
|
|
37
34
|
def format_metric_name(event_name, payload, parent)
|
@@ -61,12 +58,15 @@ module NewRelic
|
|
61
58
|
RENDER_TEMPLATE_EVENT_NAME = 'render_template.action_view'.freeze
|
62
59
|
RENDER_PARTIAL_EVENT_NAME = 'render_partial.action_view'.freeze
|
63
60
|
RENDER_COLLECTION_EVENT_NAME = 'render_collection.action_view'.freeze
|
61
|
+
RENDER_LAYOUT_EVENT_NAME = 'render_layout.action_view'.freeze
|
64
62
|
|
65
63
|
def metric_action(name)
|
66
64
|
case name
|
67
65
|
when /#{RENDER_TEMPLATE_EVENT_NAME}$/o then 'Rendering'
|
68
66
|
when RENDER_PARTIAL_EVENT_NAME then 'Partial'
|
69
67
|
when RENDER_COLLECTION_EVENT_NAME then 'Partial'
|
68
|
+
when RENDER_LAYOUT_EVENT_NAME then 'Layout'
|
69
|
+
else NewRelic::UNKNOWN
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -12,7 +12,7 @@ DependencyDetection.defer do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
executes do
|
15
|
-
NewRelic::Agent.logger.info('Installing ActiveJob instrumentation')
|
15
|
+
NewRelic::Agent.logger.info('Installing base ActiveJob instrumentation')
|
16
16
|
|
17
17
|
ActiveSupport.on_load(:active_job) do
|
18
18
|
ActiveJob::Base.around_enqueue do |job, block|
|
@@ -26,6 +26,19 @@ DependencyDetection.defer do
|
|
26
26
|
NewRelic::Agent::PrependSupportability.record_metrics_for(ActiveJob::Base)
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
executes do
|
31
|
+
if defined?(ActiveSupport) &&
|
32
|
+
ActiveJob.respond_to?(:gem_version) &&
|
33
|
+
ActiveJob.gem_version >= Gem::Version.new('6.0.0') &&
|
34
|
+
!NewRelic::Agent.config[:disable_activejob] &&
|
35
|
+
!NewRelic::Agent::Instrumentation::ActiveJobSubscriber.subscribed?
|
36
|
+
NewRelic::Agent.logger.info('Installing notifications based ActiveJob instrumentation')
|
37
|
+
|
38
|
+
ActiveSupport::Notifications.subscribe(/\A[^\.]+\.active_job\z/,
|
39
|
+
NewRelic::Agent::Instrumentation::ActiveJobSubscriber.new)
|
40
|
+
end
|
41
|
+
end
|
29
42
|
end
|
30
43
|
|
31
44
|
module NewRelic
|
@@ -58,7 +71,7 @@ module NewRelic
|
|
58
71
|
end
|
59
72
|
|
60
73
|
def self.run_in_trace(job, block, event)
|
61
|
-
trace_execution_scoped("
|
74
|
+
trace_execution_scoped("ActiveJob/#{adapter.sub(/^ActiveJob::/, '')}/Queue/#{event}/Named/#{job.queue_name}",
|
62
75
|
code_information: code_information_for_job(job)) do
|
63
76
|
block.call
|
64
77
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'new_relic/agent/instrumentation/notifications_subscriber'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Instrumentation
|
10
|
+
class ActiveJobSubscriber < NotificationsSubscriber
|
11
|
+
PAYLOAD_KEYS = %i[adapter db_runtime error job wait]
|
12
|
+
|
13
|
+
def add_segment_params(segment, payload)
|
14
|
+
PAYLOAD_KEYS.each do |key|
|
15
|
+
segment.params[key] = payload[key] if payload.key?(key)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def metric_name(name, payload)
|
20
|
+
queue = payload[:job].queue_name
|
21
|
+
method = method_from_name(name)
|
22
|
+
"Ruby/ActiveJob/#{queue}/#{method}"
|
23
|
+
end
|
24
|
+
|
25
|
+
PATTERN = /\A([^\.]+)\.active_job\z/
|
26
|
+
|
27
|
+
METHOD_NAME_MAPPING = Hash.new do |h, k|
|
28
|
+
if PATTERN =~ k
|
29
|
+
h[k] = $1
|
30
|
+
else
|
31
|
+
h[k] = NewRelic::UNKNOWN
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_from_name(name)
|
36
|
+
METHOD_NAME_MAPPING[name]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -7,6 +7,10 @@ require 'new_relic/agent/instrumentation/active_storage_subscriber'
|
|
7
7
|
DependencyDetection.defer do
|
8
8
|
named :active_storage
|
9
9
|
|
10
|
+
depends_on do
|
11
|
+
!NewRelic::Agent.config[:disable_active_storage]
|
12
|
+
end
|
13
|
+
|
10
14
|
depends_on do
|
11
15
|
defined?(ActiveStorage) &&
|
12
16
|
!NewRelic::Agent::Instrumentation::ActiveStorageSubscriber.subscribed?
|
@@ -8,36 +8,9 @@ module NewRelic
|
|
8
8
|
module Agent
|
9
9
|
module Instrumentation
|
10
10
|
class ActiveStorageSubscriber < NotificationsSubscriber
|
11
|
-
def
|
12
|
-
return unless state.is_execution_traced?
|
13
|
-
|
14
|
-
start_segment(name, id, payload)
|
15
|
-
rescue => e
|
16
|
-
log_notification_error(e, name, 'start')
|
17
|
-
end
|
18
|
-
|
19
|
-
def finish(name, id, payload)
|
20
|
-
return unless state.is_execution_traced?
|
21
|
-
|
22
|
-
finish_segment(id, payload)
|
23
|
-
rescue => e
|
24
|
-
log_notification_error(e, name, 'finish')
|
25
|
-
end
|
26
|
-
|
27
|
-
def start_segment(name, id, payload)
|
28
|
-
segment = Tracer.start_segment(name: metric_name(name, payload))
|
11
|
+
def add_segment_params(segment, payload)
|
29
12
|
segment.params[:key] = payload[:key]
|
30
13
|
segment.params[:exist] = payload[:exist] if payload.key?(:exist)
|
31
|
-
push_segment(id, segment)
|
32
|
-
end
|
33
|
-
|
34
|
-
def finish_segment(id, payload)
|
35
|
-
if segment = pop_segment(id)
|
36
|
-
if exception = exception_object(payload)
|
37
|
-
segment.notice_error(exception)
|
38
|
-
end
|
39
|
-
segment.finish
|
40
|
-
end
|
41
14
|
end
|
42
15
|
|
43
16
|
def metric_name(name, payload)
|
@@ -47,13 +20,12 @@ module NewRelic
|
|
47
20
|
end
|
48
21
|
|
49
22
|
PATTERN = /\Aservice_([^\.]*)\.active_storage\z/
|
50
|
-
UNKNOWN = "unknown".freeze
|
51
23
|
|
52
24
|
METHOD_NAME_MAPPING = Hash.new do |h, k|
|
53
25
|
if PATTERN =~ k
|
54
26
|
h[k] = $1
|
55
27
|
else
|
56
|
-
h[k] = UNKNOWN
|
28
|
+
h[k] = NewRelic::UNKNOWN
|
57
29
|
end
|
58
30
|
end
|
59
31
|
|