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
  # You can consume those events and the information they provide by registering
12
  # a log 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
  #   event.name      #=> :render
26
  #   event.duration  #=> 10 (in milliseconds)
J
José Valim 已提交
27 28
  #   event.payload   #=> { :extra => :information }
  #
29
  # When subscribing to Notifications, you can pass a pattern, to only consume
30 31
  # events that match the pattern:
  #
32
  #   ActiveSupport::Notifications.subscribe(/render/) do |event|
33 34 35
  #     @render_events << event
  #   end
  #
36
  # Notifications ships with a queue implementation that consumes and publish events
37
  # to log subscribers in a thread. You can use any queue implementation you want.
J
José Valim 已提交
38
  #
39
  module Notifications
40 41 42
    autoload :Instrumenter, 'active_support/notifications/instrumenter'
    autoload :Event, 'active_support/notifications/instrumenter'
    autoload :Fanout, 'active_support/notifications/fanout'
43

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

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

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

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

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

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

C
Carlhuda 已提交
71 72 73 74
      def unsubscribe(subscriber)
        @queue.unsubscribe(subscriber)
      end

75
      def wait
76
        @queue.wait
77
      end
J
José Valim 已提交
78 79 80
    end
  end
end