rack-mini-profiler 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba607e06976028497914287036a4b96012892cc5
4
- data.tar.gz: b4427269223c942280e544847be135d1fdd51943
3
+ metadata.gz: b5ecd2f33ab275645797ab70ae9ba6cfe498ca87
4
+ data.tar.gz: eacfe92f9cad96c73505efff1b319531ad327426
5
5
  SHA512:
6
- metadata.gz: 32f96b3ba1bb3667417e0255130aee336780167f28b06209b026ae5ccbe87542e5c100bd3297f178ead24a90deb27b460cdf90f409b63da2ba705cc7bb2fabfa
7
- data.tar.gz: c62db46c5de3423581d3f0f2ca466f338b4d390d6bdad9f3bc0e8cb7a3f210ef24295ff0dfcd85925608c6bc05f85b0f5abcccd7a17ae0e053bb658faafd01be
6
+ metadata.gz: 0b7dbc766bb2e93d055a6710b661cc26d49a3ea3ed8bf3dc78604cfbcded5e08b75a22fd05623a38f0af05dccb3103f5d53aabda4eea69690df17292cf3a4012
7
+ data.tar.gz: 1d84e3daf3b7a27bbd22b563c8ff2b70ccdf6de6d39a9707357e4229886ff901b7496230cfc3707702064a66caa3cc5123f5492c78c649bf8b288a03262151f5
@@ -1,5 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.10.1 2017-02-08
4
+
5
+ - [FIX] improve turbolinks support
6
+ - [FEATURE] make location of mini_profiler injection customizable
7
+
3
8
  ## 0.10.1 2016-05-18
4
9
 
5
10
  - [FEATURE] push forward the security checks so no work is ever done if a valid production
@@ -84,31 +89,31 @@
84
89
  - [REMOVED] Ripped out flamegraph so it can be isolated into a gem
85
90
  - [REMOVED] Ripped out pp=sample it just was never really used
86
91
 
87
- ## 1.30 - 2013-08-30
92
+ ## 0.1.30 - 2013-08-30
88
93
  - [ADDED] Rack::MiniProfiler.counter_method(klass,name) for injecting counters
89
94
  - [FIXED] Counters were not shifting the table correctly
90
95
 
91
- ## 1.29 - 2013-08-20
96
+ ## 0.1.29 - 2013-08-20
92
97
  - [ADDED] Implemented exception tracing using TracePoint see pp=trace-exceptions
93
98
  - [FIXED] SOLR patching had an incorrect monkey patch
94
99
 
95
- ## 1.28 - 2012-07-18
100
+ ## 0.1.28 - 2013-07-30
96
101
  - [FIXED] Diagnostics in abstract storage was raising not implemented killing
97
102
  ?pp=env and others
98
103
  - [FIXED] SOLR xml unescaped by mistake
99
104
 
100
- ## 1.27 - 2013-06-26
105
+ ## 0.1.27 - 2013-06-26
101
106
  - [ADDED] Rack::MiniProfiler.config.backtrace_threshold_ms
102
107
  - [ADDED] jQuery 2.0 support
103
108
  - [FIXED] Disabled global ajax handlers on MP requests @JP
104
109
 
105
- ## 1.26 - 2013-04-11
110
+ ## 0.1.26 - 2013-04-11
106
111
  - [IMPROVED] Allow Rack::MiniProfilerRails.initialize!(Rails.application), for post config intialization
107
112
 
108
- ## 1.25 - 2013-04-08
113
+ ## 0.1.25 - 2013-04-08
109
114
  - [FIXED] Missed flamegraph.html from build
110
115
 
111
- ## 1.24 - 2013-04-08
116
+ ## 0.1.24 - 2013-04-08
112
117
  - [ADDED] Flame Graph Support see: http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler
113
118
  - [ADDED] New toggle_shortcut and start_hidden options
114
119
  - [ADDED] Mongoid support
@@ -124,36 +129,36 @@
124
129
  - [FIXED] HTML5 implicit <body> tags
125
130
  - [FIXED] pp=enable
126
131
 
127
- ## 1.22 - 2012-09-20
132
+ ## 0.1.22 - 2012-09-20
128
133
  - [FIXED] Permission issue in the gem
129
134
 
130
- ## 17-September-2012
135
+ ## 2012-09-17
131
136
  - [IMPROVED] Allow rack-mini-profiler to be sourced from github
132
137
  - [IMPROVED] Extracted the pp=profile-gc-time out, the object space profiler needs to disable gc
133
138
 
134
- ## 1.21 - 2012-09-17
139
+ ## 0.1.21 - 2012-09-17
135
140
  - [ADDED] New MemchacedStore
136
141
  - [ADDED] Rails 4 support
137
142
 
138
143
  ## 2012-09-12 (Sam Saffron)
139
144
  - [ADDED] pp=profile-gc: allows you to profile the GC in Ruby 1.9.3
140
145
 
141
- ## 1.19 - 2012-09-10 (Sam Saffron)
146
+ ## 0.1.19 - 2012-09-10 (Sam Saffron)
142
147
  - [FIXED] Compatibility issue with Ruby 1.8.7
143
148
 
144
- ## 1.17 - 2012-09-09 (Sam Saffron)
149
+ ## 0.1.17 - 2012-09-09 (Sam Saffron)
145
150
  - [FIXED] pp=sample was bust unless stacktrace was installed
146
151
 
147
- ## 1.16 - 2012-09-05 (Sam Saffron)
152
+ ## 0.1.16 - 2012-09-05 (Sam Saffron)
148
153
  - [IMPROVED] Implemented stacktrace properly
149
154
  - [FIXED] Long standing problem specs (issue with memory store)
150
155
  - [FIXED] Issue where profiler would be dumped when you got a 404 in production (and any time rails is bypassed)
151
156
 
152
- ## 1.15.pre - 2012-09-04 (Sam Saffron)
157
+ ## 0.1.15.pre - 2012-09-04 (Sam Saffron)
153
158
  - [FIXED] Annoying bug where client settings were not sticking
154
159
  - [FIXED] Long standing issue with Rack::ConditionalGet stopping MiniProfiler from working properly
155
160
 
156
- ## 1.13.pre - 2012-09-03 (Sam Saffron)
161
+ ## 0.1.13.pre - 2012-09-03 (Sam Saffron)
157
162
  - [ADDED] Setting: config.backtrace_ignores = [] - an array of regexes that match on caller lines that get ignored
158
163
  - [ADDED] Setting: config.backtrace_includes = [] - an array of regexes that get included in the trace by default
159
164
  - [ADDED] pp=normal-backtrace to clear the "sticky" state
@@ -162,7 +167,7 @@
162
167
  - [IMPROVED] Changed "pp=sample" to work with "caller" no need for stack trace gem
163
168
  - [FIXED] pg gem prepared statements were not being logged correctly
164
169
 
165
- ## 1.12.pre - 2012-08-20 (Sam Saffron)
170
+ ## 0.1.12.pre - 2012-08-20 (Sam Saffron)
166
171
  - [IMPROVED] Cap X-MiniProfiler-Ids at 10, otherwise the header can get killed
167
172
 
168
173
  ## 2012-08-10 (Sam Saffron)
data/README.md CHANGED
@@ -6,7 +6,9 @@ Middleware that displays speed badge for every html page. Designed to work both
6
6
 
7
7
  #### Features
8
8
 
9
- * database profiling. Currently supports Mysql2, Postgres, Oracle (oracle_enhanced ~> 1.5.0) and Mongoid3 (with fallback support to ActiveRecord)
9
+ * Database profiling - Currently supports Mysql2, Postgres, Oracle (oracle_enhanced ~> 1.5.0) and Mongoid3 (with fallback support to ActiveRecord)
10
+ * Call-stack profiling - Flame graphs showing time spent by gem
11
+ * Memory profiling - Per-request memory usage, GC stats, and global allocation metrics
10
12
 
11
13
  #### Learn more
12
14
 
@@ -36,14 +38,24 @@ gem 'rack-mini-profiler'
36
38
 
37
39
  NOTE: Be sure to require rack_mini_profiler below the `pg` and `mysql` gems in your Gemfile. rack_mini_profiler will identify these gems if they are loaded to insert instrumentation. If included too early no SQL will show up.
38
40
 
41
+ You can also include optional libraries to enable additional features.
42
+ ```ruby
43
+ # For memory profiling (requires Ruby MRI 2.1+)
44
+ gem 'memory_profiler'
45
+
46
+ # For call-stack profiling flamegraphs (requires Ruby MRI 2.0.0+)
47
+ gem 'flamegraph'
48
+ gem 'stackprof' # For Ruby MRI 2.1+
49
+ gem 'fast_stack' # For Ruby MRI 2.0
50
+ ```
51
+
39
52
  #### Rails
40
53
 
41
- All you have to do is include the Gem and you're good to go in development. See notes below for use in production.
54
+ All you have to do is to include the Gem and you're good to go in development. See notes below for use in production.
42
55
 
43
56
  #### Rails and manual initialization
44
57
 
45
- In case you need to make sure rack_mini_profiler initialized after all other gems.
46
- Or you want to execute some code before rack_mini_profiler required.
58
+ In case you need to make sure rack_mini_profiler initialized is after all other gems, or you want to execute some code before rack_mini_profiler required:
47
59
 
48
60
  ```ruby
49
61
  gem 'rack-mini-profiler', require: false
@@ -88,6 +100,40 @@ class MyApp < Sinatra::Base
88
100
  end
89
101
  ```
90
102
 
103
+ #### Hanami
104
+ For working with hanami, you need to use rack integration. Also, you need to add `Hanami::View::Rendering::Partial#render` method for profile:
105
+
106
+ ```ruby
107
+ # config.ru
108
+ require 'rack-mini-profiler'
109
+ Rack::MiniProfiler.profile_method(Hanami::View::Rendering::Partial, :render) { "Render partial #{@options[:partial]}" }
110
+
111
+ use Rack::MiniProfiler
112
+ ```
113
+
114
+ #### Patching ActiveRecord
115
+
116
+ A typical web application spends a lot of time querying the database. rack_mini_profiler will detect the ORM that is available
117
+ and apply patches to properly collect query statistics.
118
+
119
+ To make this work, declare the orm's gem before declaring `rack-mini-profiler` in the `Gemfile`:
120
+
121
+ ```ruby
122
+ gem 'pg'
123
+ gem 'mongoid'
124
+ gem 'rack-mini-profiler'
125
+
126
+ ```
127
+
128
+ If you wish to override this behavior, the environment variable `RACK_MINI_PROFILER_PATCH` is available.
129
+
130
+ ```bash
131
+ export RACK_MINI_PROFILER_PATCH="pg,mongoid"
132
+ # or
133
+ export RACK_MINI_PROFILER_PATCH="false"
134
+ # initializers/rack_profiler.rb: SqlPatches.patch %w(mongo)
135
+ ```
136
+
91
137
  ### Flamegraphs
92
138
 
93
139
  To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler):
@@ -95,8 +141,30 @@ To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-
95
141
  * add the [**flamegraph**](https://github.com/SamSaffron/flamegraph) gem to your Gemfile
96
142
  * visit a page in your app with `?pp=flamegraph`
97
143
 
98
- Flamegraph generation is supported in MRI 2.0, 2.1, and 2.2 only.
144
+ Flamegraph generation is supported in Ruby MRI 2.0+
145
+
146
+ ### Memory Profiling
147
+
148
+ Memory allocations can be measured (using the [memory_profiler](https://github.com/SamSaffron/memory_profiler) gem)
149
+ which will show allocations broken down by gem, file location, and class and will also highlight `String` allocations.
150
+ (Requires Ruby MRI 2.1.0+)
151
+
152
+ Add `?pp=profile-memory` to the URL of any request while Rack::MiniProfiler is enabled to generate the report.
153
+
154
+ Additional query parameters can be used to filter the results.
155
+
156
+ * `memory_profiler_allow_files` - filename pattern to include (default is all files)
157
+ * `memory_profiler_ignore_files` - filename pattern to exclude (default is no exclusions)
158
+ * `memory_profiler_top` - number of results per section (defaults to 50)
159
+
160
+ The allow/ignore patterns will be treated as regular expressions.
99
161
 
162
+ Example: `?pp=profile-memory&memory_profiler_allow_files=active_record|app`
163
+
164
+ There are two additional `pp` options that can be used to analyze memory which do not require the `memory_profiler` gem
165
+
166
+ * Use `?pp=profile-gc` to report on Garbage Collection statistics (requires Ruby MRI 1.9.3+)
167
+ * Use `?pp=analyze-memory` to report on ObjectSpace statistics (requires Ruby 2.0.0+)
100
168
 
101
169
  ## Access control in non-development environments
102
170
 
@@ -153,7 +221,7 @@ end
153
221
 
154
222
  `MemoryStore` stores results in a processes heap - something that does not work well in a multi process environment.
155
223
  `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).
224
+ `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). You will need to add `gem redis`/`gem dalli` respectively to your `Gemfile` to use these stores.
157
225
 
158
226
  Additionally you may implement an `AbstractStore` for your own provider.
159
227
 
@@ -184,6 +252,16 @@ Rails.application.config.to_prepare do
184
252
  end
185
253
  ```
186
254
 
255
+ ### Profiling arbitrary block of code
256
+
257
+ It is also possible to profile any arbitrary block of code by passing a block to `Rack::MiniProfiler.step(name, opts=nil)`.
258
+
259
+ ```ruby
260
+ Rack::MiniProfiler.step('Adding two elements') do
261
+ result = 1 + 2
262
+ end
263
+ ```
264
+
187
265
  ### Using in SPA applications
188
266
 
189
267
  Single page applications built using Ember, Angular or other frameworks need some special care, as routes often change without a full page load.
@@ -234,6 +312,7 @@ disable_env_dump|`false`|`true` disables `?pp=env`, which prevents sending ENV v
234
312
  base_url_path|`'/mini-profiler-resources/'`|Path for assets; added as a prefix when naming assets and sought when responding to requests.
235
313
  collapse_results|`true`|If multiple timing results exist in a single page, collapse them till clicked.
236
314
  max_traces_to_show|20|Maximum number of mini profiler timing blocks to show on one page
315
+ html_container|`body`|The HTML container (as a jQuery selector) to inject the mini_profiler UI into
237
316
 
238
317
  ### Custom middleware ordering (required if using `Rack::Deflate` with Rails)
239
318
 
@@ -281,7 +360,7 @@ c.pre_authorize_cb = lambda { |env|
281
360
  Rails.env.development? || Rails.env.production?
282
361
  }
283
362
  tmp = Rails.root.to_s + "/tmp/miniprofiler"
284
- FileUtils.mkdir_p(tmp) unless File.exists?(tmp)
363
+ FileUtils.mkdir_p(tmp) unless File.exist?(tmp)
285
364
  c.storage_options = {:path => tmp}
286
365
  c.storage = ::Rack::MiniProfiler::FileStore
287
366
  config.middleware.use(::Rack::MiniProfiler)
@@ -64,7 +64,7 @@ var MiniProfiler = (function () {
64
64
  $('body').append(data);
65
65
  success();
66
66
  }
67
- });
67
+ }, "text");
68
68
  }
69
69
  };
70
70
 
@@ -404,7 +404,7 @@ var MiniProfiler = (function () {
404
404
  });
405
405
 
406
406
  if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
407
- $(document).bind('page:change.mini-profiler', function() {
407
+ $(document).bind('page:change.mini-profiler turbolinks:load.mini-profiler', function() {
408
408
  unbindDocumentEvents();
409
409
  });
410
410
  }
@@ -467,8 +467,8 @@ var MiniProfiler = (function () {
467
467
 
468
468
  if (options.authorized) {
469
469
  // all fetched profilings will go in here
470
- container = $('<div class="profiler-results"/>').appendTo('body');
471
-
470
+ container = $('<div class="profiler-results"/>').appendTo(options.htmlContainer);
471
+
472
472
  // MiniProfiler.RenderIncludes() sets which corner to render in - default is upper left
473
473
  container.addClass("profiler-" + options.renderPosition);
474
474
 
@@ -634,6 +634,7 @@ var MiniProfiler = (function () {
634
634
  var controls = script.getAttribute('data-controls') === 'true';
635
635
  var authorized = script.getAttribute('data-authorized') === 'true';
636
636
  var startHidden = script.getAttribute('data-start-hidden') === 'true';
637
+ var htmlContainer = script.getAttribute('data-html-container');
637
638
 
638
639
  return {
639
640
  ids: ids,
@@ -648,7 +649,8 @@ var MiniProfiler = (function () {
648
649
  authorized: authorized,
649
650
  toggleShortcut: toggleShortcut,
650
651
  startHidden: startHidden,
651
- collapseResults: collapseResults
652
+ collapseResults: collapseResults,
653
+ htmlContainer: htmlContainer
652
654
  };
653
655
  })();
654
656
 
@@ -731,7 +733,7 @@ var MiniProfiler = (function () {
731
733
  }
732
734
 
733
735
 
734
- if (major === 2 || (major === 1 && minor >= 7)) {
736
+ if (major === 3 || major === 2 || (major === 1 && minor >= 7)) {
735
737
  MiniProfiler.jQuery = $ = jQuery;
736
738
  $(deferInit);
737
739
  } else {
@@ -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}" data-collapse-results="{collapseResults}"></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}" data-html-container="{htmlContainer}"></script>
@@ -1,9 +1,9 @@
1
1
  <html>
2
2
  <head>
3
- <title>{name} ({duration} ms) - Profiling Results</title>
4
- <script type='text/javascript' src='{path}jquery.1.7.1.js?v={version}'></script>
5
- <script type='text/javascript'> var profiler = {json}; </script>
6
- {includes}
3
+ <title><%= name %> (<%= duration %> ms) - Profiling Results</title>
4
+ <script type='text/javascript' src='<%= path %>jquery.1.7.1.js?v=<%= version %>'></script>
5
+ <script type='text/javascript'> var profiler = <%= json %>; </script>
6
+ <%= includes %>
7
7
  </head>
8
8
  <body>
9
9
  <div class='profiler-result-full'></div>
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class MiniProfiler
3
- ASSET_VERSION = '12b4b45a3c42e6e15503d7a03810ff33'.freeze
3
+ ASSET_VERSION = '52dc741c63ccbaf9d87102ee24033482'.freeze
4
4
  end
5
5
  end
@@ -18,12 +18,12 @@ module Rack
18
18
  :flamegraph_sample_rate, :logger, :pre_authorize_cb, :skip_paths,
19
19
  :skip_schema_queries, :storage, :storage_failure, :storage_instance,
20
20
  :storage_options, :user_provider
21
- attr_accessor :skip_sql_param_names, :max_sql_param_length
21
+ attr_accessor :skip_sql_param_names, :suppress_encoding, :max_sql_param_length
22
22
 
23
23
  # ui accessors
24
24
  attr_accessor :collapse_results, :max_traces_to_show, :position,
25
25
  :show_children, :show_controls, :show_trivial, :start_hidden,
26
- :toggle_shortcut
26
+ :toggle_shortcut, :html_container
27
27
 
28
28
  # Deprecated options
29
29
  attr_accessor :use_existing_jquery
@@ -63,6 +63,7 @@ module Rack
63
63
  @show_trivial = false
64
64
  @start_hidden = false
65
65
  @toggle_shortcut = 'Alt+P'
66
+ @html_container = 'body'
66
67
 
67
68
  self
68
69
  }
@@ -22,7 +22,7 @@ module Rack
22
22
  end
23
23
 
24
24
  def share_template
25
- @share_template ||= ::File.read(::File.expand_path("../html/share.html", ::File.dirname(__FILE__)))
25
+ @share_template ||= ERB.new(::File.read(::File.expand_path("../html/share.html", ::File.dirname(__FILE__))))
26
26
  end
27
27
 
28
28
  def current
@@ -109,14 +109,14 @@ module Rack
109
109
  end
110
110
 
111
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
112
+ path = "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}"
113
+ version = MiniProfiler::ASSET_VERSION
114
+ json = result_json
115
+ includes = get_profile_script(env)
116
+ name = page_struct[:name]
117
+ duration = page_struct.duration_ms.round(1).to_s
118
+
119
+ MiniProfiler.share_template.result(binding)
120
120
  end
121
121
 
122
122
  def serve_html(env)
@@ -253,6 +253,10 @@ module Rack
253
253
  env['HTTP_IF_NONE_MATCH'] = ''
254
254
  end
255
255
 
256
+ orig_accept_encoding = env['HTTP_ACCEPT_ENCODING']
257
+ # Prevent response body from being compressed
258
+ env['HTTP_ACCEPT_ENCODING'] = 'identity' if config.suppress_encoding
259
+
256
260
  if query_string =~ /pp=flamegraph/
257
261
  unless defined?(Flamegraph) && Flamegraph.respond_to?(:generate)
258
262
 
@@ -279,6 +283,7 @@ module Rack
279
283
  end
280
284
  ensure
281
285
  trace.disable if trace
286
+ env['HTTP_ACCEPT_ENCODING'] = orig_accept_encoding if config.suppress_encoding
282
287
  end
283
288
 
284
289
  skip_it = current.discard
@@ -292,6 +297,14 @@ module Rack
292
297
  # we must do this here, otherwise current[:discard] is not being properly treated
293
298
  if trace_exceptions
294
299
  body.close if body.respond_to? :close
300
+
301
+ query_params = Rack::Utils.parse_nested_query(query_string)
302
+ trace_exceptions_filter = query_params['trace_exceptions_filter']
303
+ if trace_exceptions_filter
304
+ trace_exceptions_regex = Regexp.new(trace_exceptions_filter)
305
+ exceptions.reject! { |ex| ex.class.name =~ trace_exceptions_regex }
306
+ end
307
+
295
308
  return client_settings.handle_cookie(dump_exceptions exceptions)
296
309
  end
297
310
 
@@ -392,13 +405,21 @@ module Rack
392
405
  end
393
406
 
394
407
  def dump_exceptions(exceptions)
395
- headers = {'Content-Type' => 'text/plain'}
396
- body = "Exceptions (#{exceptions.length} raised during request)\n\n"
397
- exceptions.each do |e|
398
- body << "#{e.class} #{e.message}\n#{e.backtrace.join("\n")}\n\n\n\n"
399
- end
408
+ body = "Exceptions raised during request\n\n"
409
+ if exceptions.empty?
410
+ body << "No exceptions raised"
411
+ else
412
+ body << "Exceptions: (#{exceptions.size} total)\n"
413
+ exceptions.group_by(&:class).each do |klass, exceptions|
414
+ body << " #{klass.name} (#{exceptions.size})\n"
415
+ end
400
416
 
401
- [200, headers, [body]]
417
+ body << "\nBacktraces\n"
418
+ exceptions.each_with_index do |e, i|
419
+ body << "##{i+1}: #{e.class} - \"#{e.message}\"\n #{e.backtrace.join("\n ")}\n\n"
420
+ end
421
+ end
422
+ text_result(body)
402
423
  end
403
424
 
404
425
  def dump_env(env)
@@ -565,7 +586,7 @@ Append the following to your query string:
565
586
  def get_profile_script(env)
566
587
  path = if ENV["PASSENGER_BASE_URI"] then
567
588
  # added because the SCRIPT_NAME workaround below then
568
- # breaks running under a prefix as permitted by Passenger.
589
+ # breaks running under a prefix as permitted by Passenger.
569
590
  "#{ENV['PASSENGER_BASE_URI']}#{@config.base_url_path}"
570
591
  elsif env["action_controller.instance"]
571
592
  # Rails engines break SCRIPT_NAME; the following appears to discard SCRIPT_NAME
@@ -586,7 +607,8 @@ Append the following to your query string:
586
607
  :authorized => true,
587
608
  :toggleShortcut => @config.toggle_shortcut,
588
609
  :startHidden => @config.start_hidden,
589
- :collapseResults => @config.collapse_results
610
+ :collapseResults => @config.collapse_results,
611
+ :htmlContainer => @config.html_container
590
612
  }
591
613
 
592
614
  if current && current.page_struct
@@ -44,7 +44,7 @@ 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)
47
+ FileUtils.mkdir_p(@path) unless ::File.exist?(@path)
48
48
 
49
49
  @timer_struct_cache = FileCache.new(@path, "mp_timers")
50
50
  @timer_struct_lock = Mutex.new
@@ -27,6 +27,9 @@ module Rack
27
27
  ::JSON.generate( @attributes, :max_nesting => 100 )
28
28
  end
29
29
 
30
+ def as_json(options = nil)
31
+ @attributes.as_json(options)
32
+ end
30
33
  end
31
34
  end
32
35
  end
@@ -57,12 +57,19 @@ module Rack
57
57
  end
58
58
 
59
59
  def to_json(*a)
60
- attribs = @attributes.merge(
60
+ ::JSON.generate(@attributes.merge(self.extra_json))
61
+ end
62
+
63
+ def as_json(options = nil)
64
+ super(options).merge!(extra_json)
65
+ end
66
+
67
+ def extra_json
68
+ {
61
69
  :started => '/Date(%d)/' % @attributes[:started],
62
70
  :duration_milliseconds => @attributes[:root][:duration_milliseconds],
63
71
  :custom_timing_names => @attributes[:custom_timing_stats].keys.sort
64
- )
65
- ::JSON.generate(attribs, :max_nesting => 100)
72
+ }
66
73
  end
67
74
  end
68
75
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class MiniProfiler
3
- VERSION = '0.10.1'
3
+ VERSION = '0.10.2'
4
4
  end
5
5
  end
@@ -28,10 +28,6 @@ module Rack::MiniProfilerRails
28
28
  c.skip_paths << app.config.assets.prefix
29
29
  end
30
30
 
31
- if Rails.env.development?
32
- c.skip_schema_queries = true
33
- end
34
-
35
31
  unless Rails.env.development? || Rails.env.test?
36
32
  c.authorization_mode = :whitelist
37
33
  end
@@ -88,6 +84,17 @@ module Rack::MiniProfilerRails
88
84
  Rack::MiniProfilerRails.initialize!(app)
89
85
  end
90
86
 
87
+ # Suppress compression when Rack::Deflater is lower in the middleware
88
+ # stack than Rack::MiniProfiler
89
+ config.after_initialize do |app|
90
+ middlewares = app.middleware.middlewares
91
+ if Rack::MiniProfiler.config.suppress_encoding.nil? &&
92
+ middlewares.include?(Rack::Deflater) &&
93
+ middlewares.index(Rack::Deflater) > middlewares.index(Rack::MiniProfiler)
94
+ Rack::MiniProfiler.config.suppress_encoding = true
95
+ end
96
+ end
97
+
91
98
  # TODO: Implement something better here
92
99
  # config.after_initialize do
93
100
  #
@@ -47,7 +47,7 @@ module Rack
47
47
  end
48
48
  end
49
49
 
50
- if defined?(::Rails) && !SqlPatches.patched?
50
+ if defined?(::Rails)
51
51
  insert_instrumentation
52
52
  end
53
53
  end
@@ -26,5 +26,3 @@ class Mysql2::Client
26
26
  result
27
27
  end
28
28
  end
29
-
30
- SqlPatches.patched = true
@@ -66,5 +66,3 @@ class ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
66
66
  !(Rack::MiniProfiler.config.skip_schema_queries && SCHEMA_QUERY_TYPES.include?(name))
67
67
  end
68
68
  end
69
-
70
- SqlPatches.patched = true
@@ -100,5 +100,3 @@ class PG::Connection
100
100
 
101
101
  alias_method :query, :exec
102
102
  end
103
-
104
- SqlPatches.patched = true
@@ -1,16 +1,4 @@
1
1
  class SqlPatches
2
- def self.unpatched?
3
- !patched?
4
- end
5
-
6
- def self.patched?
7
- @patched
8
- end
9
-
10
- def self.patched=(val)
11
- @patched = val
12
- end
13
-
14
2
  def self.correct_version?(required_version, klass)
15
3
  Gem::Dependency.new('', required_version).match?('', klass::VERSION)
16
4
  rescue NameError
@@ -32,17 +20,45 @@ class SqlPatches
32
20
  def self.elapsed_time(start_time)
33
21
  ((Time.now - start_time).to_f * 1000).round(1)
34
22
  end
23
+
24
+ def self.sql_patches
25
+ patches = []
26
+
27
+ patches << 'mysql2' if defined?(Mysql2::Client) && Mysql2::Client.class == Class
28
+ patches << 'pg' if defined?(PG::Result) && PG::Result.class == Class
29
+ patches << 'oracle_enhanced' if defined?(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter) && ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class == Class &&
30
+ SqlPatches.correct_version?('~> 1.5.0', ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter)
31
+ # if the adapters were directly patched, don't patch again
32
+ return patches unless patches.empty?
33
+ patches << 'sequel' if defined?(Sequel::Database) && Sequel::Database.class == Class
34
+ patches << 'activerecord' if defined?(ActiveRecord) && ActiveRecord.class == Module
35
+
36
+ patches
37
+ end
38
+
39
+ def self.other_patches
40
+ patches = []
41
+ patches << 'mongo' if defined?(Mongo::Server::Connection) && Mongo.class == Module
42
+ patches << 'moped' if defined?(Moped::Node) && Moped::Node.class == Class
43
+ patches << 'plucky' if defined?(Plucky::Query) && Plucky::Query.class == Class
44
+ patches << 'rsolr' if defined?(RSolr::Connection) && RSolr::Connection.class == Class && RSolr::VERSION[0] != "0"
45
+ patches << 'nobrainer' if defined?(NoBrainer) && NoBrainer.class == Module
46
+ patches << 'riak' if defined?(Riak) && Riak.class == Module
47
+ patches << 'neo4j' if defined?(Neo4j::Core) && Neo4j::Core::Query.class == Class
48
+ patches
49
+ end
50
+
51
+ def self.all_patch_files
52
+ env_var = ENV["RACK_MINI_PROFILER_PATCH"]
53
+ return [] if env_var == "false"
54
+ env_var ? env_var.split(",").map(&:strip) : sql_patches + other_patches
55
+ end
56
+
57
+ def self.patch(patch_files = all_patch_files)
58
+ patch_files.each do |patch_file|
59
+ require "patches/db/#{patch_file}"
60
+ end
61
+ end
35
62
  end
36
63
 
37
- require 'patches/db/mysql2' if defined?(Mysql2::Client) && Mysql2::Client.class == Class
38
- require 'patches/db/pg' if defined?(PG::Result) && PG::Result.class == Class
39
- require 'patches/db/oracle_enhanced' if defined?(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter) && ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class == Class && SqlPatches.correct_version?('~> 1.5.0', ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter)
40
- require 'patches/db/mongo' if defined?(Mongo::Server::Connection) && Mongo.class == Module
41
- require 'patches/db/moped' if defined?(Moped::Node) && Moped::Node.class == Class
42
- require 'patches/db/plucky' if defined?(Plucky::Query) && Plucky::Query.class == Class
43
- require 'patches/db/rsolr' if defined?(RSolr::Connection) && RSolr::Connection.class == Class && RSolr::VERSION[0] != "0"
44
- require 'patches/db/sequel' if SqlPatches.unpatched? && defined?(Sequel::Database) && Sequel::Database.class == Class
45
- require 'patches/db/activerecord' if SqlPatches.unpatched? && defined?(ActiveRecord) && ActiveRecord.class == Module
46
- require 'patches/db/nobrainer' if defined?(NoBrainer) && NoBrainer.class == Module
47
- require 'patches/db/riak' if defined?(Riak) && Riak.class == Module
48
- require 'patches/db/neo4j' if defined?(Neo4j::Core) && Neo4j::Core::Query.class == Class
64
+ SqlPatches.patch
@@ -31,6 +31,6 @@ require 'mini_profiler/profiler'
31
31
  require 'patches/sql_patches'
32
32
  require 'patches/net_patches'
33
33
 
34
- if defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i >= 3
34
+ if defined?(::Rails) && defined?(::Rails::VERSION) && ::Rails::VERSION::MAJOR.to_i >= 3
35
35
  require 'mini_profiler_rails/railtie'
36
36
  end
@@ -30,8 +30,6 @@ Gem::Specification.new do |s|
30
30
  s.add_development_dependency 'therubyracer'
31
31
  s.add_development_dependency 'less'
32
32
  s.add_development_dependency 'flamegraph'
33
- s.add_development_dependency 'guard'
34
- s.add_development_dependency 'guard-rspec'
35
33
 
36
34
  s.require_paths = ["lib"]
37
35
  end
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.10.1
4
+ version: 0.10.2
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: 2016-05-18 00:00:00.000000000 Z
13
+ date: 2017-02-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -152,34 +152,6 @@ dependencies:
152
152
  - - ">="
153
153
  - !ruby/object:Gem::Version
154
154
  version: '0'
155
- - !ruby/object:Gem::Dependency
156
- name: guard
157
- requirement: !ruby/object:Gem::Requirement
158
- requirements:
159
- - - ">="
160
- - !ruby/object:Gem::Version
161
- version: '0'
162
- type: :development
163
- prerelease: false
164
- version_requirements: !ruby/object:Gem::Requirement
165
- requirements:
166
- - - ">="
167
- - !ruby/object:Gem::Version
168
- version: '0'
169
- - !ruby/object:Gem::Dependency
170
- name: guard-rspec
171
- requirement: !ruby/object:Gem::Requirement
172
- requirements:
173
- - - ">="
174
- - !ruby/object:Gem::Version
175
- version: '0'
176
- type: :development
177
- prerelease: false
178
- version_requirements: !ruby/object:Gem::Requirement
179
- requirements:
180
- - - ">="
181
- - !ruby/object:Gem::Version
182
- version: '0'
183
155
  description: Profiling toolkit for Rack applications with Rails integration. Client
184
156
  Side profiling, DB profiling and Server profiling.
185
157
  email: sam.saffron@gmail.com
@@ -258,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
230
  version: '0'
259
231
  requirements: []
260
232
  rubyforge_project:
261
- rubygems_version: 2.5.1
233
+ rubygems_version: 2.5.2
262
234
  signing_key:
263
235
  specification_version: 4
264
236
  summary: Profiles loading speed for rack applications.