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 166
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 189 def instrumenter InstrumentationRegistry.instance.instrumenter_for(notifier) end
# File activesupport/lib/active_support/notifications.rb, line 162 def publish(name, *args) notifier.publish(name, *args) end
# File activesupport/lib/active_support/notifications.rb, line 174 def subscribe(*args, &block) notifier.subscribe(*args, &block) end
# File activesupport/lib/active_support/notifications.rb, line 178 def subscribed(callback, *args, &block) subscriber = subscribe(*args, &callback) yield ensure unsubscribe(subscriber) end
# File activesupport/lib/active_support/notifications.rb, line 185 def unsubscribe(subscriber_or_name) notifier.unsubscribe(subscriber_or_name) end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.