peek-performance_bar 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 857b53ade1e4d64fe7f5ca135a3b3f16596ffc5f
4
- data.tar.gz: 85802d7c4c3b219814b3e1d8abe015dcee927dce
3
+ metadata.gz: 57aac4506b72753e304dd71e6d879103a806c793
4
+ data.tar.gz: 3b68b08e0a1f4f01044d23678b1aba2a32d58990
5
5
  SHA512:
6
- metadata.gz: 8f40085f3fc6ec19f00c14355f60ad6507e162aa0b41cfe3fd400df004eeb0428e28a0abec950bc0b2a673167e5734d93e7faa2915802c095dec6bba902cce7d
7
- data.tar.gz: 363db21a79d680fc00e1f1b93d903dfc890b6bc7103b04d11382dd32b168520953b8002d46c493008f10addc65f0fec83ba03d4284469f2bcdd372f9953e13a0
6
+ metadata.gz: 16c23582330e78462677b54481af3d4b3a5f5368aeb45c7244e8271c543b6c33e7e448e44f076db8c49a289be05abaeb49b43b703693202167535a0d15de4b96
7
+ data.tar.gz: a84688e829e1cfbea5cb8d6f7665586c796887c491445ff7b0b3be7d357e83c2b312ee590cf716e58d1d63562103a0e2d7f1a3821b8f4b1b3e1ff0f04a99ea59
data/CHANGELOG.md CHANGED
@@ -38,3 +38,8 @@
38
38
  # 1.2.1
39
39
 
40
40
  - Listen to Turbolinks v5 `turbolinks:request-start` and `turbolinks:load` JS events to trigger peek-performance_bar updates. - [#26](https://github.com/peek/peek-performance_bar/pull/26) [@lucasmazza](https://github.com/lucasmazza)
41
+
42
+ # 1.3.0
43
+
44
+ - Remove CoffeeScript support in favor of plain JavaScript. - [#28](https://github.com/peek/peek-performance_bar/pull/28) [@gfx](https://github.com/gfx)
45
+ - Use Rack::BodyProxy to fix X-Sendfile header being incorrectly set. - [#27](https://github.com/peek/peek-performance_bar/pull/27) [@rymai](https://github.com/rymai)
@@ -0,0 +1,192 @@
1
+ // The mission control window.performance.timing display area.
2
+ //
3
+ // Breaks the window.performance.timing numbers down into these groups:
4
+ //
5
+ // dns - Time looking up domain. Usually zero.
6
+ // tcp and ssl - Time used establishing tcp and ssl connections.
7
+ // redirect - Time spent redirecting since navigation began.
8
+ // app - Real server time as recorded in the app.
9
+ // latency - Extra backend and network time where browser was waiting.
10
+ // frontend - Time spent loading and rendering the DOM until interactive.
11
+ //
12
+ // Not all frontend time is counted. The page is considered ready when the
13
+ // domInteractive ready state is reached. This is before DOMContentLoaded and
14
+ // onload javascript handlers.
15
+ class PerformanceBar {
16
+ static initClass() {
17
+ // Additional app info to show with the app timing.
18
+ this.prototype.appInfo = null;
19
+
20
+ // The pixel width we're rendering the timing graph into.
21
+ this.prototype.width = null;
22
+ }
23
+
24
+ // Format a time as ms or s based on how big it is.
25
+ static formatTime(value) {
26
+ if (value >= 1000) {
27
+ return `${(value / 1000).toFixed(3)}s`;
28
+ } else {
29
+ return `${value.toFixed(0)}ms`;
30
+ }
31
+ }
32
+
33
+ // Create a new PerformanceBar view bound to a given element. The el and width
34
+ // options should be provided here.
35
+ constructor(options) {
36
+ if (options == null) { options = {}; }
37
+ this.el = $('#peek-view-performance-bar .performance-bar');
38
+ for (let k in options) { let v = options[k]; this[k] = v; }
39
+ if (this.width == null) { this.width = this.el.width(); }
40
+ if (this.timing == null) { this.timing = window.performance.timing; }
41
+ }
42
+
43
+ // Render the performance bar in the associated element. This is a little weird
44
+ // because it includes the server-side rendering time reported with the
45
+ // response document which may not line up when using the back/forward button
46
+ // and loading from cache.
47
+ render(serverTime) {
48
+ if (serverTime == null) { serverTime = 0; }
49
+ this.el.empty();
50
+ this.addBar('frontend', '#90d35b', 'domLoading', 'domInteractive');
51
+
52
+ // time spent talking with the app according to performance.timing
53
+ let perfNetworkTime = (this.timing.responseEnd - this.timing.requestStart);
54
+
55
+ // only include serverTime if it's less than than the browser reported
56
+ // talking-to-the-app time; otherwise, assume we're loading from cache.
57
+ if (serverTime && (serverTime <= perfNetworkTime)) {
58
+ let networkTime = perfNetworkTime - serverTime;
59
+ this.addBar('latency / receiving', '#f1faff',
60
+ this.timing.requestStart + serverTime,
61
+ this.timing.requestStart + serverTime + networkTime);
62
+ this.addBar('app', '#90afcf',
63
+ this.timing.requestStart,
64
+ this.timing.requestStart + serverTime,
65
+ this.appInfo);
66
+ } else {
67
+ this.addBar('backend', '#c1d7ee', 'requestStart', 'responseEnd');
68
+ }
69
+
70
+ this.addBar('tcp / ssl', '#45688e', 'connectStart', 'connectEnd');
71
+ this.addBar('redirect', '#0c365e', 'redirectStart', 'redirectEnd');
72
+ this.addBar('dns', '#082541', 'domainLookupStart', 'domainLookupEnd');
73
+
74
+ return this.el;
75
+ }
76
+
77
+ // Determine if the page has reached the interactive state yet.
78
+ isLoaded() {
79
+ return this.timing.domInteractive;
80
+ }
81
+
82
+ // Integer unix timestamp representing the very beginning of the graph.
83
+ start() {
84
+ return this.timing.navigationStart;
85
+ }
86
+
87
+ // Integer unix timestamp representing the very end of the graph.
88
+ end() {
89
+ return this.timing.domInteractive;
90
+ }
91
+
92
+ // Total number of milliseconds between the start and end times.
93
+ total() {
94
+ return this.end() - this.start();
95
+ }
96
+
97
+ // Helper used to add a bar to the graph.
98
+ addBar(name, color, start, end, info) {
99
+ if (typeof start === 'string') { start = this.timing[start]; }
100
+ if (typeof end === 'string') { end = this.timing[end]; }
101
+
102
+ // Skip missing stats
103
+ if ((start == null) || (end == null)) { return; }
104
+
105
+ let time = end - start;
106
+ let offset = start - this.start();
107
+ let left = this.mapH(offset);
108
+ let width = this.mapH(time);
109
+
110
+ let title = `${name}: ${PerformanceBar.formatTime(time)}`;
111
+ let bar = $('<li></li>', {title, class: 'peek-tooltip'});
112
+ bar.css({
113
+ width: `${width}px`,
114
+ left: `${left}px`,
115
+ background: color
116
+ });
117
+ bar.tipsy({gravity: $.fn.tipsy.autoNS});
118
+ return this.el.append(bar);
119
+ }
120
+
121
+ // Map a time offset value to a horizontal pixel offset.
122
+ mapH(offset) {
123
+ return offset * (this.width / this.total());
124
+ }
125
+ }
126
+ PerformanceBar.initClass();
127
+
128
+ let renderPerformanceBar = function() {
129
+ let resp = $('#peek-server_response_time');
130
+ let time = Math.round(resp.data('time') * 1000);
131
+
132
+ let bar = new PerformanceBar;
133
+ bar.render(time);
134
+
135
+ let span = $('<span>', {'class': 'peek-tooltip', title: 'Total navigation time for this page.'})
136
+ .text(PerformanceBar.formatTime(bar.total()));
137
+ span.tipsy({gravity: $.fn.tipsy.autoNS});
138
+ return updateStatus(span);
139
+ };
140
+
141
+ var updateStatus = html => $('#serverstats').html(html);
142
+
143
+ let ajaxStart = null;
144
+ $(document).on('pjax:start page:fetch turbolinks:request-start', event => ajaxStart = event.timeStamp);
145
+
146
+ $(document).on('pjax:end page:load turbolinks:load', function(event, xhr) {
147
+ if (ajaxStart == null) { return; }
148
+ let ajaxEnd = event.timeStamp;
149
+ let total = ajaxEnd - ajaxStart;
150
+ let serverTime = xhr ? parseInt(xhr.getResponseHeader('X-Runtime')) : 0;
151
+
152
+ // Defer to include the timing of pjax hook evaluation
153
+ return setTimeout(function() {
154
+ let tech;
155
+ let now = new Date().getTime();
156
+ let bar = new PerformanceBar({
157
+ timing: {
158
+ requestStart: ajaxStart,
159
+ responseEnd: ajaxEnd,
160
+ domLoading: ajaxEnd,
161
+ domInteractive: now
162
+ },
163
+ isLoaded() { return true; },
164
+ start() { return ajaxStart; },
165
+ end() { return now; }
166
+ });
167
+
168
+ bar.render(serverTime);
169
+
170
+ if ($.fn.pjax != null) {
171
+ tech = 'PJAX';
172
+ } else {
173
+ tech = 'Turbolinks';
174
+ }
175
+
176
+ let span = $('<span>', {'class': 'peek-tooltip', title: `${tech} navigation time`})
177
+ .text(PerformanceBar.formatTime(total));
178
+ span.tipsy({gravity: $.fn.tipsy.autoNS});
179
+ updateStatus(span);
180
+
181
+ return ajaxStart = null;
182
+ }
183
+ , 0);
184
+ });
185
+
186
+ $(function() {
187
+ if (window.performance) {
188
+ return renderPerformanceBar();
189
+ } else {
190
+ return $('#peek-view-performance-bar').remove();
191
+ }
192
+ });
@@ -1,5 +1,5 @@
1
1
  module Peek
2
2
  module PerformanceBar
3
- VERSION = '1.2.1'
3
+ VERSION = '1.3.0'
4
4
  end
5
5
  end
@@ -1,3 +1,5 @@
1
+ require "rack/body_proxy"
2
+
1
3
  module Peek
2
4
  module Views
3
5
  class PerformanceBar
@@ -104,32 +106,6 @@ module Peek
104
106
  warn "ProcessUtilization#record_request failed: #{boom.inspect}"
105
107
  end
106
108
 
107
- # Body wrapper. Yields to the block when body is closed. This is used to
108
- # signal when a response is fully finished processing.
109
- class Body
110
- def initialize(body, &block)
111
- @body = body
112
- @block = block
113
- end
114
-
115
- def each(&block)
116
- @body.each(&block)
117
- end
118
-
119
- def close
120
- @body.close if @body.respond_to?(:close)
121
- @block.call
122
- nil
123
- end
124
-
125
- # Delegate calls to @body to be compatible with other middlewares
126
- def method_missing(name, *args, &block)
127
- super unless @body.respond_to?(name)
128
-
129
- @body.send(name, *args, &block)
130
- end
131
- end
132
-
133
109
  # Rack entry point.
134
110
  def call(env)
135
111
  @env = env
@@ -142,7 +118,7 @@ module Peek
142
118
  env['process.total_requests'] = total_requests
143
119
 
144
120
  status, headers, body = @app.call(env)
145
- body = Body.new(body) { record_request }
121
+ body = Rack::BodyProxy.new(body) { record_request }
146
122
  [status, headers, body]
147
123
  end
148
124
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peek-performance_bar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garrett Bjerkhoel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-04 00:00:00.000000000 Z
11
+ date: 2017-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: peek
@@ -37,7 +37,7 @@ files:
37
37
  - LICENSE.txt
38
38
  - README.md
39
39
  - Rakefile
40
- - app/assets/javascripts/peek/views/performance_bar.coffee
40
+ - app/assets/javascripts/peek/views/performance_bar.js
41
41
  - app/assets/stylesheets/peek/views/performance_bar.scss
42
42
  - app/helpers/peek/performance_bar_helper.rb
43
43
  - app/views/peek/results/_performance_bar.html.erb
@@ -67,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
67
  version: '0'
68
68
  requirements: []
69
69
  rubyforge_project:
70
- rubygems_version: 2.5.1
70
+ rubygems_version: 2.6.11
71
71
  signing_key:
72
72
  specification_version: 4
73
73
  summary: Take a peek into the MySQL queries made during your application's requests.
@@ -1,167 +0,0 @@
1
- # The mission control window.performance.timing display area.
2
- #
3
- # Breaks the window.performance.timing numbers down into these groups:
4
- #
5
- # dns - Time looking up domain. Usually zero.
6
- # tcp and ssl - Time used establishing tcp and ssl connections.
7
- # redirect - Time spent redirecting since navigation began.
8
- # app - Real server time as recorded in the app.
9
- # latency - Extra backend and network time where browser was waiting.
10
- # frontend - Time spent loading and rendering the DOM until interactive.
11
- #
12
- # Not all frontend time is counted. The page is considered ready when the
13
- # domInteractive ready state is reached. This is before DOMContentLoaded and
14
- # onload javascript handlers.
15
- class PerformanceBar
16
- # Additional app info to show with the app timing.
17
- appInfo: null
18
-
19
- # The pixel width we're rendering the timing graph into.
20
- width: null
21
-
22
- # Format a time as ms or s based on how big it is.
23
- @formatTime: (value) ->
24
- if value >= 1000
25
- "#{(value / 1000).toFixed(3)}s"
26
- else
27
- "#{value.toFixed(0)}ms"
28
-
29
- # Create a new PerformanceBar view bound to a given element. The el and width
30
- # options should be provided here.
31
- constructor: (options={}) ->
32
- @el = $('#peek-view-performance-bar .performance-bar')
33
- @[k] = v for k, v of options
34
- @width ?= @el.width()
35
- @timing ?= window.performance.timing
36
-
37
- # Render the performance bar in the associated element. This is a little weird
38
- # because it includes the server-side rendering time reported with the
39
- # response document which may not line up when using the back/forward button
40
- # and loading from cache.
41
- render: (serverTime=0) ->
42
- @el.empty()
43
- @addBar 'frontend', '#90d35b', 'domLoading', 'domInteractive'
44
-
45
- # time spent talking with the app according to performance.timing
46
- perfNetworkTime = (@timing.responseEnd - @timing.requestStart)
47
-
48
- # only include serverTime if it's less than than the browser reported
49
- # talking-to-the-app time; otherwise, assume we're loading from cache.
50
- if serverTime and serverTime <= perfNetworkTime
51
- networkTime = perfNetworkTime - serverTime
52
- @addBar 'latency / receiving', '#f1faff',
53
- @timing.requestStart + serverTime,
54
- @timing.requestStart + serverTime + networkTime
55
- @addBar 'app', '#90afcf',
56
- @timing.requestStart,
57
- @timing.requestStart + serverTime,
58
- @appInfo
59
- else
60
- @addBar 'backend', '#c1d7ee', 'requestStart', 'responseEnd'
61
-
62
- @addBar 'tcp / ssl', '#45688e', 'connectStart', 'connectEnd'
63
- @addBar 'redirect', '#0c365e', 'redirectStart', 'redirectEnd'
64
- @addBar 'dns', '#082541', 'domainLookupStart', 'domainLookupEnd'
65
-
66
- @el
67
-
68
- # Determine if the page has reached the interactive state yet.
69
- isLoaded: ->
70
- @timing.domInteractive
71
-
72
- # Integer unix timestamp representing the very beginning of the graph.
73
- start: ->
74
- @timing.navigationStart
75
-
76
- # Integer unix timestamp representing the very end of the graph.
77
- end: ->
78
- @timing.domInteractive
79
-
80
- # Total number of milliseconds between the start and end times.
81
- total: ->
82
- @end() - @start()
83
-
84
- # Helper used to add a bar to the graph.
85
- addBar: (name, color, start, end, info) ->
86
- start = @timing[start] if typeof start is 'string'
87
- end = @timing[end] if typeof end is 'string'
88
-
89
- # Skip missing stats
90
- return unless start? and end?
91
-
92
- time = end - start
93
- offset = start - @start()
94
- left = @mapH(offset)
95
- width = @mapH(time)
96
-
97
- title = "#{name}: #{PerformanceBar.formatTime(time)}"
98
- bar = $ '<li></li>', title: title, class: 'peek-tooltip'
99
- bar.css
100
- width: "#{width}px"
101
- left: "#{left}px"
102
- background: color
103
- bar.tipsy gravity: $.fn.tipsy.autoNS
104
- @el.append bar
105
-
106
- # Map a time offset value to a horizontal pixel offset.
107
- mapH: (offset) ->
108
- offset * (@width / @total())
109
-
110
- renderPerformanceBar = ->
111
- resp = $('#peek-server_response_time')
112
- time = Math.round(resp.data('time') * 1000)
113
-
114
- bar = new PerformanceBar
115
- bar.render time
116
-
117
- span = $('<span>', {'class': 'peek-tooltip', title: 'Total navigation time for this page.'})
118
- .text(PerformanceBar.formatTime(bar.total()))
119
- span.tipsy gravity: $.fn.tipsy.autoNS
120
- updateStatus span
121
-
122
- updateStatus = (html) ->
123
- $('#serverstats').html html
124
-
125
- ajaxStart = null
126
- $(document).on 'pjax:start page:fetch turbolinks:request-start', (event) ->
127
- ajaxStart = event.timeStamp
128
-
129
- $(document).on 'pjax:end page:load turbolinks:load', (event, xhr) ->
130
- return unless ajaxStart?
131
- ajaxEnd = event.timeStamp
132
- total = ajaxEnd - ajaxStart
133
- serverTime = if xhr then parseInt(xhr.getResponseHeader('X-Runtime')) else 0
134
-
135
- # Defer to include the timing of pjax hook evaluation
136
- setTimeout ->
137
- now = new Date().getTime()
138
- bar = new PerformanceBar
139
- timing:
140
- requestStart: ajaxStart,
141
- responseEnd: ajaxEnd,
142
- domLoading: ajaxEnd,
143
- domInteractive: now
144
- isLoaded: -> true
145
- start: -> ajaxStart
146
- end: -> now
147
-
148
- bar.render serverTime
149
-
150
- if $.fn.pjax?
151
- tech = 'PJAX'
152
- else
153
- tech = 'Turbolinks'
154
-
155
- span = $('<span>', {'class': 'peek-tooltip', title: "#{tech} navigation time"})
156
- .text(PerformanceBar.formatTime(total))
157
- span.tipsy gravity: $.fn.tipsy.autoNS
158
- updateStatus span
159
-
160
- ajaxStart = null
161
- , 0
162
-
163
- $ ->
164
- if window.performance
165
- renderPerformanceBar()
166
- else
167
- $('#peek-view-performance-bar').remove()