rack-mini-profiler 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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