diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 049528fe7..404a29623 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -30,6 +30,10 @@ nav_order: 5 *Reegan Viljoen* +* Add helper instrumentation. + + *Reegan Viljoen* + ## 3.13.0 * Add ruby head and YJIT to CI. diff --git a/docs/guide/instrumentation.md b/docs/guide/instrumentation.md index c1230a212..d2f828ebf 100644 --- a/docs/guide/instrumentation.md +++ b/docs/guide/instrumentation.md @@ -29,6 +29,24 @@ ActiveSupport::Notifications.subscribe("render.view_component") do |event| # or end ``` +## Instrument helpers + +To enable helpers instrumentation, use the `instrument_helpers` option wich will instrument all helpers used in the rendering of a ViewComponent: + +```ruby +# config/application.rb +# Enable ActiveSupport notifications for all ViewComponents +config.view_component.instrument_helpers = true +config.view_component.use_deprecated_instrumentation_name = false +``` + +```ruby +ActiveSupport::Notifications.subscribe("render.view_component.helpers") do |event| # or !render.view_component + event.name # => "render.view_component" + event.payload # => { name: "MyComponent", identifier: "/Users/mona/project/app/components/my_component.rb" } +end +``` + ## Viewing instrumentation sums in the browser developer tools When using `render.view_component` with `config.server_timing = true` (default in development) in Rails 7, the browser developer tools display the sum total timing information in Network > Timing under the key `render.view_component`. diff --git a/lib/view_component/config.rb b/lib/view_component/config.rb index 85e119faf..1e18434d9 100644 --- a/lib/view_component/config.rb +++ b/lib/view_component/config.rb @@ -17,6 +17,7 @@ def defaults preview_route: "/rails/view_components", show_previews_source: false, instrumentation_enabled: false, + instrument_helpers: false, use_deprecated_instrumentation_name: true, render_monkey_patch_enabled: true, view_component_path: "app/components", @@ -113,6 +114,11 @@ def defaults # Whether ActiveSupport notifications are enabled. # Defaults to `false`. + # @!attribute instrument_helpers + # @return [Boolean] + # Whether ActiveSupport notifications are enabled for helpers. + # Defaults to `false`. + # @!attribute use_deprecated_instrumentation_name # @return [Boolean] # Whether ActiveSupport Notifications use the private name `"!render.view_component"` diff --git a/lib/view_component/instrumentation.rb b/lib/view_component/instrumentation.rb index d63efd283..afb7f8eb2 100644 --- a/lib/view_component/instrumentation.rb +++ b/lib/view_component/instrumentation.rb @@ -20,6 +20,19 @@ def render_in(view_context, &block) end end + def helpers + super unless ViewComponent::Base.config.instrumentation_helpers + ActiveSupport::Notifications.instrument( + "#{notification_name}.helpers", + { + name: self.class.name, + identifier: self.class.identifier + } + ) do + super + end + end + private def notification_name diff --git a/test/sandbox/app/components/instrumentation_component.html.erb b/test/sandbox/app/components/instrumentation_component.html.erb index d2d68fe70..692f4692f 100644 --- a/test/sandbox/app/components/instrumentation_component.html.erb +++ b/test/sandbox/app/components/instrumentation_component.html.erb @@ -1 +1,2 @@
hello,world!
+<%= helpers.message %> diff --git a/test/sandbox/test/instrumentation_test.rb b/test/sandbox/test/instrumentation_test.rb index b2d4d0490..8607993c4 100644 --- a/test/sandbox/test/instrumentation_test.rb +++ b/test/sandbox/test/instrumentation_test.rb @@ -29,4 +29,19 @@ def test_instrumentation_with_deprecated_name assert_equal(events.size, 1) assert_equal("!render.view_component", events[0].name) end + + def test_helpers_instrumentation + with_config_option(:use_deprecated_instrumentation_name, false) do + with_config_option(:instrument_helpers, true) do + events = [] + ActiveSupport::Notifications.subscribe("render.view_component.helpers") do |*args| + events << ActiveSupport::Notifications::Event.new(*args) + end + render_inline(InstrumentationComponent.new) + + assert_equal(events.size, 1) + assert_equal("render.view_component.helpers", events[0].name) + end + end + end end