NotificationTracer
A convenient way to process ActiveSupport notifications together with the call stack.
Installation
Add gem 'notification_tracer'
to your Gemfile.
Usage
The ActiveSupport::Notifications
API allows a consumer to subscribe to specific notification events that match a provided pattern. The NotificationTracer::Subscriber
wraps and streamlines this process, passing matching event data to a callback:
subscriber = NotificationTracer::Subscriber.new(
pattern: 'matches.notification',
callback: ->(**opts){ puts opts.inspect }
)
:pattern can be either a String
(exact matching) or a Regexp
(pattern matching).
:callback must respond to .call
with the following options:
- :stack ==> the cleaned Ruby callstack
- :payload ==> an event-specific data hash
- :duration ==> how long the event took
- :event_id ==> a unique id for this event
- :event_name ==> the full name of the event
Subscriber
initialization also takes an optional parameter, :cleaner, for scrubbing the callstack. It is recommended to use an instance of ActiveSupport::BacktraceCleaner
but any object with a clean :: Array -> Array
method is acceptable.
You must explicitly call .subscribe
on the Subscriber
in order to start receiving events:
:005 > subscriber.subscribed?
=> false
:006 > subscriber.subscribe
=> #<NotificationTracer::Subscriber:0x007fb03b8b8628 @pattern="matches.notification", @callback=#<Proc:0x007fb03b8b8740@(irb):3 (lambda)>, @real_subscriber=#<ActiveSupport::Notifications::Fanout::Subscribers::Timed:0x007fb03b8836a8 ...>
:007 > subscriber.subscribed?
=> true
:008 > 10.times.each{ subscriber.subscribe } # no harm to recall subscribe
=> 10
:009 > subscriber.subscribed?
=> true
:010 > subscriber.unsubscribe
=> #<NotificationTracer::Subscriber:0x007fb03b8b8628 @pattern="matches.notification", @callback=#<Proc:0x007fb03b8b8740@(irb):3 (lambda)>, @real_subscriber=nil, ...>
:011 > subscriber.subscribed?
=> false
Rails Specific
NotificationTracer::RailsSql
provides out-of-the-box logging of sql.active_record
events:
tracer = NotificationTracer::RailsSql.new(
matcher: <a callable that takes a sql string and returns true or false>,
formatter: <a callable that merges :stack, :sql, :duration, and :uuid into a single output>,
logger: <a callable that records the output of the formatter>,
lines: <limits the stack trace to the first N lines, or nil for no limit>,
silence_rails_code: <true or false, includes framework code in the stack trace>
)
tracer.start # subscribes & enables logging
tracer.pause # disables logging
tracer.stop # unsubscribes & disables logging
An example :formatter can be found in NotificationTracer::SqlFormatter
. This implementation converts the SQL event data into a String suitable for a text logger. It takes an optional parameter, :prefix, which prepends a given String to all messages.
For convenience, NotificationTracer.rails_sql
creates a RailsSql
instance with a SqlFormatter
formatter:
log_users_sql = NotificationTracer.rails_sql(
prefix: 'DEBUG 2847428',
logger: ->(msg){ Rails.logger.debug(msg) },
matcher: ->(sql){ sql =~ /users/ }
); log_users_sql.start
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/fledman/notification_tracer.
License
The gem is available as open source under the terms of the MIT License.