notifications.rb 2.2 KB
Newer Older
1
require 'active_support/core_ext/module/delegation'
J
José Valim 已提交
2 3

module ActiveSupport
4 5
  # Notifications provides an instrumentation API for Ruby. To instrument an
  # action in Ruby you just need to do:
J
José Valim 已提交
6
  #
7
  #   ActiveSupport::Notifications.instrument(:render, :extra => :information) do
J
José Valim 已提交
8 9 10
  #     render :text => "Foo"
  #   end
  #
11 12
  # You can consume those events and the information they provide by registering
  # a subscriber. For instance, let's store all instrumented events in an array:
J
José Valim 已提交
13
  #
14 15
  #   @events = []
  #
16 17
  #   ActiveSupport::Notifications.subscribe do |*args|
  #     @events << ActiveSupport::Notifications::Event.new(*args)
18
  #   end
J
José Valim 已提交
19
  #
20
  #   ActiveSupport::Notifications.instrument(:render, :extra => :information) do
J
José Valim 已提交
21 22 23
  #     render :text => "Foo"
  #   end
  #
24
  #   event = @events.first
J
José Valim 已提交
25 26 27 28 29
  #   event.name      #=> :render
  #   event.duration  #=> 10 (in miliseconds)
  #   event.result    #=> "Foo"
  #   event.payload   #=> { :extra => :information }
  #
30
  # When subscribing to Notifications, you can pass a pattern, to only consume
31 32
  # events that match the pattern:
  #
33
  #   ActiveSupport::Notifications.subscribe(/render/) do |event|
34 35 36
  #     @render_events << event
  #   end
  #
37
  # Notifications ships with a queue implementation that consumes and publish events
38
  # to subscribers in a thread. You can use any queue implementation you want.
J
José Valim 已提交
39
  #
40
  module Notifications
41 42 43
    autoload :Instrumenter, 'active_support/notifications/instrumenter'
    autoload :Event, 'active_support/notifications/instrumenter'
    autoload :Fanout, 'active_support/notifications/fanout'
44

45
    class << self
46
      attr_writer :notifier
47
      delegate :publish, :subscribe, :to => :notifier
48
      delegate :instrument, :to => :instrumenter
49

50 51
      def notifier
        @notifier ||= Notifier.new
52
      end
53 54 55 56

      def instrumenter
        Thread.current[:"instrumentation_#{notifier.object_id}"] ||= Instrumenter.new(notifier)
      end
57 58
    end

59 60
    class Notifier
      def initialize(queue = Fanout.new)
61 62 63
        @queue = queue
      end

64 65
      def publish(*args)
        @queue.publish(*args)
66 67
      end

68 69
      def subscribe(pattern = nil, &block)
        @queue.bind(pattern).subscribe(&block)
J
José Valim 已提交
70 71
      end

72
      def wait
73
        @queue.wait
74
      end
J
José Valim 已提交
75 76 77
    end
  end
end