notifications.rb 2.3 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 47
      attr_writer :notifier
      delegate :publish, :subscribe, :instrument, :to => :notifier
48

49 50
      def notifier
        @notifier ||= Notifier.new
51 52 53
      end
    end

54 55
    class Notifier
      def initialize(queue = Fanout.new)
56 57 58
        @queue = queue
      end

59 60
      def publish(*args)
        @queue.publish(*args)
61 62
      end

63 64
      def subscribe(pattern = nil, &block)
        @queue.bind(pattern).subscribe(&block)
J
José Valim 已提交
65 66
      end

67
      def wait
68
        @queue.wait
69
      end
70

71
      delegate :instrument, :to => :current_instrumenter
72

73 74 75
      private
        def current_instrumenter
          Thread.current[:"instrumentation_#{object_id}"] ||= Notifications::Instrumenter.new(self)
76
        end
J
José Valim 已提交
77 78 79
    end
  end
end