require-profiler 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +5 -0
- data/lib/require_profiler/plugins/http_plugin.rb +42 -0
- data/lib/require_profiler/plugins/yaml_plugin.rb +42 -0
- data/lib/require_profiler/plugins.rb +23 -0
- data/lib/require_profiler/printer/call_stack.rb +1 -1
- data/lib/require_profiler/reporter.rb +4 -3
- data/lib/require_profiler/version.rb +1 -1
- data/lib/require_profiler.rb +3 -0
- metadata +60 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e11b353825774069b1dea2916f61688970a61ea00e59c54ccd68d39e311f452
|
|
4
|
+
data.tar.gz: 1580e8719935ec0d70d98f48fdad60207e777a475a86640e9d1cdac390993329
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ce85f247ab89347bbd51a609e10254bd1aaf485ae892476a3e67fb722f5037d68b76a153560e8172ea2c9b605aafc005f7accb35a11e77913eba9b7d80616974
|
|
7
|
+
data.tar.gz: c0897c79cb3cf3bca1c612d9794ebd00f8ff3d295d98b2faf664190f4bc6d0ba235e01b11a06e3edb7f79197db848d2923b15ae34850cdb9b2febf0349219877
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -108,6 +108,10 @@ Now you can use Speedscope to dig deeper.
|
|
|
108
108
|
|
|
109
109
|
**NOTE:** The `stackprof` gem must be present in your Gemfile for that.
|
|
110
110
|
|
|
111
|
+
### YAML and HTTP support
|
|
112
|
+
|
|
113
|
+
Require Profiler also captures HTTP requests and YAML file loading and add them to the profile, so you can find which Ruby files trigger the corresponding actions on load. NOTE: For HTTP requests tracking, you MUST add [sniffer][] gem to your Gemfile.
|
|
114
|
+
|
|
111
115
|
### Configuration
|
|
112
116
|
|
|
113
117
|
`RequireProfiler.start` accepts the following keyword arguments:
|
|
@@ -189,3 +193,4 @@ The gem is available as open source under the terms of the [MIT License](http://
|
|
|
189
193
|
|
|
190
194
|
[speedscope]: https://www.speedscope.app/
|
|
191
195
|
[require-hooks]: https://github.com/ruby-next/require-hooks
|
|
196
|
+
[sniffer]: https://github.com/aderyabin/sniffer
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RequireProfiler
|
|
4
|
+
module Plugins
|
|
5
|
+
# Track HTTP calls using Sniffer and add the to the require profile
|
|
6
|
+
class HTTPPlugin < Base
|
|
7
|
+
def activate!
|
|
8
|
+
begin
|
|
9
|
+
require "sniffer"
|
|
10
|
+
rescue LoadError
|
|
11
|
+
return
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Sniffer.config.logger = Logger.new(IO::NULL)
|
|
15
|
+
|
|
16
|
+
Sniffer.config.middleware do |chain|
|
|
17
|
+
chain.add HTTPPlugin, reporter
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Sniffer::DataItem::Request.include(Module.new do
|
|
21
|
+
def require_path
|
|
22
|
+
@url ||= "#{method.to_s.upcase}:#{(port == 443) ? "https" : "http"}://#{host}#{query}"
|
|
23
|
+
end
|
|
24
|
+
end)
|
|
25
|
+
|
|
26
|
+
Sniffer.enable!
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Sniffer hook interface
|
|
30
|
+
def request(data_item)
|
|
31
|
+
reporter.handle_event(Reporter::Event.new(type: :start, kind: :http, path: data_item.request.require_path))
|
|
32
|
+
yield
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def response(data_item)
|
|
36
|
+
yield
|
|
37
|
+
time = data_item.response.timing
|
|
38
|
+
reporter.handle_event(Reporter::Event.new(type: :end, path: data_item.request.require_path, time:))
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RequireProfiler
|
|
4
|
+
module Plugins
|
|
5
|
+
# Track loading YAML files
|
|
6
|
+
class YAMLPlugin < Base
|
|
7
|
+
module Patch
|
|
8
|
+
def load_file(path, ...)
|
|
9
|
+
YAMLPlugin.track(path) { super }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def unsafe_load_file(path, ...)
|
|
13
|
+
YAMLPlugin.track(path) { super }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def safe_load_file(path, ...)
|
|
17
|
+
YAMLPlugin.track(path) { super }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
attr_accessor :reporter
|
|
23
|
+
|
|
24
|
+
def track(path)
|
|
25
|
+
reporter.handle_event(Reporter::Event.new(type: :start, kind: :yml, path:))
|
|
26
|
+
start = Time.now
|
|
27
|
+
yield
|
|
28
|
+
ensure
|
|
29
|
+
time = Time.now - start
|
|
30
|
+
reporter.handle_event(Reporter::Event.new(type: :end, path:, time:))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def activate!
|
|
35
|
+
require "yaml"
|
|
36
|
+
|
|
37
|
+
YAMLPlugin.reporter = reporter
|
|
38
|
+
::YAML.singleton_class.prepend(Patch)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RequireProfiler
|
|
4
|
+
module Plugins
|
|
5
|
+
class << self
|
|
6
|
+
def register_reporter(reporter)
|
|
7
|
+
HTTPPlugin.new(reporter).activate! unless ENV["REQUIRE_PROFILER_HTTP"] == "false"
|
|
8
|
+
YAMLPlugin.new(reporter).activate! unless ENV["REQUIRE_PROFILER_YAML"] == "false"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class Base
|
|
13
|
+
attr_reader :reporter
|
|
14
|
+
|
|
15
|
+
def initialize(reporter)
|
|
16
|
+
@reporter = reporter
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
autoload :HTTPPlugin, "require_profiler/plugins/http_plugin"
|
|
21
|
+
autoload :YAMLPlugin, "require_profiler/plugins/yaml_plugin"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -8,7 +8,7 @@ module RequireProfiler
|
|
|
8
8
|
return unless flush?(node)
|
|
9
9
|
|
|
10
10
|
path = node.path.sub(prefix_stripper, "")
|
|
11
|
-
self_parts = path.split("/")
|
|
11
|
+
self_parts = (node.kind == :path) ? path.split("/") : [path]
|
|
12
12
|
|
|
13
13
|
parts += self_parts.size.times.map { self_parts.take(_1 + 1).join("/") }
|
|
14
14
|
# We only show self-time, so exclude children
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module RequireProfiler
|
|
4
4
|
class Reporter
|
|
5
|
-
class Event < Struct.new(:type, :path, :time, keyword_init: true)
|
|
5
|
+
class Event < Struct.new(:type, :path, :time, :kind, keyword_init: true)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
class Node < Struct.new(:path, :time, :parent, :children, :focused, keyword_init: true)
|
|
8
|
+
class Node < Struct.new(:path, :time, :parent, :children, :kind, :focused, keyword_init: true)
|
|
9
9
|
def initialize(...)
|
|
10
10
|
super
|
|
11
11
|
self.children ||= []
|
|
12
12
|
self.focused = false
|
|
13
|
+
self.kind ||= :path
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def focused!
|
|
@@ -37,7 +38,7 @@ module RequireProfiler
|
|
|
37
38
|
|
|
38
39
|
def handle_event_sync(event)
|
|
39
40
|
if event.type == :start
|
|
40
|
-
node = Node.new(path: event.path, children: [])
|
|
41
|
+
node = Node.new(path: event.path, children: [], kind: event.kind)
|
|
41
42
|
parent = stack.last
|
|
42
43
|
|
|
43
44
|
if parent
|
data/lib/require_profiler.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module RequireProfiler
|
|
4
4
|
autoload :Reporter, "require_profiler/reporter"
|
|
5
5
|
autoload :Printer, "require_profiler/printer"
|
|
6
|
+
autoload :Plugins, "require_profiler/plugins"
|
|
6
7
|
|
|
7
8
|
# Autoload doesn't work here, because we call it from the hooks for the first time
|
|
8
9
|
require "require_profiler/ruby_profiling"
|
|
@@ -38,6 +39,8 @@ module RequireProfiler
|
|
|
38
39
|
time = Time.now - start
|
|
39
40
|
reporter.handle_event(Reporter::Event.new(type: :end, path:, time:))
|
|
40
41
|
end
|
|
42
|
+
|
|
43
|
+
Plugins.register_reporter(reporter) unless ENV["REQUIRE_PROFILER_PLUGINS"] == "false"
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
def stop
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: require-profiler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vladimir Dementyev
|
|
@@ -37,6 +37,34 @@ dependencies:
|
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '1.15'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: benchmark
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: logger
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
40
68
|
- !ruby/object:Gem::Dependency
|
|
41
69
|
name: rake
|
|
42
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -65,6 +93,34 @@ dependencies:
|
|
|
65
93
|
- - ">="
|
|
66
94
|
- !ruby/object:Gem::Version
|
|
67
95
|
version: '3.9'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: sniffer
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: webmock
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '3.26'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '3.26'
|
|
68
124
|
description: 'Profile Ruby #require/#load/etc calls'
|
|
69
125
|
email:
|
|
70
126
|
- Vladimir Dementyev
|
|
@@ -78,6 +134,9 @@ files:
|
|
|
78
134
|
- lib/equire-prof.rb
|
|
79
135
|
- lib/require-profiler.rb
|
|
80
136
|
- lib/require_profiler.rb
|
|
137
|
+
- lib/require_profiler/plugins.rb
|
|
138
|
+
- lib/require_profiler/plugins/http_plugin.rb
|
|
139
|
+
- lib/require_profiler/plugins/yaml_plugin.rb
|
|
81
140
|
- lib/require_profiler/printer.rb
|
|
82
141
|
- lib/require_profiler/printer/call_stack.rb
|
|
83
142
|
- lib/require_profiler/printer/json.rb
|