rack-mini-profiler 0.10.1 → 0.10.2

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