Class: NewRelic::Agent::Instrumentation::NotificationsSubscriber
- Inherits:
-
Object
- Object
- NewRelic::Agent::Instrumentation::NotificationsSubscriber
show all
- Defined in:
- lib/new_relic/agent/instrumentation/notifications_subscriber.rb
Direct Known Subclasses
ActionCableSubscriber, ActionControllerOtherSubscriber, ActionControllerSubscriber, ActionDispatchSubscriber, ActionMailboxSubscriber, ActionMailerSubscriber, ActionViewSubscriber, ActiveJobSubscriber, ActiveRecordSubscriber, ActiveStorageSubscriber, ActiveSupportSubscriber, CustomEventsSubscriber
Class Method Summary
collapse
Instance Method Summary
collapse
-
#add_segment_params(segment, payload) ⇒ Object
-
#define_exception_method ⇒ Object
-
#finish(name, id, payload) ⇒ Object
-
#finish_segment(id, payload) ⇒ Object
-
#initialize ⇒ NotificationsSubscriber
constructor
A new instance of NotificationsSubscriber.
-
#log_notification_error(error, name, event_type) ⇒ Object
-
#metric_name(name, payload) ⇒ Object
-
#pop_segment(id) ⇒ Object
-
#push_segment(id, segment) ⇒ Object
-
#segment_stack ⇒ Object
-
#start(name, id, payload) ⇒ Object
The agent doesn’t use the traditional ActiveSupport::Notifications.subscribe pattern due to threading issues discovered on initial instrumentation.
-
#start_segment(name, id, payload) ⇒ Object
-
#state ⇒ Object
Constructor Details
Returns a new instance of NotificationsSubscriber.
9
10
11
12
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 9
def initialize
@queue_key = ['NewRelic', self.class.name, object_id].join('-')
define_exception_method
end
|
Class Method Details
.find_all_subscribers ⇒ Object
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 18
def self.find_all_subscribers
instance_variable_names = [:@subscribers, :@string_subscribers, :@other_subscribers]
all_subscribers = []
notifier = ActiveSupport::Notifications.notifier
instance_variable_names.each do |name|
if notifier.instance_variable_defined?(name)
subscribers = notifier.instance_variable_get(name)
if subscribers.is_a?(Array)
all_subscribers += subscribers
elsif subscribers.is_a?(Hash)
subscribers.values.each { |array| all_subscribers += array }
end
end
end
all_subscribers
end
|
.subscribe(pattern) ⇒ Object
42
43
44
45
46
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 42
def self.subscribe(pattern)
if !subscribed?
ActiveSupport::Notifications.subscribe(pattern, new)
end
end
|
.subscribed? ⇒ Boolean
14
15
16
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 14
def self.subscribed?
find_all_subscribers.find { |s| s.instance_variable_get(:@delegate).class == self }
end
|
Instance Method Details
#add_segment_params(segment, payload) ⇒ Object
84
85
86
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 84
def add_segment_params(segment, payload)
end
|
#define_exception_method ⇒ Object
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 117
def define_exception_method
return if defined?(exception_object)
return unless defined?(::ActiveSupport::VERSION)
if ::ActiveSupport::VERSION::STRING < '5.0.0'
def exception_object(payload)
exception_class, message = payload[:exception]
return nil unless exception_class
NewRelic::Agent::NoticeableError.new(exception_class, message)
end
else
def exception_object(payload)
payload[:exception_object]
end
end
end
|
#finish(name, id, payload) ⇒ Object
60
61
62
63
64
65
66
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 60
def finish(name, id, payload)
return unless state.is_execution_traced?
finish_segment(id, payload)
rescue => e
log_notification_error(e, name, 'finish')
end
|
#finish_segment(id, payload) ⇒ Object
74
75
76
77
78
79
80
81
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 74
def finish_segment(id, payload)
if segment = pop_segment(id)
if exception = exception_object(payload)
segment.notice_error(exception)
end
segment.finish
end
end
|
#log_notification_error(error, name, event_type) ⇒ Object
93
94
95
96
97
98
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 93
def log_notification_error(error, name, event_type)
NewRelic::Agent.logger.error("Error during #{event_type} callback for event '#{name}':")
NewRelic::Agent.logger.log_exception(:error, error)
end
|
#metric_name(name, payload) ⇒ Object
89
90
91
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 89
def metric_name(name, payload)
"Ruby/#{name}"
end
|
#pop_segment(id) ⇒ Object
104
105
106
107
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 104
def pop_segment(id)
segment = segment_stack[id].pop
segment
end
|
#push_segment(id, segment) ⇒ Object
100
101
102
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 100
def push_segment(id, segment)
segment_stack[id].push(segment)
end
|
#segment_stack ⇒ Object
109
110
111
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 109
def segment_stack
Thread.current[@queue_key] ||= Hash.new { |h, id| h[id] = [] }
end
|
#start(name, id, payload) ⇒ Object
The agent doesn’t use the traditional ActiveSupport::Notifications.subscribe pattern due to threading issues discovered on initial instrumentation. Instead we define a #start and #finish method, which Rails responds to. See: github.com/rails/rails/issues/12069
52
53
54
55
56
57
58
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 52
def start(name, id, payload)
return unless state.is_execution_traced?
start_segment(name, id, payload)
rescue => e
log_notification_error(e, name, 'start')
end
|
#start_segment(name, id, payload) ⇒ Object
68
69
70
71
72
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 68
def start_segment(name, id, payload)
segment = Tracer.start_segment(name: metric_name(name, payload))
add_segment_params(segment, payload)
push_segment(id, segment)
end
|
#state ⇒ Object
113
114
115
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 113
def state
NewRelic::Agent::Tracer.state
end
|