stack_tracy 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +18 -0
- data/README.md +45 -14
- data/VERSION +1 -1
- data/bin/tracy +2 -2
- data/demo.rb +8 -0
- data/lib/stack_tracy/cli.rb +26 -0
- data/lib/stack_tracy/core_ext/kernel.rb +5 -2
- data/lib/stack_tracy/sinatra.rb +13 -4
- data/lib/stack_tracy/version.rb +1 -1
- data/lib/stack_tracy.rb +15 -7
- data/stack_tracy.gemspec +2 -1
- data/test/unit/test_tracy.rb +27 -3
- data/ui/assets/comments.js +15 -0
- data/ui/assets/stack_tracy.css +8 -11
- data/ui/assets/stack_tracy.js +8 -2
- data/ui/index.html.erb +55 -62
- metadata +16 -2
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
= StackTracy CHANGELOG
|
2
2
|
|
3
|
+
== Version 0.1.4 (August 25, 2012)
|
4
|
+
|
5
|
+
* Added major improvements regarding browser performance when opening heavy HTML stack trace pages:
|
6
|
+
- using padding instead of non-breakable spaces (doh!)
|
7
|
+
- reduced white lines and white space
|
8
|
+
- added a threshold (< 0.001s) for folding calls at default and rendering its 'child calls' as comment (see http://ravirajsblog.blogspot.nl/2010/12/another-hack-to-render-heavy-html-pages.html)
|
9
|
+
- parsing commented 'child calls' at initial unfold
|
10
|
+
* Falling back to current directory when invoking StackTracy.open (or `tracy` within the Terminal)
|
11
|
+
* Letting StackTracy auto-determine its dump directory when calling `stack_tracy(:open) {}`
|
12
|
+
* Clearing StackTracy.stack_trace after having invoked StackTracy.dump
|
13
|
+
* Displaying passed path when invoking StackTracy.open with use_current_stack_trace == true
|
14
|
+
* Improved StackTracy::Sinatra middleware a bit regarding the `/tracy` route
|
15
|
+
* Added three configuration options:
|
16
|
+
- dump_source_location (default: `false`) include the source location when dumping recorded stack trace
|
17
|
+
- limit (default: `7500`) stack traces with more calls than the limit will be limited (core class / module calls will be excluded) when displaying
|
18
|
+
- threshold (default: `0.001`) fold calls faster than the threshold when exceeding the calls limit
|
19
|
+
* Enhanced the CLI interface `tracy` by using Thor in order to process the :limit and :threshold option
|
20
|
+
|
3
21
|
== Version 0.1.3 (August 19, 2012)
|
4
22
|
|
5
23
|
* Being able to compile StackTracy native extension on Windows (thanks ramsees for issuing)
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ The gem is partly written in C to reduce the application performance as minimal
|
|
10
10
|
|
11
11
|
![Dick .. Stack Tracy](http://codehero.es/images/stack_tracy.jpg)
|
12
12
|
|
13
|
-
Watch ["**Using StackTracy within a small Sinatra application**"](https://vimeo.com/archan937/stacktracy) to see StackTracy in action!
|
13
|
+
Watch the ["**Using StackTracy within a small Sinatra application**"](https://vimeo.com/archan937/stacktracy) **screencast** to see StackTracy in action!
|
14
14
|
|
15
15
|
## Installation
|
16
16
|
|
@@ -80,12 +80,15 @@ A couple of examples:
|
|
80
80
|
|
81
81
|
### Configure StackTracy
|
82
82
|
|
83
|
-
You can configure the default stack tree reduction behaviour
|
83
|
+
You can configure `StackTracy` regarding the default stack tree reduction behaviour, its dump directory and whether to include the source location when dumping recorded stack events:
|
84
84
|
|
85
85
|
StackTracy.configure do |c|
|
86
|
-
c.dump_dir
|
87
|
-
c.
|
88
|
-
c.
|
86
|
+
c.dump_dir = "." #=> default: Dir::tmpdir
|
87
|
+
c.dump_source_location = "." #=> default: false
|
88
|
+
c.limit = 1000 #=> default: 7500
|
89
|
+
c.threshold = 0.005 #=> default: 0.001
|
90
|
+
c.only = "Foo*" #=> default: nil
|
91
|
+
c.exclude = %w(Foo::Bar Foo::CandyBar) #=> default: nil
|
89
92
|
end
|
90
93
|
|
91
94
|
### Using recorded stack events
|
@@ -155,6 +158,14 @@ You can dump (optionally filtered) recorded stack events to a CSV file.
|
|
155
158
|
|
156
159
|
This is what the contents of `result.csv` would look like:
|
157
160
|
|
161
|
+
event;;;singleton;object;method;nsec;call;depth;duration
|
162
|
+
c-call;;;false;Kernel;puts;1344466943040581120;Kernel#puts;0;0.000120832
|
163
|
+
c-call;;;false;IO;puts;1344466943040599040;IO#puts;1;9.1904e-05
|
164
|
+
c-call;;;false;IO;write;1344466943040613120;IO#write;2;3.2768e-05
|
165
|
+
c-call;;;false;IO;write;1344466943040658944;IO#write;2;1.9968e-05
|
166
|
+
|
167
|
+
When invoking `StackTracy.dump "result.csv", true` and thus including the source location:
|
168
|
+
|
158
169
|
event;file;line;singleton;object;method;nsec;call;depth;duration
|
159
170
|
c-call;(pry);2;false;Kernel;puts;1344466943040581120;Kernel#puts;0;0.000120832
|
160
171
|
c-call;(pry);2;false;IO;puts;1344466943040599040;IO#puts;1;9.1904e-05
|
@@ -167,16 +178,32 @@ You can easily view the dumped stack events within your browser by either callin
|
|
167
178
|
|
168
179
|
[1] pry(main)> StackTracy.open "some/dir/file.csv"
|
169
180
|
|
170
|
-
or the following within the Terminal:
|
171
|
-
|
172
|
-
$ tracy "some/dir/file.csv"
|
173
|
-
|
174
181
|
Your default browser will be launched in which the stack events will be displayed.
|
175
182
|
|
176
|
-
When passing no path,
|
183
|
+
When passing no path, StackTracy will look for `stack_events-<random generated postfix>.csv` in either the default dump directory, the current directory or `Dir::tmpdir` and display it in the browser. When not found, it will display the last compiled stack tree when available:
|
177
184
|
|
178
185
|
$ tracy
|
179
186
|
|
187
|
+
### Using the CLI (command line interface)
|
188
|
+
|
189
|
+
Another way for viewing stack events in your browser is using the CLI `tracy` within the Terminal:
|
190
|
+
|
191
|
+
$ tracy #=> let StackTracy auto-determine which file to display
|
192
|
+
$ tracy . #=> display the last data file within the current directory
|
193
|
+
$ tracy foo/bar.csv #=> display foo/bar.csv
|
194
|
+
|
195
|
+
To get info about its options, type `tracy help open`:
|
196
|
+
|
197
|
+
$ tracy help open
|
198
|
+
Usage:
|
199
|
+
tracy open [PATH]
|
200
|
+
|
201
|
+
Options:
|
202
|
+
-l, [--limit=LIMIT]
|
203
|
+
-t, [--threshold=THRESHOLD]
|
204
|
+
|
205
|
+
Display StackTracy data within the browser (PATH is optional)
|
206
|
+
|
180
207
|
### Kernel#stack_tracy
|
181
208
|
|
182
209
|
As already mentioned, there is a convenience method called `stack_tracy` convenience method. The following shows a couple variants with its equivalent "normal implementation".
|
@@ -268,8 +295,9 @@ Its equivalent:
|
|
268
295
|
[1] pry(main)> StackTracy.start
|
269
296
|
[2] pry(main)> puts "testing"
|
270
297
|
[3] pry(main)> StackTracy.stop
|
271
|
-
[4] pry(main)>
|
272
|
-
[
|
298
|
+
[4] pry(main)> StackTracy.dump do |file|
|
299
|
+
[4] pry(main)> StackTracy.open file, true
|
300
|
+
[4] pry(main)> end
|
273
301
|
|
274
302
|
## Hooking into Sinatra requests
|
275
303
|
|
@@ -278,7 +306,7 @@ You can easily hook `StackTracy` into [Sinatra](http://www.sinatrarb.com) reques
|
|
278
306
|
require "sinatra"
|
279
307
|
require "stack_tracy"
|
280
308
|
|
281
|
-
use StackTracy::Sinatra
|
309
|
+
use StackTracy::Sinatra, :open
|
282
310
|
|
283
311
|
get "/" do
|
284
312
|
"Hello world!"
|
@@ -286,7 +314,9 @@ You can easily hook `StackTracy` into [Sinatra](http://www.sinatrarb.com) reques
|
|
286
314
|
|
287
315
|
**Note**: Make sure you have the `sinatra` and `stack_tracy` gems installed.
|
288
316
|
|
289
|
-
Open the Sinatra application in your browser at [http://localhost:4567](http://localhost:4567) and
|
317
|
+
Open the Sinatra application in your browser at [http://localhost:4567](http://localhost:4567) and the complete stack tree will be displayed in your browser! ^^
|
318
|
+
|
319
|
+
You can also open [http://localhost:4567/tracy](http://localhost:4567/tracy) afterwards by the way.
|
290
320
|
|
291
321
|
### Taking more control
|
292
322
|
|
@@ -354,6 +384,7 @@ For support, remarks and requests, please mail me at [paul.engel@holder.nl](mail
|
|
354
384
|
|
355
385
|
* Two functions within the StackTracy C implementation are taken from [ruby-prof](https://github.com/rdp/ruby-prof).
|
356
386
|
* The table sort within the Cumulatives tab is implemented with [TinySort](http://tinysort.sjeiti.com/).
|
387
|
+
* Being able to improve browser performance when loading heavy HTML stack trace pages using Ravi Raj's ([@raviraj4u](https://twitter.com/raviraj4u)) blog post: [http://ravirajsblog.blogspot.nl/2010/12/another-hack-to-render-heavy-html-pages.html](http://ravirajsblog.blogspot.nl/2010/12/another-hack-to-render-heavy-html-pages.html)
|
357
388
|
|
358
389
|
## License
|
359
390
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/bin/tracy
CHANGED
data/demo.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "stack_tracy"
|
3
|
+
|
4
|
+
module StackTracy
|
5
|
+
class CLI < Thor
|
6
|
+
|
7
|
+
default_task :open
|
8
|
+
|
9
|
+
desc "open [PATH]", "Display StackTracy data within the browser (PATH is optional)"
|
10
|
+
method_options [:limit, "-l"] => :numeric, [:threshold, "-t"] => :numeric
|
11
|
+
def open(path = ".")
|
12
|
+
StackTracy.open path, false, options.threshold, options.limit
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def method_missing(method, *args)
|
18
|
+
if File.exists? File.expand_path(method.to_s)
|
19
|
+
`tracy open #{method} #{args.join " "}`
|
20
|
+
else
|
21
|
+
raise Error, "Unrecognized command \"#{method}\". Please consult `tracy help`."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -5,6 +5,8 @@ module Kernel
|
|
5
5
|
options = arg
|
6
6
|
arg = nil
|
7
7
|
end
|
8
|
+
threshold = options.delete :threshold
|
9
|
+
limit = options.delete :limit
|
8
10
|
StackTracy.start options
|
9
11
|
yield
|
10
12
|
StackTracy.stop
|
@@ -13,8 +15,9 @@ module Kernel
|
|
13
15
|
elsif arg == :dump
|
14
16
|
StackTracy.dump
|
15
17
|
elsif arg == :open
|
16
|
-
|
17
|
-
|
18
|
+
StackTracy.dump do |file|
|
19
|
+
StackTracy.open file, true, threshold, limit
|
20
|
+
end
|
18
21
|
elsif arg.is_a? String
|
19
22
|
StackTracy.dump arg
|
20
23
|
end
|
data/lib/stack_tracy/sinatra.rb
CHANGED
@@ -10,10 +10,9 @@ module StackTracy
|
|
10
10
|
|
11
11
|
def call(env)
|
12
12
|
request = ::Sinatra::Request.new env
|
13
|
-
if request.path.match /^\/tracy
|
14
|
-
return open($1)
|
13
|
+
if request.path.match /^\/tracy(-.*)?/
|
14
|
+
return open($1.to_s.gsub(/^-/, ""))
|
15
15
|
end
|
16
|
-
|
17
16
|
if @before_filter.nil? || !!@before_filter.call(request.path, request.params)
|
18
17
|
result = nil
|
19
18
|
stack_tracy @arg || Dir::tmpdir, @options do
|
@@ -28,7 +27,17 @@ module StackTracy
|
|
28
27
|
private
|
29
28
|
|
30
29
|
def open(match)
|
31
|
-
|
30
|
+
if match.empty?
|
31
|
+
if StackTracy.stack_trace.empty?
|
32
|
+
StackTracy.open nil, false, @options[:threshold], @options[:limit]
|
33
|
+
else
|
34
|
+
StackTracy.dump do |file|
|
35
|
+
StackTracy.open file, true, @options[:threshold], @options[:limit]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
else
|
39
|
+
StackTracy.open match, false, @options[:threshold], @options[:limit]
|
40
|
+
end
|
32
41
|
[200, {"Content-Type" => "text/html;charset=utf-8", "Content-Length" => Rack::Utils.bytesize("").to_s}, ""]
|
33
42
|
end
|
34
43
|
|
data/lib/stack_tracy/version.rb
CHANGED
data/lib/stack_tracy.rb
CHANGED
@@ -18,7 +18,7 @@ module StackTracy
|
|
18
18
|
:active_record => "ActiveRecord::Base",
|
19
19
|
:data_mapper => "DataMapper::Resource"
|
20
20
|
}
|
21
|
-
@options = Struct.new(:dump_dir, :only, :exclude).new(Dir::tmpdir)
|
21
|
+
@options = Struct.new(:dump_dir, :dump_source_location, :limit, :threshold, :only, :exclude).new(Dir::tmpdir, false, 7500, 0.001)
|
22
22
|
|
23
23
|
class Error < StandardError; end
|
24
24
|
|
@@ -67,26 +67,32 @@ module StackTracy
|
|
67
67
|
}
|
68
68
|
end
|
69
69
|
|
70
|
-
def dump(path = nil, *only)
|
70
|
+
def dump(path = nil, dump_source_location = nil, *only)
|
71
71
|
unless path && path.match(/\.csv$/)
|
72
72
|
path = File.join [path || @options.dump_dir, "stack_events-#{SecureRandom.hex(3)}.csv"].compact
|
73
73
|
end
|
74
74
|
File.expand_path(path).tap do |path|
|
75
|
-
|
75
|
+
bool = dump_source_location.nil? ? @options[:dump_source_location] : dump_source_location
|
76
|
+
keys = [:event, (:file if bool), (:line if bool), :singleton, :object, :method, :nsec, :time, :call, :depth, :duration]
|
76
77
|
File.open(path, "w") do |file|
|
77
78
|
file << keys.join(";") + "\n"
|
78
79
|
select(only).each do |event|
|
79
80
|
file << event.values_at(*keys).join(";") + "\n"
|
80
81
|
end
|
81
82
|
end
|
83
|
+
yield path if block_given?
|
84
|
+
stack_trace.clear
|
82
85
|
end
|
83
86
|
end
|
84
87
|
|
85
|
-
def open(path = nil, use_current_stack_trace = false)
|
86
|
-
|
88
|
+
def open(path = nil, use_current_stack_trace = false, threshold = nil, limit = nil)
|
89
|
+
if use_current_stack_trace
|
90
|
+
file = File.expand_path(path) if path
|
91
|
+
else
|
87
92
|
unless path && path.match(/\.csv$/)
|
88
|
-
path
|
89
|
-
path ||= Dir[File.join(
|
93
|
+
path = Dir[File.join(path || @options.dump_dir, "stack_events-*.csv")].sort_by{|f| File.mtime(f)}.last
|
94
|
+
path ||= Dir[File.join(".", "stack_events-*.csv")].sort_by{|f| File.mtime(f)}.last
|
95
|
+
path ||= Dir[File.join(Dir::tmpdir, "stack_events-*.csv")].sort_by{|f| File.mtime(f)}.last
|
90
96
|
end
|
91
97
|
if path
|
92
98
|
file = File.expand_path(path)
|
@@ -98,6 +104,8 @@ module StackTracy
|
|
98
104
|
index = ui("index.html")
|
99
105
|
|
100
106
|
if use_current_stack_trace || (file && File.exists?(file))
|
107
|
+
threshold = threshold.nil? ? @options[:threshold] : threshold
|
108
|
+
limit = limit.nil? ? @options[:limit] : limit
|
101
109
|
events = use_current_stack_trace ? select : StackTracy::EventInfo.to_hashes(File.read(file))
|
102
110
|
erb = ERB.new File.new(ui("index.html.erb")).read
|
103
111
|
File.open(index, "w"){|f| f.write erb.result(binding)}
|
data/stack_tracy.gemspec
CHANGED
@@ -13,8 +13,9 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
14
|
gem.name = "stack_tracy"
|
15
15
|
gem.require_paths = ["lib"]
|
16
|
-
gem.version = "0.1.
|
16
|
+
gem.version = "0.1.4"
|
17
17
|
|
18
18
|
gem.add_dependency "rich_support", "~> 0.1.2"
|
19
19
|
gem.add_dependency "launchy", "2.1.0"
|
20
|
+
gem.add_dependency "thor"
|
20
21
|
end
|
data/test/unit/test_tracy.rb
CHANGED
@@ -25,7 +25,7 @@ module Unit
|
|
25
25
|
it "should be configurable" do
|
26
26
|
StackTracy.config do |c|
|
27
27
|
assert_equal true, c.is_a?(Struct)
|
28
|
-
assert_equal [:dump_dir, :only, :exclude], c.members
|
28
|
+
assert_equal [:dump_dir, :dump_source_location, :limit, :threshold, :only, :exclude], c.members
|
29
29
|
c.only = "Kernel"
|
30
30
|
c.exclude = ["IO", "String"]
|
31
31
|
end
|
@@ -77,8 +77,8 @@ module Unit
|
|
77
77
|
end
|
78
78
|
}
|
79
79
|
|
80
|
-
|
81
|
-
|
80
|
+
assert_equal true, StackTracy.stack_trace.first.call?
|
81
|
+
assert_equal false, StackTracy.stack_trace.first.return?
|
82
82
|
|
83
83
|
StackTracy.config do |c|
|
84
84
|
c.exclude = ["IO"]
|
@@ -130,6 +130,30 @@ module Unit
|
|
130
130
|
}
|
131
131
|
end
|
132
132
|
|
133
|
+
it "should clear StackTracy.stack_trace after having invoked StackTracy.dump" do
|
134
|
+
stack_tracy do
|
135
|
+
puts "testing"
|
136
|
+
end
|
137
|
+
assert_equal false, StackTracy.stack_trace.empty?
|
138
|
+
|
139
|
+
StackTracy.dump
|
140
|
+
assert_equal true, StackTracy.stack_trace.empty?
|
141
|
+
|
142
|
+
stack_tracy do
|
143
|
+
puts "testing"
|
144
|
+
end
|
145
|
+
assert_equal false, StackTracy.stack_trace.empty?
|
146
|
+
|
147
|
+
StackTracy.expects(:foo)
|
148
|
+
StackTracy.dump do |file|
|
149
|
+
assert file.match(/\/.*\.csv/)
|
150
|
+
assert_equal false, StackTracy.stack_trace.empty?
|
151
|
+
StackTracy.foo
|
152
|
+
end
|
153
|
+
|
154
|
+
assert_equal true, StackTracy.stack_trace.empty?
|
155
|
+
end
|
156
|
+
|
133
157
|
it "should filter methods as expected" do
|
134
158
|
stack_tracy do
|
135
159
|
puts "testing"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
jQuery.fn.comments = function() {
|
2
|
+
var comments = [];
|
3
|
+
|
4
|
+
this.each(function(i, node) {
|
5
|
+
var child = node.firstChild;
|
6
|
+
while (child) {
|
7
|
+
if (child.nodeType === 8) {
|
8
|
+
comments.push(child.nodeValue);
|
9
|
+
}
|
10
|
+
child = child.nextSibling;
|
11
|
+
}
|
12
|
+
});
|
13
|
+
|
14
|
+
return comments;
|
15
|
+
};
|
data/ui/assets/stack_tracy.css
CHANGED
@@ -56,24 +56,25 @@ a {
|
|
56
56
|
#page .tab-pane {
|
57
57
|
line-height: 28px; }
|
58
58
|
|
59
|
-
#page .tab-pane div {
|
60
|
-
border-bottom: 1px solid #EFEFEF; }
|
61
|
-
|
62
59
|
#page .tab-pane div.head {
|
63
60
|
padding-bottom: 4px;
|
64
61
|
font-weight: bold; }
|
65
62
|
#page .tab-pane div.head a {
|
66
63
|
color: #222; }
|
67
64
|
|
68
|
-
#page .tab-pane div.
|
65
|
+
#page .tab-pane div.head,
|
66
|
+
#page .tab-pane div.body div {
|
67
|
+
border-bottom: 1px solid #EFEFEF; }
|
68
|
+
|
69
|
+
#page .tab-pane div.body div.group {
|
69
70
|
border: 0; }
|
70
71
|
|
71
72
|
#page .tab-pane div span.time,
|
72
73
|
#page .tab-pane div span.average,
|
73
74
|
#page .tab-pane div span.duration,
|
74
75
|
#page .tab-pane div span.count {
|
75
|
-
width:
|
76
|
-
padding-right:
|
76
|
+
width: 70px;
|
77
|
+
padding-right: 20px;
|
77
78
|
text-align: right;
|
78
79
|
display: -moz-inline-block;
|
79
80
|
display: inline-block;
|
@@ -82,17 +83,13 @@ a {
|
|
82
83
|
|
83
84
|
#page .tab-pane div span.call {
|
84
85
|
width: 950px;
|
85
|
-
padding-left: 15px;
|
86
86
|
display: -moz-inline-block;
|
87
87
|
display: inline-block;
|
88
88
|
*display: inline;
|
89
89
|
zoom: 1; }
|
90
90
|
|
91
91
|
#page #cumulatives div span.count {
|
92
|
-
width:
|
93
|
-
|
94
|
-
#page #cumulatives div span.call {
|
95
|
-
width: 790px; }
|
92
|
+
width: 45px; }
|
96
93
|
|
97
94
|
#footer {
|
98
95
|
padding-top: 45px;
|
data/ui/assets/stack_tracy.js
CHANGED
@@ -4,7 +4,13 @@ StackTracy = (function() {
|
|
4
4
|
var sortation = [];
|
5
5
|
|
6
6
|
var toggle = function(event) {
|
7
|
-
$(event.target).closest("div").next("div.group")
|
7
|
+
var group = $(event.target).closest("div").next("div.group");
|
8
|
+
var comments = group.comments();
|
9
|
+
if (comments.length) {
|
10
|
+
group.html(comments.join("\n"));
|
11
|
+
} else {
|
12
|
+
group.toggle();
|
13
|
+
}
|
8
14
|
};
|
9
15
|
|
10
16
|
$(function() {
|
@@ -16,7 +22,7 @@ StackTracy = (function() {
|
|
16
22
|
});
|
17
23
|
|
18
24
|
return {
|
19
|
-
version: "0.1.
|
25
|
+
version: "0.1.4",
|
20
26
|
sort: function(column) {
|
21
27
|
sortation[column] = sortation[column] == "asc" ? "desc" : "asc";
|
22
28
|
$("#cumulatives>.body>div").tsort("span:eq(" + column + ")[abbr]", {
|
data/ui/index.html.erb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
<script src="assets/jquery.js" type="text/javascript"></script>
|
9
9
|
<script src="assets/bootstrap-tab.js" type="text/javascript"></script>
|
10
10
|
<script src="assets/tiny_sort.js" type="text/javascript"></script>
|
11
|
+
<script src="assets/comments.js" type="text/javascript"></script>
|
11
12
|
<script src="assets/stack_tracy.js" type="text/javascript"></script>
|
12
13
|
<link href="assets/bootstrap-tab.css" type="text/css" rel="stylesheet" media="screen"/>
|
13
14
|
<link href="assets/stack_tracy.css" type="text/css" rel="stylesheet" media="screen"/>
|
@@ -26,26 +27,27 @@
|
|
26
27
|
<a href="#cumulatives" data-toggle="tab">Cumulatives</a>
|
27
28
|
</li>
|
28
29
|
</ul>
|
29
|
-
<div class="tab-content"
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
<div class="tab-content"><%
|
31
|
+
limited = events.size > limit
|
32
|
+
threshold = nil unless limited
|
33
|
+
excluded_objects = if limited
|
34
|
+
%w(Array BasicObject Enumerable Fixnum Float Hash IO Integer Kernel Module Mutex Numeric Object Rational String Symbol Thread Time)
|
35
|
+
else
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
comment_depth = nil
|
39
|
+
last_depth = nil
|
40
|
+
last_duration = nil
|
41
|
+
corrections = []
|
42
|
+
cumulatives = {} %>
|
40
43
|
<div class="tab-pane active" id="stack_trace">
|
41
44
|
<div class="head">
|
42
45
|
<span class="time">Time</span>
|
43
46
|
<span class="duration">Duration</span>
|
44
47
|
<span class="call">Call</span>
|
45
48
|
</div>
|
46
|
-
<div class="body"
|
47
|
-
|
48
|
-
<%
|
49
|
+
<div class="body"><%
|
50
|
+
events.each_with_index do |event, index|
|
49
51
|
skip = excluded_objects.include?(event[:object]) || "#{event[:object]}".match(/^#/)
|
50
52
|
cumulatives[event[:call]] ||= {:duration => 0.0, :count => 0}
|
51
53
|
cumulatives[event[:call]][:duration] += event[:duration].to_f
|
@@ -54,37 +56,38 @@
|
|
54
56
|
corrections.size.times do |i|
|
55
57
|
event[:depth] <= corrections[0] ? corrections.shift : break
|
56
58
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
59
|
+
if skip
|
60
|
+
corrections.unshift event[:depth] if corrections.empty? || corrections.first != event[:depth]
|
61
|
+
else
|
62
|
+
if last_depth.to_i < event[:depth] - corrections.size %>
|
63
|
+
<div class="group"><% if threshold && comment_depth.nil? && last_duration && last_duration < threshold %><% comment_depth = event[:depth] - corrections.size %><%= "\n<!--" %><% end %><% else
|
64
|
+
close_tags = ((event[:depth] - corrections.size + 1)..last_depth.to_i).collect do |depth|
|
65
|
+
if comment_depth && depth == comment_depth
|
66
|
+
comment_depth = nil
|
67
|
+
"\n-->\n</div>"
|
68
|
+
else
|
69
|
+
"\n</div>"
|
70
|
+
end
|
71
|
+
end.reverse.join("")
|
72
|
+
%><%= close_tags %><% end %>
|
73
|
+
<div>
|
74
|
+
<span class="time"><%= "%.6f" % event[:time] %></span>
|
75
|
+
<span class="duration"><%= event[:duration] ? ("%.6f" % event[:duration]) : "?" %></span>
|
76
|
+
<span style="padding-left: <%= 10 * (event[:depth] - corrections.size) %>px"><% if (next_event = events[index + 1]) && next_event[:depth] > event[:depth] %><a class="toggler" href="#" onclick="return false"><%= event[:call] %></a><% else %><%= event[:call] %><% end %></span>
|
77
|
+
</div><%
|
78
|
+
last_depth = event[:depth] - corrections.size
|
79
|
+
last_duration = event[:duration]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
close_tags = (1..last_depth.to_i).collect do |depth|
|
83
|
+
if comment_depth && depth == comment_depth
|
84
|
+
comment_depth = nil
|
85
|
+
"\n-->\n</div>"
|
86
|
+
else
|
87
|
+
"\n</div>"
|
88
|
+
end
|
89
|
+
end.reverse.join("")
|
90
|
+
%><%= close_tags %>
|
88
91
|
</div>
|
89
92
|
</div>
|
90
93
|
<div class="tab-pane" id="cumulatives">
|
@@ -94,23 +97,13 @@
|
|
94
97
|
<span class="count"><a href="javascript:StackTracy.sort(2)">Count</a></span>
|
95
98
|
<span class="call"><a href="javascript:StackTracy.sort(3)">Call</a></span>
|
96
99
|
</div>
|
97
|
-
<div class="body"
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
<%= "%.6f" % stats[:duration] %>
|
105
|
-
</span>
|
106
|
-
<span class="count" abbr="<%= stats[:count] %>">
|
107
|
-
<%= stats[:count] %>
|
108
|
-
</span>
|
109
|
-
<span class="call" abbr="<%= call.gsub("<", "<").gsub(">", ">") %>">
|
110
|
-
<%= call.gsub("<", "<").gsub(">", ">") %>
|
111
|
-
</span>
|
112
|
-
</div>
|
113
|
-
<% end %>
|
100
|
+
<div class="body"><% cumulatives.sort{|(ak, av), (bk, bv)| bv[:average] <=> av[:average]}.each do |call, stats| %>
|
101
|
+
<div>
|
102
|
+
<span class="average" abbr="<%= "%.6f" % stats[:average] %>"><%= "%.6f" % stats[:average] %></span>
|
103
|
+
<span class="duration" abbr="<%= "%.6f" % stats[:duration] %>"><%= "%.6f" % stats[:duration] %></span>
|
104
|
+
<span class="count" abbr="<%= stats[:count] %>"><%= stats[:count] %></span>
|
105
|
+
<span class="call" abbr="<%= call.gsub("<", "<").gsub(">", ">") %>"><%= call.gsub("<", "<").gsub(">", ">") %></span>
|
106
|
+
</div><% end %>
|
114
107
|
</div>
|
115
108
|
</div>
|
116
109
|
</div>
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: stack_tracy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Paul Engel
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-08-
|
13
|
+
date: 2012-08-26 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rich_support
|
@@ -34,6 +34,17 @@ dependencies:
|
|
34
34
|
version: 2.1.0
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: thor
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
37
48
|
description: Investigate and detect slow methods within the stack trace of your Ruby (optionally Sinatra) application
|
38
49
|
email:
|
39
50
|
- paul.engel@holder.nl
|
@@ -53,10 +64,12 @@ files:
|
|
53
64
|
- VERSION
|
54
65
|
- benchmarks/benchmark.rb
|
55
66
|
- bin/tracy
|
67
|
+
- demo.rb
|
56
68
|
- ext/stack_tracy/extconf.rb
|
57
69
|
- ext/stack_tracy/stack_tracy.c
|
58
70
|
- ext/stack_tracy/stack_tracy.h
|
59
71
|
- lib/stack_tracy.rb
|
72
|
+
- lib/stack_tracy/cli.rb
|
60
73
|
- lib/stack_tracy/core_ext.rb
|
61
74
|
- lib/stack_tracy/core_ext/kernel.rb
|
62
75
|
- lib/stack_tracy/event_info.rb
|
@@ -69,6 +82,7 @@ files:
|
|
69
82
|
- test/unit/test_tracy.rb
|
70
83
|
- ui/assets/bootstrap-tab.css
|
71
84
|
- ui/assets/bootstrap-tab.js
|
85
|
+
- ui/assets/comments.js
|
72
86
|
- ui/assets/jquery.js
|
73
87
|
- ui/assets/stack_tracy.css
|
74
88
|
- ui/assets/stack_tracy.js
|