All Articles

Using Rails secret weapon: ActiveSupport::Notifications

Ruby on Rails has a powerful weapon that not all developers knows about its existence. ActiveSupport Instrumentations is used by Rails framework to handle events that happen when the application is running.

The instrumentation API provided by Active Support allows developers to provide hooks which other developers may hook into. There are several of these within the Rails framework. With this API, developers can choose to be notified when certain events occur inside their application or another piece of Ruby code.

Lucky we can use this tool at our disposal.

How it works

It looks like a PUB/SUB pattern.

In software architecture, publish–subscribe is a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers. Instead, published messages are characterized into classes, without knowledge of what, if any, subscribers there may be. Similarly, subscribers express interest in one or more classes, and only receive messages that are of interest, without knowledge of what, if any, publishers there are. - Wikipedia

Subscribing to an event is pretty easy:

# config/initializers/events.rb
ActiveSupport::Notifications.subscribe "my_custom.event" do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)
end

The event variable will contain something like this

=> #<ActiveSupport::Notifications::Event:0x0000559258433df8
 @children=[],
 @duration=nil,
 @end=2018-07-03 12:47:46 +0000,
 @name="my_custom.event",
 @payload={:foo=>"bar"},
 @time=2018-07-03 12:47:46 +0000,
 @transaction_id="37bb01f75132e0c0505publisher6">

Notice the @payload? We can send additional data within the event.

Instrumenting an event

There is a method called instrument that publish the event.

You can use it like this:

ActiveSupport::Notifications.instrument "my_custom.event", { foo: "bar" }

Easy right?

Real world example

Let’s say that you have an external service that handles application metrics, such as Segment.IO, Keen IO, and many others.

You can use this pattern to send events to one of this services.

# config/initializers/events.rb
# We can use regex to subscribe!
ActiveSupport::Notifications.subscribe /metrics/ do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)
  MyMetricsService.send(event.name, event.payload)
end

# app/controllers/my_controller.rb
def create
  # some code
  ActiveSupport::Notifications.instrument "metrics.item_purchased", { uid: item.id }
end

You can read more about ActiveSupport Instrumentation here

Hope it helps :)