rack-mini-profiler 0.1.8 → 0.1.13.pre
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 +33 -0
- data/README.md +33 -0
- data/lib/html/includes.css +1 -1
- data/lib/html/includes.js +16 -9
- data/lib/html/includes.less +1 -1
- data/lib/html/includes.tmpl +2 -2
- data/lib/mini_profiler/client_settings.rb +65 -0
- data/lib/mini_profiler/client_timer_struct.rb +0 -0
- data/lib/mini_profiler/config.rb +1 -1
- data/lib/mini_profiler/context.rb +0 -0
- data/lib/mini_profiler/page_timer_struct.rb +0 -0
- data/lib/mini_profiler/profiler.rb +69 -45
- data/lib/mini_profiler/profiling_methods.rb +1 -2
- data/lib/mini_profiler/request_timer_struct.rb +0 -0
- data/lib/mini_profiler/sql_timer_struct.rb +11 -1
- data/lib/mini_profiler/storage/abstract_store.rb +0 -0
- data/lib/mini_profiler/storage/file_store.rb +0 -0
- data/lib/mini_profiler/storage/memory_store.rb +0 -1
- data/lib/mini_profiler/storage/redis_store.rb +0 -0
- data/lib/mini_profiler/timer_struct.rb +3 -1
- data/lib/mini_profiler_rails/railtie.rb +1 -1
- data/lib/patches/sql_patches.rb +46 -0
- data/lib/rack-mini-profiler.rb +0 -0
- data/rack-mini-profiler.gemspec +1 -1
- metadata +7 -9
data/CHANGELOG
CHANGED
@@ -30,3 +30,36 @@
|
|
30
30
|
* Bug fix to ensure non Rails installs have mini profiler
|
31
31
|
* Version 0.1.7
|
32
32
|
|
33
|
+
30-July-2012 - Sam
|
34
|
+
|
35
|
+
* Made compliant with ancient versions of Rack (including Rack used by Rails2)
|
36
|
+
* Fixed broken share link
|
37
|
+
* Fixed crashes on startup (in MemoryStore and FileStore)
|
38
|
+
* Version 0.1.8
|
39
|
+
* Unicode fix
|
40
|
+
* Version 0.1.9
|
41
|
+
|
42
|
+
7-August-2012 - Sam
|
43
|
+
|
44
|
+
* Added option to disable profiler for the current session (pp=disable / pp=enable)
|
45
|
+
* yajl compatability contributed by Sven Riedel
|
46
|
+
|
47
|
+
10-August-2012 - Sam
|
48
|
+
|
49
|
+
* Added basic prepared statement profiling for postgres
|
50
|
+
|
51
|
+
20-August-2012 - Sam
|
52
|
+
|
53
|
+
* 1.12.pre
|
54
|
+
* Cap X-MiniProfiler-Ids at 10, otherwise the header can get killed
|
55
|
+
|
56
|
+
3-September-2012 - Sam
|
57
|
+
|
58
|
+
* 1.13.pre
|
59
|
+
* pg gem prepared statements were not being logged correctly
|
60
|
+
* added setting config.backtrace_ignores = [] - an array of regexes that match on caller lines that get ignored
|
61
|
+
* added setting config.backtrace_includes = [] - an array of regexes that get included in the trace by default
|
62
|
+
* cleaned up the way client settings are stored
|
63
|
+
* made pp=full-backtrace "sticky"
|
64
|
+
* added pp=normal-backtrace to clear the "sticky" state
|
65
|
+
* change "pp=sample" to work with "caller" no need for stack trace gem
|
data/README.md
CHANGED
@@ -85,11 +85,44 @@ Rack::MiniProfiler.config.position = 'right'
|
|
85
85
|
|
86
86
|
In a Rails app, this can be done conveniently in an initializer such as config/initializers/mini_profiler.rb.
|
87
87
|
|
88
|
+
## Rails 2.X support
|
89
|
+
|
90
|
+
To get MiniProfiler working with Rails 2.3.X you need to do the initialization manually as well as monkey patch away an incompatibility between activesupport and json_pure.
|
91
|
+
|
92
|
+
Add the following code to your environment.rb (or just in a specific environment such as development.rb) for initialization and configuration of MiniProfiler.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# configure and initialize MiniProfiler
|
96
|
+
require 'rack-mini-profiler'
|
97
|
+
c = ::Rack::MiniProfiler.config
|
98
|
+
c.pre_authorize_cb = lambda { |env|
|
99
|
+
Rails.env.development? || Rails.env.production?
|
100
|
+
}
|
101
|
+
tmp = Rails.root.to_s + "/tmp/miniprofiler"
|
102
|
+
FileUtils.mkdir_p(tmp) unless File.exists?(tmp)
|
103
|
+
c.storage_options = {:path => tmp}
|
104
|
+
c.storage = ::Rack::MiniProfiler::FileStore
|
105
|
+
config.middleware.use(::Rack::MiniProfiler)
|
106
|
+
::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"}
|
107
|
+
::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{@virtual_path}"}
|
108
|
+
|
109
|
+
# monkey patch away an activesupport and json_pure incompatability
|
110
|
+
# http://pivotallabs.com/users/alex/blog/articles/1332-monkey-patch-of-the-day-activesupport-vs-json-pure-vs-ruby-1-8
|
111
|
+
if JSON.const_defined?(:Pure)
|
112
|
+
class JSON::Pure::Generator::State
|
113
|
+
include ActiveSupport::CoreExtensions::Hash::Except
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
88
118
|
## Available Options
|
89
119
|
|
90
120
|
* pre_authorize_cb - A lambda callback you can set to determine whether or not mini_profiler should be visible on a given request. Default in a Rails environment is only on in development mode. If in a Rack app, the default is always on.
|
91
121
|
* position - Can either be 'right' or 'left'. Default is 'left'.
|
92
122
|
* skip_schema_queries - Whether or not you want to log the queries about the schema of your tables. Default is 'false', 'true' in rails development.
|
123
|
+
* use_existing_jquery - Use the version of jQuery on the page as opposed to the self contained one
|
124
|
+
* auto_inject (default true) - when false the miniprofiler script is not injected in the page
|
125
|
+
* backtrace_filter - a regex you can use to filter out unwanted lines from the backtraces
|
93
126
|
|
94
127
|
## Special query strings
|
95
128
|
|
data/lib/html/includes.css
CHANGED
@@ -58,7 +58,7 @@
|
|
58
58
|
.profiler-results .profiler-popup .profiler-timings th,.profiler-results .profiler-popup .profiler-timings td{padding-left:6px;padding-right:6px;}
|
59
59
|
.profiler-results .profiler-popup .profiler-timings th{font-size:95%;padding-bottom:3px;}
|
60
60
|
.profiler-results .profiler-popup .profiler-timings .profiler-label{max-width:275px;}
|
61
|
-
.profiler-results .profiler-queries{display:none;z-index:2147483643;position:absolute;overflow-y:auto;overflow-x:
|
61
|
+
.profiler-results .profiler-queries{display:none;z-index:2147483643;position:absolute;overflow-y:auto;overflow-x:auto;background-color:#fff;}.profiler-results .profiler-queries th{font-size:17px;}
|
62
62
|
.profiler-results.profiler-min .profiler-result{display:none;}
|
63
63
|
.profiler-results.profiler-min .profiler-controls span{display:none;}
|
64
64
|
.profiler-results.profiler-min .profiler-controls .profiler-min-max{border-right:none;padding:0px;margin:0px;}
|
data/lib/html/includes.js
CHANGED
@@ -5,7 +5,8 @@ var MiniProfiler = (function ($) {
|
|
5
5
|
container,
|
6
6
|
controls,
|
7
7
|
fetchedIds = [],
|
8
|
-
fetchingIds = []
|
8
|
+
fetchingIds = [], // so we never pull down a profiler twice
|
9
|
+
ajaxStartTime
|
9
10
|
;
|
10
11
|
|
11
12
|
var hasLocalStorage = function () {
|
@@ -73,15 +74,15 @@ var MiniProfiler = (function ($) {
|
|
73
74
|
clientPerformance = null;
|
74
75
|
clientProbes = null;
|
75
76
|
|
76
|
-
if (
|
77
|
-
|
78
|
-
|
79
|
-
clientProbes =
|
80
|
-
for (j = 0; j < clientProbes.length; j++) {
|
81
|
-
clientProbes[j].d = clientProbes[j].d.getTime();
|
82
|
-
}
|
83
|
-
mPt.t = [];
|
77
|
+
if (window.mPt) {
|
78
|
+
clientProbes = mPt.results();
|
79
|
+
for (j = 0; j < clientProbes.length; j++) {
|
80
|
+
clientProbes[j].d = clientProbes[j].d.getTime();
|
84
81
|
}
|
82
|
+
mPt.flush();
|
83
|
+
}
|
84
|
+
|
85
|
+
if (id == options.currentId) {
|
85
86
|
|
86
87
|
clientPerformance = getClientPerformance();
|
87
88
|
|
@@ -113,6 +114,9 @@ var MiniProfiler = (function ($) {
|
|
113
114
|
|
114
115
|
}
|
115
116
|
}
|
117
|
+
} else if (ajaxStartTime != null && clientProbes.length > 0) {
|
118
|
+
clientPerformance = { timing: { navigationStart: ajaxStartTime.getTime() } };
|
119
|
+
ajaxStartTime = null;
|
116
120
|
}
|
117
121
|
|
118
122
|
if ($.inArray(id, fetchedIds) < 0 && $.inArray(id, fetchingIds) < 0) {
|
@@ -449,6 +453,9 @@ var MiniProfiler = (function ($) {
|
|
449
453
|
jQuery(document).ajaxComplete(jQueryAjaxComplete);
|
450
454
|
}
|
451
455
|
|
456
|
+
if (jQuery(document).ajaxStart)
|
457
|
+
jQuery(document).ajaxStart(function () { ajaxStartTime = new Date(); });
|
458
|
+
|
452
459
|
// fetch results after ASP Ajax calls
|
453
460
|
if (typeof (Sys) != 'undefined' && typeof (Sys.WebForms) != 'undefined' && typeof (Sys.WebForms.PageRequestManager) != 'undefined') {
|
454
461
|
// Get the instance of PageRequestManager.
|
data/lib/html/includes.less
CHANGED
data/lib/html/includes.tmpl
CHANGED
@@ -43,7 +43,7 @@
|
|
43
43
|
{{if HasSqlTimings}}
|
44
44
|
<td colspan="2" class="profiler-number profiler-percent-in-sql" title="${MiniProfiler.getSqlTimingsCount(Root)} queries spent ${MiniProfiler.formatDuration(DurationMillisecondsInSql)} ms of total request time">
|
45
45
|
${MiniProfiler.formatDuration(DurationMillisecondsInSql / DurationMilliseconds * 100)}
|
46
|
-
<span class="profiler-unit">% in
|
46
|
+
<span class="profiler-unit">% in qry</span>
|
47
47
|
</td>
|
48
48
|
{{/if}}
|
49
49
|
</tr>
|
@@ -141,7 +141,7 @@
|
|
141
141
|
<td class="profiler-duration {{if HasDuplicateSqlTimings}}profiler-warning{{/if}}" title="{{if HasDuplicateSqlTimings}}duplicate queries detected - {{/if}}${ExecutedReaders} reader, ${ExecutedScalars} scalar, ${ExecutedNonQueries} non-query statements executed">
|
142
142
|
<a class="profiler-queries-show">
|
143
143
|
{{if HasDuplicateSqlTimings}}<span class="profiler-nuclear">!</span>{{/if}}
|
144
|
-
${SqlTimings.length} <span class="profiler-unit">
|
144
|
+
${SqlTimings.length} <span class="profiler-unit">qry</span>
|
145
145
|
</a>
|
146
146
|
</td>
|
147
147
|
<td class="profiler-duration" title="aggregate duration of all queries in this step (excludes children)">
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Rack
|
2
|
+
class MiniProfiler
|
3
|
+
class ClientSettings
|
4
|
+
|
5
|
+
COOKIE_NAME = "__profilin"
|
6
|
+
|
7
|
+
BACKTRACE_DEFAULT = nil
|
8
|
+
BACKTRACE_FULL = 1
|
9
|
+
BACKTRACE_NONE = 2
|
10
|
+
|
11
|
+
attr_accessor :disable_profiling
|
12
|
+
attr_accessor :backtrace_level
|
13
|
+
|
14
|
+
|
15
|
+
def initialize(env)
|
16
|
+
request = ::Rack::Request.new(env)
|
17
|
+
@cookie = request.cookies[COOKIE_NAME]
|
18
|
+
if @cookie
|
19
|
+
@cookie.split(",").map{|pair| pair.split("=")}.each do |k,v|
|
20
|
+
@orig_disable_profiling = @disable_profiling = (v=='t') if k == "dp"
|
21
|
+
@backtrace_level = v.to_i if k == "bt"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
@backtrace_level = nil if !@backtrace_level.nil? && (@backtrace_level == 0 || @backtrace_level > BACKTRACE_NONE)
|
26
|
+
@orig_backtrace_level = @backtrace_level
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def write!(headers)
|
31
|
+
if @orig_disable_profiling != @disable_profiling || @orig_backtrace_level != @backtrace_level || @cookie.nil?
|
32
|
+
settings = {"p" => "t" }
|
33
|
+
settings["dp"] = "t" if @disable_profiling
|
34
|
+
settings["bt"] = @backtrace_level if @backtrace_level
|
35
|
+
settings_string = settings.map{|k,v| "#{k}=#{v}"}.join(",")
|
36
|
+
Rack::Utils.set_cookie_header!(headers, COOKIE_NAME, :value => settings_string)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def discard_cookie!(headers)
|
41
|
+
Rack::Utils.delete_cookie_header!(headers, COOKIE_NAME)
|
42
|
+
end
|
43
|
+
|
44
|
+
def has_cookie?
|
45
|
+
!@cookie.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
def disable_profiling?
|
49
|
+
@disable_profiling
|
50
|
+
end
|
51
|
+
|
52
|
+
def backtrace_full?
|
53
|
+
@backtrace_level == BACKTRACE_FULL
|
54
|
+
end
|
55
|
+
|
56
|
+
def backtrace_default?
|
57
|
+
@backtrace_level == BACKTRACE_DEFAULT
|
58
|
+
end
|
59
|
+
|
60
|
+
def backtrace_none?
|
61
|
+
@backtrace_level == BACKTRACE_NONE
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
File without changes
|
data/lib/mini_profiler/config.rb
CHANGED
@@ -13,7 +13,7 @@ module Rack
|
|
13
13
|
end
|
14
14
|
|
15
15
|
attr_accessor :auto_inject, :base_url_path, :pre_authorize_cb, :position,
|
16
|
-
:backtrace_remove, :
|
16
|
+
:backtrace_remove, :backtrace_includes, :backtrace_ignores, :skip_schema_queries,
|
17
17
|
:storage, :user_provider, :storage_instance, :storage_options, :skip_paths, :authorization_mode, :use_existing_jquery
|
18
18
|
|
19
19
|
def self.default
|
File without changes
|
File without changes
|
@@ -13,6 +13,7 @@ require 'mini_profiler/storage/file_store'
|
|
13
13
|
require 'mini_profiler/config'
|
14
14
|
require 'mini_profiler/profiling_methods'
|
15
15
|
require 'mini_profiler/context'
|
16
|
+
require 'mini_profiler/client_settings'
|
16
17
|
|
17
18
|
module Rack
|
18
19
|
|
@@ -56,20 +57,6 @@ module Rack
|
|
56
57
|
self.current.discard = true if current
|
57
58
|
end
|
58
59
|
|
59
|
-
# user has the mini profiler cookie, only used when config.authorization_mode == :whitelist
|
60
|
-
def has_profiling_cookie?(env)
|
61
|
-
env['HTTP_COOKIE'] && env['HTTP_COOKIE'].include?("__profilin=stylin")
|
62
|
-
end
|
63
|
-
|
64
|
-
# remove the mini profiler cookie, only used when config.authorization_mode == :whitelist
|
65
|
-
def remove_profiling_cookie(headers)
|
66
|
-
Rack::Utils.delete_cookie_header!(headers, '__profilin')
|
67
|
-
end
|
68
|
-
|
69
|
-
def set_profiling_cookie(headers)
|
70
|
-
Rack::Utils.set_cookie_header!(headers, '__profilin', 'stylin')
|
71
|
-
end
|
72
|
-
|
73
60
|
def create_current(env={}, options={})
|
74
61
|
# profiling the request
|
75
62
|
self.current = Context.new
|
@@ -180,54 +167,75 @@ module Rack
|
|
180
167
|
|
181
168
|
|
182
169
|
def call(env)
|
170
|
+
|
171
|
+
client_settings = ClientSettings.new(env)
|
172
|
+
|
183
173
|
status = headers = body = nil
|
174
|
+
query_string = env['QUERY_STRING']
|
184
175
|
path = env['PATH_INFO']
|
185
176
|
|
186
177
|
skip_it = (@config.pre_authorize_cb && !@config.pre_authorize_cb.call(env)) ||
|
187
178
|
(@config.skip_paths && @config.skip_paths.any?{ |p| path[0,p.length] == p}) ||
|
188
|
-
|
179
|
+
query_string =~ /pp=skip/
|
189
180
|
|
190
|
-
has_profiling_cookie =
|
181
|
+
has_profiling_cookie = client_settings.has_cookie?
|
191
182
|
|
192
183
|
if skip_it || (@config.authorization_mode == :whitelist && !has_profiling_cookie)
|
193
184
|
status,headers,body = @app.call(env)
|
194
185
|
if !skip_it && @config.authorization_mode == :whitelist && !has_profiling_cookie && MiniProfiler.request_authorized?
|
195
|
-
|
186
|
+
client_settings.write!(headers)
|
196
187
|
end
|
197
188
|
return [status,headers,body]
|
198
189
|
end
|
199
190
|
|
200
191
|
# handle all /mini-profiler requests here
|
201
|
-
return serve_html(env) if
|
192
|
+
return serve_html(env) if path.start_with? @config.base_url_path
|
193
|
+
|
194
|
+
has_disable_cookie = client_settings.disable_profiling?
|
195
|
+
# manual session disable / enable
|
196
|
+
if query_string =~ /pp=disable/ || has_disable_cookie
|
197
|
+
skip_it = true
|
198
|
+
end
|
199
|
+
|
200
|
+
if query_string =~ /pp=enable/
|
201
|
+
skip_it = false
|
202
|
+
end
|
203
|
+
|
204
|
+
if skip_it
|
205
|
+
status,headers,body = @app.call(env)
|
206
|
+
client_settings.disable_profiling = true
|
207
|
+
client_settings.write!(headers)
|
208
|
+
return [status,headers,body]
|
209
|
+
end
|
202
210
|
|
203
211
|
MiniProfiler.create_current(env, @config)
|
204
212
|
MiniProfiler.deauthorize_request if @config.authorization_mode == :whitelist
|
205
|
-
if
|
213
|
+
if query_string =~ /pp=normal-backtrace/
|
214
|
+
client_settings.backtrace_level = ClientSettings::BACKTRACE_DEFAULT
|
215
|
+
elsif query_string =~ /pp=no-backtrace/
|
206
216
|
current.skip_backtrace = true
|
207
|
-
|
217
|
+
client_settings.backtrace_level = ClientSettings::BACKTRACE_NONE
|
218
|
+
elsif query_string =~ /pp=full-backtrace/ || client_settings.backtrace_full?
|
208
219
|
current.full_backtrace = true
|
220
|
+
client_settings.backtrace_level = ClientSettings::BACKTRACE_FULL
|
221
|
+
elsif client_settings.backtrace_none?
|
222
|
+
current.skip_backtrace = true
|
209
223
|
end
|
210
224
|
|
211
225
|
done_sampling = false
|
212
226
|
quit_sampler = false
|
213
227
|
backtraces = nil
|
214
228
|
missing_stacktrace = false
|
215
|
-
if
|
229
|
+
if query_string =~ /pp=sample/
|
216
230
|
backtraces = []
|
217
231
|
t = Thread.current
|
218
232
|
Thread.new {
|
219
233
|
begin
|
220
|
-
require 'stacktrace' rescue nil
|
221
|
-
if !t.respond_to? :stacktrace
|
222
|
-
missing_stacktrace = true
|
223
|
-
quit_sampler = true
|
224
|
-
return
|
225
|
-
end
|
226
234
|
i = 10000 # for sanity never grab more than 10k samples
|
227
235
|
while i > 0
|
228
236
|
break if done_sampling
|
229
237
|
i -= 1
|
230
|
-
backtraces << t.
|
238
|
+
backtraces << t.backtrace
|
231
239
|
sleep 0.001
|
232
240
|
end
|
233
241
|
ensure
|
@@ -240,6 +248,7 @@ module Rack
|
|
240
248
|
start = Time.now
|
241
249
|
begin
|
242
250
|
status,headers,body = @app.call(env)
|
251
|
+
client_settings.write!(headers)
|
243
252
|
ensure
|
244
253
|
if backtraces
|
245
254
|
done_sampling = true
|
@@ -249,21 +258,21 @@ module Rack
|
|
249
258
|
|
250
259
|
skip_it = current.discard
|
251
260
|
if (config.authorization_mode == :whitelist && !MiniProfiler.request_authorized?)
|
252
|
-
|
261
|
+
client_settings.discard_cookie!(headers)
|
253
262
|
skip_it = true
|
254
263
|
end
|
255
264
|
|
256
265
|
return [status,headers,body] if skip_it
|
257
266
|
|
258
267
|
# we must do this here, otherwise current[:discard] is not being properly treated
|
259
|
-
if
|
268
|
+
if query_string =~ /pp=env/
|
260
269
|
body.close if body.respond_to? :close
|
261
270
|
return dump_env env
|
262
271
|
end
|
263
272
|
|
264
|
-
if
|
273
|
+
if query_string =~ /pp=help/
|
265
274
|
body.close if body.respond_to? :close
|
266
|
-
return help
|
275
|
+
return help(nil, client_settings)
|
267
276
|
end
|
268
277
|
|
269
278
|
page_struct = current.page_struct
|
@@ -271,7 +280,7 @@ module Rack
|
|
271
280
|
|
272
281
|
if backtraces
|
273
282
|
body.close if body.respond_to? :close
|
274
|
-
return help(:stacktrace) if missing_stacktrace
|
283
|
+
return help(:stacktrace, client_settings) if missing_stacktrace
|
275
284
|
return analyze(backtraces, page_struct)
|
276
285
|
end
|
277
286
|
|
@@ -282,6 +291,8 @@ module Rack
|
|
282
291
|
|
283
292
|
# inject headers, script
|
284
293
|
if status == 200
|
294
|
+
|
295
|
+
client_settings.write!(headers)
|
285
296
|
|
286
297
|
# mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
|
287
298
|
# Rack::ETag has already inserted some nonesense in the chain
|
@@ -311,6 +322,7 @@ module Rack
|
|
311
322
|
end
|
312
323
|
end
|
313
324
|
|
325
|
+
client_settings.write!(headers)
|
314
326
|
[status, headers, body]
|
315
327
|
ensure
|
316
328
|
# Make sure this always happens
|
@@ -318,7 +330,15 @@ module Rack
|
|
318
330
|
end
|
319
331
|
|
320
332
|
def inject(fragment, script)
|
321
|
-
fragment.sub(/<\/body>/i
|
333
|
+
fragment.sub(/<\/body>/i) do
|
334
|
+
# if for whatever crazy reason we dont get a utf string,
|
335
|
+
# just force the encoding, no utf in the mp scripts anyway
|
336
|
+
if script.respond_to?(:encoding) && script.respond_to?(:force_encoding)
|
337
|
+
(script + "</body>").force_encoding(fragment.encoding)
|
338
|
+
else
|
339
|
+
script + "</body>"
|
340
|
+
end
|
341
|
+
end
|
322
342
|
end
|
323
343
|
|
324
344
|
def dump_env(env)
|
@@ -330,21 +350,25 @@ module Rack
|
|
330
350
|
[200, headers, [body]]
|
331
351
|
end
|
332
352
|
|
333
|
-
def help(category = nil)
|
353
|
+
def help(category = nil, client_settings)
|
334
354
|
headers = {'Content-Type' => 'text/plain'}
|
335
355
|
body = "Append the following to your query string:
|
336
356
|
|
337
357
|
pp=help : display this screen
|
338
358
|
pp=env : display the rack environment
|
339
359
|
pp=skip : skip mini profiler for this request
|
340
|
-
pp=no-backtrace : don't collect stack traces from all the SQL executed
|
341
|
-
pp=
|
342
|
-
pp=
|
360
|
+
pp=no-backtrace #{"(*) " if client_settings.backtrace_none?}: don't collect stack traces from all the SQL executed (sticky, use pp=normal-backtrace to enable)
|
361
|
+
pp=normal-backtrace #{"(*) " if client_settings.backtrace_default?}: collect stack traces from all the SQL executed and filter normally
|
362
|
+
pp=full-backtrace #{"(*) " if client_settings.backtrace_full?}: enable full backtraces for SQL executed (use pp=normal-backtrace to disable)
|
363
|
+
pp=sample : sample stack traces and return a report isolating heavy usage (experimental)
|
364
|
+
pp=disable : disable profiling for this session
|
365
|
+
pp=enable : enable profiling for this session (if previously disabled)
|
343
366
|
"
|
344
367
|
if (category == :stacktrace)
|
345
368
|
body = "pp=stacktrace requires the stacktrace gem - add gem 'stacktrace' to your Gemfile"
|
346
369
|
end
|
347
370
|
|
371
|
+
client_settings.write!(headers)
|
348
372
|
[200, headers, [body]]
|
349
373
|
end
|
350
374
|
|
@@ -358,13 +382,12 @@ module Rack
|
|
358
382
|
fulldump << "\n\n"
|
359
383
|
distinct = {}
|
360
384
|
trace.each do |frame|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
seen[
|
365
|
-
seen[name] += 1
|
385
|
+
unless distinct[frame]
|
386
|
+
distinct[frame] = true
|
387
|
+
seen[frame] ||= 0
|
388
|
+
seen[frame] += 1
|
366
389
|
end
|
367
|
-
fulldump <<
|
390
|
+
fulldump << frame << "\n"
|
368
391
|
end
|
369
392
|
end
|
370
393
|
|
@@ -382,7 +405,8 @@ module Rack
|
|
382
405
|
end
|
383
406
|
|
384
407
|
def ids_json(env)
|
385
|
-
ids
|
408
|
+
# cap at 10 ids, otherwise there is a chance you can blow the header
|
409
|
+
ids = [current.page_struct["Id"]] + (@storage.get_unviewed_ids(user(env)) || [])[0..8]
|
386
410
|
::JSON.generate(ids.uniq)
|
387
411
|
end
|
388
412
|
|
@@ -9,7 +9,7 @@ module Rack
|
|
9
9
|
end
|
10
10
|
|
11
11
|
# perform a profiling step on given block
|
12
|
-
def step(name)
|
12
|
+
def step(name, opts = nil)
|
13
13
|
if current
|
14
14
|
parent_timer = current.current_timer
|
15
15
|
result = nil
|
@@ -20,7 +20,6 @@ module Rack
|
|
20
20
|
current_timer.record_time
|
21
21
|
current.current_timer = parent_timer
|
22
22
|
end
|
23
|
-
result
|
24
23
|
else
|
25
24
|
yield if block_given?
|
26
25
|
end
|
File without changes
|
@@ -14,7 +14,17 @@ module Rack
|
|
14
14
|
# Clean up the stack trace if there are options to do so
|
15
15
|
Kernel.caller.each do |ln|
|
16
16
|
ln.gsub!(Rack::MiniProfiler.config.backtrace_remove, '') if Rack::MiniProfiler.config.backtrace_remove and !full_backtrace
|
17
|
-
if
|
17
|
+
if full_backtrace or
|
18
|
+
(
|
19
|
+
(
|
20
|
+
Rack::MiniProfiler.config.backtrace_includes.nil? or
|
21
|
+
Rack::MiniProfiler.config.backtrace_includes.all?{|regex| ln =~ regex}
|
22
|
+
) and
|
23
|
+
(
|
24
|
+
Rack::MiniProfiler.config.backtrace_ignores.nil? or
|
25
|
+
Rack::MiniProfiler.config.backtrace_ignores.all?{|regex| !(ln =~ regex)}
|
26
|
+
)
|
27
|
+
)
|
18
28
|
stack_trace << ln << "\n"
|
19
29
|
end
|
20
30
|
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -22,7 +22,9 @@ module Rack
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def to_json(*a)
|
25
|
-
|
25
|
+
# this does could take in an option hash, but the only interesting there is max_nesting.
|
26
|
+
# if this becomes an option we could increase
|
27
|
+
::JSON.generate( @attributes, :max_nesting => 100 )
|
26
28
|
end
|
27
29
|
|
28
30
|
end
|
@@ -31,7 +31,7 @@ module MiniProfilerRails
|
|
31
31
|
|
32
32
|
# Quiet the SQL stack traces
|
33
33
|
c.backtrace_remove = Rails.root.to_s + "/"
|
34
|
-
c.
|
34
|
+
c.backtrace_includes = [/^\/?(app|config|lib|test)/]
|
35
35
|
c.skip_schema_queries = Rails.env != 'production'
|
36
36
|
|
37
37
|
# Install the Middleware
|
data/lib/patches/sql_patches.rb
CHANGED
@@ -91,6 +91,24 @@ if SqlPatches.class_exists? "PG::Result"
|
|
91
91
|
class PG::Connection
|
92
92
|
alias_method :exec_without_profiling, :exec
|
93
93
|
alias_method :async_exec_without_profiling, :async_exec
|
94
|
+
alias_method :exec_prepared_without_profiling, :exec_prepared
|
95
|
+
alias_method :send_query_prepared_without_profiling, :send_query_prepared
|
96
|
+
alias_method :prepare_without_profiling, :prepare
|
97
|
+
|
98
|
+
def prepare(*args,&blk)
|
99
|
+
# we have no choice but to do this here,
|
100
|
+
# if we do the check for profiling first, our cache may miss critical stuff
|
101
|
+
|
102
|
+
@prepare_map ||= {}
|
103
|
+
@prepare_map[args[0]] = args[1]
|
104
|
+
# dont leak more than 10k ever
|
105
|
+
@prepare_map = {} if @prepare_map.length > 1000
|
106
|
+
|
107
|
+
current = ::Rack::MiniProfiler.current
|
108
|
+
return prepare_without_profiling(*args,&blk) unless current
|
109
|
+
|
110
|
+
prepare_without_profiling(*args,&blk)
|
111
|
+
end
|
94
112
|
|
95
113
|
def exec(*args,&blk)
|
96
114
|
current = ::Rack::MiniProfiler.current
|
@@ -104,6 +122,34 @@ if SqlPatches.class_exists? "PG::Result"
|
|
104
122
|
result
|
105
123
|
end
|
106
124
|
|
125
|
+
def exec_prepared(*args,&blk)
|
126
|
+
current = ::Rack::MiniProfiler.current
|
127
|
+
return exec_prepared_without_profiling(*args,&blk) unless current
|
128
|
+
|
129
|
+
start = Time.now
|
130
|
+
result = exec_prepared_without_profiling(*args,&blk)
|
131
|
+
elapsed_time = ((Time.now - start).to_f * 1000).round(1)
|
132
|
+
mapped = args[0]
|
133
|
+
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
134
|
+
result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(mapped, elapsed_time))
|
135
|
+
|
136
|
+
result
|
137
|
+
end
|
138
|
+
|
139
|
+
def send_query_prepared(*args,&blk)
|
140
|
+
current = ::Rack::MiniProfiler.current
|
141
|
+
return send_query_prepared_without_profiling(*args,&blk) unless current
|
142
|
+
|
143
|
+
start = Time.now
|
144
|
+
result = send_query_prepared_without_profiling(*args,&blk)
|
145
|
+
elapsed_time = ((Time.now - start).to_f * 1000).round(1)
|
146
|
+
mapped = args[0]
|
147
|
+
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
148
|
+
result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(mapped, elapsed_time))
|
149
|
+
|
150
|
+
result
|
151
|
+
end
|
152
|
+
|
107
153
|
def async_exec(*args,&blk)
|
108
154
|
current = ::Rack::MiniProfiler.current
|
109
155
|
return exec_without_profiling(*args,&blk) unless current
|
data/lib/rack-mini-profiler.rb
CHANGED
File without changes
|
data/rack-mini-profiler.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "rack-mini-profiler"
|
3
|
-
s.version = "0.1.
|
3
|
+
s.version = "0.1.13.pre"
|
4
4
|
s.summary = "Profiles loading speed for rack applications."
|
5
5
|
s.authors = ["Aleks Totic","Sam Saffron", "Robin Ward"]
|
6
6
|
s.description = "Page loading speed displayed on every page. Optimize while you develop, performance is a feature."
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-mini-profiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.13.pre
|
5
|
+
prerelease: 7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Aleks Totic
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-09-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rack
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- lib/mini_profiler/request_timer_struct.rb
|
92
92
|
- lib/mini_profiler/timer_struct.rb
|
93
93
|
- lib/mini_profiler/page_timer_struct.rb
|
94
|
+
- lib/mini_profiler/client_settings.rb
|
94
95
|
- lib/mini_profiler/context.rb
|
95
96
|
- lib/mini_profiler/config.rb
|
96
97
|
- lib/mini_profiler/profiling_methods.rb
|
@@ -130,16 +131,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
131
|
version: '0'
|
131
132
|
segments:
|
132
133
|
- 0
|
133
|
-
hash: -
|
134
|
+
hash: -879601329
|
134
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
136
|
none: false
|
136
137
|
requirements:
|
137
|
-
- - ! '
|
138
|
+
- - ! '>'
|
138
139
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
140
|
-
segments:
|
141
|
-
- 0
|
142
|
-
hash: -902573215
|
140
|
+
version: 1.3.1
|
143
141
|
requirements: []
|
144
142
|
rubyforge_project:
|
145
143
|
rubygems_version: 1.8.24
|