Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 213 lines (201 sloc) 7.311 kB
60736fe @tenderlove push the autoloads up to requires
tenderlove authored
1 require 'active_support/notifications/instrumenter'
2 require 'active_support/notifications/fanout'
e12901e @wangjohn Changed the ScopeRegistry and the InstrumentationRegistry to use the
wangjohn authored
3 require 'active_support/per_thread_registry'
60736fe @tenderlove push the autoloads up to requires
tenderlove authored
4
3c9a37c @josevalim Added Orchestra.
josevalim authored
5 module ActiveSupport
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
6 # = Notifications
3c9a37c @josevalim Added Orchestra.
josevalim authored
7 #
d71d5ba update AS docs [ci skip]
Francesco Rodriguez authored
8 # <tt>ActiveSupport::Notifications</tt> provides an instrumentation API for
9 # Ruby.
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
10 #
11 # == Instrumenters
12 #
13 # To instrument an event you just need to do:
14 #
f4e1805 update some AS code examples to 1.9 hash syntax [ci skip]
Francesco Rodriguez authored
15 # ActiveSupport::Notifications.instrument('render', extra: :information) do
16 # render text: 'Foo'
3c9a37c @josevalim Added Orchestra.
josevalim authored
17 # end
18 #
30af171 @rishijain added description for rails generators, and fixed sentence formation …
rishijain authored
19 # That first executes the block and then notifies all subscribers once done.
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
20 #
f4e1805 update some AS code examples to 1.9 hash syntax [ci skip]
Francesco Rodriguez authored
21 # In the example above +render+ is the name of the event, and the rest is called
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
22 # the _payload_. The payload is a mechanism that allows instrumenters to pass
23 # extra information to subscribers. Payloads consist of a hash whose contents
24 # are arbitrary and generally depend on the event.
25 #
26 # == Subscribers
27 #
5d0f8ab @josevalim Orchestra listeners have their own queue.
josevalim authored
28 # You can consume those events and the information they provide by registering
5917c6e Improve documentation for subscribe block
Grant Hutchins & Sabrina Staedt authored
29 # a subscriber.
30 #
31 # ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
32 # name # => String, name of the event (such as 'render' from above)
33 # start # => Time, when the instrumented block started execution
34 # finish # => Time, when the instrumented block ended execution
35 # id # => String, unique ID for this notification
36 # payload # => Hash, the payload
37 # end
38 #
39 # For instance, let's store all "render" events in an array:
3c9a37c @josevalim Added Orchestra.
josevalim authored
40 #
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
41 # events = []
5d0f8ab @josevalim Orchestra listeners have their own queue.
josevalim authored
42 #
f4e1805 update some AS code examples to 1.9 hash syntax [ci skip]
Francesco Rodriguez authored
43 # ActiveSupport::Notifications.subscribe('render') do |*args|
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
44 # events << ActiveSupport::Notifications::Event.new(*args)
5d0f8ab @josevalim Orchestra listeners have their own queue.
josevalim authored
45 # end
3c9a37c @josevalim Added Orchestra.
josevalim authored
46 #
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
47 # That code returns right away, you are just subscribing to "render" events.
c779a47 Documentation: make it clearer that subscribers are not notified asyn…
Schnittchen authored
48 # The block is saved and will be called whenever someone instruments "render":
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
49 #
f4e1805 update some AS code examples to 1.9 hash syntax [ci skip]
Francesco Rodriguez authored
50 # ActiveSupport::Notifications.instrument('render', extra: :information) do
51 # render text: 'Foo'
3c9a37c @josevalim Added Orchestra.
josevalim authored
52 # end
53 #
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
54 # event = events.first
55 # event.name # => "render"
755af49 @fxn edit pass to apply API guideline wrt the use of "# =>" in example code
fxn authored
56 # event.duration # => 10 (in milliseconds)
f4e1805 update some AS code examples to 1.9 hash syntax [ci skip]
Francesco Rodriguez authored
57 # event.payload # => { extra: :information }
3c9a37c @josevalim Added Orchestra.
josevalim authored
58 #
32df313 @bsodmike Fix further typos in ActiveSupport::Notifications
bsodmike authored
59 # The block in the <tt>subscribe</tt> call gets the name of the event, start
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
60 # timestamp, end timestamp, a string with a unique identifier for that event
61 # (something like "535801666f04d0298cd6"), and a hash with the payload, in
62 # that order.
63 #
64 # If an exception happens during that particular instrumentation the payload will
32df313 @bsodmike Fix further typos in ActiveSupport::Notifications
bsodmike authored
65 # have a key <tt>:exception</tt> with an array of two elements as value: a string with
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
66 # the name of the exception class, and the exception message.
67 #
32df313 @bsodmike Fix further typos in ActiveSupport::Notifications
bsodmike authored
68 # As the previous example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
69 # is able to take the arguments as they come and provide an object-oriented
70 # interface to that data.
5d0f8ab @josevalim Orchestra listeners have their own queue.
josevalim authored
71 #
b744199 @bsodmike Add documentation to detail passing of an object as the second
bsodmike authored
72 # It is also possible to pass an object as the second parameter passed to the
73 # <tt>subscribe</tt> method instead of a block:
74 #
75 # module ActionController
76 # class PageRequest
77 # def call(name, started, finished, unique_id, payload)
f4e1805 update some AS code examples to 1.9 hash syntax [ci skip]
Francesco Rodriguez authored
78 # Rails.logger.debug ['notification:', name, started, finished, unique_id, payload].join(' ')
b744199 @bsodmike Add documentation to detail passing of an object as the second
bsodmike authored
79 # end
80 # end
81 # end
82 #
83 # ActiveSupport::Notifications.subscribe('process_action.action_controller', ActionController::PageRequest.new)
84 #
85 # resulting in the following output within the logs including a hash with the payload:
86 #
87 # notification: process_action.action_controller 2012-04-13 01:08:35 +0300 2012-04-13 01:08:35 +0300 af358ed7fab884532ec7 {
8553b7a @AvnerCohen 1.9 hash syntax in activesupport
AvnerCohen authored
88 # controller: "Devise::SessionsController",
89 # action: "new",
90 # params: {"action"=>"new", "controller"=>"devise/sessions"},
91 # format: :html,
92 # method: "GET",
93 # path: "/login/sign_in",
94 # status: 200,
95 # view_runtime: 279.3080806732178,
96 # db_runtime: 40.053
b744199 @bsodmike Add documentation to detail passing of an object as the second
bsodmike authored
97 # }
98 #
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
99 # You can also subscribe to all events whose name matches a certain regexp:
100 #
101 # ActiveSupport::Notifications.subscribe(/render/) do |*args|
102 # ...
5d0f8ab @josevalim Orchestra listeners have their own queue.
josevalim authored
103 # end
104 #
32df313 @bsodmike Fix further typos in ActiveSupport::Notifications
bsodmike authored
105 # and even pass no argument to <tt>subscribe</tt>, in which case you are subscribing
b33232f @fxn expands the documentation of AS::Notifications
fxn authored
106 # to all events.
107 #
d287e90 @fxn implements AS::Notifications.subscribed, which provides subscriptions…
fxn authored
108 # == Temporary Subscriptions
109 #
110 # Sometimes you do not want to subscribe to an event for the entire life of
56f16e2 @fxn fixes typo
fxn authored
111 # the application. There are two ways to unsubscribe.
d287e90 @fxn implements AS::Notifications.subscribed, which provides subscriptions…
fxn authored
112 #
a59269d @fxn warns against using temporary subscribers
fxn authored
113 # WARNING: The instrumentation framework is designed for long-running subscribers,
114 # use this feature sparingly because it wipes some internal caches and that has
115 # a negative impact on performance.
116 #
d287e90 @fxn implements AS::Notifications.subscribed, which provides subscriptions…
fxn authored
117 # === Subscribe While a Block Runs
118 #
119 # You can subscribe to some event temporarily while some block runs. For
120 # example, in
121 #
122 # callback = lambda {|*args| ... }
123 # ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
124 # ...
125 # end
126 #
127 # the callback will be called for all "sql.active_record" events instrumented
128 # during the execution of the block. The callback is unsubscribed automatically
129 # after that.
130 #
131 # === Manual Unsubscription
132 #
133 # The +subscribe+ method returns a subscriber object:
134 #
135 # subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
136 # ...
137 # end
138 #
139 # To prevent that block from being called anymore, just unsubscribe passing
140 # that reference:
141 #
142 # ActiveSupport::Notifications.unsubscribe(subscriber)
143 #
a67fdc0 @tgxworld Update documentation to reflect unsubscription with name.
tgxworld authored
144 # You can also unsubscribe by passing the name of the subscriber object. Note
145 # that this will unsubscribe all subscriptions with the given name:
146 #
147 # ActiveSupport::Notifications.unsubscribe("render")
148 #
d287e90 @fxn implements AS::Notifications.subscribed, which provides subscriptions…
fxn authored
149 # == Default Queue
150 #
e93e255 @dwbutler Documentation: Notifications queue does not run in a thread.
dwbutler authored
151 # Notifications ships with a queue implementation that consumes and publishes events
152 # to all log subscribers. You can use any queue implementation you want.
3c9a37c @josevalim Added Orchestra.
josevalim authored
153 #
2d7abe2 @josevalim Renamed Orchestra to Notifications once again [#3321 state:resolved]
josevalim authored
154 module Notifications
7b5225a @josevalim Abstract publishing, subscribing and instrumenting in Orchestra.
josevalim authored
155 class << self
bf8e205 @tenderlove move fanout back to a global variable, add a mutex for safety
tenderlove authored
156 attr_accessor :notifier
157
3d0579f @tenderlove speed up notification publishing by writing the delegate method
tenderlove authored
158 def publish(name, *args)
159 notifier.publish(name, *args)
160 end
ba8d89c Performance optimizations to handle cases of instrumentors that are n…
Carlhuda authored
161
ff0d842 @josevalim Revert the previous three commits.
josevalim authored
162 def instrument(name, payload = {})
644a179 @tenderlove remove global cache
tenderlove authored
163 if notifier.listening?(name)
ff0d842 @josevalim Revert the previous three commits.
josevalim authored
164 instrumenter.instrument(name, payload) { yield payload if block_given? }
ba8d89c Performance optimizations to handle cases of instrumentors that are n…
Carlhuda authored
165 else
ff0d842 @josevalim Revert the previous three commits.
josevalim authored
166 yield payload if block_given?
ba8d89c Performance optimizations to handle cases of instrumentors that are n…
Carlhuda authored
167 end
168 end
169
170 def subscribe(*args, &block)
644a179 @tenderlove remove global cache
tenderlove authored
171 notifier.subscribe(*args, &block)
ba8d89c Performance optimizations to handle cases of instrumentors that are n…
Carlhuda authored
172 end
173
d287e90 @fxn implements AS::Notifications.subscribed, which provides subscriptions…
fxn authored
174 def subscribed(callback, *args, &block)
175 subscriber = subscribe(*args, &callback)
176 yield
177 ensure
178 unsubscribe(subscriber)
179 end
180
a67fdc0 @tgxworld Update documentation to reflect unsubscription with name.
tgxworld authored
181 def unsubscribe(subscriber_or_name)
182 notifier.unsubscribe(subscriber_or_name)
ba8d89c Performance optimizations to handle cases of instrumentors that are n…
Carlhuda authored
183 end
7b5225a @josevalim Abstract publishing, subscribing and instrumenting in Orchestra.
josevalim authored
184
74f6cce @josevalim instrumenter should be accessible from ActiveSupport::Notifications.
josevalim authored
185 def instrumenter
5584ddc @tenderlove Stop using method missing for singleton delegation.
tenderlove authored
186 InstrumentationRegistry.instance.instrumenter_for(notifier)
b62c197 @wangjohn Creating an object to consolidate thread locals which hold the
wangjohn authored
187 end
188 end
189
190 # This class is a registry which holds all of the +Instrumenter+ objects
191 # in a particular thread local. To access the +Instrumenter+ object for a
192 # particular +notifier+, you can call the following method:
193 #
194 # InstrumentationRegistry.instrumenter_for(notifier)
195 #
196 # The instrumenters for multiple notifiers are held in a single instance of
197 # this class.
198 class InstrumentationRegistry # :nodoc:
e12901e @wangjohn Changed the ScopeRegistry and the InstrumentationRegistry to use the
wangjohn authored
199 extend ActiveSupport::PerThreadRegistry
b62c197 @wangjohn Creating an object to consolidate thread locals which hold the
wangjohn authored
200
201 def initialize
202 @registry = {}
203 end
204
205 def instrumenter_for(notifier)
206 @registry[notifier] ||= Instrumenter.new(notifier)
a01d9da @tenderlove make the fanout notifier local to the current thread
tenderlove authored
207 end
208 end
bf8e205 @tenderlove move fanout back to a global variable, add a mutex for safety
tenderlove authored
209
210 self.notifier = Fanout.new
3c9a37c @josevalim Added Orchestra.
josevalim authored
211 end
212 end
Something went wrong with that request. Please try again.