aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/subscriber.rb
diff options
context:
space:
mode:
authorDaniel Schierbeck <dasch@zendesk.com>2013-04-15 15:23:46 +0200
committerDaniel Schierbeck <dasch@zendesk.com>2013-04-16 14:39:22 +0200
commit5f07048dfdcc86bf78d0a498c5f23fa4dec917f7 (patch)
treeba1aabafd14af3df6a3b580fd9fea8569e0ef7a4 /activesupport/lib/active_support/subscriber.rb
parentc78da9aed9453bf2c933392e7ae7831f3d2ef73e (diff)
downloadrails-5f07048dfdcc86bf78d0a498c5f23fa4dec917f7.tar.gz
rails-5f07048dfdcc86bf78d0a498c5f23fa4dec917f7.tar.bz2
rails-5f07048dfdcc86bf78d0a498c5f23fa4dec917f7.zip
Extract a base class from ActiveSupport::LogSubscriber
Adds a ActiveSupport::Subscriber base class that LogSubscriber inherits from. By inheriting from Subscriber, other kinds of subscribers can take advantage of the event attachment system.
Diffstat (limited to 'activesupport/lib/active_support/subscriber.rb')
-rw-r--r--activesupport/lib/active_support/subscriber.rb76
1 files changed, 76 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/subscriber.rb b/activesupport/lib/active_support/subscriber.rb
new file mode 100644
index 0000000000..a6ad473b59
--- /dev/null
+++ b/activesupport/lib/active_support/subscriber.rb
@@ -0,0 +1,76 @@
+module ActiveSupport
+ # ActiveSupport::Subscriber is an object set to consume
+ # ActiveSupport::Notifications. The subscriber dispatches notifications to
+ # a registered object based on its given namespace.
+ #
+ # An example would be Active Record subscriber responsible for collecting
+ # statistics about queries:
+ #
+ # module ActiveRecord
+ # class StatsSubscriber < ActiveSupport::Subscriber
+ # def sql(event)
+ # Statsd.timing("sql.#{event.payload[:name]}", event.duration)
+ # end
+ # end
+ # end
+ #
+ # And it's finally registered as:
+ #
+ # ActiveRecord::Subscriber.attach_to :active_record
+ #
+ # Since we need to know all instance methods before attaching the log
+ # subscriber, the line above should be called after your
+ # <tt>ActiveRecord::Subscriber</tt> definition.
+ #
+ # After configured, whenever a "sql.active_record" notification is published,
+ # it will properly dispatch the event (ActiveSupport::Notifications::Event) to
+ # the `sql` method.
+ class Subscriber
+ class << self
+
+ # Attach the subscriber to a namespace.
+ def attach_to(namespace, subscriber=new, notifier=ActiveSupport::Notifications)
+ subscribers << subscriber
+
+ subscriber.public_methods(false).each do |event|
+ next if %w{ start finish }.include?(event.to_s)
+
+ notifier.subscribe("#{event}.#{namespace}", subscriber)
+ end
+ end
+
+ def subscribers
+ @@subscribers ||= []
+ end
+ end
+
+ def initialize
+ @queue_key = [self.class.name, object_id].join "-"
+ super
+ end
+
+ def start(name, id, payload)
+ e = ActiveSupport::Notifications::Event.new(name, Time.now, nil, id, payload)
+ parent = event_stack.last
+ parent << e if parent
+
+ event_stack.push e
+ end
+
+ def finish(name, id, payload)
+ finished = Time.now
+ event = event_stack.pop
+ event.end = finished
+ event.payload.merge!(payload)
+
+ method = name.split('.').first
+ send(method, event)
+ end
+
+ private
+
+ def event_stack
+ Thread.current[@queue_key] ||= []
+ end
+ end
+end