rack-mini-profiler 0.1.7 → 0.1.8

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.

data/CHANGELOG CHANGED
@@ -24,3 +24,9 @@
24
24
  * Added some more client probing built in to rails
25
25
  * More tests
26
26
 
27
+ 18-July-2012 - Sam
28
+
29
+ * Added First Paint time for chrome
30
+ * Bug fix to ensure non Rails installs have mini profiler
31
+ * Version 0.1.7
32
+
data/README.md CHANGED
@@ -47,6 +47,24 @@ class MyApp < Sinatra::Base
47
47
  end
48
48
  ```
49
49
 
50
+ ## Storage
51
+
52
+ By default, rack-mini-profiler stores its results in a memory store:
53
+
54
+ ```ruby
55
+ # our default
56
+ Rack::MiniProfiler.config.storage = Rack::MiniProfiler::MemoryStore
57
+ ```
58
+
59
+ There are 2 other available storage engines, `RedisStore` and `FileStore`.
60
+
61
+ MemoryStore is stores results in a processes heap - something that does not work well in a multi process environment.
62
+ FileStore stores results in the file system - something that may not work well in a multi machine environment.
63
+
64
+ Additionally you may implement an AbstractStore for your own provider.
65
+
66
+ Rails hooks up a FileStore for all environments.
67
+
50
68
  ## Running the Specs
51
69
 
52
70
  ```
@@ -1,6 +1,6 @@
1
- <script type="text/javascript">
1
+ <script type="text/javascript">
2
2
  (function(){{
3
- var init = function() {{
3
+ var init = function() {{
4
4
  var load = function(s,f){{
5
5
  var sc = document.createElement('script');
6
6
  sc.async = 'async';
@@ -14,8 +14,8 @@
14
14
  }};
15
15
 
16
16
  document.getElementsByTagName('head')[0].appendChild(sc);
17
- }};
18
-
17
+ }};
18
+
19
19
  var initMp = function(){{
20
20
  load('{path}includes.js?v={version}',function(){{
21
21
  MiniProfiler.init({{
@@ -32,18 +32,18 @@
32
32
  }});
33
33
  }});
34
34
  }};
35
- if ({useExistingjQuery}) {{
35
+ if ({useExistingjQuery} && typeof(jQuery) === 'function') {{
36
36
  jQueryMP = jQuery;
37
37
  initMp();
38
38
  }} else {{
39
39
  load('{path}jquery.1.7.1.js?v={version}', initMp);
40
40
  }}
41
-
41
+
42
42
  }};
43
43
 
44
- var w = 0;
44
+ var w = 0;
45
45
  var f = false;
46
- var deferInit = function(){{
46
+ var deferInit = function(){{
47
47
  if (f) return;
48
48
  if (window.performance && window.performance.timing && window.performance.timing.loadEventEnd == 0 && w < 10000){{
49
49
  setTimeout(deferInit, 100);
@@ -59,4 +59,4 @@
59
59
  var o = window.onload;
60
60
  window.onload = function(){{if(o)o; deferInit()}};
61
61
  }})();
62
- </script>
62
+ </script>
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <head>
3
+ <title>{name} ({duration} ms) - Profiling Results</title>
4
+ <script type='text/javascript' src='{path}jquery.1.7.1.js?v={version}'></script>
5
+ <script type='text/javascript'> var profiler = {json}; </script>
6
+ {includes}
7
+ </head>
8
+ <body>
9
+ <div class='profiler-result-full'></div>
10
+ </body>
11
+ </html>
@@ -23,7 +23,7 @@ module Rack
23
23
  super
24
24
  end
25
25
 
26
- def init_from_form_data(env, page_struct)
26
+ def self.init_from_form_data(env, page_struct)
27
27
  timings = []
28
28
  clientTimes, clientPerf, baseTime = nil
29
29
  form = env['rack.request.form_hash']
@@ -67,8 +67,10 @@ module Rack
67
67
  timings.push("Name" => k, "Start" => clientTimes[k].to_i - baseTime, "Duration" => -1)
68
68
  end
69
69
 
70
- self['RedirectCount'] = env['rack.request.form_hash']['clientPerformance']['navigation']['redirectCount']
71
- self['Timings'] = timings
70
+ rval = self.new
71
+ rval['RedirectCount'] = env['rack.request.form_hash']['clientPerformance']['navigation']['redirectCount']
72
+ rval['Timings'] = timings
73
+ rval
72
74
  end
73
75
  end
74
76
 
@@ -14,7 +14,7 @@ module Rack
14
14
 
15
15
  attr_accessor :auto_inject, :base_url_path, :pre_authorize_cb, :position,
16
16
  :backtrace_remove, :backtrace_filter, :skip_schema_queries,
17
- :storage, :user_provider, :storage_instance, :storage_options, :skip_paths, :authorization_mode
17
+ :storage, :user_provider, :storage_instance, :storage_options, :skip_paths, :authorization_mode, :use_existing_jquery
18
18
 
19
19
  def self.default
20
20
  new.instance_eval {
@@ -30,6 +30,7 @@ module Rack
30
30
  @storage = MiniProfiler::MemoryStore
31
31
  @user_provider = Proc.new{|env| Rack::Request.new(env).ip}
32
32
  @authorization_mode = :allow_all
33
+ @use_existing_jquery = false
33
34
  self
34
35
  }
35
36
  end
@@ -16,7 +16,7 @@ module Rack
16
16
  "Level" => 0,
17
17
  "User" => "unknown user",
18
18
  "HasUserViewed" => false,
19
- "ClientTimings" => ClientTimerStruct.new,
19
+ "ClientTimings" => nil,
20
20
  "DurationMilliseconds" => 0,
21
21
  "HasTrivialTimings" => true,
22
22
  "HasAllTrivialTimigs" => false,
@@ -6,7 +6,6 @@ require 'mini_profiler/page_timer_struct'
6
6
  require 'mini_profiler/sql_timer_struct'
7
7
  require 'mini_profiler/client_timer_struct'
8
8
  require 'mini_profiler/request_timer_struct'
9
- require 'mini_profiler/body_add_proxy'
10
9
  require 'mini_profiler/storage/abstract_store'
11
10
  require 'mini_profiler/storage/memory_store'
12
11
  require 'mini_profiler/storage/redis_store'
@@ -101,8 +100,9 @@ module Rack
101
100
  @app = app
102
101
  @config.base_url_path << "/" unless @config.base_url_path.end_with? "/"
103
102
  unless @config.storage_instance
104
- @storage = @config.storage_instance = @config.storage.new(@config.storage_options)
103
+ @config.storage_instance = @config.storage.new(@config.storage_options)
105
104
  end
105
+ @storage = @config.storage_instance
106
106
  end
107
107
 
108
108
  def user(env)
@@ -118,7 +118,7 @@ module Rack
118
118
  return [404, {}, ["Request not found: #{request['id']} - user #{user(env)}"]]
119
119
  end
120
120
  unless page_struct['HasUserViewed']
121
- page_struct['ClientTimings'].init_from_form_data(env, page_struct)
121
+ page_struct['ClientTimings'] = ClientTimerStruct.init_from_form_data(env, page_struct)
122
122
  page_struct['HasUserViewed'] = true
123
123
  @storage.save(page_struct)
124
124
  @storage.set_viewed(user(env), id)
@@ -151,8 +151,17 @@ module Rack
151
151
  return [404, {}, ["Not found"]] unless ::File.exists? full_path
152
152
  f = Rack::File.new nil
153
153
  f.path = full_path
154
- f.cache_control = "max-age:86400"
155
- f.serving env
154
+
155
+ begin
156
+ f.cache_control = "max-age:86400"
157
+ f.serving env
158
+ rescue
159
+ # old versions of rack have a different api
160
+ status, headers, body = f.serving
161
+ headers.merge! 'Cache-Control' => "max-age:86400"
162
+ [status, headers, body]
163
+ end
164
+
156
165
  end
157
166
 
158
167
 
@@ -245,7 +254,7 @@ module Rack
245
254
  end
246
255
 
247
256
  return [status,headers,body] if skip_it
248
-
257
+
249
258
  # we must do this here, otherwise current[:discard] is not being properly treated
250
259
  if env["QUERY_STRING"] =~ /pp=env/
251
260
  body.close if body.respond_to? :close
@@ -274,6 +283,12 @@ module Rack
274
283
  # inject headers, script
275
284
  if status == 200
276
285
 
286
+ # mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
287
+ # Rack::ETag has already inserted some nonesense in the chain
288
+ headers.delete('ETag')
289
+ headers.delete('Date')
290
+ headers['Cache-Control'] = 'must-revalidate, private, max-age=0'
291
+
277
292
  # inject header
278
293
  if headers.is_a? Hash
279
294
  headers['X-MiniProfiler-Ids'] = ids_json(env)
@@ -283,21 +298,29 @@ module Rack
283
298
  if current.inject_js \
284
299
  && headers.has_key?('Content-Type') \
285
300
  && !headers['Content-Type'].match(/text\/html/).nil? then
286
- body = MiniProfiler::BodyAddProxy.new(body, self.get_profile_script(env))
301
+
302
+ response = Rack::Response.new([], status, headers)
303
+ script = self.get_profile_script(env)
304
+ if String === body
305
+ response.write inject(body,script)
306
+ else
307
+ body.each { |fragment| response.write inject(fragment, script) }
308
+ end
309
+ body.close if body.respond_to? :close
310
+ return response.finish
287
311
  end
288
312
  end
289
313
 
290
- # mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
291
- # Rack::ETag has already inserted some nonesense in the chain
292
- headers.delete('ETag')
293
- headers.delete('Date')
294
- headers['Cache-Control'] = 'must-revalidate, private, max-age=0'
295
314
  [status, headers, body]
296
315
  ensure
297
316
  # Make sure this always happens
298
317
  current = nil
299
318
  end
300
319
 
320
+ def inject(fragment, script)
321
+ fragment.sub(/<\/body>/i, script + "</body>")
322
+ end
323
+
301
324
  def dump_env(env)
302
325
  headers = {'Content-Type' => 'text/plain'}
303
326
  body = ""
@@ -380,7 +403,7 @@ module Rack
380
403
  showControls = false
381
404
  currentId = current.page_struct["Id"]
382
405
  authorized = true
383
- useExistingjQuery = false
406
+ useExistingjQuery = @config.use_existing_jquery
384
407
  # TODO : cache this snippet
385
408
  script = IO.read(::File.expand_path('../html/profile_handler.js', ::File.dirname(__FILE__)))
386
409
  # replace the variables
@@ -39,9 +39,14 @@ module Rack
39
39
 
40
40
  me = self
41
41
  Thread.new do
42
- while true do
43
- me.cleanup_cache if MiniProfiler.instance
44
- sleep(3600)
42
+ begin
43
+ while true do
44
+ # TODO: a sane retry count before bailing
45
+ me.cleanup_cache
46
+ sleep(3600)
47
+ end
48
+ rescue
49
+ # don't crash the thread, we can clean up next time
45
50
  end
46
51
  end
47
52
  end
@@ -83,10 +88,6 @@ module Rack
83
88
  }
84
89
  end
85
90
 
86
-
87
- private
88
-
89
-
90
91
  def cleanup_cache
91
92
  files = Dir.entries(@path)
92
93
  @timer_struct_lock.synchronize {
@@ -52,10 +52,6 @@ module Rack
52
52
  }
53
53
  end
54
54
 
55
-
56
- private
57
-
58
-
59
55
  def cleanup_cache
60
56
  expire_older_than = ((Time.now.to_f - MiniProfiler::MemoryStore::EXPIRE_TIMER_CACHE) * 1000).to_i
61
57
  @timer_struct_lock.synchronize {
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  module MiniProfilerRails
2
4
 
3
5
  class Railtie < ::Rails::Railtie
@@ -22,7 +24,7 @@ module MiniProfilerRails
22
24
 
23
25
  # The file store is just so much less flaky
24
26
  tmp = Rails.root.to_s + "/tmp/miniprofiler"
25
- Dir::mkdir(tmp) unless File.exists?(tmp)
27
+ FileUtils.mkdir_p(tmp) unless File.exists?(tmp)
26
28
 
27
29
  c.storage_options = {:path => tmp}
28
30
  c.storage = Rack::MiniProfiler::FileStore
@@ -1,6 +1,6 @@
1
- require File.expand_path('mini_profiler/profiler', File.dirname(__FILE__) )
2
- require File.expand_path('patches/sql_patches', File.dirname(__FILE__) )
1
+ require 'mini_profiler/profiler'
2
+ require 'patches/sql_patches'
3
3
 
4
4
  if defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3
5
- require File.expand_path('mini_profiler_rails/railtie', File.dirname(__FILE__) )
5
+ require 'mini_profiler_rails/railtie'
6
6
  end
@@ -1,9 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rack-mini-profiler"
3
- s.version = "0.1.7"
3
+ s.version = "0.1.8"
4
4
  s.summary = "Profiles loading speed for rack applications."
5
5
  s.authors = ["Aleks Totic","Sam Saffron", "Robin Ward"]
6
- s.date = "2012-04-02"
7
6
  s.description = "Page loading speed displayed on every page. Optimize while you develop, performance is a feature."
8
7
  s.email = "sam.saffron@gmail.com"
9
8
  s.homepage = "http://miniprofiler.com"
@@ -14,9 +13,9 @@ Gem::Specification.new do |s|
14
13
  "README.md",
15
14
  "CHANGELOG"
16
15
  ]
17
- s.add_runtime_dependency 'rack', '>= 1.1.3'
16
+ s.add_runtime_dependency 'rack', '>= 1.1.3'
18
17
  if RUBY_VERSION < "1.9"
19
- s.add_runtime_dependency 'json', '>= 1.6'
18
+ s.add_runtime_dependency 'json', '>= 1.6'
20
19
  end
21
20
 
22
21
  s.add_development_dependency 'rake'
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.7
4
+ version: 0.1.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-04-02 00:00:00.000000000 Z
14
+ date: 2012-07-30 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rack
@@ -93,7 +93,6 @@ files:
93
93
  - lib/mini_profiler/page_timer_struct.rb
94
94
  - lib/mini_profiler/context.rb
95
95
  - lib/mini_profiler/config.rb
96
- - lib/mini_profiler/body_add_proxy.rb
97
96
  - lib/mini_profiler/profiling_methods.rb
98
97
  - lib/mini_profiler/client_timer_struct.rb
99
98
  - lib/mini_profiler/profiler.rb
@@ -104,6 +103,7 @@ files:
104
103
  - lib/rack-mini-profiler.rb
105
104
  - lib/html/jquery.1.7.1.js
106
105
  - lib/html/includes.tmpl
106
+ - lib/html/share.html
107
107
  - lib/html/includes.less
108
108
  - lib/html/list.css
109
109
  - lib/html/includes.js
@@ -130,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
130
  version: '0'
131
131
  segments:
132
132
  - 0
133
- hash: -348401747
133
+ hash: -902573215
134
134
  required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  none: false
136
136
  requirements:
@@ -139,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
139
  version: '0'
140
140
  segments:
141
141
  - 0
142
- hash: -348401747
142
+ hash: -902573215
143
143
  requirements: []
144
144
  rubyforge_project:
145
145
  rubygems_version: 1.8.24
@@ -1,45 +0,0 @@
1
- module Rack
2
- class MiniProfiler
3
-
4
- # This class acts as a proxy to the Body so that we can
5
- # safely append to the end without knowing about the internals
6
- # of the body class.
7
- class BodyAddProxy
8
- def initialize(body, additional_text)
9
- @body = body
10
- @additional_text = additional_text
11
- end
12
-
13
- def respond_to?(*args)
14
- super or @body.respond_to?(*args)
15
- end
16
-
17
- def method_missing(*args, &block)
18
- @body.__send__(*args, &block)
19
- end
20
-
21
- # In the case of to_str we don't want to use method_missing as it might avoid
22
- # a call to each (such as in Rack::Test)
23
- def to_str
24
- result = ""
25
- each {|token| result << token}
26
- result
27
- end
28
-
29
- def each(&block)
30
-
31
- # In ruby 1.9 we don't support String#each
32
- if @body.is_a?(String)
33
- yield @body
34
- else
35
- @body.each(&block)
36
- end
37
-
38
- yield @additional_text
39
- self
40
- end
41
-
42
- end
43
-
44
- end
45
- end