module ActiveSupport::Notifications
Уведомления
ActiveSupport::Notifications предоставляет API для инструментирования Ruby.
Инструментаторы
Для инструментирования события вам нужно просто сделать следующее:
ActiveSupport::Notifications.instrument('render', extra: :information) do
render plain: '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 plain: 'Foo'
end
event = events.first
event.name # => "render"
event.duration # => 10 (in milliseconds)
event.payload # => { extra: :information }
Блок в вызове subscribe получает имя события, отметку времени начала, отметку времени окончания, строку с уникальным идентификатором для этого события (что-то вроде «535801666f04d0298cd6») и хэш с данными в указанном порядке.
Если во время конкретного инструментирования произойдёт исключение, данные будут содержать ключ :exception со значением — массивом из двух элементов: строкой с именем класса исключения и сообщением об исключении. Ключ :exception_object данных будет содержать само исключение в качестве значения.
Как показано в предыдущем примере, класс 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)
что приведёт к выводу следующего сообщения в логах, включая хэш с данными:
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 164
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 187 def instrumenter InstrumentationRegistry.instance.instrumenter_for(notifier) end
# File activesupport/lib/active_support/notifications.rb, line 160 def publish(name, *args) notifier.publish(name, *args) end
# File activesupport/lib/active_support/notifications.rb, line 172 def subscribe(*args, &block) notifier.subscribe(*args, &block) end
# File activesupport/lib/active_support/notifications.rb, line 176 def subscribed(callback, *args, &block) subscriber = subscribe(*args, &callback) yield ensure unsubscribe(subscriber) end
# File activesupport/lib/active_support/notifications.rb, line 183 def unsubscribe(subscriber_or_name) notifier.unsubscribe(subscriber_or_name) end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.