diff --git a/lib/jsonapi/serializer/instrumentation.rb b/lib/jsonapi/serializer/instrumentation.rb new file mode 100644 index 0000000..4f555df --- /dev/null +++ b/lib/jsonapi/serializer/instrumentation.rb @@ -0,0 +1,27 @@ +require 'active_support/notifications' + +module JSONAPI + module Serializer + # Support for instrumentation + module Instrumentation + # Performance instrumentation namespace + NOTIFICATION_NAMESPACE = 'render.jsonapi-serializer.'.freeze + + # Patch methods to use instrumentation... + %w[ + serializable_hash + get_included_records + relationships_hash + ].each do |method_name| + define_method(method_name) do |*args| + ActiveSupport::Notifications.instrument( + NOTIFICATION_NAMESPACE + method_name, + { name: self.class.name, serializer: self.class } + ) do + super(*args) + end + end + end + end + end +end diff --git a/spec/fixtures/actor.rb b/spec/fixtures/actor.rb index df72a8a..f85120a 100644 --- a/spec/fixtures/actor.rb +++ b/spec/fixtures/actor.rb @@ -1,4 +1,5 @@ require 'active_support/cache' +require 'jsonapi/serializer/instrumentation' class Actor < User attr_accessor :movies, :movie_ids @@ -70,3 +71,9 @@ module Cached ) end end + +module Instrumented + class ActorSerializer < ::ActorSerializer + include ::JSONAPI::Serializer::Instrumentation + end +end diff --git a/spec/integration/instrumentation_spec.rb b/spec/integration/instrumentation_spec.rb new file mode 100644 index 0000000..59ad425 --- /dev/null +++ b/spec/integration/instrumentation_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +# Needed to subscribe to `active_support/notifications` +require 'concurrent' + +RSpec.describe JSONAPI::Serializer do + let(:serializer) do + Instrumented::ActorSerializer.new(Actor.fake) + end + + it do + payload = event_name = nil + notification_name = ( + ::JSONAPI::Serializer::Instrumentation::NOTIFICATION_NAMESPACE + + 'serializable_hash' + ) + + ActiveSupport::Notifications.subscribe( + notification_name + ) do |ev_name, _s, _f, _i, ev_payload| + event_name = ev_name + payload = ev_payload + end + + expect(serializer.serializable_hash).not_to be_nil + + expect(event_name).to eq('render.jsonapi-serializer.serializable_hash') + expect(payload[:name]).to eq(serializer.class.name) + expect(payload[:serializer]).to eq(serializer.class) + end +end