rack-mini-profiler 0.1.26 → 0.1.31

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack-mini-profiler might be problematic. Click here for more details.

@@ -4,7 +4,7 @@ module Rack
4
4
  class MiniProfiler
5
5
 
6
6
  class RequestTimerStruct < TimerStruct
7
-
7
+
8
8
  def self.createRoot(name, page)
9
9
  rt = RequestTimerStruct.new(name, page, nil)
10
10
  rt["IsRoot"]= true
@@ -77,7 +77,7 @@ module Rack
77
77
  self['SqlTimings'].push(timer)
78
78
  self['HasSqlTimings'] = true
79
79
  self['SqlTimingsDurationMilliseconds'] += elapsed_ms
80
- page['DurationMillisecondsInSql'] += elapsed_ms
80
+ page['DurationMillisecondsInSql'] += elapsed_ms
81
81
  timer
82
82
  end
83
83
 
@@ -103,13 +103,13 @@ module Rack
103
103
  self['DurationMilliseconds'] = milliseconds
104
104
  self['IsTrivial'] = true if milliseconds < self["TrivialDurationThresholdMilliseconds"]
105
105
  self['DurationWithoutChildrenMilliseconds'] = milliseconds - @children_duration
106
-
106
+
107
107
  if @parent
108
108
  @parent.children_duration += milliseconds
109
109
  end
110
110
 
111
- end
111
+ end
112
112
  end
113
113
  end
114
-
114
+
115
115
  end
@@ -8,7 +8,7 @@ module Rack
8
8
  def initialize(query, duration_ms, page, parent, skip_backtrace = false, full_backtrace = false)
9
9
 
10
10
  stack_trace = nil
11
- unless skip_backtrace
11
+ unless skip_backtrace || duration_ms < Rack::MiniProfiler.config.backtrace_threshold_ms
12
12
  # Allow us to filter the stack trace
13
13
  stack_trace = ""
14
14
  # Clean up the stack trace if there are options to do so
@@ -1,7 +1,7 @@
1
1
  module Rack
2
2
  class MiniProfiler
3
3
  class AbstractStore
4
-
4
+
5
5
  def save(page_struct)
6
6
  raise NotImplementedError.new("save is not implemented")
7
7
  end
@@ -23,9 +23,10 @@ module Rack
23
23
  end
24
24
 
25
25
  def diagnostics(user)
26
- raise NotImplementedError.new("diagnostics not implemented")
26
+ # this is opt in, no need to explode if not implemented
27
+ ""
27
28
  end
28
-
29
+
29
30
  end
30
31
  end
31
32
  end
@@ -3,7 +3,7 @@ module Rack
3
3
  class RedisStore < AbstractStore
4
4
 
5
5
  EXPIRES_IN_SECONDS = 60 * 60 * 24
6
-
6
+
7
7
  def initialize(args = nil)
8
8
  @args = args || {}
9
9
  @prefix = @args.delete(:prefix) || 'MPRedisStore'
@@ -12,7 +12,7 @@ module Rack
12
12
  end
13
13
 
14
14
  def save(page_struct)
15
- redis.setex "#{@prefix}#{page_struct['Id']}", @expires_in_seconds, Marshal::dump(page_struct)
15
+ redis.setex "#{@prefix}#{page_struct['Id']}", @expires_in_seconds, Marshal::dump(page_struct)
16
16
  end
17
17
 
18
18
  def load(id)
@@ -41,7 +41,7 @@ unviewed_ids: #{get_unviewed_ids(user)}
41
41
  "
42
42
  end
43
43
 
44
- private
44
+ private
45
45
 
46
46
  def redis
47
47
  return @redis_connection if @redis_connection
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class MiniProfiler
3
- VERSION = 'e777c6e0fdfb9a725e857c8ca3eab18f'.freeze
3
+ VERSION = '55905d0d15f4dc1e14b29260abce19b2'.freeze
4
4
  end
5
5
  end
@@ -200,7 +200,12 @@ if SqlPatches.class_exists?("RSolr::Connection") && RSolr::VERSION[0] != "0" #
200
200
 
201
201
  data = "#{request_context[:method].upcase} #{request_context[:uri]}"
202
202
  if request_context[:method] == :post and request_context[:data]
203
- data << "\n#{Rack::Utils.unescape(request_context[:data])}"
203
+ if request_context[:headers].include?("Content-Type") and request_context[:headers]["Content-Type"] == "text/xml"
204
+ # it's xml, unescaping isn't needed
205
+ data << "\n#{request_context[:data]}"
206
+ else
207
+ data << "\n#{Rack::Utils.unescape(request_context[:data])}"
208
+ end
204
209
  end
205
210
  result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(data, elapsed_time))
206
211
 
@@ -1,11 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rack-mini-profiler"
3
- s.version = "0.1.26"
3
+ s.version = "0.1.31"
4
4
  s.summary = "Profiles loading speed for rack applications."
5
5
  s.authors = ["Sam Saffron", "Robin Ward","Aleks Totic"]
6
6
  s.description = "Profiling toolkit for Rack applications with Rails integration. Client Side profiling, DB profiling and Server profiling."
7
7
  s.email = "sam.saffron@gmail.com"
8
8
  s.homepage = "http://miniprofiler.com"
9
+ s.license = "MIT"
9
10
  s.files = [
10
11
  'rack-mini-profiler.gemspec',
11
12
  ].concat( Dir.glob('Ruby/lib/**/*').reject {|f| File.directory?(f) || f =~ /~$/ } )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-mini-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.26
4
+ version: 0.1.31
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-04-11 00:00:00.000000000 Z
13
+ date: 2013-09-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -89,7 +89,6 @@ files:
89
89
  - Ruby/lib/html/includes.js
90
90
  - Ruby/lib/html/list.js
91
91
  - Ruby/lib/html/jquery.1.7.1.js
92
- - Ruby/lib/html/flamegraph.html
93
92
  - Ruby/lib/html/includes.css
94
93
  - Ruby/lib/mini_profiler/context.rb
95
94
  - Ruby/lib/mini_profiler/page_timer_struct.rb
@@ -103,20 +102,21 @@ files:
103
102
  - Ruby/lib/mini_profiler/gc_profiler.rb
104
103
  - Ruby/lib/mini_profiler/client_timer_struct.rb
105
104
  - Ruby/lib/mini_profiler/sql_timer_struct.rb
105
+ - Ruby/lib/mini_profiler/gc_profiler_ruby_head.rb
106
106
  - Ruby/lib/mini_profiler/config.rb
107
107
  - Ruby/lib/mini_profiler/custom_timer_struct.rb
108
108
  - Ruby/lib/mini_profiler/version.rb
109
109
  - Ruby/lib/mini_profiler/timer_struct.rb
110
110
  - Ruby/lib/mini_profiler/profiler.rb
111
111
  - Ruby/lib/mini_profiler/request_timer_struct.rb
112
- - Ruby/lib/mini_profiler/flame_graph.rb
113
112
  - Ruby/lib/patches/net_patches.rb
114
113
  - Ruby/lib/patches/sql_patches.rb
115
114
  - Ruby/lib/rack-mini-profiler.rb
116
115
  - Ruby/README.md
117
116
  - Ruby/CHANGELOG
118
117
  homepage: http://miniprofiler.com
119
- licenses: []
118
+ licenses:
119
+ - MIT
120
120
  metadata: {}
121
121
  post_install_message:
122
122
  rdoc_options: []
@@ -134,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
134
  version: '0'
135
135
  requirements: []
136
136
  rubyforge_project:
137
- rubygems_version: 2.0.2
137
+ rubygems_version: 2.0.3
138
138
  signing_key:
139
139
  specification_version: 4
140
140
  summary: Profiles loading speed for rack applications.
@@ -1,325 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
5
- <script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.0.8/d3.min.js"></script>
6
- <!-- <script src="http://cdnjs.cloudflare.com/ajax/libs/sugar/1.3.8/sugar.min.js"></script> -->
7
- <meta charset=utf-8 />
8
- <title>Flame Graph of Page</title>
9
- <style>
10
- .info {height: 40px;}
11
- .legend div {
12
- display: block;
13
- float: left;
14
- width: 150px;
15
- margin: 0 8px 8px;
16
- padding: 4px;
17
- height: 50px;
18
- }
19
- </style>
20
- </head>
21
- <body>
22
- <div class="graph"></div>
23
- <div class="info"></div>
24
- <div class="legend"></div>
25
-
26
- <script>
27
-
28
- var data = /*DATA*/;
29
- var maxX = 0;
30
- var maxY = 0;
31
-
32
- debounce = function(func, wait, trickle) {
33
- var timeout;
34
-
35
- timeout = null;
36
- return function() {
37
- var args, context, currentWait, later;
38
- context = this;
39
- args = arguments;
40
- later = function() {
41
- timeout = null;
42
- return func.apply(context, args);
43
- };
44
-
45
- if (timeout && trickle) {
46
- // already queued, let it through
47
- return;
48
- }
49
-
50
- if (typeof wait === "function") {
51
- currentWait = wait();
52
- } else {
53
- currentWait = wait;
54
- }
55
-
56
- if (timeout) {
57
- clearTimeout(timeout);
58
- }
59
-
60
- timeout = setTimeout(later, currentWait);
61
- return timeout;
62
- };
63
- };
64
-
65
-
66
- var guessGem = function(frame)
67
- {
68
- var split = frame.split('/gems/');
69
- if(split.length == 1) {
70
- split = frame.split('/app/');
71
- if(split.length == 1) {
72
- split = frame.split('/lib/');
73
- }
74
-
75
- split = split[Math.max(split.length-2,0)].split('/');
76
- return split[split.length-1];
77
- }
78
- else
79
- {
80
- return split[split.length -1].split('/')[0];
81
- }
82
- }
83
-
84
- var guessMethod = function(frame) {
85
- var split = frame.split('`');
86
- if(split.length == 2) {
87
- return split[1].split("'")[0];
88
- }
89
- return '?';
90
- }
91
-
92
- var guessFile = function(frame) {
93
- var split = frame.split(".rb:");
94
- if(split.length == 2) {
95
- split = split[0].split('/');
96
- return split[split.length - 1];
97
- }
98
- return "";
99
- }
100
-
101
- $.each(data, function(){
102
- maxX = Math.max(maxX, this.x + this.width);
103
- maxY = Math.max(maxY, this.y);
104
- this.shortName = /* guessGem(this.frame) + " " + guessFile(this.frame) + " " */ guessMethod(this.frame);
105
- });
106
-
107
- var width = $(window).width();
108
- var height = $(window).height() / 1.2;
109
-
110
- $('.graph').width(width).height(height);
111
-
112
- var xScale = d3.scale.linear()
113
- .domain([0, maxX])
114
- .range([0, width]);
115
-
116
- var yScale = d3.scale.linear()
117
- .domain([0, maxY])
118
- .range([0,height]);
119
-
120
- var realHeight = 0;
121
- var debouncedHeightCheck = debounce(function(){
122
- if (realHeight > 15) {
123
- svg.selectAll('text').attr('display','show');
124
- } else {
125
- svg.selectAll('text').attr('display','none');
126
- }
127
- }, 200);
128
-
129
- function zoom()
130
- {
131
- svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
132
-
133
- realHeight = yScale(1) * d3.event.scale;
134
- debouncedHeightCheck();
135
- }
136
-
137
- var svg = d3.select(".graph")
138
- .append("svg")
139
- .attr("width", "100%")
140
- .attr("height", "100%")
141
- .attr("pointer-events", "all")
142
- .append('svg:g')
143
- .call(d3.behavior.zoom().on("zoom", zoom))
144
- .append('svg:g');
145
-
146
-
147
- // so zoom works everywhere
148
- svg.append("rect")
149
- .attr("x",function(d) { return xScale(0); })
150
- .attr("y",function(d) { return yScale(0);})
151
- .attr("width", function(d){return xScale(maxX);})
152
- .attr("height", yScale(maxY))
153
- .attr("fill", "white");
154
-
155
- var color = function() {
156
- var r = parseInt(205 + Math.random() * 50);
157
- var g = parseInt(Math.random() * 230);
158
- var b = parseInt(Math.random() * 55);
159
- return "rgb(" + r + "," + g + "," + b + ")";
160
- }
161
- var info = {};
162
-
163
- // http://stackoverflow.com/questions/1960473/unique-values-in-an-array
164
- Array.prototype.getUnique = function() {
165
- var o = {}, a = []
166
- for (var i = 0; i < this.length; i++) o[this[i]] = 1
167
- for (var e in o) a.push(e)
168
- return a
169
- }
170
-
171
- var samplePercent = function(samples){
172
- return "(" + samples +
173
- " sample" + (samples == 1 ? "" : "s") + " - " +
174
- ((samples / maxX) * 100).toFixed(2) + "%)";
175
- }
176
-
177
- var mouseover = function(d) {
178
- var i = info[d.frame];
179
- $('.info').text( d.frame + " " + samplePercent(i.samples.length));
180
- d3.selectAll(i.nodes)
181
- .attr('opacity',0.5);
182
- };
183
-
184
- var mouseout = function(d) {
185
- var i = info[d.frame];
186
- $('.info').text("");
187
- d3.selectAll(i.nodes)
188
- .attr('opacity',1);
189
- };
190
-
191
- // http://stackoverflow.com/a/7419630
192
- var rainbow = function(numOfSteps, step) {
193
- // This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distiguishable vibrant markers in Google Maps and other apps.
194
- // Adam Cole, 2011-Sept-14
195
- // HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
196
- var r, g, b;
197
- var h = step / numOfSteps;
198
- var i = ~~(h * 6);
199
- var f = h * 6 - i;
200
- var q = 1 - f;
201
- switch(i % 6){
202
- case 0: r = 1, g = f, b = 0; break;
203
- case 1: r = q, g = 1, b = 0; break;
204
- case 2: r = 0, g = 1, b = f; break;
205
- case 3: r = 0, g = q, b = 1; break;
206
- case 4: r = f, g = 0, b = 1; break;
207
- case 5: r = 1, g = 0, b = q; break;
208
- }
209
- var c = "#" + ("00" + (~ ~(r * 255)).toString(16)).slice(-2) + ("00" + (~ ~(g * 255)).toString(16)).slice(-2) + ("00" + (~ ~(b * 255)).toString(16)).slice(-2);
210
- return (c);
211
- }
212
-
213
- // assign some colors, analyze samples per gem
214
- var gemStats = {}
215
-
216
- $.each(data, function(){
217
-
218
- var gem = guessGem(this.frame);
219
- var stat = gemStats[gem];
220
-
221
- if(!stat) {
222
- gemStats[gem] = stat = {samples: [], frames: []};
223
- }
224
-
225
- stat.frames.push(this.frame);
226
- for(var j=0; j < this.width; j++){
227
- stat.samples.push(this.x + j);
228
- }
229
- });
230
-
231
- var totalGems = 0;
232
- $.each(gemStats, function(){totalGems++;});
233
-
234
-
235
- var currentIndex = 0;
236
- $.each(gemStats, function(k,stat){
237
-
238
- stat.color = rainbow(totalGems, currentIndex);
239
- stat.samples = stat.samples.getUnique();
240
-
241
- for(var x=0; x < stat.frames.length; x++) {
242
- info[stat.frames[x]] = {nodes: [], samples: [], color: stat.color};
243
- }
244
-
245
- currentIndex += 1;
246
- });
247
-
248
-
249
- // see: http://bl.ocks.org/mundhradevang/1387786
250
- function fontSize(d,i) {
251
- var size = yScale(1) / 3;
252
- // var words = d.shortName.split(' ');
253
- var word = d.shortName; // words[0];
254
- var width = xScale(d.width+100);
255
- var height = yScale(1);
256
- var length = 0;
257
- d3.select(this).style("font-size", size + "px").text(word);
258
- while(((this.getBBox().width >= width) || (this.getBBox().height >= height)) && (size > 12))
259
- {
260
- size -= 0.1;
261
- d3.select(this).style("font-size", size + "px");
262
- }
263
-
264
- d3.select(this).attr("dy", size);
265
- }
266
-
267
- svg.selectAll("g")
268
- .data(data)
269
- .enter()
270
- .append("g")
271
- .each(function(){
272
- d3.select(this)
273
- .append("rect")
274
- .attr("x",function(d) { return xScale(d.x-1); })
275
- .attr("y",function(d) { return yScale(maxY - d.y);})
276
- .attr("width", function(d){return xScale(d.width);})
277
- .attr("height", yScale(1))
278
- .attr("fill", function(d){
279
- var i = info[d.frame];
280
- if(!i) {
281
- info[d.frame] = i = {nodes: [], samples: [], color: color()};
282
- }
283
- i.nodes.push(this);
284
- for(var j=0; j < d.width; j++){
285
- i.samples.push(d.x + j);
286
- }
287
- return i.color;
288
- })
289
- .on("mouseover", mouseover)
290
- .on("mouseout", mouseout);
291
-
292
- d3.select(this)
293
- .append("text")
294
- .attr("x",function(d) { return xScale(d.x - 0.98); })
295
- .attr("y",function(d) { return yScale(maxY - d.y);})
296
- .on("mouseover", mouseover)
297
- .on("mouseout", mouseout)
298
- .each(fontSize)
299
- .attr("display", "none");
300
-
301
- });
302
-
303
-
304
- // Samples may overlap on the same line
305
- for (var r in info) {
306
- if (info[r].samples) {
307
- info[r].samples = info[r].samples.getUnique();
308
- }
309
- };
310
-
311
-
312
- // render the legend
313
- $.each(gemStats, function(k,v){
314
- var node = $("<div></div>")
315
- .css("background-color", v.color)
316
- .text(k + " " + samplePercent(v.samples.length)) ;
317
- $('.legend').append(node);
318
- });
319
-
320
-
321
-
322
- </script>
323
- </body>
324
- </html>
325
-