модуль ActiveSupport::Notifications
Уведомления
ActiveSupport::Notifications предоставляет API для инструментирования Ruby.
Инструментаторы
Для инструментирования события необходимо выполнить следующее:
ActiveSupport::Notifications.instrument('render', extra: :information) do
render text: 'Foo'
end
Это сначала выполняет блок, а затем уведомляет всех подписчиков по завершении.
В примере выше render — имя события, а всё остальное — данные. Данные — это механизм, позволяющий инструментаторам передавать дополнительную информацию подписчикам. Данные представляют собой хеш, содержимое которого произвольно и обычно зависит от события.
Подписчики
Вы можете потреблять эти события и предоставляемую ими информацию, зарегистрировав подписчика.
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 this notification
payload # => Hash, the payload
end
Например, давайте сохраним все события «render» в массиве:
events = []
ActiveSupport::Notifications.subscribe('render') do |*args|
events << ActiveSupport::Notifications::Event.new(*args)
end
Этот код возвращает значение немедленно; вы просто подписываетесь на события «render». Блок сохраняется и будет вызываться всякий раз, когда кто-то инструментирует «render»:
ActiveSupport::Notifications.instrument('render', extra: :information) do
render text: 'Foo'
end
event = events.first
event.name # => "render"
event.duration # => 10 (in milliseconds)
event.payload # => { extra: :information }
Блок в вызове subscribe получает имя события, начальную метку времени, конечную метку времени, строку с уникальным идентификатором для этого события (что-то вроде «535801666f04d0298cd6») и хеш с данными в этом порядке.
Если во время данного инструментирования произойдёт исключение, в данных будет иметься ключ :exception со значением массива из двух элементов: строка с именем класса исключения и сообщение об исключении.
Как показывает предыдущий пример, класс ActiveSupport::Notifications::Event способен принимать аргументы как есть и предоставлять объектно-ориентированный интерфейс к этим данным.
Также возможно передать объект в качестве второго параметра, передаваемого в метод 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)
что приводит к следующему выводу в логах, включая хеш с данными:
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, в этом случае вы подписываетесь на все события.
Временные подписки
Иногда вы не хотите подписываться на событие на протяжении всего срока службы приложения. Есть два способа отказаться от подписки.
ПРЕДУПРЕЖДЕНИЕ: Фреймворк инструментирования предназначен для подписчиков с длительным сроком службы. Используйте эту функцию экономно, поскольку она очищает некоторые внутренние кэши, что негативно сказывается на производительности.
Подписка во время выполнения блока
Вы можете временно подписаться на некоторое событие во время выполнения блока. Например, в
callback = lambda {|*args| ... }
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
...
end обработчик вызывается для всех событий «sql.active_record», инструментированных во время выполнения блока. Обработчик отписывается автоматически после этого.
Ручная отписка
Метод subscribe возвращает объект подписчика:
subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
...
end Чтобы больше не вызывать этот блок, просто отпишитесь, передав эту ссылку:
ActiveSupport::Notifications.unsubscribe(subscriber)
Вы также можете отписаться, передав имя объекта подписчика. Обратите внимание, что это приведет к отписке от всех подписок с заданным именем:
ActiveSupport::Notifications.unsubscribe("render")
Очередь по умолчанию
Уведомления поставляются с реализацией очереди, которая потребляет и публикует события всем подписчикам журналов. Вы можете использовать любую реализацию очереди, которую хотите.
Атрибуты
Общедоступные методы класса
# File activesupport/lib/active_support/notifications.rb, line 162
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 # File activesupport/lib/active_support/notifications.rb, line 185 def instrumenter InstrumentationRegistry.instance.instrumenter_for(notifier) end
# File activesupport/lib/active_support/notifications.rb, line 158 def publish(name, *args) notifier.publish(name, *args) end
# File activesupport/lib/active_support/notifications.rb, line 170 def subscribe(*args, &block) notifier.subscribe(*args, &block) end
# File activesupport/lib/active_support/notifications.rb, line 174 def subscribed(callback, *args, &block) subscriber = subscribe(*args, &callback) yield ensure unsubscribe(subscriber) end
# File activesupport/lib/active_support/notifications.rb, line 181 def unsubscribe(subscriber_or_name) notifier.unsubscribe(subscriber_or_name) end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.