通知物件
ActiveSupport::Notifications
提供一個 Ruby 用的 instrumentation API。
工頭
要量測一個事件,你只要做
ActiveSupport::Notifications.instrument('render', extra: :information) do
render plain: 'Foo'
end
這會先執行區塊,然後在執行完時通知所有訂閱者。
在上面的範例裡,render
是這個事件的名稱,其餘的稱為酬載。酬載機制讓工頭可以將額外的資訊傳給訂閱者。酬載由一個 hash 構成,其內容是任意的,且通常會依事件而定。
訂閱者
你可以透過註冊訂閱者來使用這些事件和它們提供的資訊。
ActiveSupport::Notifications.subscribe('render') do |event|
event.name # => "render"
event.duration # => 10 (in milliseconds)
event.payload # => { extra: :information }
event.allocations # => 1826 (objects)
end
Event
物件會記錄 CPU 時間和分配。如果你不需要這個功能,也可以傳遞一個區塊,這個區塊接受五個參數
ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
name # => String, name of the event (such as 'render' from above)
start # => Time, when the instrumented block started execution
finish # => Time, when the instrumented block ended execution
id # => String, unique ID for the instrumenter that fired the event
payload # => Hash, the payload
end
這裡,start
和 finish
值代表時鐘時間。如果你有準確度上的疑慮,可以註冊一個單調訂閱者。
ActiveSupport::Notifications.monotonic_subscribe('render') do |name, start, finish, id, payload|
name # => String, name of the event (such as 'render' from above)
start # => Float, monotonic time when the instrumented block started execution
finish # => Float, monotonic time when the instrumented block ended execution
id # => String, unique ID for the instrumenter that fired the event
payload # => Hash, the payload
end
例如,我們來用一個陣列儲存所有的「render」事件
events = []
ActiveSupport::Notifications.subscribe('render') do |event|
events << event
end
這段程式碼可以立即回傳,你只是在訂閱「render」事件。這個區塊會被儲存,且每當有人量測「render」時就會被呼叫
ActiveSupport::Notifications.instrument('render', extra: :information) do
render plain: 'Foo'
end
event = events.first
event.name # => "render"
event.duration # => 10 (in milliseconds)
event.payload # => { extra: :information }
event.allocations # => 1826 (objects)
如果在那個特定量測期間發生例外,酬載會有個鍵 :exception
,其值是一個有兩個元素的陣列:一個字串代表例外類別,和一個例外訊息。酬載的 :exception_object
鍵會有這個例外的本身做為其值
event.payload[:exception] # => ["ArgumentError", "Invalid value"]
event.payload[:exception_object] # => #<ArgumentError: Invalid value>
正如早期範例所示,類別 ActiveSupport::Notifications::Event
可以照它們來的情況處理參數,並提供一個物件導向的介面來處理這些資料。
也可以傳遞一個回應 call
方法的物件,當成 subscribe
方法的第二個參數,取代區塊
module ActionController
class PageRequest
def call(name, started, finished, unique_id, payload)
Rails.logger.debug ['notification:', name, started, finished, unique_id, payload].join(' ')
end
end
end
ActiveSupport::Notifications.subscribe('process_action.action_controller', ActionController::PageRequest.new)
這會在日誌內產生下列輸出,包括一個有酬載的 hash
notification: process_action.action_controller 2012-04-13 01:08:35 +0300 2012-04-13 01:08:35 +0300 af358ed7fab884532ec7 {
controller: "Devise::SessionsController",
action: "new",
params: {"action"=>"new", "controller"=>"devise/sessions"},
format: :html,
method: "GET",
path: "/login/sign_in",
status: 200,
view_runtime: 279.3080806732178,
db_runtime: 40.053
}
你也可以訂閱符合某個正則表示式名稱的所有事件
ActiveSupport::Notifications.subscribe(/render/) do |*args|
...
end
甚至不傳遞任何參數給 subscribe
,這樣你就會訂閱所有事件。
暫時訂閱
有時候你不會想要在應用程式整個生命週期訂閱某個事件。有兩種取消訂閱的方法。
警告:此 instrumentation 架構是為常駐式訂閱者所設計,請謹慎使用這個功能,因為它會清除一些內部快取,這會對效能有負面影響。
在區塊執行期間訂閱
你可以暫時訂閱某個事件,在某個區塊執行期間。例如,在
callback = lambda {|event| ... }
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
...
end
所有在區塊執行期間量測的「sql.active_record」事件的 callback 都會被呼叫。callback 會在之後自動取消訂閱。
要使用單調的時間記錄 started
和 finished
值,請指定選用的 :monotonic
選項給 subscribed
方法。預設 :monotonic
選項設定為 false
。
callback = lambda {|name, started, finished, unique_id, payload| ... }
ActiveSupport::Notifications.subscribed(callback, "sql.active_record", monotonic: true) do
...
end
手動取消訂閱
subscribe
方法會回傳一個訂閱者物件
subscriber = ActiveSupport::Notifications.subscribe("render") do |event|
...
end
若要阻止這個區塊再被呼叫,只需傳遞該參照就能取消訂閱
ActiveSupport::Notifications.unsubscribe(subscriber)
您也可以透過傳遞訂閱者物件的名稱來取消訂閱。請注意,這會取消所有與給定名稱相符的訂閱
ActiveSupport::Notifications.unsubscribe("render")
使用正規表示法或其他模式匹配物件的訂閱者將會持續訂閱所有符合其原始模式的事件,除非這些事件符合傳遞給 unsubscribe
的字串
subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
ActiveSupport::Notifications.unsubscribe('render_template.action_view')
subscriber.matches?('render_template.action_view') # => false
subscriber.matches?('render_partial.action_view') # => true
預設佇列
通知
附帶一個佇列實作,用於消費和發布事件至所有日誌訂閱者。您可以使用任何您想要的佇列實作。
- 類別 ActiveSupport::Notifications::Event
- 類別 ActiveSupport::Notifications::Fanout
- 類別 ActiveSupport::Notifications::InstrumentationSubscriberError
- 類別 ActiveSupport::Notifications::Instrumenter
屬性
[RW] | notifier |
類別公開方法
instrument(name, payload = {}) 連結
來源: 顯示 | 在 GitHub 上
# File activesupport/lib/active_support/notifications.rb, line 208 def instrument(name, payload = {}) if notifier.listening?(name) instrumenter.instrument(name, payload) { yield payload if block_given? } else yield payload if block_given? end end
instrumenter() 連結
來源: 顯示 | 在 GitHub 上
# File activesupport/lib/active_support/notifications.rb, line 269 def instrumenter registry[notifier] ||= Instrumenter.new(notifier) end
monotonic_subscribe(pattern = nil, callback = nil, &block) 連結
執行與訂閱相同的功能,但 start
和 finish
區塊參數以單調時間呈現,而非以絕對時間呈現。單調時間不會向前或向後跳動(因為 NTP 或夏令時間)。在時間持續性很重要的時候,請使用 monotonic_subscribe
。例如,計算兩個事件之間的經過時間。
來源: 顯示 | 在 GitHub 上
# File activesupport/lib/active_support/notifications.rb, line 254 def monotonic_subscribe(pattern = nil, callback = nil, &block) notifier.subscribe(pattern, callback, monotonic: true, &block) end
publish(name, *args) 連結
來源: 顯示 | 在 GitHub 上
# File activesupport/lib/active_support/notifications.rb, line 200 def publish(name, *args) notifier.publish(name, *args) end
subscribe(pattern = nil, callback = nil, &block) 連結
使用傳遞的 區塊
訂閱給定的事件名稱。
您可以透過傳遞 字串
來訂閱事件,以符合確切的事件名稱,或透過傳遞 正規表示法
來符合所有符合模式的事件。
如果傳遞給方法的區塊只接受一個參數,它會將 事件
物件傳遞給區塊
ActiveSupport::Notifications.subscribe(/render/) do |event|
@event = event
end
否則 區塊
會收到五個參數,其中包含有關事件的資訊
ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
name # => String, name of the event (such as 'render' from above)
start # => Time, when the instrumented block started execution
finish # => Time, when the instrumented block ended execution
id # => String, unique ID for the instrumenter that fired the event
payload # => Hash, the payload
end
如果傳遞了無效的事件名稱型別,會擲回錯誤
ActiveSupport::Notifications.subscribe(:render) {|event| ...}
#=> ArgumentError (pattern must be specified as a String, Regexp or empty)
來源: 顯示 | 在 GitHub 上
# File activesupport/lib/active_support/notifications.rb, line 244 def subscribe(pattern = nil, callback = nil, &block) notifier.subscribe(pattern, callback, monotonic: false, &block) end