singed 0.1.0 → 0.2.0
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/README.md +16 -6
- data/lib/singed/cli.rb +13 -3
- data/lib/singed/flamegraph.rb +1 -1
- data/lib/singed/kernel_ext.rb +3 -3
- data/lib/singed.rb +1 -1
- data/singed.gemspec +2 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b94bd39d1904f3d339e34974c5ad88bec590c2373ffedc6ffba15a4bce0fbb06
|
4
|
+
data.tar.gz: dcf1af83d2b05c7cc2d20566045a99781385408c6316ef183fa3cba77ec8538f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3155afc39b9bc923718a488ebc170f3c0b03ecdf8eb945af93a85ad489a3825dd464a10dc8289795b30b91e6ff0ce43a488f348a5e2cacd1308417626228edd
|
7
|
+
data.tar.gz: f0f054893e83aceb2f3342317f30e732e75c79af1fa61164e7b637fea5ae18b03b8aee5eac68b4d05facc4a37e62a5e1ef833d1aa86df55046de7e8686fc2aac
|
data/README.md
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
# Singed
|
2
2
|
|
3
|
-
Singed makes it easy to get a flamegraph anywhere in your code base
|
3
|
+
Singed makes it easy to get a flamegraph anywhere in your code base. It wraps profiling your code with [stackprof](https://github.com/tmm1/stackprof) or [rbspy](https://github.com/rbspy/rbspy), and then launching [speedscope](https://github.com/jlfwong/speedscope) to view it.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add to `Gemfile`:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem "singed"
|
11
|
+
```
|
12
|
+
|
13
|
+
Then run `bundle install`
|
4
14
|
|
5
15
|
## Usage
|
6
16
|
|
7
|
-
|
17
|
+
Simplest is calling with a block:
|
8
18
|
|
9
19
|
```ruby
|
10
20
|
flamegraph {
|
@@ -22,7 +32,7 @@ Singed.output_directory = "tmp/slowness-exploration"
|
|
22
32
|
If you are calling it in a loop, or with different variations, you can include a label on the filename:
|
23
33
|
|
24
34
|
```ruby
|
25
|
-
flamegraph(
|
35
|
+
flamegraph("rspec") {
|
26
36
|
# your code here
|
27
37
|
}
|
28
38
|
```
|
@@ -64,7 +74,7 @@ class EmployeesController < ApplicationController
|
|
64
74
|
end
|
65
75
|
```
|
66
76
|
|
67
|
-
This won't catch the entire request though, just once it's been routed to controller and a response has been served.
|
77
|
+
This won't catch the entire request though, just once it's been routed to controller and a response has been served (ie no middleware).
|
68
78
|
|
69
79
|
### Rack/Rails requests
|
70
80
|
|
@@ -84,7 +94,7 @@ There is a `singed` command line you can use that will record a flamegraph from
|
|
84
94
|
|
85
95
|
```shell
|
86
96
|
$ bundle binstub singed # if you want to be able to call it like bin/singed
|
87
|
-
$ bundle exec singed -- bin/rails
|
97
|
+
$ bundle exec singed -- bin/rails runner 'Model.all.to_a'
|
88
98
|
```
|
89
99
|
|
90
100
|
The flamegraph is opened afterwards.
|
@@ -98,5 +108,5 @@ The `open` is expected to be available.
|
|
98
108
|
|
99
109
|
## Alternatives
|
100
110
|
|
101
|
-
- using [rbspy](https://rbspy.github.io/)
|
111
|
+
- using [rbspy](https://rbspy.github.io/) directly
|
102
112
|
- using [stackprof](https://github.com/tmm1/stackprof) (a dependency of singed) directly
|
data/lib/singed/cli.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'shellwords'
|
2
2
|
require 'tmpdir'
|
3
3
|
require 'optionparser'
|
4
|
+
require 'pathname'
|
4
5
|
|
5
6
|
# NOTE: we defer requiring singed until we run. that lets Rails load it if its in the gemfile, so the railtie has had a chance to run
|
6
7
|
|
@@ -64,6 +65,7 @@ module Singed
|
|
64
65
|
|
65
66
|
Singed.output_directory = @output_directory if @output_directory
|
66
67
|
Singed.output_directory ||= Dir.tmpdir
|
68
|
+
FileUtils.mkdir_p Singed.output_directory
|
67
69
|
@filename = Singed::Flamegraph.generate_filename(label: 'cli')
|
68
70
|
|
69
71
|
options = {
|
@@ -86,11 +88,19 @@ module Singed
|
|
86
88
|
prompt_password
|
87
89
|
end
|
88
90
|
|
89
|
-
|
91
|
+
rbspy = lambda do
|
90
92
|
# don't run things with spring, because it forks and rbspy won't see it
|
91
93
|
sudo ['rbspy', *rbspy_args], reason: 'Singed needs to run as root, but will drop permissions back to your user.', env: { 'DISABLE_SPRING' => '1' }
|
92
94
|
end
|
93
95
|
|
96
|
+
if defined?(Bundler)
|
97
|
+
Bundler.with_unbundled_env do
|
98
|
+
rbspy.call
|
99
|
+
end
|
100
|
+
else
|
101
|
+
rbspy.call
|
102
|
+
end
|
103
|
+
|
94
104
|
unless filename.exist?
|
95
105
|
puts "#{filename} doesn't exist. Maybe rbspy had a failure capturing it? Check the scrollback."
|
96
106
|
exit 1
|
@@ -102,9 +112,9 @@ module Singed
|
|
102
112
|
end
|
103
113
|
|
104
114
|
# clean the report, similar to how Singed::Report does
|
105
|
-
json = JSON.parse(filename.read)
|
115
|
+
json = JSON.parse(filename.read)
|
106
116
|
json['shared']['frames'].each do |frame|
|
107
|
-
frame[
|
117
|
+
frame['file'] = Singed.filter_line(frame['file'])
|
108
118
|
end
|
109
119
|
filename.write(JSON.dump(json))
|
110
120
|
|
data/lib/singed/flamegraph.rb
CHANGED
@@ -53,7 +53,7 @@ module Singed
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def self.generate_filename(label: nil, time: Time.now) # rubocop:disable Rails/TimeZone
|
56
|
-
formatted_time = time.
|
56
|
+
formatted_time = time.strftime('%Y%m%d%H%M%S')
|
57
57
|
basename_parts = ['speedscope', label, formatted_time].compact
|
58
58
|
|
59
59
|
file = Singed.output_directory.join("#{basename_parts.join('-')}.json")
|
data/lib/singed/kernel_ext.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
module Kernel
|
2
|
-
def flamegraph(label = nil, open: true, ignore_gc: false, interval: 1000, &block)
|
2
|
+
def flamegraph(label = nil, open: true, ignore_gc: false, interval: 1000, io: $stdout, &block)
|
3
3
|
fg = Singed::Flamegraph.new(label: label, ignore_gc: ignore_gc, interval: interval)
|
4
4
|
result = fg.record(&block)
|
5
5
|
fg.save
|
6
6
|
|
7
7
|
if open
|
8
8
|
# use npx, so we don't have to add it as a dependency
|
9
|
-
puts "🔥📈 #{'Captured flamegraph, opening with'.colorize(:bold).colorize(:red)}: #{fg.open_command}"
|
9
|
+
io.puts "🔥📈 #{'Captured flamegraph, opening with'.colorize(:bold).colorize(:red)}: #{fg.open_command}"
|
10
10
|
fg.open
|
11
11
|
else
|
12
|
-
puts "🔥📈 #{'Captured flamegraph to file'.colorize(:bold).colorize(:red)}: #{fg.filename}"
|
12
|
+
io.puts "🔥📈 #{'Captured flamegraph to file'.colorize(:bold).colorize(:red)}: #{fg.filename}"
|
13
13
|
end
|
14
14
|
|
15
15
|
result
|
data/lib/singed.rb
CHANGED
data/singed.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'singed'
|
5
5
|
|
6
|
-
spec.version = '0.
|
6
|
+
spec.version = '0.2.0'
|
7
7
|
spec.authors = ['Josh Nichols']
|
8
8
|
spec.email = ['josh.nichols@gusto.com']
|
9
9
|
|
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency 'stackprof'
|
23
23
|
|
24
24
|
spec.add_development_dependency 'rake', '~> 13.0'
|
25
|
+
spec.add_development_dependency 'rspec'
|
25
26
|
|
26
27
|
# For more information and examples about making a new gem, checkout our
|
27
28
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: singed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Nichols
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
description:
|
56
70
|
email:
|
57
71
|
- josh.nichols@gusto.com
|