Skip to content

Commit 298458f

Browse files
authored
Merge pull request #55 from jhawthorn/as_notifications_schema2
Add Hook for ActiveSupport::Notifications
2 parents 33f1e3a + 9370147 commit 298458f

File tree

8 files changed

+140
-14
lines changed

8 files changed

+140
-14
lines changed

examples/rails.rb

+1-9
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,7 @@ def show
110110
# warm up
111111
make_request.call
112112

113-
Vernier.trace(out: "rails.json") do |collector|
114-
ActiveSupport::Notifications.monotonic_subscribe do |name, start, finish, id, payload|
115-
collector.add_marker(
116-
name:,
117-
start: (start * 1_000_000_000).to_i,
118-
finish: (finish * 1_000_000_000).to_i,
119-
)
120-
end
121-
113+
Vernier.trace(out: "rails.json", hooks: [:rails]) do |collector|
122114
1000.times do
123115
make_request.call
124116
end

ext/vernier/vernier.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1632,7 +1632,7 @@ static VALUE collector_new(VALUE self, VALUE mode, VALUE options) {
16321632
rb_raise(rb_eArgError, "invalid mode");
16331633
}
16341634
VALUE obj = TypedData_Wrap_Struct(self, &rb_collector_type, collector);
1635-
rb_funcall(obj, rb_intern("initialize"), 1, mode);
1635+
rb_funcall(obj, rb_intern("initialize"), 2, mode, options);
16361636
return obj;
16371637
}
16381638

lib/vernier.rb

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
require_relative "vernier/version"
44
require_relative "vernier/collector"
55
require_relative "vernier/result"
6+
require_relative "vernier/hooks"
67
require_relative "vernier/vernier"
78
require_relative "vernier/output/firefox"
89
require_relative "vernier/output/top"
910

1011
module Vernier
1112
class Error < StandardError; end
1213

13-
def self.trace(mode: :wall, out: nil, interval: nil)
14-
collector = Vernier::Collector.new(mode, { interval: })
14+
def self.trace(mode: :wall, out: nil, interval: nil, hooks: nil)
15+
collector = Vernier::Collector.new(mode, { interval:, hooks: })
1516
collector.start
1617

1718
result = nil

lib/vernier/collector.rb

+22-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,28 @@
44

55
module Vernier
66
class Collector
7-
def initialize(mode)
7+
def initialize(mode, options={})
88
@mode = mode
99
@markers = []
10+
@hooks = []
11+
12+
if options[:hooks]
13+
Array(options[:hooks]).each do |hook|
14+
add_hook(hook)
15+
end
16+
end
17+
@hooks.each do |hook|
18+
hook.enable
19+
end
20+
end
21+
22+
private def add_hook(hook)
23+
case hook
24+
when :rails, :activesupport
25+
@hooks << Vernier::Hooks::ActiveSupport.new(self)
26+
else
27+
warn "Unknown hook: #{hook}"
28+
end
1029
end
1130

1231
##
@@ -47,6 +66,8 @@ def record_interval(category, name = category)
4766
def stop
4867
result = finish
4968

69+
result.hooks = @hooks
70+
5071
end_time = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
5172
result.pid = Process.pid
5273
result.end_time = end_time

lib/vernier/hooks.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
module Vernier
4+
module Hooks
5+
autoload :ActiveSupport, "vernier/hooks/active_support"
6+
end
7+
end

lib/vernier/hooks/active_support.rb

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# frozen_string_literal: true
2+
3+
module Vernier
4+
module Hooks
5+
class ActiveSupport
6+
def initialize(collector)
7+
@collector = collector
8+
end
9+
10+
def enable
11+
require "active_support"
12+
@subscription = ::ActiveSupport::Notifications.monotonic_subscribe do |name, start, finish, id, payload|
13+
data = { type: name }
14+
data.update(payload)
15+
@collector.add_marker(
16+
name: name,
17+
start: (start * 1_000_000_000.0).to_i,
18+
finish: (finish * 1_000_000_000.0).to_i,
19+
data: data
20+
)
21+
end
22+
end
23+
24+
def disable
25+
ActiveSupport::Notifications.unsubscribe(@subscription)
26+
@subscription = nil
27+
end
28+
29+
FIREFOX_MARKER_SCHEMA = Ractor.make_shareable([
30+
{
31+
name: "sql.active_record",
32+
display: [ "marker-chart", "marker-table" ],
33+
data: [
34+
{
35+
key: "sql",
36+
format: "string"
37+
},
38+
{
39+
key: "name",
40+
format: "string"
41+
},
42+
{
43+
key: "type_casted_binds",
44+
label: "binds",
45+
format: "string"
46+
}
47+
]
48+
},
49+
{
50+
name: "instantiation.active_record",
51+
display: [ "marker-chart", "marker-table" ],
52+
data: [
53+
{
54+
key: "record_count",
55+
format: "integer"
56+
},
57+
{
58+
key: "class_name",
59+
format: "string"
60+
}
61+
]
62+
},
63+
{
64+
name: "process_action.action_controller",
65+
display: [ "marker-chart", "marker-table" ],
66+
data: [
67+
{
68+
key: "controller",
69+
format: "string"
70+
},
71+
{
72+
key: "action",
73+
format: "string"
74+
},
75+
{
76+
key: "status",
77+
format: "integer"
78+
},
79+
{
80+
key: "path",
81+
format: "string"
82+
},
83+
{
84+
key: "method",
85+
format: "string"
86+
}
87+
]
88+
}
89+
])
90+
91+
def firefox_marker_schema
92+
FIREFOX_MARKER_SCHEMA
93+
end
94+
end
95+
end
96+
end

lib/vernier/output/firefox.rb

+8-1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ def data
141141
end
142142

143143
def marker_schema
144+
hook_additions = profile.hooks.flat_map do |hook|
145+
if hook.respond_to?(:firefox_marker_schema)
146+
hook.firefox_marker_schema
147+
end
148+
end.compact
149+
144150
[
145151
{
146152
name: "GVL_THREAD_RESUMED",
@@ -151,7 +157,8 @@ def marker_schema
151157
value: "The thread has acquired the GVL and is executing"
152158
}
153159
]
154-
}
160+
},
161+
*hook_additions
155162
]
156163
end
157164

lib/vernier/result.rb

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ class Result
33
attr_reader :stack_table, :frame_table, :func_table
44
attr_reader :markers
55

6+
attr_accessor :hooks
7+
68
attr_accessor :pid, :end_time
79
attr_accessor :threads
810
attr_accessor :meta

0 commit comments

Comments
 (0)