rack-mini-profiler 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,25 +1,23 @@
1
- <script id="profilerTemplate" type="text/x-jquery-tmpl">
2
-
1
+ <script id="profilerTemplate" type="text/x-dot-tmpl">
3
2
  <div class="profiler-result">
4
-
5
- <div class="profiler-button {{if has_duplicate_sql_timings}}profiler-warning{{/if}}">
6
- {{if has_duplicate_sql_timings}}<span class="profiler-nuclear">!</span>{{/if}}
7
- <span class="profiler-number">
8
- ${MiniProfiler.formatDuration(duration_milliseconds)} <span class="profiler-unit">ms</span>
9
- </span>
10
- {{if MiniProfiler.showTotalSqlCount()}}
3
+ <div class="profiler-button {{? it.has_duplicate_sql_timings}}profiler-warning{{?}}">
4
+ {{? it.has_duplicate_sql_timings}}<span class="profiler-nuclear">!</span>{{?}}
11
5
  <span class="profiler-number">
12
- ${sql_count} <span class="profiler-unit">sql</span>
6
+ {{= MiniProfiler.formatDuration(it.duration_milliseconds)}} <span class="profiler-unit">ms</span>
13
7
  </span>
14
- {{/if}}
8
+ {{? MiniProfiler.showTotalSqlCount()}}
9
+ <span class="profiler-number">
10
+ {{= it.sql_count}} <span class="profiler-unit">sql</span>
11
+ </span>
12
+ {{?}}
15
13
  </div>
16
14
 
17
15
  <div class="profiler-popup">
18
16
  <div class="profiler-info">
19
17
  <span class="profiler-name">
20
- ${name} <span class="profiler-overall-duration">(${MiniProfiler.formatDuration(duration_milliseconds)} ms)</span>
18
+ {{= it.name}} <span class="profiler-overall-duration">({{= MiniProfiler.formatDuration(it.duration_milliseconds)}} ms)</span>
21
19
  </span>
22
- <span class="profiler-server-time">${machine_name} on ${MiniProfiler.renderDate(started)}</span>
20
+ <span class="profiler-server-time">{{= it.machine_name}} on {{= MiniProfiler.renderDate(it.started)}}</span>
23
21
  </div>
24
22
  <div class="profiler-output">
25
23
  <table class="profiler-timings">
@@ -29,200 +27,192 @@
29
27
  <th>duration (ms)</th>
30
28
  <th class="profiler-duration-with-children">with children (ms)</th>
31
29
  <th class="time-from-start">from start (ms)</th>
32
- {{if has_sql_timings}}
30
+ {{? it.has_sql_timings}}
33
31
  <th colspan="2">query time (ms)</th>
34
- {{/if}}
35
- {{each custom_timing_names}}
36
- <th colspan="2">${$value.toLowerCase()} (ms)</th>
37
- {{/each}}
32
+ {{?}}
33
+ {{~ it.custom_timing_names :value}}
34
+ <th colspan="2">{{= value.toLowerCase() }} (ms)</th>
35
+ {{~}}
38
36
  </tr>
39
37
  </thead>
40
38
  <tbody>
41
- {{tmpl({timing:root, page:this.data}) "#timingTemplate"}}
39
+ {{= MiniProfiler.templates.timingTemplate({timing: it.root, page: it}) }}
42
40
  </tbody>
43
41
  <tfoot>
44
42
  <tr>
45
43
  <td colspan="3">
46
- {{if !client_timings}}
47
- {{tmpl "#linksTemplate"}}
48
- {{/if}}
44
+ {{? !it.client_timings}}
45
+ {{= MiniProfiler.templates.linksTemplate({timing: it.root, page: it}) }}
46
+ {{?}}
49
47
  <a class="profiler-toggle-duration-with-children" title="toggles column with aggregate child durations">show time with children</a>
50
48
  </td>
51
- {{if has_sql_timings}}
52
- <td colspan="2" class="profiler-number profiler-percent-in-sql" title="${MiniProfiler.getSqlTimingsCount(root)} queries spent ${MiniProfiler.formatDuration(duration_milliseconds_in_sql)} ms of total request time">
53
- ${MiniProfiler.formatDuration(duration_milliseconds_in_sql / duration_milliseconds * 100)}
54
- <span class="profiler-unit">% in sql</span>
55
- </td>
56
- {{/if}}
57
- {{each custom_timing_names}}
58
- <td colspan="2" class="profiler-number profiler-percentage-in-sql" title="${custom_timing_stats[$value].count} ${$value.toLowerCase()} invocations spent ${MiniProfiler.formatDuration(custom_timing_stats[$value].duration)} ms of total request time">
59
- ${MiniProfiler.formatDuration(custom_timing_stats[$value].duration / duration_milliseconds * 100)}
60
- <span class="profiler-unit">% in ${$value.toLowerCase()}</span>
61
- </td>
62
- {{/each}}
49
+ {{? it.has_sql_timings}}
50
+ <td colspan="2" class="profiler-number profiler-percent-in-sql" title="{{= MiniProfiler.getSqlTimingsCount(it.root) }} queries spent {{= MiniProfiler.formatDuration(it.duration_milliseconds_in_sql) }} ms of total request time">
51
+ {{= MiniProfiler.formatDuration(it.duration_milliseconds_in_sql / it.duration_milliseconds * 100) }}
52
+ <span class="profiler-unit">% in sql</span>
53
+ </td>
54
+ {{?}}
55
+ {{~ it.custom_timing_names :value}}
56
+ <td colspan="2" class="profiler-number profiler-percentage-in-sql" title="{{= it.custom_timing_stats[value].count }} {{= value.toLowerCase() }} invocations spent {{= MiniProfiler.formatDuration(it.custom_timing_stats[value].duration) }} ms of total request time">
57
+ {{= MiniProfiler.formatDuration(it.custom_timing_stats[value].duration / duration_milliseconds * 100) }}
58
+ <span class="profiler-unit">% in {{= value.toLowerCase() }}</span>
59
+ </td>
60
+ {{~}}
63
61
  </tr>
64
62
  </tfoot>
65
63
  </table>
66
- {{if client_timings}}
67
- <table class="profiler-timings profiler-client-timings">
68
- <thead>
69
- <tr>
70
- <th>client event</th>
71
- <th>duration (ms)</th>
72
- <th>from start (ms)</th>
73
- </tr>
74
- </thead>
75
- <tbody>
76
- {{each MiniProfiler.getClientTimings(client_timings)}}
77
- <tr class="{{if $value.isTrivial }}profiler-trivial{{/if}}">
78
- <td class="profiler-label">${$value.name}</td>
79
- <td class="profiler-duration">
80
- {{if $value.duration >= 0}}
81
- <span class="profiler-unit"></span>${MiniProfiler.formatDuration($value.duration)}
82
- {{/if}}
83
- </td>
84
- <td class="profiler-duration time-from-start">
85
- <span class="profiler-unit">+</span>${MiniProfiler.formatDuration($value.start)}
64
+ {{? it.client_timings}}
65
+ <table class="profiler-timings profiler-client-timings">
66
+ <thead>
67
+ <tr>
68
+ <th>client event</th>
69
+ <th>duration (ms)</th>
70
+ <th>from start (ms)</th>
71
+ </tr>
72
+ </thead>
73
+ <tbody>
74
+ {{~ MiniProfiler.getClientTimings(it.client_timings) :value}}
75
+ <tr class="{{? value.isTrivial }}profiler-trivial{{?}}">
76
+ <td class="profiler-label">{{= value.name }}</td>
77
+ <td class="profiler-duration">
78
+ {{? value.duration >= 0}}
79
+ <span class="profiler-unit"></span>{{= MiniProfiler.formatDuration(value.duration) }}
80
+ {{?}}
81
+ </td>
82
+ <td class="profiler-duration time-from-start">
83
+ <span class="profiler-unit">+</span>{{= MiniProfiler.formatDuration(value.start) }}
84
+ </td>
85
+ </tr>
86
+ {{~}}
87
+ </tbody>
88
+ <tfoot>
89
+ <td colspan="3">
90
+ {{= MiniProfiler.templates.linksTemplate({timing: it.root, page: it}) }}
86
91
  </td>
87
- </tr>
88
- {{/each}}
89
- </tbody>
90
- <tfoot>
91
- <td colspan="3">
92
- {{tmpl "#linksTemplate"}}
93
- </td>
94
- </tfoot>
95
- </table>
96
- {{/if}}
92
+ </tfoot>
93
+ </table>
94
+ {{?}}
97
95
  </div>
98
96
  </div>
99
97
 
100
- {{if has_sql_timings}}
101
- <div class="profiler-queries">
102
- <table>
103
- <thead>
104
- <tr>
105
- <th style="text-align:right">step<br />time from start<br />query type<br />duration</th>
106
- <th style="text-align:left">call stack<br />query</th>
107
- </tr>
108
- </thead>
109
- <tbody>
110
- {{each(i, s) MiniProfiler.getSqlTimings(root)}}
111
- {{tmpl({ g:s.prevGap }) "#sqlGapTemplate"}}
112
- {{tmpl({ i:i, s:s }) "#sqlTimingTemplate"}}
113
- {{if s.nextGap}}
114
- {{tmpl({ g:s.nextGap }) "#sqlGapTemplate"}}
115
- {{/if}}
116
- {{/each}}
117
- </tbody>
118
- </table>
119
- <p class="profiler-trivial-gap-container">
120
- <a class="profiler-toggle-trivial-gaps" href="#">show trivial gaps</a>
121
- </p>
122
- </div>
123
- {{/if}}
124
-
98
+ {{? it.has_sql_timings}}
99
+ <div class="profiler-queries">
100
+ <table>
101
+ <thead>
102
+ <tr>
103
+ <th style="text-align:right">step<br />time from start<br />query type<br />duration</th>
104
+ <th style="text-align:left">call stack<br />query</th>
105
+ </tr>
106
+ </thead>
107
+ <tbody>
108
+ {{~ MiniProfiler.getSqlTimings(it.root) :value:index}}
109
+ {{= MiniProfiler.templates.sqlGapTemplate({g: value.prevGap}) }}
110
+ {{= MiniProfiler.templates.sqlTimingTemplate({i: index, s: value}) }}
111
+ {{? value.nextGap}}
112
+ {{= MiniProfiler.templates.sqlGapTemplate({g: value.nextGap}) }}
113
+ {{?}}
114
+ {{~}}
115
+ </tbody>
116
+ </table>
117
+ <p class="profiler-trivial-gap-container">
118
+ <a class="profiler-toggle-trivial-gaps">show trivial gaps</a>
119
+ </p>
120
+ </div>
121
+ {{?}}
125
122
  </div>
126
-
127
123
  </script>
128
124
 
129
- <script id="linksTemplate" type="text/x-jquery-tmpl">
130
- <a href="${MiniProfiler.shareUrl(id)}" class="profiler-share-profiler-results" target="_blank">share</a>
131
- <a href="${MiniProfiler.moreUrl()}" class="profiler-more-actions">more</a>
132
- {{if custom_link}}
133
- <a href="${custom_link}" class="profiler-custom-link" target="_blank">${custom_link_name}</a>
134
- {{/if}}
135
- {{if has_trivial_timings}}
136
- <a class="profiler-toggle-trivial" data-show-on-load="${has_all_trivial_timings}" title="toggles any rows with &lt; ${trivial_duration_threshold_milliseconds} ms">
137
- show trivial
138
- </a>
139
- {{/if}}
125
+ <script id="linksTemplate" type="text/x-dot-tmpl">
126
+ <a href="{{= MiniProfiler.shareUrl(it.page.id) }}" class="profiler-share-profiler-results" target="_blank">share</a>
127
+ <a href="{{= MiniProfiler.moreUrl(it.timing.name) }}" class="profiler-more-actions">more</a>
128
+ {{? it.custom_link}}
129
+ <a href="{{= it.custom_link }}" class="profiler-custom-link" target="_blank">{{= it.custom_link_name }}</a>
130
+ {{?}}
131
+ {{? it.has_trivial_timings}}
132
+ <a class="profiler-toggle-trivial" data-show-on-load="{{= it.has_all_trivial_timings }}" title="toggles any rows with &lt; {{= it.trivial_duration_threshold_milliseconds }} ms">
133
+ show trivial
134
+ </a>
135
+ {{?}}
140
136
  </script>
141
137
 
142
- <script id="timingTemplate" type="text/x-jquery-tmpl">
143
-
144
- <tr class="{{if timing.is_trivial }}profiler-trivial{{/if}}" data-timing-id="${timing.id}">
145
- <td class="profiler-label" title="{{if timing.name && timing.name.length > 45 }}${timing.name}{{/if}}">
146
- <span class="profiler-indent">${MiniProfiler.renderIndent(timing.depth)}</span> ${timing.name.slice(0,45)}{{if timing.name && timing.name.length > 45 }}...{{/if}}
138
+ <script id="timingTemplate" type="text/x-dot-tmpl">
139
+ <tr class="{{? it.timing.is_trivial }}profiler-trivial{{?}}" data-timing-id="{{= it.timing.id }}">
140
+ <td class="profiler-label" title="{{? it.timing.name && it.timing.name.length > 45 }}{{= it.timing.name }}{{?}}">
141
+ <span class="profiler-indent">{{= MiniProfiler.renderIndent(it.timing.depth) }}</span> {{= it.timing.name.slice(0,45) }}{{? it.timing.name && it.timing.name.length > 45 }}...{{?}}
147
142
  </td>
148
143
  <td class="profiler-duration" title="duration of this step without any children's durations">
149
- ${MiniProfiler.formatDuration(timing.duration_without_children_milliseconds)}
144
+ {{= MiniProfiler.formatDuration(it.timing.duration_without_children_milliseconds) }}
150
145
  </td>
151
146
  <td class="profiler-duration profiler-duration-with-children" title="duration of this step and its children">
152
- ${MiniProfiler.formatDuration(timing.duration_milliseconds)}
147
+ {{= MiniProfiler.formatDuration(it.timing.duration_milliseconds) }}
153
148
  </td>
154
149
  <td class="profiler-duration time-from-start" title="time elapsed since profiling started">
155
- <span class="profiler-unit">+</span>${MiniProfiler.formatDuration(timing.start_milliseconds)}
150
+ <span class="profiler-unit">+</span>{{= MiniProfiler.formatDuration(it.timing.start_milliseconds) }}
156
151
  </td>
157
152
 
158
- {{if timing.has_sql_timings}}
159
- <td class="profiler-duration {{if timing.has_duplicate_sql_timings}}profiler-warning{{/if}}" title="{{if timing.has_duplicate_sql_timings}}duplicate queries detected - {{/if}}{{if timing.executed_readers > 0 || timing.executed_scalars > 0 || timing.executed_non_queries > 0}}${timing.executed_readers} reader, ${timing.executed_scalars} scalar, ${timing.executed_non_queries} non-query statements executed{{/if}}">
153
+ {{? it.timing.has_sql_timings}}
154
+ <td class="profiler-duration {{? it.timing.has_duplicate_sql_timings}}profiler-warning{{?}}" title="{{? it.timing.has_duplicate_sql_timings}}duplicate queries detected - {{?}}{{? it.timing.executed_readers > 0 || it.timing.executed_scalars > 0 || it.timing.executed_non_queries > 0}}{{= it.timing.executed_readers }} reader, {{= it.timing.executed_scalars }} scalar, {{= it.timing.executed_non_queries }} non-query statements executed{{?}}">
160
155
  <a class="profiler-queries-show">
161
- {{if timing.has_duplicate_sql_timings}}<span class="profiler-nuclear">!</span>{{/if}}
162
- ${timing.sql_timings.length} <span class="profiler-unit">sql</span>
156
+ {{? it.timing.has_duplicate_sql_timings}}<span class="profiler-nuclear">!</span>{{?}}
157
+ {{= it.timing.sql_timings.length }} <span class="profiler-unit">sql</span>
163
158
  </a>
164
159
  </td>
165
160
  <td class="profiler-duration" title="aggregate duration of all queries in this step (excludes children)">
166
- ${MiniProfiler.formatDuration(timing.sql_timings_duration_milliseconds)}
161
+ {{= MiniProfiler.formatDuration(it.timing.sql_timings_duration_milliseconds) }}
167
162
  </td>
168
- {{else}}
163
+ {{??}}
169
164
  <td colspan="2"></td>
170
- {{/if}}
165
+ {{?}}
171
166
 
172
- {{each page.custom_timing_names}}
173
- {{if timing.custom_timings && timing.custom_timings[$value]}}
174
- <td class="profiler-duration" title="aggregate number of all ${$value.toLowerCase()} invocations in this step (excludes children)">
175
- ${timing.custom_timings[$value].length} ${$value.toLowerCase()}
167
+ {{~ it.page.custom_timing_names :value}}
168
+ {{? it.timing.custom_timings && it.timing.custom_timings[value]}}
169
+ <td class="profiler-duration" title="aggregate number of all {{= value.toLowerCase() }} invocations in this step (excludes children)">
170
+ {{= it.timing.custom_timings[value].length }} {{= value.toLowerCase() }}
176
171
  </td>
177
- <td class="profiler-duration" title="aggregate duration of all ${$value.toLowerCase()} invocations in this step (excludes children)">
178
- ${MiniProfiler.formatDuration(timing.custom_timing_stats[$value].duration)}
172
+ <td class="profiler-duration" title="aggregate duration of all {{= value.toLowerCase() }} invocations in this step (excludes children)">
173
+ {{= MiniProfiler.formatDuration(it.timing.custom_timing_stats[value].duration) }}
179
174
  </td>
180
- {{else}}
175
+ {{??}}
181
176
  <td colspan="2"></td>
182
- {{/if}}
183
- {{/each}}
177
+ {{?}}
178
+ {{~}}
184
179
 
185
180
  </tr>
186
181
 
187
- {{if timing.has_children}}
188
- {{each timing.children}}
189
- {{tmpl({timing: $value, page: page}) "#timingTemplate"}}
190
- {{/each}}
191
- {{/if}}
192
-
182
+ {{? it.timing.has_children}}
183
+ {{~ it.timing.children :value}}
184
+ {{= MiniProfiler.templates.timingTemplate({timing: value, page: it}) }}
185
+ {{~}}
186
+ {{?}}
193
187
  </script>
194
188
 
195
- <script id="sqlTimingTemplate" type="text/x-jquery-tmpl">
196
-
197
- <tr class="${s.row_class}" data-timing-id="${s.parent_timing_id}">
189
+ <script id="sqlTimingTemplate" type="text/x-dot-tmpl">
190
+ <tr class="{{= it.s.row_class || '' }}" data-timing-id="{{= it.s.parent_timing_id }}">
198
191
  <td class="profiler-info">
199
- <div>${s.parent_timing_name}</div>
200
- <div class="profiler-number"><span class="profiler-unit">T+</span>${MiniProfiler.formatDuration(s.start_milliseconds)} <span class="profiler-unit">ms</span></div>
192
+ <div>{{= it.s.parent_timing_name }}</div>
193
+ <div class="profiler-number"><span class="profiler-unit">T+</span>{{= MiniProfiler.formatDuration(it.s.start_milliseconds) }} <span class="profiler-unit">ms</span></div>
201
194
  <div>
202
- {{if s.is_duplicate}}<span class="profiler-warning">DUPLICATE</span>{{/if}}
203
- ${MiniProfiler.renderExecuteType(s.execute_type)}
195
+ {{? it.s.is_duplicate}}<span class="profiler-warning">DUPLICATE</span>{{?}}
196
+ {{= MiniProfiler.renderExecuteType(it.s.execute_type) }}
204
197
  </div>
205
- <div title="{{if s.execute_type == 3}}first result fetched: ${s.first_fetch_duration_milliseconds}ms{{/if}}">${MiniProfiler.formatDuration(s.duration_milliseconds)} <span class="profiler-unit">ms</span></div>
198
+ <div title="{{? it.s.execute_type == 3}}first result fetched: {{= it.s.first_fetch_duration_milliseconds }}ms{{?}}">{{= MiniProfiler.formatDuration(it.s.duration_milliseconds) }} <span class="profiler-unit">ms</span></div>
206
199
  </td>
207
200
  <td>
208
201
  <div class="query">
209
- <pre class="profiler-stack-trace">${s.stack_trace_snippet}</pre>
210
- <pre class="prettyprint lang-sql"><code>${s.formatted_command_string}; ${MiniProfiler.formatParameters(s.parameters)}</code></pre>
202
+ <pre class="profiler-stack-trace">{{= it.s.stack_trace_snippet }}</pre>
203
+ <pre class="prettyprint lang-sql"><code>{{= it.s.formatted_command_string }}; {{= MiniProfiler.formatParameters(it.s.parameters) }}</code></pre>
211
204
  </div>
212
205
  </td>
213
206
  </tr>
214
-
215
207
  </script>
216
208
 
217
- <script id="sqlGapTemplate" type="text/x-jquery-tmpl">
218
-
219
- <tr class="profiler-gap-info{{if g.duration < 4}} profiler-trivial-gaps{{/if}}">
209
+ <script id="sqlGapTemplate" type="text/x-dot-tmpl">
210
+ <tr class="profiler-gap-info{{? it.g.duration < 4}} profiler-trivial-gaps{{?}}">
220
211
  <td class="profiler-info">
221
- ${g.duration} <span class="profiler-unit">ms</span>
212
+ {{= it.g.duration }} <span class="profiler-unit">ms</span>
222
213
  </td>
223
214
  <td class="query">
224
- <div>${g.topReason.name} &mdash; ${g.topReason.duration.toFixed(2)} <span class="profiler-unit">ms</span></div>
215
+ <div>{{= it.g.topReason.name }} &mdash; {{= it.g.topReason.duration.toFixed(2) }} <span class="profiler-unit">ms</span></div>
225
216
  </td>
226
217
  </tr>
227
-
228
218
  </script>
@@ -1,7 +1,6 @@
1
1
  <html>
2
2
  <head>
3
3
  <title><%= name %> (<%= duration %> ms) - Profiling Results</title>
4
- <script type='text/javascript' src='<%= path %>jquery.1.7.1.js?v=<%= version %>'></script>
5
4
  <script type='text/javascript'> var profiler = <%= json %>; </script>
6
5
  <%= includes %>
7
6
  </head>
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module Rack
2
3
  class MiniProfiler
3
- ASSET_VERSION = '355f78011d9b95de14a5b1014b088681'.freeze
4
+ ASSET_VERSION = '0ade3000608cde95db93022b6576d63a'
4
5
  end
5
- end
6
+ end
@@ -34,9 +34,9 @@ module Rack
34
34
  end
35
35
  end
36
36
  @enabled = true
37
- @disable_env_dump = false
38
37
  @max_sql_param_length = 0 # disable sql parameter collection by default
39
38
  @skip_sql_param_names = /password/ # skips parameters with the name password by default
39
+ @enable_advanced_debugging_tools = false
40
40
 
41
41
  # ui parameters
42
42
  @autorized = true
@@ -47,7 +47,7 @@ module Rack
47
47
  @show_trivial = false
48
48
  @show_total_sql_count = false
49
49
  @start_hidden = false
50
- @toggle_shortcut = 'Alt+P'
50
+ @toggle_shortcut = 'alt+p'
51
51
  @html_container = 'body'
52
52
  @position = "top-left"
53
53
 
@@ -57,10 +57,10 @@ module Rack
57
57
 
58
58
  attr_accessor :authorization_mode, :auto_inject, :backtrace_ignores,
59
59
  :backtrace_includes, :backtrace_remove, :backtrace_threshold_ms,
60
- :base_url_path, :disable_caching, :disable_env_dump, :enabled,
60
+ :base_url_path, :disable_caching, :enabled,
61
61
  :flamegraph_sample_rate, :logger, :pre_authorize_cb, :skip_paths,
62
62
  :skip_schema_queries, :storage, :storage_failure, :storage_instance,
63
- :storage_options, :user_provider
63
+ :storage_options, :user_provider, :enable_advanced_debugging_tools
64
64
  attr_accessor :skip_sql_param_names, :suppress_encoding, :max_sql_param_length
65
65
 
66
66
  # ui accessors
@@ -62,6 +62,11 @@ module Rack
62
62
  Thread.current[:mp_authorized]
63
63
  end
64
64
 
65
+ def advanced_tools_message
66
+ <<~TEXT
67
+ This feature is disabled by default, to enable set the enable_advanced_debugging_tools option to true in Mini Profiler config.
68
+ TEXT
69
+ end
65
70
  end
66
71
 
67
72
  #
@@ -71,7 +76,7 @@ module Rack
71
76
  MiniProfiler.config.merge!(config)
72
77
  @config = MiniProfiler.config
73
78
  @app = app
74
- @config.base_url_path << "/" unless @config.base_url_path.end_with? "/"
79
+ @config.base_url_path += "/" unless @config.base_url_path.end_with? "/"
75
80
  unless @config.storage_instance
76
81
  @config.storage_instance = @config.storage.new(@config.storage_options)
77
82
  end
@@ -84,11 +89,11 @@ module Rack
84
89
 
85
90
  def serve_results(env)
86
91
  request = Rack::Request.new(env)
87
- id = request[:id]
92
+ id = request.params['id']
88
93
  page_struct = @storage.load(id)
89
94
  unless page_struct
90
95
  @storage.set_viewed(user(env), id)
91
- id = ERB::Util.html_escape(request['id'])
96
+ id = ERB::Util.html_escape(request.params['id'])
92
97
  user_info = ERB::Util.html_escape(user(env))
93
98
  return [404, {}, ["Request not found: #{id} - user #{user_info}"]]
94
99
  end
@@ -147,6 +152,14 @@ module Rack
147
152
  @config
148
153
  end
149
154
 
155
+ def advanced_debugging_enabled?
156
+ config.enable_advanced_debugging_tools
157
+ end
158
+
159
+ def tool_disabled_message(client_settings)
160
+ client_settings.handle_cookie(text_result(Rack::MiniProfiler.advanced_tools_message))
161
+ end
162
+
150
163
  def call(env)
151
164
 
152
165
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -195,12 +208,14 @@ module Rack
195
208
 
196
209
  # profile gc
197
210
  if query_string =~ /pp=profile-gc/
211
+ return tool_disabled_message(client_settings) if !advanced_debugging_enabled?
198
212
  current.measure = false if current
199
213
  return client_settings.handle_cookie(Rack::MiniProfiler::GCProfiler.new.profile_gc(@app, env))
200
214
  end
201
215
 
202
216
  # profile memory
203
217
  if query_string =~ /pp=profile-memory/
218
+ return tool_disabled_message(client_settings) if !advanced_debugging_enabled?
204
219
  query_params = Rack::Utils.parse_nested_query(query_string)
205
220
  options = {
206
221
  ignore_files: query_params['memory_profiler_ignore_files'],
@@ -307,12 +322,14 @@ module Rack
307
322
  return client_settings.handle_cookie(dump_exceptions exceptions)
308
323
  end
309
324
 
310
- if query_string =~ /pp=env/ && !config.disable_env_dump
325
+ if query_string =~ /pp=env/
326
+ return tool_disabled_message(client_settings) if !advanced_debugging_enabled?
311
327
  body.close if body.respond_to? :close
312
328
  return client_settings.handle_cookie(dump_env env)
313
329
  end
314
330
 
315
331
  if query_string =~ /pp=analyze-memory/
332
+ return tool_disabled_message(client_settings) if !advanced_debugging_enabled?
316
333
  body.close if body.respond_to? :close
317
334
  return client_settings.handle_cookie(analyze_memory)
318
335
  end
@@ -331,6 +348,17 @@ module Rack
331
348
  return client_settings.handle_cookie(self.flamegraph(flamegraph))
332
349
  end
333
350
 
351
+ if path == '/rack-mini-profiler/requests'
352
+ blank_page_html = <<~HTML
353
+ <html>
354
+ <head></head>
355
+ <body></body>
356
+ </html>
357
+ HTML
358
+
359
+ status, headers, body = [200, { 'Content-Type' => 'text/html' }, [blank_page_html.dup]]
360
+ end
361
+
334
362
  begin
335
363
  @storage.save(page_struct)
336
364
  # no matter what it is, it should be unviewed, otherwise we will miss POST
@@ -369,7 +397,7 @@ module Rack
369
397
 
370
398
  # inject header
371
399
  if headers.is_a? Hash
372
- headers['X-MiniProfiler-Ids'] = ids_json(env)
400
+ headers['X-MiniProfiler-Ids'] = ids_comma_separated(env)
373
401
  end
374
402
 
375
403
  if current.inject_js && content_type =~ /text\/html/
@@ -528,7 +556,7 @@ module Rack
528
556
 
529
557
  def make_link(postfix, env)
530
558
  link = env["PATH_INFO"] + "?" + env["QUERY_STRING"].sub("pp=help", "pp=#{postfix}")
531
- "pp=<a href='#{link}'>#{postfix}</a>"
559
+ "pp=<a href='#{ERB::Util.html_escape(link)}'>#{postfix}</a>"
532
560
  end
533
561
 
534
562
  def help(client_settings, env)
@@ -574,10 +602,6 @@ Append the following to your query string:
574
602
  all
575
603
  end
576
604
 
577
- def ids_json(env)
578
- ::JSON.generate(ids(env))
579
- end
580
-
581
605
  def ids_comma_separated(env)
582
606
  ids(env).join(",")
583
607
  end