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 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 and dump directory of `StackTracy`:
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 = "." #=> default: Dir::tmpdir
87
- c.only = "Foo*" #=> default: nil
88
- c.exclude = %w(Foo::Bar Foo::CandyBar) #=> default: nil
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, `tracy` will look for `stack_events-<random generated postfix>.csv` in either the default dump directory or in `Dir::tmpdir` and display it in the browser. When not found, it will display the last compiled stack tree when available:
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)> file = StackTracy.dump Dir::tmpdir
272
- [5] pry(main)> StackTracy.open file
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 open [http://localhost:4567/tracy](http://localhost:4567/tracy) afterwards and the complete stack tree will be displayed in your browser! ^^
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.3
1
+ 0.1.4
data/bin/tracy CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "rubygems"
4
- require "stack_tracy"
4
+ require "stack_tracy/cli"
5
5
 
6
6
  begin
7
- StackTracy.open ARGV.first
7
+ StackTracy::CLI.start
8
8
  rescue StackTracy::Error => e
9
9
  puts e.message.red
10
10
  end
data/demo.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "sinatra"
2
+ require "stack_tracy"
3
+
4
+ use StackTracy::Sinatra, :open, :threshold => 0.002, :limit => 250
5
+
6
+ get "/" do
7
+ "Hello World!"
8
+ end
@@ -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
- file = StackTracy.dump Dir::tmpdir
17
- StackTracy.open file, true
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
@@ -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
- StackTracy.open match.to_s.empty? ? nil : match, (match.to_s.empty? && @arg.to_s != "dump" && !StackTracy.stack_trace.empty?)
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
 
@@ -1,7 +1,7 @@
1
1
  module StackTracy #:nodoc:
2
2
  MAJOR = 0
3
3
  MINOR = 1
4
- TINY = 3
4
+ TINY = 4
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join(".")
7
7
  end
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
- keys = [:event, :file, :line, :singleton, :object, :method, :nsec, :time, :call, :depth, :duration]
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
- unless use_current_stack_trace
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 = Dir[File.join(path || @options.dump_dir, "stack_events-*.csv")].sort_by{|f| File.mtime(f)}.last
89
- path ||= Dir[File.join(path || Dir::tmpdir, "stack_events-*.csv")].sort_by{|f| File.mtime(f)}.last
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.3"
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
@@ -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
- assert StackTracy.stack_trace.first.call?
81
- assert !StackTracy.stack_trace.first.return?
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
+ };
@@ -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.group {
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: 100px;
76
- padding-right: 15px;
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: 65px; }
93
-
94
- #page #cumulatives div span.call {
95
- width: 790px; }
92
+ width: 45px; }
96
93
 
97
94
  #footer {
98
95
  padding-top: 45px;
@@ -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").toggle();
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.3",
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
- current_depth = 0
32
- excluded_objects = if events.size > 7500
33
- %w(Array BasicObject Enumerable Fixnum Float Hash IO Kernel Module Mutex Numeric Object Rational String Symbol Thread Time)
34
- else
35
- []
36
- end
37
- corrections = []
38
- cumulatives = {}
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
- <% events.each_with_index do |event, index| %>
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
- <% if skip %>
59
- <% corrections.unshift event[:depth] if corrections.empty? || corrections.first != event[:depth] %>
60
- <% else %>
61
- <% if current_depth < event[:depth] - corrections.size %>
62
- <div class="group">
63
- <% elsif current_depth > event[:depth] - corrections.size %>
64
- <%= "</div>" * (current_depth - (event[:depth] - corrections.size)) %>
65
- <% end %>
66
- <div>
67
- <span class="time">
68
- <%= "%.6f" % event[:time] %>
69
- </span>
70
- <span class="duration">
71
- <%= event[:duration] ? ("%.6f" % event[:duration]) : "?" %>
72
- </span>
73
- <span class="call">
74
- <%= "&nbsp;&nbsp;&nbsp;" * (event[:depth] - corrections.size) %>
75
- <% if (next_event = events[index + 1]) && next_event[:depth] > event[:depth] %>
76
- <a class="toggler" href="#" onclick="return false">
77
- <%= event[:call] %>
78
- </a>
79
- <% else %>
80
- <%= event[:call] %>
81
- <% end %>
82
- </span>
83
- </div>
84
- <% current_depth = event[:depth] - corrections.size %>
85
- <% end %>
86
- <% end %>
87
- <%= "</div>" * current_depth %>
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
- <% cumulatives.sort{|(ak, av), (bk, bv)| bv[:average] <=> av[:average]}.each do |call, stats| %>
99
- <div>
100
- <span class="average" abbr="<%= "%.6f" % stats[:average] %>">
101
- <%= "%.6f" % stats[:average] %>
102
- </span>
103
- <span class="duration" abbr="<%= "%.6f" % stats[:duration] %>">
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("<", "&lt;").gsub(">", "&gt;") %>">
110
- <%= call.gsub("<", "&lt;").gsub(">", "&gt;") %>
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("<", "&lt;").gsub(">", "&gt;") %>"><%= call.gsub("<", "&lt;").gsub(">", "&gt;") %></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.3
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-18 00:00:00 Z
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