rack-mini-profiler 0.9.8 → 0.9.9
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/README.md +40 -19
- data/lib/html/includes.css +12 -0
- data/lib/html/includes.js +53 -18
- data/lib/html/includes.less +17 -3
- data/lib/html/profile_handler.js +1 -1
- data/lib/mini_profiler/asset_version.rb +1 -1
- data/lib/mini_profiler/config.rb +2 -1
- data/lib/mini_profiler/gc_profiler.rb +18 -22
- data/lib/mini_profiler/profiler.rb +47 -63
- data/lib/mini_profiler/profiling_methods.rb +17 -11
- data/lib/mini_profiler/storage/file_store.rb +2 -0
- data/lib/mini_profiler/timer_struct/page.rb +8 -0
- data/lib/mini_profiler/timer_struct/request.rb +8 -0
- data/lib/mini_profiler/timer_struct/sql.rb +2 -2
- data/lib/mini_profiler/version.rb +1 -1
- data/lib/mini_profiler_rails/railtie.rb +17 -10
- data/lib/patches/db/activerecord.rb +2 -0
- data/lib/patches/db/mongo.rb +5 -1
- data/lib/patches/db/neo4j.rb +14 -0
- data/lib/patches/db/riak.rb +103 -0
- data/lib/patches/sql_patches.rb +3 -1
- data/rack-mini-profiler.gemspec +1 -1
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 09e877779936ca60a9be72fc14ae574a450cd338
|
4
|
+
data.tar.gz: b53fc49ccabb1d8560c0ee8014199388fbf6749a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5b9ced034cd204f59eb4be61c718a97960fed72a7e4484af99748b9ed62eb7a736a7ebc78668b46b71f743432c53758ced36f918a1c31859c7f965917f0c826
|
7
|
+
data.tar.gz: 3c97726e0f276ff8b1bd3cf220f64f4b9908ca950b4485f6c9978c05d3479582aa166314e0dbc2afb2c1cb478ebb6801f1459a9cb4bcc51df7cec7826ee96356
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
##
|
4
|
+
|
5
|
+
## 0.9.9 2016-03-06
|
6
|
+
|
7
|
+
- [FIX] removes alias_method_chain in favor of alias_method until Ruby 1.9.3 (@ayfredlund)
|
8
|
+
- [FIX] Dont block mongo when already patched for another db (@rrooding @kbrock)
|
9
|
+
- [FIX] get_profile_script when running under passenger configured with RailsBaseURI (@nspring)
|
10
|
+
- [FEATURE] Add support for neo4j (@ProGM)
|
11
|
+
- [FIX] ArgumentError: comparison of String with 200 failed (@paweljw)
|
12
|
+
- [FEATURE] Add support for Riak (@janx)
|
13
|
+
- [PERF] GC profiler much faster (@dgynn)
|
14
|
+
- [FIX] If local storage is disabled don't bomb out (@elia)
|
15
|
+
- [FIX] Create tmp directory when actually using it (@kbrock)
|
16
|
+
- [ADDED] Default collapse_results setting that collapses multiple timings on same page to a single one (@sam)
|
17
|
+
- [ADDED] Rack::MiniProfiler.profile_singleton_method (@kbrock)
|
18
|
+
- [CHANGE] Added Rack 2.0 support (and dropped support for Rack 1.1) (@dgynn)
|
19
|
+
|
3
20
|
## 0.9.8 - 2015-11-27 (Sam Saffron)
|
4
21
|
|
5
22
|
- [FEATURE] disable_env_dump config setting (@mathias)
|
data/README.md
CHANGED
@@ -66,11 +66,17 @@ end
|
|
66
66
|
|
67
67
|
```ruby
|
68
68
|
require 'rack-mini-profiler'
|
69
|
+
|
70
|
+
home = lambda { |env|
|
71
|
+
[200, {'Content-Type' => 'text/html'}, ["<html><body>hello!</body></html>"]]
|
72
|
+
}
|
73
|
+
|
69
74
|
builder = Rack::Builder.new do
|
70
75
|
use Rack::MiniProfiler
|
71
|
-
|
72
|
-
map('/') { run get }
|
76
|
+
map('/') { run home }
|
73
77
|
end
|
78
|
+
|
79
|
+
run builder
|
74
80
|
```
|
75
81
|
|
76
82
|
#### Sinatra
|
@@ -145,11 +151,11 @@ if Rails.env.production?
|
|
145
151
|
end
|
146
152
|
```
|
147
153
|
|
148
|
-
MemoryStore stores results in a processes heap - something that does not work well in a multi process environment.
|
149
|
-
FileStore stores results in the file system - something that may not work well in a multi machine environment.
|
150
|
-
RedisStore
|
154
|
+
`MemoryStore` stores results in a processes heap - something that does not work well in a multi process environment.
|
155
|
+
`FileStore` stores results in the file system - something that may not work well in a multi machine environment.
|
156
|
+
`RedisStore`/`MemcacheStore` work in multi process and multi machine environments (`RedisStore` only saves results for up to 24 hours so it won't continue to fill up Redis).
|
151
157
|
|
152
|
-
Additionally you may implement an AbstractStore for your own provider.
|
158
|
+
Additionally you may implement an `AbstractStore` for your own provider.
|
153
159
|
|
154
160
|
### User result segregation
|
155
161
|
|
@@ -167,6 +173,17 @@ Rack::MiniProfiler.config.user_provider = Proc.new{ |env| CurrentUser.get(env) }
|
|
167
173
|
|
168
174
|
The string this function returns should be unique for each user on the system (for anonymous you may need to fall back to ip address)
|
169
175
|
|
176
|
+
### Profiling specific methods
|
177
|
+
|
178
|
+
You can increase the granularity of profiling by measuring the performance of specific methods. Add methods of interest to an initializer.
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
Rails.application.config.to_prepare do
|
182
|
+
::Rack::MiniProfiler.profile_singleton_method(User, :non_admins) { |a| "executing all_non_admins" }
|
183
|
+
::Rack::MiniProfiler.profile_method(User, :favorite_post) { |a| "executing favorite_post" }
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
170
187
|
### Configuration Options
|
171
188
|
|
172
189
|
You can set configuration options using the configuration accessor on `Rack::MiniProfiler`.
|
@@ -178,19 +195,23 @@ Rack::MiniProfiler.config.start_hidden = true
|
|
178
195
|
```
|
179
196
|
The available configuration options are:
|
180
197
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
198
|
+
Option|Default|Description
|
199
|
+
-------|---|--------
|
200
|
+
pre_authorize_cb|Rails: dev only<br>Rack: always on|A lambda callback that returns true to make mini_profiler visible on a given request.
|
201
|
+
position|`'left'`|Display mini_profiler on `'right'` or `'left'`.
|
202
|
+
skip_paths|`[]`|Paths that skip profiling.
|
203
|
+
skip_schema_queries|Rails dev: `'true'`<br>Othwerwise: `'false'`|`'true'` to log schema queries.
|
204
|
+
auto_inject|`true`|`true` to inject the miniprofiler script in the page.
|
205
|
+
backtrace_ignores|`[]`|Regexes of lines to be removed from backtraces.
|
206
|
+
backtrace_includes|Rails: `[/^\/?(app|config|lib|test)/]`<br>Rack: `[]`|Regexes of lines to keep in backtraces.
|
207
|
+
backtrace_remove|rails: `Rails.root`<br>Rack: `nil`|A string or regex to remove part of each line in the backtrace.
|
208
|
+
toggle_shortcut|Alt+P|Keyboard shortcut to toggle the mini_profiler's visibility. See [jquery.hotkeys](https://github.com/jeresig/jquery.hotkeys).
|
209
|
+
start_hidden|`false`|`false` to make mini_profiler visible on page load.
|
210
|
+
backtrace_threshold_ms|`0`|Minimum SQL query elapsed time before a backtrace is recorded. Backtrace recording can take a couple of milliseconds on rubies earlier than 2.0, impacting performance for very small queries.
|
211
|
+
flamegraph_sample_rate|`0.5ms`|How often to capture stack traces for flamegraphs.
|
212
|
+
disable_env_dump|`false`|`true` disables `?pp=env`, which prevents sending ENV vars over HTTP.
|
213
|
+
base_url_path|`'/mini-profiler-resources/'`|Path for assets; added as a prefix when naming assets and sought when responding to requests.
|
214
|
+
collapse_results|`true`|If multiple timing results exist in a single page, collapse them till clicked.
|
194
215
|
|
195
216
|
### Custom middleware ordering (required if using `Rack::Deflate` with Rails)
|
196
217
|
|
data/lib/html/includes.css
CHANGED
@@ -267,6 +267,7 @@
|
|
267
267
|
.profiler-results.profiler-left {
|
268
268
|
left: 0px;
|
269
269
|
}
|
270
|
+
.profiler-results.profiler-left.profiler-no-controls .profiler-totals,
|
270
271
|
.profiler-results.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button,
|
271
272
|
.profiler-results.profiler-left .profiler-controls {
|
272
273
|
-webkit-border-bottom-right-radius: 10px;
|
@@ -280,6 +281,7 @@
|
|
280
281
|
.profiler-results.profiler-right {
|
281
282
|
right: 0px;
|
282
283
|
}
|
284
|
+
.profiler-results.profiler-right.profiler-no-controls .profiler-totals,
|
283
285
|
.profiler-results.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button,
|
284
286
|
.profiler-results.profiler-right .profiler-controls {
|
285
287
|
-webkit-border-bottom-left-radius: 10px;
|
@@ -316,6 +318,16 @@
|
|
316
318
|
color: #fff;
|
317
319
|
font-weight: normal;
|
318
320
|
}
|
321
|
+
.profiler-results .profiler-totals .profiler-reqs {
|
322
|
+
font-family: Consolas, monospace, serif;
|
323
|
+
font-size: 10px;
|
324
|
+
margin-left: 6px;
|
325
|
+
}
|
326
|
+
.profiler-results .profiler-totals .profiler-reqs:before {
|
327
|
+
font-family: Consolas, monospace, serif;
|
328
|
+
content: "×";
|
329
|
+
margin-right: 1px;
|
330
|
+
}
|
319
331
|
.profiler-results .profiler-controls {
|
320
332
|
display: block;
|
321
333
|
font-size: 12px;
|
data/lib/html/includes.js
CHANGED
@@ -10,9 +10,12 @@ var MiniProfiler = (function () {
|
|
10
10
|
ajaxStartTime
|
11
11
|
;
|
12
12
|
|
13
|
-
var hasLocalStorage = function () {
|
13
|
+
var hasLocalStorage = function (keyPrefix) {
|
14
14
|
try {
|
15
|
-
|
15
|
+
// attempt to save to localStorage as Safari private windows will throw an error
|
16
|
+
localStorage[keyPrefix+'-test'] = '1';
|
17
|
+
localStorage.removeItem(keyPrefix+'-test');
|
18
|
+
return 'localStorage' in window && window['localStorage'] !== null ;
|
16
19
|
} catch (e) {
|
17
20
|
return false;
|
18
21
|
}
|
@@ -23,7 +26,7 @@ var MiniProfiler = (function () {
|
|
23
26
|
};
|
24
27
|
|
25
28
|
var save = function (keyPrefix, value) {
|
26
|
-
if (!hasLocalStorage()) { return; }
|
29
|
+
if (!hasLocalStorage(keyPrefix)) { return; }
|
27
30
|
|
28
31
|
// clear old keys with this prefix, if any
|
29
32
|
for (var i = 0; i < localStorage.length; i++) {
|
@@ -37,7 +40,7 @@ var MiniProfiler = (function () {
|
|
37
40
|
};
|
38
41
|
|
39
42
|
var load = function (keyPrefix) {
|
40
|
-
if (!hasLocalStorage()) { return null; }
|
43
|
+
if (!hasLocalStorage(keyPrefix)) { return null; }
|
41
44
|
|
42
45
|
return localStorage[getVersionedKey(keyPrefix)];
|
43
46
|
};
|
@@ -62,7 +65,7 @@ var MiniProfiler = (function () {
|
|
62
65
|
};
|
63
66
|
|
64
67
|
var getClientPerformance = function() {
|
65
|
-
return window.performance
|
68
|
+
return window.performance === null ? null : window.performance;
|
66
69
|
};
|
67
70
|
|
68
71
|
var fetchResults = function (ids) {
|
@@ -86,7 +89,7 @@ var MiniProfiler = (function () {
|
|
86
89
|
|
87
90
|
clientPerformance = getClientPerformance();
|
88
91
|
|
89
|
-
if (clientPerformance
|
92
|
+
if (clientPerformance !== null) {
|
90
93
|
// ie is buggy strip out functions
|
91
94
|
var copy = { navigation: {}, timing: {} };
|
92
95
|
|
@@ -114,7 +117,7 @@ var MiniProfiler = (function () {
|
|
114
117
|
|
115
118
|
}
|
116
119
|
}
|
117
|
-
} else if (ajaxStartTime
|
120
|
+
} else if (ajaxStartTime !== null && clientProbes && clientProbes.length > 0) {
|
118
121
|
clientPerformance = { timing: { navigationStart: ajaxStartTime.getTime() } };
|
119
122
|
ajaxStartTime = null;
|
120
123
|
}
|
@@ -146,9 +149,39 @@ var MiniProfiler = (function () {
|
|
146
149
|
return $('#profilerTemplate').tmpl(json);
|
147
150
|
};
|
148
151
|
|
152
|
+
var totalsControl;
|
153
|
+
var reqs = 0;
|
154
|
+
var totalTime = 0;
|
155
|
+
|
149
156
|
var buttonShow = function (json) {
|
150
157
|
var result = renderTemplate(json);
|
151
158
|
|
159
|
+
totalTime += parseFloat(json.duration_milliseconds, 10);
|
160
|
+
reqs++;
|
161
|
+
|
162
|
+
if (!controls && reqs > 1 && options.collapseResults) {
|
163
|
+
if (!totalsControl) {
|
164
|
+
container.find('.profiler-result').hide();
|
165
|
+
|
166
|
+
totalsControl = $("<div class='profiler-result'><div class='profiler-button profiler-totals'></div></div>");
|
167
|
+
totalsControl.appendTo(container);
|
168
|
+
totalsControl.click(function(){
|
169
|
+
totalsControl.parent().find('.profiler-result').show();
|
170
|
+
totalsControl.hide();
|
171
|
+
options.collapseResults = false;
|
172
|
+
});
|
173
|
+
|
174
|
+
totalsControl.find('.profiler-button').show();
|
175
|
+
}
|
176
|
+
|
177
|
+
var reqsHtml = reqs > 1 ? ("<span class='profiler-reqs'>" + reqs + "</span>") : "";
|
178
|
+
totalsControl.find('.profiler-button').html("<span class='profiler-number'>" +
|
179
|
+
totalTime.toFixed(1) + "</span> <span class='profiler-unit'>ms</span>" +
|
180
|
+
reqsHtml);
|
181
|
+
|
182
|
+
result.hide();
|
183
|
+
}
|
184
|
+
|
152
185
|
if (controls)
|
153
186
|
result.insertBefore(controls);
|
154
187
|
else
|
@@ -480,7 +513,7 @@ var MiniProfiler = (function () {
|
|
480
513
|
PageRequestManager.add_endRequest(function (sender, args) {
|
481
514
|
if (args) {
|
482
515
|
var response = args.get_response();
|
483
|
-
if (response.get_responseAvailable() && response._xmlHttpRequest
|
516
|
+
if (response.get_responseAvailable() && response._xmlHttpRequest !== null) {
|
484
517
|
var stringIds = args.get_response().getResponseHeader('X-MiniProfiler-Ids');
|
485
518
|
if (stringIds) {
|
486
519
|
var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds);
|
@@ -557,14 +590,14 @@ var MiniProfiler = (function () {
|
|
557
590
|
}
|
558
591
|
}
|
559
592
|
|
560
|
-
if (this.miniprofiler.prev_onreadystatechange
|
593
|
+
if (this.miniprofiler.prev_onreadystatechange !== null)
|
561
594
|
return this.miniprofiler.prev_onreadystatechange.apply(this, arguments);
|
562
595
|
};
|
563
596
|
}
|
564
597
|
}
|
565
598
|
|
566
599
|
return _send.apply(this, arguments);
|
567
|
-
}
|
600
|
+
};
|
568
601
|
}
|
569
602
|
|
570
603
|
// some elements want to be hidden on certain doc events
|
@@ -594,11 +627,12 @@ var MiniProfiler = (function () {
|
|
594
627
|
var maxTraces = parseInt(script.getAttribute('data-max-traces'), 10);
|
595
628
|
}
|
596
629
|
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
630
|
+
var collapseResults = script.getAttribute('data-collapse-results') === 'true';
|
631
|
+
var trivial = script.getAttribute('data-trivial') === 'true';
|
632
|
+
var children = script.getAttribute('data-children') === 'true';
|
633
|
+
var controls = script.getAttribute('data-controls') === 'true';
|
634
|
+
var authorized = script.getAttribute('data-authorized') === 'true';
|
635
|
+
var startHidden = script.getAttribute('data-start-hidden') === 'true';
|
602
636
|
|
603
637
|
return {
|
604
638
|
ids: ids,
|
@@ -612,7 +646,8 @@ var MiniProfiler = (function () {
|
|
612
646
|
currentId: currentId,
|
613
647
|
authorized: authorized,
|
614
648
|
toggleShortcut: toggleShortcut,
|
615
|
-
startHidden: startHidden
|
649
|
+
startHidden: startHidden,
|
650
|
+
collapseResults: collapseResults
|
616
651
|
};
|
617
652
|
})();
|
618
653
|
|
@@ -842,7 +877,7 @@ var MiniProfiler = (function () {
|
|
842
877
|
var processTimes = function (elem, parent) {
|
843
878
|
var duration = { start: elem.start_milliseconds, finish: (elem.start_milliseconds + elem.duration_milliseconds) };
|
844
879
|
elem.richTiming = [duration];
|
845
|
-
if (parent
|
880
|
+
if (parent !== null) {
|
846
881
|
elem.parent = parent;
|
847
882
|
elem.parent.richTiming = removeDuration(elem.parent.richTiming, duration);
|
848
883
|
}
|
@@ -877,7 +912,7 @@ var MiniProfiler = (function () {
|
|
877
912
|
|
878
913
|
var determineGap = function (gap, node, match) {
|
879
914
|
var overlap = determineOverlap(gap, node);
|
880
|
-
if (match
|
915
|
+
if (match === null || overlap > match.duration) {
|
881
916
|
match = { name: node.name, duration: overlap };
|
882
917
|
}
|
883
918
|
else if (match.name == node.name) {
|
data/lib/html/includes.less
CHANGED
@@ -247,7 +247,7 @@
|
|
247
247
|
}
|
248
248
|
|
249
249
|
// ajaxed-in results will be appended to this
|
250
|
-
.profiler-results
|
250
|
+
.profiler-results
|
251
251
|
{
|
252
252
|
z-index:@zindex + 3;
|
253
253
|
position:fixed;
|
@@ -258,7 +258,7 @@
|
|
258
258
|
&.profiler-left {
|
259
259
|
left:0px;
|
260
260
|
|
261
|
-
&.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
|
261
|
+
&.profiler-no-controls .profiler-totals, &.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
|
262
262
|
-webkit-border-bottom-right-radius: @radius;
|
263
263
|
-moz-border-radius-bottomright: @radius;
|
264
264
|
border-bottom-right-radius: @radius;
|
@@ -272,7 +272,7 @@
|
|
272
272
|
&.profiler-right {
|
273
273
|
right:0px;
|
274
274
|
|
275
|
-
&.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
|
275
|
+
&.profiler-no-controls .profiler-totals, &.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
|
276
276
|
-webkit-border-bottom-left-radius: @radius;
|
277
277
|
-moz-border-radius-bottomleft: @radius;
|
278
278
|
border-bottom-left-radius: @radius;
|
@@ -306,6 +306,20 @@
|
|
306
306
|
}
|
307
307
|
}
|
308
308
|
|
309
|
+
|
310
|
+
.profiler-totals {
|
311
|
+
.profiler-reqs {
|
312
|
+
font-family: @codeFonts;
|
313
|
+
font-size: 10px;
|
314
|
+
margin-left: 6px;
|
315
|
+
&:before {
|
316
|
+
font-family: @codeFonts;
|
317
|
+
content: "×";
|
318
|
+
margin-right: 1px;
|
319
|
+
}
|
320
|
+
}
|
321
|
+
}
|
322
|
+
|
309
323
|
.profiler-controls {
|
310
324
|
display: block;
|
311
325
|
font-size:12px;
|
data/lib/html/profile_handler.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<script async type="text/javascript" id="mini-profiler" src="{path}includes.js?v={version}" data-version="{version}" data-path="{path}" data-current-id="{currentId}" data-ids="{ids}" data-position="{position}" data-trivial="{showTrivial}" data-children="{showChildren}" data-max-traces="{maxTracesToShow}" data-controls="{showControls}" data-authorized="{authorized}" data-toggle-shortcut="{toggleShortcut}" data-start-hidden="{startHidden}"></script>
|
1
|
+
<script async type="text/javascript" id="mini-profiler" src="{path}includes.js?v={version}" data-version="{version}" data-path="{path}" data-current-id="{currentId}" data-ids="{ids}" data-position="{position}" data-trivial="{showTrivial}" data-children="{showChildren}" data-max-traces="{maxTracesToShow}" data-controls="{showControls}" data-authorized="{authorized}" data-toggle-shortcut="{toggleShortcut}" data-start-hidden="{startHidden}" data-collapse-results="{collapseResults}"></script>
|
data/lib/mini_profiler/config.rb
CHANGED
@@ -18,7 +18,7 @@ module Rack
|
|
18
18
|
:flamegraph_sample_rate, :logger, :position, :pre_authorize_cb,
|
19
19
|
:skip_paths, :skip_schema_queries, :start_hidden, :storage,
|
20
20
|
:storage_failure, :storage_instance, :storage_options, :toggle_shortcut,
|
21
|
-
:user_provider
|
21
|
+
:user_provider, :collapse_results
|
22
22
|
|
23
23
|
# Deprecated options
|
24
24
|
attr_accessor :use_existing_jquery
|
@@ -48,6 +48,7 @@ module Rack
|
|
48
48
|
end
|
49
49
|
@enabled = true
|
50
50
|
@disable_env_dump = false
|
51
|
+
@collapse_results = true
|
51
52
|
self
|
52
53
|
}
|
53
54
|
end
|
@@ -6,18 +6,15 @@ class Rack::MiniProfiler::GCProfiler
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def object_space_stats
|
9
|
-
stats =
|
10
|
-
ids =
|
9
|
+
stats = Hash.new(0).compare_by_identity
|
10
|
+
ids = Hash.new.compare_by_identity
|
11
11
|
|
12
12
|
@ignore << stats.__id__
|
13
13
|
@ignore << ids.__id__
|
14
14
|
|
15
|
-
i=0
|
16
15
|
ObjectSpace.each_object { |o|
|
17
16
|
begin
|
18
|
-
|
19
|
-
i += 1
|
20
|
-
stats[o.class] = i
|
17
|
+
stats[o.class] += 1
|
21
18
|
ids[o.__id__] = o if Integer === o.__id__
|
22
19
|
rescue NoMethodError
|
23
20
|
# protect against BasicObject
|
@@ -38,12 +35,12 @@ class Rack::MiniProfiler::GCProfiler
|
|
38
35
|
end
|
39
36
|
|
40
37
|
def diff_object_stats(before, after)
|
41
|
-
diff = {}
|
38
|
+
diff = {}.compare_by_identity
|
42
39
|
after.each do |k,v|
|
43
|
-
diff[k] = v -
|
40
|
+
diff[k] = v - before[k]
|
44
41
|
end
|
45
42
|
before.each do |k,v|
|
46
|
-
diff[k] = 0 - v unless after
|
43
|
+
diff[k] = 0 - v unless after.has_key?(k)
|
47
44
|
end
|
48
45
|
|
49
46
|
diff
|
@@ -97,11 +94,6 @@ class Rack::MiniProfiler::GCProfiler
|
|
97
94
|
# for memsize_of
|
98
95
|
require 'objspace'
|
99
96
|
|
100
|
-
body = [];
|
101
|
-
|
102
|
-
stat_before,stat_after,diff,string_analysis,
|
103
|
-
new_objects, memory_allocated, stat, memory_before, objects_before = nil
|
104
|
-
|
105
97
|
# clean up before
|
106
98
|
GC.start
|
107
99
|
stat = GC.stat
|
@@ -118,13 +110,17 @@ class Rack::MiniProfiler::GCProfiler
|
|
118
110
|
new_objects, memory_allocated = analyze_growth(stat_before[:ids], stat_after[:ids])
|
119
111
|
objects_before, memory_before = analyze_initial_state(stat_before[:ids])
|
120
112
|
|
113
|
+
body = []
|
121
114
|
|
122
115
|
body << "
|
123
116
|
Overview
|
124
|
-
|
125
|
-
Initial state: object count
|
117
|
+
--------
|
118
|
+
Initial state: object count: #{objects_before}
|
119
|
+
Memory allocated outside heap (bytes): #{memory_before}
|
126
120
|
|
127
|
-
GC Stats:
|
121
|
+
GC Stats:
|
122
|
+
--------
|
123
|
+
#{stat.map{|k,v| "#{k} : #{v}" }.sort!.join("\n")}
|
128
124
|
|
129
125
|
New bytes allocated outside of Ruby heaps: #{memory_allocated}
|
130
126
|
New objects: #{new_objects}
|
@@ -132,16 +128,16 @@ New objects: #{new_objects}
|
|
132
128
|
|
133
129
|
body << "
|
134
130
|
ObjectSpace delta caused by request:
|
135
|
-
|
136
|
-
diff.to_a.
|
137
|
-
body << "#{k} : #{v}\n"
|
131
|
+
-----------------------------------\n"
|
132
|
+
diff.to_a.delete_if{|_k, v| v == 0}.sort_by! { |_k, v| v }.reverse_each do |k,v|
|
133
|
+
body << "#{k} : #{v}\n"
|
138
134
|
end
|
139
135
|
|
140
136
|
body << "\n
|
141
137
|
ObjectSpace stats:
|
142
138
|
-----------------\n"
|
143
139
|
|
144
|
-
stat_after[:stats].to_a.
|
140
|
+
stat_after[:stats].to_a.sort_by!{ |_k, v| v }.reverse_each do |k,v|
|
145
141
|
body << "#{k} : #{v}\n"
|
146
142
|
end
|
147
143
|
|
@@ -150,7 +146,7 @@ ObjectSpace stats:
|
|
150
146
|
String stats:
|
151
147
|
------------\n"
|
152
148
|
|
153
|
-
string_analysis.to_a.
|
149
|
+
string_analysis.to_a.sort_by!{ |_k, v| -v }.take(1000).each do |string,count|
|
154
150
|
body << "#{count} : #{string}\n"
|
155
151
|
end
|
156
152
|
|
@@ -17,6 +17,10 @@ module Rack
|
|
17
17
|
@config ||= Config.default
|
18
18
|
end
|
19
19
|
|
20
|
+
def resources_root
|
21
|
+
@resources_root ||= ::File.expand_path("../../html", __FILE__)
|
22
|
+
end
|
23
|
+
|
20
24
|
def share_template
|
21
25
|
@share_template ||= ::File.read(::File.expand_path("../html/share.html", ::File.dirname(__FILE__)))
|
22
26
|
end
|
@@ -37,10 +41,11 @@ module Rack
|
|
37
41
|
|
38
42
|
def create_current(env={}, options={})
|
39
43
|
# profiling the request
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
+
context = Context.new
|
45
|
+
context.inject_js = config.auto_inject && (!env['HTTP_X_REQUESTED_WITH'].eql? 'XMLHttpRequest')
|
46
|
+
context.page_struct = TimerStruct::Page.new(env)
|
47
|
+
context.current_timer = context.page_struct[:root]
|
48
|
+
self.current = context
|
44
49
|
end
|
45
50
|
|
46
51
|
def authorize_request
|
@@ -92,24 +97,26 @@ module Rack
|
|
92
97
|
@storage.set_viewed(user(env), id)
|
93
98
|
end
|
94
99
|
|
95
|
-
result_json = page_struct.to_json
|
96
100
|
# If we're an XMLHttpRequest, serve up the contents as JSON
|
97
101
|
if request.xhr?
|
102
|
+
result_json = page_struct.to_json
|
98
103
|
[200, { 'Content-Type' => 'application/json'}, [result_json]]
|
99
104
|
else
|
100
|
-
|
101
105
|
# Otherwise give the HTML back
|
102
|
-
html =
|
103
|
-
html.gsub!(/\{path\}/, "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}")
|
104
|
-
html.gsub!(/\{version\}/, MiniProfiler::ASSET_VERSION)
|
105
|
-
html.gsub!(/\{json\}/, result_json)
|
106
|
-
html.gsub!(/\{includes\}/, get_profile_script(env))
|
107
|
-
html.gsub!(/\{name\}/, page_struct[:name])
|
108
|
-
html.gsub!(/\{duration\}/, "%.1f" % page_struct.duration_ms)
|
109
|
-
|
106
|
+
html = generate_html(page_struct, env)
|
110
107
|
[200, {'Content-Type' => 'text/html'}, [html]]
|
111
108
|
end
|
109
|
+
end
|
112
110
|
|
111
|
+
def generate_html(page_struct, env, result_json = page_struct.to_json)
|
112
|
+
html = MiniProfiler.share_template.dup
|
113
|
+
html.sub!('{path}', "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}")
|
114
|
+
html.sub!('{version}', MiniProfiler::ASSET_VERSION)
|
115
|
+
html.sub!('{json}', result_json)
|
116
|
+
html.sub!('{includes}', get_profile_script(env))
|
117
|
+
html.sub!('{name}', page_struct[:name])
|
118
|
+
html.sub!('{duration}', page_struct.duration_ms.round(1).to_s)
|
119
|
+
html
|
113
120
|
end
|
114
121
|
|
115
122
|
def serve_html(env)
|
@@ -117,21 +124,11 @@ module Rack
|
|
117
124
|
|
118
125
|
return serve_results(env) if file_name.eql?('results')
|
119
126
|
|
120
|
-
|
121
|
-
|
122
|
-
f = Rack::File.new nil
|
123
|
-
f.path = full_path
|
124
|
-
|
125
|
-
begin
|
126
|
-
f.cache_control = "max-age:86400"
|
127
|
-
f.serving env
|
128
|
-
rescue
|
129
|
-
# old versions of rack have a different api
|
130
|
-
status, headers, body = f.serving
|
131
|
-
headers.merge! 'Cache-Control' => "max-age:86400"
|
132
|
-
[status, headers, body]
|
133
|
-
end
|
127
|
+
resources_env = env.dup
|
128
|
+
resources_env['PATH_INFO'] = file_name
|
134
129
|
|
130
|
+
rack_file = Rack::File.new(MiniProfiler.resources_root, {'Cache-Control' => 'max-age:86400'})
|
131
|
+
rack_file.call(resources_env)
|
135
132
|
end
|
136
133
|
|
137
134
|
|
@@ -197,11 +194,13 @@ module Rack
|
|
197
194
|
client_settings.disable_profiling = false
|
198
195
|
end
|
199
196
|
|
197
|
+
# profile gc
|
200
198
|
if query_string =~ /pp=profile-gc/
|
201
199
|
current.measure = false if current
|
202
200
|
return Rack::MiniProfiler::GCProfiler.new.profile_gc(@app, env)
|
203
201
|
end
|
204
202
|
|
203
|
+
# profile memory
|
205
204
|
if query_string =~ /pp=profile-memory/
|
206
205
|
query_params = Rack::Utils.parse_nested_query(query_string)
|
207
206
|
options = {
|
@@ -291,7 +290,7 @@ module Rack
|
|
291
290
|
if (config.authorization_mode == :whitelist && !MiniProfiler.request_authorized?)
|
292
291
|
# this is non-obvious, don't kill the profiling cookie on errors or short requests
|
293
292
|
# this ensures that stuff that never reaches the rails stack does not kill profiling
|
294
|
-
if status >= 200 && status < 300 && ((Time.now - start) > 0.1)
|
293
|
+
if status.to_i >= 200 && status.to_i < 300 && ((Time.now - start) > 0.1)
|
295
294
|
client_settings.discard_cookie!(headers)
|
296
295
|
end
|
297
296
|
skip_it = true
|
@@ -389,39 +388,17 @@ module Rack
|
|
389
388
|
end
|
390
389
|
|
391
390
|
def inject(fragment, script)
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
regex = /<\/html>/i
|
401
|
-
close_tag = '</html>'
|
402
|
-
else
|
403
|
-
# implicit </body> and </html>. Don't do anything.
|
404
|
-
|
405
|
-
return fragment
|
406
|
-
end
|
407
|
-
|
408
|
-
matches = fragment.scan(regex).length
|
409
|
-
index = 1
|
410
|
-
fragment.gsub(regex) do
|
411
|
-
# though malformed there is an edge case where /body exists earlier in the html, work around
|
412
|
-
if index < matches
|
413
|
-
index += 1
|
414
|
-
close_tag
|
415
|
-
else
|
416
|
-
|
417
|
-
# if for whatever crazy reason we dont get a utf string,
|
418
|
-
# just force the encoding, no utf in the mp scripts anyway
|
419
|
-
if script.respond_to?(:encoding) && script.respond_to?(:force_encoding)
|
420
|
-
(script + close_tag).force_encoding(fragment.encoding)
|
421
|
-
else
|
422
|
-
script + close_tag
|
423
|
-
end
|
391
|
+
# find explicit or implicit body
|
392
|
+
index = fragment.rindex(/<\/body>/i) || fragment.rindex(/<\/html>/i)
|
393
|
+
if index
|
394
|
+
# if for whatever crazy reason we dont get a utf string,
|
395
|
+
# just force the encoding, no utf in the mp scripts anyway
|
396
|
+
if script.respond_to?(:encoding) && script.respond_to?(:force_encoding)
|
397
|
+
script = script.force_encoding(fragment.encoding)
|
424
398
|
end
|
399
|
+
fragment.insert(index, script)
|
400
|
+
else
|
401
|
+
fragment
|
425
402
|
end
|
426
403
|
end
|
427
404
|
|
@@ -594,7 +571,13 @@ Append the following to your query string:
|
|
594
571
|
# * you have disabled auto append behaviour throught :auto_inject => false flag
|
595
572
|
# * you do not want script to be automatically appended for the current page. You can also call cancel_auto_inject
|
596
573
|
def get_profile_script(env)
|
597
|
-
path = if
|
574
|
+
path = if ENV["PASSENGER_BASE_URI"] then
|
575
|
+
# added because the SCRIPT_NAME workaround below then
|
576
|
+
# breaks running under a prefix as permitted by Passenger.
|
577
|
+
"#{ENV['PASSENGER_BASE_URI']}#{@config.base_url_path}"
|
578
|
+
elsif env["action_controller.instance"]
|
579
|
+
# Rails engines break SCRIPT_NAME; the following appears to discard SCRIPT_NAME
|
580
|
+
# since url_for appears documented to return any String argument unmodified
|
598
581
|
env["action_controller.instance"].url_for("#{@config.base_url_path}")
|
599
582
|
else
|
600
583
|
"#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}"
|
@@ -610,7 +593,8 @@ Append the following to your query string:
|
|
610
593
|
:showControls => false,
|
611
594
|
:authorized => true,
|
612
595
|
:toggleShortcut => @config.toggle_shortcut,
|
613
|
-
:startHidden => @config.start_hidden
|
596
|
+
:startHidden => @config.start_hidden,
|
597
|
+
:collapseResults => @config.collapse_results
|
614
598
|
}
|
615
599
|
|
616
600
|
if current && current.page_struct
|
@@ -3,9 +3,9 @@ module Rack
|
|
3
3
|
module ProfilingMethods
|
4
4
|
|
5
5
|
def record_sql(query, elapsed_ms)
|
6
|
-
return unless current
|
6
|
+
return unless current && current.current_timer
|
7
7
|
c = current
|
8
|
-
c.current_timer.add_sql(query, elapsed_ms, c.page_struct, c.skip_backtrace, c.full_backtrace)
|
8
|
+
c.current_timer.add_sql(query, elapsed_ms, c.page_struct, c.skip_backtrace, c.full_backtrace)
|
9
9
|
end
|
10
10
|
|
11
11
|
def start_step(name)
|
@@ -26,10 +26,9 @@ module Rack
|
|
26
26
|
def step(name, opts = nil)
|
27
27
|
if current
|
28
28
|
parent_timer = current.current_timer
|
29
|
-
result = nil
|
30
29
|
current.current_timer = current_timer = current.current_timer.add_child(name)
|
31
30
|
begin
|
32
|
-
|
31
|
+
yield if block_given?
|
33
32
|
ensure
|
34
33
|
current_timer.record_time
|
35
34
|
current.current_timer = parent_timer
|
@@ -87,34 +86,37 @@ module Rack
|
|
87
86
|
end
|
88
87
|
end
|
89
88
|
|
90
|
-
result = nil
|
91
89
|
parent_timer = Rack::MiniProfiler.current.current_timer
|
92
90
|
|
93
91
|
if type == :counter
|
94
92
|
start = Time.now
|
95
93
|
begin
|
96
|
-
|
94
|
+
self.send without_profiling, *args, &orig
|
97
95
|
ensure
|
98
96
|
duration_ms = (Time.now - start).to_f * 1000
|
99
97
|
parent_timer.add_custom(name, duration_ms, Rack::MiniProfiler.current.page_struct )
|
100
98
|
end
|
101
99
|
else
|
102
|
-
page_struct = Rack::MiniProfiler.current.page_struct
|
103
|
-
|
104
100
|
Rack::MiniProfiler.current.current_timer = current_timer = parent_timer.add_child(name)
|
105
101
|
begin
|
106
|
-
|
102
|
+
self.send without_profiling, *args, &orig
|
107
103
|
ensure
|
108
104
|
current_timer.record_time
|
109
105
|
Rack::MiniProfiler.current.current_timer = parent_timer
|
110
106
|
end
|
111
107
|
end
|
112
|
-
|
113
|
-
result
|
114
108
|
end
|
115
109
|
klass.send :alias_method, method, with_profiling
|
116
110
|
end
|
117
111
|
|
112
|
+
def profile_singleton_method(klass, method, type = :profile, &blk)
|
113
|
+
profile_method(singleton_class(klass), method, type, &blk)
|
114
|
+
end
|
115
|
+
|
116
|
+
def unprofile_singleton_method(klass, method)
|
117
|
+
unprofile_method(singleton_class(klass), method)
|
118
|
+
end
|
119
|
+
|
118
120
|
# Add a custom timing. These are displayed similar to SQL/query time in
|
119
121
|
# columns expanding to the right.
|
120
122
|
#
|
@@ -140,6 +142,10 @@ module Rack
|
|
140
142
|
|
141
143
|
private
|
142
144
|
|
145
|
+
def singleton_class(klass)
|
146
|
+
class << klass; self; end
|
147
|
+
end
|
148
|
+
|
143
149
|
def clean_method_name(method)
|
144
150
|
method.to_s.gsub(/[\?\!]/, "")
|
145
151
|
end
|
@@ -44,6 +44,8 @@ module Rack
|
|
44
44
|
@path = args[:path]
|
45
45
|
@expires_in_seconds = args[:expires_in] || EXPIRES_IN_SECONDS
|
46
46
|
raise ArgumentError.new :path unless @path
|
47
|
+
FileUtils.mkdir_p(@path) unless ::File.exists?(@path)
|
48
|
+
|
47
49
|
@timer_struct_cache = FileCache.new(@path, "mp_timers")
|
48
50
|
@timer_struct_lock = Mutex.new
|
49
51
|
@user_view_cache = FileCache.new(@path, "mp_views")
|
@@ -40,10 +40,18 @@ module Rack
|
|
40
40
|
self[:root] = TimerStruct::Request.createRoot(name, self)
|
41
41
|
end
|
42
42
|
|
43
|
+
def name
|
44
|
+
@attributes[:name]
|
45
|
+
end
|
46
|
+
|
43
47
|
def duration_ms
|
44
48
|
@attributes[:root][:duration_milliseconds]
|
45
49
|
end
|
46
50
|
|
51
|
+
def duration_ms_in_sql
|
52
|
+
@attributes[:duration_milliseconds_in_sql]
|
53
|
+
end
|
54
|
+
|
47
55
|
def root
|
48
56
|
@attributes[:root]
|
49
57
|
end
|
@@ -44,10 +44,18 @@ module Rack
|
|
44
44
|
@page = page
|
45
45
|
end
|
46
46
|
|
47
|
+
def name
|
48
|
+
@attributes[:name]
|
49
|
+
end
|
50
|
+
|
47
51
|
def duration_ms
|
48
52
|
self[:duration_milliseconds]
|
49
53
|
end
|
50
54
|
|
55
|
+
def duration_ms_in_sql
|
56
|
+
@attributes[:duration_milliseconds_in_sql]
|
57
|
+
end
|
58
|
+
|
51
59
|
def start_ms
|
52
60
|
self[:start_milliseconds]
|
53
61
|
end
|
@@ -17,11 +17,11 @@ module Rack
|
|
17
17
|
(
|
18
18
|
(
|
19
19
|
Rack::MiniProfiler.config.backtrace_includes.nil? or
|
20
|
-
Rack::MiniProfiler.config.backtrace_includes.
|
20
|
+
Rack::MiniProfiler.config.backtrace_includes.any?{|regex| ln =~ regex}
|
21
21
|
) and
|
22
22
|
(
|
23
23
|
Rack::MiniProfiler.config.backtrace_ignores.nil? or
|
24
|
-
Rack::MiniProfiler.config.backtrace_ignores.
|
24
|
+
Rack::MiniProfiler.config.backtrace_ignores.none?{|regex| ln =~ regex}
|
25
25
|
)
|
26
26
|
)
|
27
27
|
stack_trace << ln << "\n"
|
@@ -4,9 +4,9 @@ module Rack::MiniProfilerRails
|
|
4
4
|
|
5
5
|
# call direct if needed to do a defer init
|
6
6
|
def self.initialize!(app)
|
7
|
-
|
7
|
+
|
8
8
|
raise "MiniProfilerRails initialized twice. Set `require: false' for rack-mini-profiler in your Gemfile" if @already_initialized
|
9
|
-
|
9
|
+
|
10
10
|
c = Rack::MiniProfiler.config
|
11
11
|
|
12
12
|
# By default, only show the MiniProfiler in development mode.
|
@@ -24,7 +24,9 @@ module Rack::MiniProfilerRails
|
|
24
24
|
|
25
25
|
c.skip_paths ||= []
|
26
26
|
|
27
|
-
|
27
|
+
if serves_static_assets?(app)
|
28
|
+
c.skip_paths << app.config.assets.prefix
|
29
|
+
end
|
28
30
|
|
29
31
|
if Rails.env.development?
|
30
32
|
c.skip_schema_queries = true
|
@@ -41,7 +43,6 @@ module Rack::MiniProfilerRails
|
|
41
43
|
# The file store is just so much less flaky
|
42
44
|
base_path = Rails.application.config.paths['tmp'].first rescue "#{Rails.root}/tmp"
|
43
45
|
tmp = base_path + '/miniprofiler'
|
44
|
-
FileUtils.mkdir_p(tmp) unless File.exists?(tmp)
|
45
46
|
|
46
47
|
c.storage_options = {:path => tmp}
|
47
48
|
c.storage = Rack::MiniProfiler::FileStore
|
@@ -61,17 +62,23 @@ module Rack::MiniProfilerRails
|
|
61
62
|
ActiveSupport.on_load(:action_view) do
|
62
63
|
::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{@virtual_path}"}
|
63
64
|
end
|
64
|
-
|
65
|
+
|
65
66
|
@already_initialized = true
|
66
67
|
end
|
67
68
|
|
68
69
|
def self.serves_static_assets?(app)
|
69
|
-
|
70
|
-
|
71
|
-
if
|
72
|
-
|
70
|
+
config = app.config
|
71
|
+
|
72
|
+
if !config.respond_to?(:assets) || !config.assets.respond_to?(:prefix)
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
|
76
|
+
if ::Rails.version >= "5.0.0"
|
77
|
+
::Rails.configuration.public_file_server.enabled
|
78
|
+
elsif ::Rails.version >= "4.2.0"
|
79
|
+
::Rails.configuration.serve_static_files
|
73
80
|
else
|
74
|
-
|
81
|
+
::Rails.configuration.serve_static_assets
|
75
82
|
end
|
76
83
|
end
|
77
84
|
|
@@ -21,6 +21,8 @@ module Rack
|
|
21
21
|
rval = log_without_miniprofiler(*args, &block)
|
22
22
|
|
23
23
|
# Don't log schema queries if the option is set
|
24
|
+
# return rval unless sql =~ /\"vms\"/
|
25
|
+
# return rval unless sql =~ /\"(vms|ext_management_systems)\"/
|
24
26
|
return rval if Rack::MiniProfiler.config.skip_schema_queries and name =~ /SCHEMA/
|
25
27
|
|
26
28
|
elapsed_time = SqlPatches.elapsed_time(start)
|
data/lib/patches/db/mongo.rb
CHANGED
@@ -8,5 +8,9 @@ class Mongo::Server::Connection
|
|
8
8
|
end
|
9
9
|
return result
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
|
+
# TODO: change to Module#prepend as soon as Ruby 1.9.3 support is dropped
|
13
|
+
alias_method :dispatch_without_timing, :dispatch
|
14
|
+
alias_method :dispatch, :dispatch_with_timing
|
15
|
+
|
12
16
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Neo4j::Core::Query
|
2
|
+
alias_method :response_without_miniprofiler, :response
|
3
|
+
|
4
|
+
def response
|
5
|
+
return @response if @response
|
6
|
+
start = Time.now
|
7
|
+
rval = response_without_miniprofiler
|
8
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
9
|
+
Rack::MiniProfiler.record_sql(to_cypher, elapsed_time)
|
10
|
+
rval
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_method :response_with_miniprofiler, :response
|
14
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# riak-client 2.2.2 patches
|
2
|
+
class Riak::Multiget
|
3
|
+
class <<self
|
4
|
+
alias_method :get_all_without_profiling, :get_all
|
5
|
+
def get_all(client, fetch_list)
|
6
|
+
return get_all_without_profiling(client, fetch_list) unless SqlPatches.should_measure?
|
7
|
+
|
8
|
+
start = Time.now
|
9
|
+
result = get_all_without_profiling(client, fetch_list)
|
10
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
11
|
+
record = ::Rack::MiniProfiler.record_sql("get_all size=#{fetch_list.size}", elapsed_time)
|
12
|
+
|
13
|
+
result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Riak::Client
|
19
|
+
|
20
|
+
alias_method :buckets_without_profiling, :buckets
|
21
|
+
def buckets(options={}, &blk)
|
22
|
+
profile("buckets #{options}") { buckets_without_profiling(options, &blk) }
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :client_id_without_profiling, :client_id
|
26
|
+
def client_id
|
27
|
+
profile("client_id") { client_id_without_profiling }
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method :delete_object_without_profiling, :delete_object
|
31
|
+
def delete_object(bucket, key, options={})
|
32
|
+
profile("delete_object bucket=#{bucket.name} key=#{key} options=#{options}") { delete_object_without_profiling(bucket, key, options) }
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :get_bucket_props_without_profiling, :get_bucket_props
|
36
|
+
def get_bucket_props(bucket, options={})
|
37
|
+
profile("get_bucket_props bucket=#{bucket.name} options=#{options}") { get_bucket_props_without_profiling(bucket, options) }
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :get_index_without_profiling, :get_index
|
41
|
+
def get_index(bucket, index, query, options={})
|
42
|
+
profile("get_index bucket=#{bucket.name} index=#{index} query=#{query} options=#{options}") { get_index_without_profiling(bucket, index, query, options) }
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :get_preflist_without_profiling, :get_preflist
|
46
|
+
def get_preflist(bucket, key, type=nil, options={})
|
47
|
+
profile("get_preflist bucket=#{bucket.name} key=#{key} type=#{type} options=#{options}") { get_preflist_without_profiling(bucket, key, type, options) }
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_method :get_object_without_profiling, :get_object
|
51
|
+
def get_object(bucket, key, options={})
|
52
|
+
profile("get_object bucket=#{bucket.name} key=#{key} options=#{options}") { get_object_without_profiling(bucket, key, options) }
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :list_keys_without_profiling, :list_keys
|
56
|
+
def list_keys(bucket, options={}, &block)
|
57
|
+
profile("list_keys bucket=#{bucket.name} options=#{options}") { list_keys_without_profiling(bucket, options, &block) }
|
58
|
+
end
|
59
|
+
|
60
|
+
alias_method :mapred_without_profiling, :mapred
|
61
|
+
def mapred(mr, &block)
|
62
|
+
profile("mapred") { mapred_without_profiling(mr, &block) }
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method :ping_without_profiling, :ping
|
66
|
+
def ping
|
67
|
+
profile("ping") { ping_without_profiling }
|
68
|
+
end
|
69
|
+
|
70
|
+
alias_method :reload_object_without_profiling, :reload_object
|
71
|
+
def reload_object(object, options={})
|
72
|
+
profile("reload_object bucket=#{object.bucket.name} key=#{object.key} vclock=#{object.vclock} options=#{options}") { reload_object_without_profiling(object, options) }
|
73
|
+
end
|
74
|
+
|
75
|
+
alias_method :set_bucket_props_without_profiling, :set_bucket_props
|
76
|
+
def set_bucket_props(bucket, properties, type=nil)
|
77
|
+
profile("set_bucket_props bucket=#{bucket.name} type=#{type}") { set_bucket_props_without_profiling(bucket, properties, type) }
|
78
|
+
end
|
79
|
+
|
80
|
+
alias_method :clear_bucket_props_without_profiling, :clear_bucket_props
|
81
|
+
def clear_bucket_props(bucket, options={})
|
82
|
+
profile("clear_bucket_props bucket=#{bucket.name} options=#{options}") { clear_bucket_props_without_profiling(bucket, options) }
|
83
|
+
end
|
84
|
+
|
85
|
+
alias_method :store_object_without_profiling, :store_object
|
86
|
+
def store_object(object, options={})
|
87
|
+
profile("store_object bucket=#{object.bucket.name} key=#{object.key} vclock=#{object.vclock} options=#{options}") { store_object_without_profiling(object, options) }
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def profile(request, &blk)
|
93
|
+
return yield unless SqlPatches.should_measure?
|
94
|
+
|
95
|
+
start = Time.now
|
96
|
+
result = yield
|
97
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
98
|
+
record = ::Rack::MiniProfiler.record_sql(request, elapsed_time)
|
99
|
+
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
data/lib/patches/sql_patches.rb
CHANGED
@@ -46,10 +46,12 @@ end
|
|
46
46
|
require 'patches/db/mysql2' if defined?(Mysql2::Client) && SqlPatches.class_exists?("Mysql2::Client")
|
47
47
|
require 'patches/db/pg' if defined?(PG::Result) && SqlPatches.class_exists?("PG::Result")
|
48
48
|
require 'patches/db/oracle_enhanced' if defined?(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter) && SqlPatches.class_exists?("ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter") && SqlPatches.correct_version?('~> 1.5.0', ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter)
|
49
|
-
require 'patches/db/mongo' if defined?(Mongo)
|
49
|
+
require 'patches/db/mongo' if defined?(Mongo) && SqlPatches.module_exists?("Mongo")
|
50
50
|
require 'patches/db/moped' if defined?(Moped::Node) && SqlPatches.class_exists?("Moped::Node")
|
51
51
|
require 'patches/db/plucky' if defined?(Plucky::Query) && SqlPatches.class_exists?("Plucky::Query")
|
52
52
|
require 'patches/db/rsolr' if defined?(RSolr::Connection) && SqlPatches.class_exists?("RSolr::Connection") && RSolr::VERSION[0] != "0"
|
53
53
|
require 'patches/db/sequel' if defined?(Sequel::Database) && !SqlPatches.patched? && SqlPatches.class_exists?("Sequel::Database")
|
54
54
|
require 'patches/db/activerecord' if defined?(ActiveRecord) &&!SqlPatches.patched? && SqlPatches.module_exists?("ActiveRecord")
|
55
55
|
require 'patches/db/nobrainer' if defined?(NoBrainer) && SqlPatches.module_exists?("NoBrainer")
|
56
|
+
require 'patches/db/riak' if defined?(Riak) && SqlPatches.module_exists?("Riak")
|
57
|
+
require 'patches/db/neo4j' if defined?(Neo4j::Core) && SqlPatches.class_exists?("Neo4j::Core::Query")
|
data/rack-mini-profiler.gemspec
CHANGED
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.9.
|
4
|
+
version: 0.9.9
|
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:
|
13
|
+
date: 2016-03-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.
|
21
|
+
version: 1.2.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 1.
|
28
|
+
version: 1.2.0
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: rake
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -226,10 +226,12 @@ files:
|
|
226
226
|
- lib/patches/db/mongo.rb
|
227
227
|
- lib/patches/db/moped.rb
|
228
228
|
- lib/patches/db/mysql2.rb
|
229
|
+
- lib/patches/db/neo4j.rb
|
229
230
|
- lib/patches/db/nobrainer.rb
|
230
231
|
- lib/patches/db/oracle_enhanced.rb
|
231
232
|
- lib/patches/db/pg.rb
|
232
233
|
- lib/patches/db/plucky.rb
|
234
|
+
- lib/patches/db/riak.rb
|
233
235
|
- lib/patches/db/rsolr.rb
|
234
236
|
- lib/patches/db/sequel.rb
|
235
237
|
- lib/patches/net_patches.rb
|
@@ -256,7 +258,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
258
|
version: '0'
|
257
259
|
requirements: []
|
258
260
|
rubyforge_project:
|
259
|
-
rubygems_version: 2.4.5
|
261
|
+
rubygems_version: 2.4.5
|
260
262
|
signing_key:
|
261
263
|
specification_version: 4
|
262
264
|
summary: Profiles loading speed for rack applications.
|