stackprof-webnav 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,410 @@
1
+ /*! normalize.css v2.1.2 | MIT License | git.io/normalize */
2
+
3
+ /* ==========================================================================
4
+ HTML5 display definitions
5
+ ========================================================================== */
6
+
7
+ /**
8
+ * Correct `block` display not defined in IE 8/9.
9
+ */
10
+
11
+ article,
12
+ aside,
13
+ details,
14
+ figcaption,
15
+ figure,
16
+ footer,
17
+ header,
18
+ hgroup,
19
+ main,
20
+ nav,
21
+ section,
22
+ summary {
23
+ display: block;
24
+ }
25
+
26
+ /**
27
+ * Correct `inline-block` display not defined in IE 8/9.
28
+ */
29
+
30
+ audio,
31
+ canvas,
32
+ video {
33
+ display: inline-block;
34
+ }
35
+
36
+ /**
37
+ * Prevent modern browsers from displaying `audio` without controls.
38
+ * Remove excess height in iOS 5 devices.
39
+ */
40
+
41
+ audio:not([controls]) {
42
+ display: none;
43
+ height: 0;
44
+ }
45
+
46
+ /**
47
+ * Address `[hidden]` styling not present in IE 8/9.
48
+ * Hide the `template` element in IE, Safari, and Firefox < 22.
49
+ */
50
+
51
+ [hidden],
52
+ template {
53
+ display: none;
54
+ }
55
+
56
+ script {
57
+ display: none !important;
58
+ }
59
+
60
+ /* ==========================================================================
61
+ Base
62
+ ========================================================================== */
63
+
64
+ /**
65
+ * 1. Set default font family to sans-serif.
66
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
67
+ * user zoom.
68
+ */
69
+
70
+ html {
71
+ font-family: sans-serif; /* 1 */
72
+ -ms-text-size-adjust: 100%; /* 2 */
73
+ -webkit-text-size-adjust: 100%; /* 2 */
74
+ }
75
+
76
+ /**
77
+ * Remove default margin.
78
+ */
79
+
80
+ body {
81
+ margin: 0;
82
+ }
83
+
84
+ /* ==========================================================================
85
+ Links
86
+ ========================================================================== */
87
+
88
+ /**
89
+ * Remove the gray background color from active links in IE 10.
90
+ */
91
+
92
+ a {
93
+ background: transparent;
94
+ }
95
+
96
+ /**
97
+ * Address `outline` inconsistency between Chrome and other browsers.
98
+ */
99
+
100
+ a:focus {
101
+ outline: thin dotted;
102
+ }
103
+
104
+ /**
105
+ * Improve readability when focused and also mouse hovered in all browsers.
106
+ */
107
+
108
+ a:active,
109
+ a:hover {
110
+ outline: 0;
111
+ }
112
+
113
+ /* ==========================================================================
114
+ Typography
115
+ ========================================================================== */
116
+
117
+ /**
118
+ * Address variable `h1` font-size and margin within `section` and `article`
119
+ * contexts in Firefox 4+, Safari 5, and Chrome.
120
+ */
121
+
122
+ h1 {
123
+ font-size: 2em;
124
+ margin: 0.67em 0;
125
+ }
126
+
127
+ /**
128
+ * Address styling not present in IE 8/9, Safari 5, and Chrome.
129
+ */
130
+
131
+ abbr[title] {
132
+ border-bottom: 1px dotted;
133
+ }
134
+
135
+ /**
136
+ * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
137
+ */
138
+
139
+ b,
140
+ strong {
141
+ font-weight: bold;
142
+ }
143
+
144
+ /**
145
+ * Address styling not present in Safari 5 and Chrome.
146
+ */
147
+
148
+ dfn {
149
+ font-style: italic;
150
+ }
151
+
152
+ /**
153
+ * Address differences between Firefox and other browsers.
154
+ */
155
+
156
+ hr {
157
+ -moz-box-sizing: content-box;
158
+ box-sizing: content-box;
159
+ height: 0;
160
+ }
161
+
162
+ /**
163
+ * Address styling not present in IE 8/9.
164
+ */
165
+
166
+ mark {
167
+ background: #ff0;
168
+ color: #000;
169
+ }
170
+
171
+ /**
172
+ * Correct font family set oddly in Safari 5 and Chrome.
173
+ */
174
+
175
+ code,
176
+ kbd,
177
+ pre,
178
+ samp {
179
+ font-family: monospace, serif;
180
+ font-size: 1em;
181
+ }
182
+
183
+ /**
184
+ * Improve readability of pre-formatted text in all browsers.
185
+ */
186
+
187
+ pre {
188
+ white-space: pre-wrap;
189
+ }
190
+
191
+ /**
192
+ * Set consistent quote types.
193
+ */
194
+
195
+ q {
196
+ quotes: "\201C" "\201D" "\2018" "\2019";
197
+ }
198
+
199
+ /**
200
+ * Address inconsistent and variable font size in all browsers.
201
+ */
202
+
203
+ small {
204
+ font-size: 80%;
205
+ }
206
+
207
+ /**
208
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
209
+ */
210
+
211
+ sub,
212
+ sup {
213
+ font-size: 75%;
214
+ line-height: 0;
215
+ position: relative;
216
+ vertical-align: baseline;
217
+ }
218
+
219
+ sup {
220
+ top: -0.5em;
221
+ }
222
+
223
+ sub {
224
+ bottom: -0.25em;
225
+ }
226
+
227
+ /* ==========================================================================
228
+ Embedded content
229
+ ========================================================================== */
230
+
231
+ /**
232
+ * Remove border when inside `a` element in IE 8/9.
233
+ */
234
+
235
+ img {
236
+ border: 0;
237
+ }
238
+
239
+ /**
240
+ * Correct overflow displayed oddly in IE 9.
241
+ */
242
+
243
+ svg:not(:root) {
244
+ overflow: hidden;
245
+ }
246
+
247
+ /* ==========================================================================
248
+ Figures
249
+ ========================================================================== */
250
+
251
+ /**
252
+ * Address margin not present in IE 8/9 and Safari 5.
253
+ */
254
+
255
+ figure {
256
+ margin: 0;
257
+ }
258
+
259
+ /* ==========================================================================
260
+ Forms
261
+ ========================================================================== */
262
+
263
+ /**
264
+ * Define consistent border, margin, and padding.
265
+ */
266
+
267
+ fieldset {
268
+ border: 1px solid #c0c0c0;
269
+ margin: 0 2px;
270
+ padding: 0.35em 0.625em 0.75em;
271
+ }
272
+
273
+ /**
274
+ * 1. Correct `color` not being inherited in IE 8/9.
275
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
276
+ */
277
+
278
+ legend {
279
+ border: 0; /* 1 */
280
+ padding: 0; /* 2 */
281
+ }
282
+
283
+ /**
284
+ * 1. Correct font family not being inherited in all browsers.
285
+ * 2. Correct font size not being inherited in all browsers.
286
+ * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
287
+ */
288
+
289
+ button,
290
+ input,
291
+ select,
292
+ textarea {
293
+ font-family: inherit; /* 1 */
294
+ font-size: 100%; /* 2 */
295
+ margin: 0; /* 3 */
296
+ }
297
+
298
+ /**
299
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
300
+ * the UA stylesheet.
301
+ */
302
+
303
+ button,
304
+ input {
305
+ line-height: normal;
306
+ }
307
+
308
+ /**
309
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
310
+ * All other form control elements do not inherit `text-transform` values.
311
+ * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
312
+ * Correct `select` style inheritance in Firefox 4+ and Opera.
313
+ */
314
+
315
+ button,
316
+ select {
317
+ text-transform: none;
318
+ }
319
+
320
+ /**
321
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
322
+ * and `video` controls.
323
+ * 2. Correct inability to style clickable `input` types in iOS.
324
+ * 3. Improve usability and consistency of cursor style between image-type
325
+ * `input` and others.
326
+ */
327
+
328
+ button,
329
+ html input[type="button"], /* 1 */
330
+ input[type="reset"],
331
+ input[type="submit"] {
332
+ -webkit-appearance: button; /* 2 */
333
+ cursor: pointer; /* 3 */
334
+ }
335
+
336
+ /**
337
+ * Re-set default cursor for disabled elements.
338
+ */
339
+
340
+ button[disabled],
341
+ html input[disabled] {
342
+ cursor: default;
343
+ }
344
+
345
+ /**
346
+ * 1. Address box sizing set to `content-box` in IE 8/9.
347
+ * 2. Remove excess padding in IE 8/9.
348
+ */
349
+
350
+ input[type="checkbox"],
351
+ input[type="radio"] {
352
+ box-sizing: border-box; /* 1 */
353
+ padding: 0; /* 2 */
354
+ }
355
+
356
+ /**
357
+ * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
358
+ * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
359
+ * (include `-moz` to future-proof).
360
+ */
361
+
362
+ input[type="search"] {
363
+ -webkit-appearance: textfield; /* 1 */
364
+ -moz-box-sizing: content-box;
365
+ -webkit-box-sizing: content-box; /* 2 */
366
+ box-sizing: content-box;
367
+ }
368
+
369
+ /**
370
+ * Remove inner padding and search cancel button in Safari 5 and Chrome
371
+ * on OS X.
372
+ */
373
+
374
+ input[type="search"]::-webkit-search-cancel-button,
375
+ input[type="search"]::-webkit-search-decoration {
376
+ -webkit-appearance: none;
377
+ }
378
+
379
+ /**
380
+ * Remove inner padding and border in Firefox 4+.
381
+ */
382
+
383
+ button::-moz-focus-inner,
384
+ input::-moz-focus-inner {
385
+ border: 0;
386
+ padding: 0;
387
+ }
388
+
389
+ /**
390
+ * 1. Remove default vertical scrollbar in IE 8/9.
391
+ * 2. Improve readability and alignment in all browsers.
392
+ */
393
+
394
+ textarea {
395
+ overflow: auto; /* 1 */
396
+ vertical-align: top; /* 2 */
397
+ }
398
+
399
+ /* ==========================================================================
400
+ Tables
401
+ ========================================================================== */
402
+
403
+ /**
404
+ * Remove most spacing between table cells.
405
+ */
406
+
407
+ table {
408
+ border-collapse: collapse;
409
+ border-spacing: 0;
410
+ }
@@ -0,0 +1,85 @@
1
+ require 'better_errors'
2
+ require 'stringio'
3
+
4
+ module StackProf
5
+ module Webnav
6
+ class Presenter
7
+ attr_reader :report
8
+ def initialize report
9
+ @report = report
10
+ end
11
+
12
+ def file_overview path
13
+ buffer = StringIO.new
14
+ report.print_file(path, buffer)
15
+ data = buffer.string.split("\n").map {|l| l.split('|').first}
16
+
17
+ {
18
+ :lineinfo => data,
19
+ :code => BetterErrors::CodeFormatter::HTML.new(path, 0, 9999).output
20
+ }
21
+ end
22
+
23
+ def overview_frames
24
+ report.frames.map do |frame, info|
25
+ call, total = info.values_at(:samples, :total_samples)
26
+ {
27
+ :total => total,
28
+ :total_pct => percent(total.to_f/report.overall_samples),
29
+ :samples => call,
30
+ :samples_pct => percent(call.to_f/report.overall_samples),
31
+ :method => info[:name]
32
+ }
33
+ end
34
+ end
35
+
36
+ def method_info name
37
+ name = /#{Regexp.escape name}/ unless Regexp === name
38
+ frames = report.frames.select do |frame, info|
39
+ info[:name] =~ name
40
+ end.map do |frame, info|
41
+ file, line = info.values_at(:file, :line)
42
+
43
+ {
44
+ :callers => callers(frame, info),
45
+ :callees => callees(frame, info),
46
+ :location => file,
47
+ :source => BetterErrors::CodeFormatter::HTML.new(file, line).output
48
+ }
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def percent value
55
+ "%2.2f%" % (value*100)
56
+ end
57
+
58
+ def callers frame, info
59
+ report.data[:frames].select do |id, other|
60
+ other[:edges] && other[:edges].include?(frame)
61
+ end.map do |id, other|
62
+ [other[:name], other[:edges][frame]]
63
+ end.sort_by(&:last).reverse.map do |name, weight|
64
+ {
65
+ :weight => weight,
66
+ :pct => percent(weight.to_f/info[:total_samples]),
67
+ :method => name
68
+ }
69
+ end
70
+ end
71
+
72
+ def callees frame, info
73
+ (info[:edges] || []).map do |k, weight|
74
+ [report.data[:frames][k][:name], weight]
75
+ end.sort_by { |k,v| -v }.map do |name, weight|
76
+ {
77
+ :weight => weight,
78
+ :pct => percent(weight.to_f/(info[:total_samples]-info[:samples])),
79
+ :method => name
80
+ }
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,68 @@
1
+ require 'nyny'
2
+ require 'haml'
3
+ require "stackprof"
4
+ require 'sprockets'
5
+ require_relative 'presenter'
6
+
7
+ module StackProf
8
+ module Webnav
9
+ class Server < NYNY::App
10
+ class << self
11
+ attr_accessor :report_dump_path
12
+
13
+ def presenter
14
+ report = StackProf::Report.new(Marshal.load(File.open(report_dump_path).read))
15
+ @presenter ||= Presenter.new(report)
16
+ end
17
+ end
18
+
19
+ helpers do
20
+ def template_path name
21
+ File.join(__dir__, name)
22
+ end
23
+
24
+ def render_with_layout *args
25
+ args[0] = template_path("views/#{args[0]}.haml")
26
+ render(template_path('views/layout.haml')) { render(*args) }
27
+ end
28
+
29
+ def presenter
30
+ Server.presenter
31
+ end
32
+
33
+ def method_url name
34
+ "/method?name=#{URI.escape(name)}"
35
+ end
36
+
37
+ def file_url path
38
+ "/file?path=#{URI.escape(path)}"
39
+ end
40
+ end
41
+
42
+ sprockets = Sprockets::Environment.new do |env|
43
+ env.append_path(File.join(__dir__, 'css'))
44
+ end.index
45
+ builder.map('/assets'){ run sprockets }
46
+
47
+ get '/' do
48
+ @file = Server.report_dump_path
49
+ @action = "overview"
50
+ @frames = presenter.overview_frames
51
+ render_with_layout :overview
52
+ end
53
+
54
+ get '/method' do
55
+ @action = params[:name]
56
+ @frames = presenter.method_info(params[:name])
57
+ render_with_layout :method
58
+ end
59
+
60
+ get '/file' do
61
+ path = params[:path]
62
+ @path = path
63
+ @data = presenter.file_overview(path)
64
+ render_with_layout :file
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,73 @@
1
+ require 'better_errors'
2
+
3
+ module StackProf
4
+ module Webnav
5
+ class Presenter
6
+ attr_reader :report
7
+ def initialize report
8
+ @report = report
9
+ end
10
+
11
+ def overview_frames
12
+ report.frames.map do |frame, info|
13
+ call, total = info.values_at(:samples, :total_samples)
14
+ {
15
+ :total => total,
16
+ :total_pct => percent(total.to_f/report.overall_samples),
17
+ :samples => call,
18
+ :samples_pct => percent(call.to_f/report.overall_samples),
19
+ :method => info[:name]
20
+ }
21
+ end
22
+ end
23
+
24
+ def method_info name
25
+ name = /#{Regexp.escape name}/ unless Regexp === name
26
+ frames = report.frames.select do |frame, info|
27
+ info[:name] =~ name
28
+ end.map do |frame, info|
29
+ file, line = info.values_at(:file, :line)
30
+
31
+ {
32
+ :callers => callers(frame, info),
33
+ :callees => callees(frame, info),
34
+ :location => "#{file}:#{line}",
35
+ :source => BetterErrors::CodeFormatter::HTML.new(file, line).output
36
+ }
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def percent value
43
+ "%2.2f%" % (value*100)
44
+ end
45
+
46
+ def callers frame, info
47
+ report.data[:frames].select do |id, other|
48
+ other[:edges] && other[:edges].include?(frame)
49
+ end.map do |id, other|
50
+ [other[:name], other[:edges][frame]]
51
+ end.sort_by(&:last).reverse.map do |name, weight|
52
+ {
53
+ :weight => weight,
54
+ :pct => percent(weight.to_f/info[:total_samples]),
55
+ :method => name
56
+ }
57
+ end
58
+ end
59
+
60
+ def callees frame, info
61
+ (info[:edges] || []).map do |k, weight|
62
+ [report.data[:frames][k][:name], weight]
63
+ end.sort_by { |k,v| -v }.map do |name, weight|
64
+ {
65
+ :weight => weight,
66
+ :pct => percent(weight.to_f/(info[:total_samples]-info[:samples])),
67
+ :method => name
68
+ }
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,5 @@
1
+ module StackProf
2
+ module Webnav
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ %h3 StackProf Navigator - #{@path}
2
+ %hr
3
+
4
+ %a{:href => '/'} &#8592; Back to overview
5
+ %br
6
+ %br
7
+
8
+ .code_linenums
9
+ - @data[:lineinfo].each do |l|
10
+ %span= l
11
+ != @data[:code]
@@ -0,0 +1,9 @@
1
+ %html
2
+ %head
3
+ %title Stackprof navigator
4
+ %link(rel="stylesheet" href="/assets/application.css")
5
+
6
+ %body
7
+ .row
8
+ .large-12.columns
9
+ = yield
@@ -0,0 +1,46 @@
1
+ %h3 StackProf Navigator - #{@action} (#{@frames.count} frames)
2
+ %hr
3
+
4
+ %a{:href => '/'} &#8592; Back to overview
5
+ %br
6
+
7
+ - @frames.each do |frame|
8
+ %h4
9
+ %a{:href => file_url(frame[:location])}= frame[:location]
10
+ - if frame[:callers].any?
11
+ %table
12
+ %thead
13
+ %th Callers
14
+ %th
15
+ %th
16
+ %th
17
+ %tbody
18
+ - frame[:callers].each do |caller|
19
+ %tr
20
+ %td
21
+ %td= caller[:weight]
22
+ %td= caller[:pct]
23
+ %td
24
+ %a{:href => method_url(caller[:method])}
25
+ = caller[:method]
26
+
27
+ - if frame[:callees].any?
28
+ %table
29
+ %thead
30
+ %th Callees
31
+ %th
32
+ %th
33
+ %th
34
+ %tbody
35
+ - frame[:callees].each do |caller|
36
+ %tr
37
+ %td
38
+ %td= caller[:weight]
39
+ %td= caller[:pct]
40
+ %td
41
+ %a{:href => method_url(caller[:method])}
42
+ = caller[:method]
43
+
44
+ %h4 Code
45
+ != frame[:source]
46
+ %hr