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
41
42
|
# 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
44
45
46
47
48
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 44
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
86
87
88
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 86
def add_segment_params(segment, payload)
end
|
#define_exception_method ⇒ Object
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 119
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
62
63
64
65
66
67
68
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 62
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
76
77
78
79
80
81
82
83
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 76
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
95
96
97
98
99
100
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 95
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
91
92
93
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 91
def metric_name(name, payload)
"Ruby/#{name}"
end
|
#pop_segment(id) ⇒ Object
106
107
108
109
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 106
def pop_segment(id)
segment = segment_stack[id].pop
segment
end
|
#push_segment(id, segment) ⇒ Object
102
103
104
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 102
def push_segment(id, segment)
segment_stack[id].push(segment)
end
|
#segment_stack ⇒ Object
111
112
113
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 111
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
54
55
56
57
58
59
60
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 54
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
70
71
72
73
74
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 70
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
115
116
117
|
# File 'lib/new_relic/agent/instrumentation/notifications_subscriber.rb', line 115
def state
NewRelic::Agent::Tracer.state
end
|