rack-mini-profiler 0.1.2 → 0.1.3

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

Potentially problematic release.


This version of rack-mini-profiler might be problematic. Click here for more details.

@@ -6,3 +6,12 @@
6
6
  * Fixed bug where unviewed missing ids never got cleared
7
7
  * Supress all '/assets/' in the rails tie (makes debugging easier)
8
8
  * record_sql was mega buggy
9
+
10
+ 9-July-2012 - Sam
11
+
12
+ * Cleaned up mechanism for profiling in production, all you need to do now
13
+ is call Rack::MiniProfiler.authorize_request to get profiling working in
14
+ production
15
+ * Added option to display full backtraces pp=full-backtrace
16
+ * Cleaned up railties, got rid of the post authorize callback
17
+ * Version 0.1.3
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Middleware that displays speed badge for every html page. Designed to work both in production and in development.
4
4
 
5
- ## Using mini-profiler in your app
5
+ ## Using rack-mini-profiler in your app
6
6
 
7
7
  Install/add to Gemfile
8
8
 
@@ -13,6 +13,20 @@ Using Rails:
13
13
 
14
14
  All you have to do is include the Gem and you're good to go in development.
15
15
 
16
+ rack-mini-profiler is designed with production profiling in mind. To enable that just run `Rack::MiniProfiler.authorize_request` once you know a request is allowed to profile.
17
+
18
+ For example:
19
+
20
+ ```ruby
21
+ # A hook in your ApplicationController
22
+ def authorize
23
+ if current_user.is_admin?
24
+ Rack::MiniProfiler.authorize_request
25
+ end
26
+ end
27
+ ````
28
+
29
+
16
30
  Using Builder:
17
31
 
18
32
  ```ruby
@@ -56,9 +70,10 @@ In a Rails app, this can be done conveniently in an initializer such as config/i
56
70
  ## Available Options
57
71
 
58
72
  * pre_authorize_cb - A lambda callback you can set to determine whether or not mini_profiler should be visible on a given request. Default in a Rails environment is only on in development mode. If in a Rack app, the default is always on.
59
- * post_authorize_cb - A lambda that is called after your request executed to ensure you really have access to the results.
60
73
  * position - Can either be 'right' or 'left'. Default is 'left'.
61
74
  * skip_schema_queries - Whether or not you want to log the queries about the schema of your tables. Default is 'false', 'true' in rails development.
62
75
 
76
+ ## Special query strings
63
77
 
78
+ If you include the query string `pp=help` at the end of your request you will see the various option you have. You can use these options to extend or contract the amount of diagnostics rack-mini-profiler gathers.
64
79
 
@@ -12,9 +12,9 @@ module Rack
12
12
  @attributes
13
13
  end
14
14
 
15
- attr_accessor :auto_inject, :base_url_path, :pre_authorize_cb, :post_authorize_cb, :position,
15
+ attr_accessor :auto_inject, :base_url_path, :pre_authorize_cb, :position,
16
16
  :backtrace_remove, :backtrace_filter, :skip_schema_queries,
17
- :storage, :user_provider, :storage_instance, :storage_options, :skip_paths
17
+ :storage, :user_provider, :storage_instance, :storage_options, :skip_paths, :authorization_mode
18
18
 
19
19
  def self.default
20
20
  new.instance_eval {
@@ -25,11 +25,11 @@ module Rack
25
25
  @pre_authorize_cb = lambda {|env| true}
26
26
 
27
27
  # called after rack chain, to ensure we are REALLY allowed to profile
28
- @post_authorize_cb = nil
29
28
  @position = 'left' # Where it is displayed
30
29
  @skip_schema_queries = false
31
30
  @storage = MiniProfiler::MemoryStore
32
31
  @user_provider = Proc.new{|env| Rack::Request.new(env).ip}
32
+ @authorization_mode = :allow_all
33
33
  self
34
34
  }
35
35
  end
@@ -114,15 +114,26 @@ module Rack
114
114
  # we use TLS cause we need access to this from sql blocks and code blocks that have no access to env
115
115
  Thread.current['profiler.mini.private'] = c
116
116
  end
117
+
118
+ def current
119
+ MiniProfiler.current
120
+ end
121
+
122
+ def current=(c)
123
+ MiniProfiler.current=c
124
+ end
117
125
 
126
+ # discard existing results, don't track this request
118
127
  def self.discard_results
119
128
  current[:discard] = true if current
120
129
  end
121
-
130
+
131
+ # user has the mini profiler cookie, only used when config.authorization_mode == :whitelist
122
132
  def self.has_profiling_cookie?(env)
123
133
  env['HTTP_COOKIE'] && env['HTTP_COOKIE'].include?("__profilin=stylin")
124
134
  end
125
135
 
136
+ # remove the mini profiler cookie, only used when config.authorization_mode == :whitelist
126
137
  def self.remove_profiling_cookie(headers)
127
138
  Rack::Utils.delete_cookie_header!(headers, '__profilin')
128
139
  end
@@ -131,14 +142,6 @@ module Rack
131
142
  Rack::Utils.set_cookie_header!(headers, '__profilin', 'stylin')
132
143
  end
133
144
 
134
- def current
135
- MiniProfiler.current
136
- end
137
-
138
- def current=(c)
139
- MiniProfiler.current=c
140
- end
141
-
142
145
  def config
143
146
  @config
144
147
  end
@@ -151,21 +154,32 @@ module Rack
151
154
  self.current['current_timer'] = current['page_struct']['Root']
152
155
  end
153
156
 
157
+ def self.authorize_request
158
+ Thread.current[:mp_authorized] = true
159
+ end
154
160
 
155
- def call(env)
156
- status = headers = body = nil
161
+ def self.deauthorize_request
162
+ Thread.current[:mp_authorized] = nil
163
+ end
157
164
 
165
+ def self.request_authorized?
166
+ Thread.current[:mp_authorized]
167
+ end
168
+
169
+ def call(env)
170
+ status = headers = body = nil
158
171
  path = env['PATH_INFO']
159
- # only profile if authorized
160
- if !@config.pre_authorize_cb.call(env) ||
161
- (@config.skip_paths && @config.skip_paths.any?{ |p| path[0,p.length] == p}) ||
162
- env["QUERY_STRING"] =~ /pp=skip/
163
172
 
173
+ skip_it = (@config.pre_authorize_cb && !@config.pre_authorize_cb.call(env)) ||
174
+ (@config.skip_paths && @config.skip_paths.any?{ |p| path[0,p.length] == p}) ||
175
+ env["QUERY_STRING"] =~ /pp=skip/
176
+
177
+ has_profiling_cookie = self.class.has_profiling_cookie?(env)
178
+
179
+ if skip_it || (@config.authorization_mode == :whitelist && !has_profiling_cookie)
164
180
  status,headers,body = @app.call(env)
165
- if @config.post_authorize_cb
166
- if @config.post_authorize_cb.call(env)
167
- self.class.set_profiling_cookie(headers)
168
- end
181
+ if !skip_it && @config.authorization_mode == :whitelist && !has_profiling_cookie && MiniProfiler.request_authorized?
182
+ self.class.set_profiling_cookie(headers)
169
183
  end
170
184
  return [status,headers,body]
171
185
  end
@@ -174,10 +188,14 @@ module Rack
174
188
  return serve_html(env) if env['PATH_INFO'].start_with? @config.base_url_path
175
189
 
176
190
  MiniProfiler.create_current(env, @config)
191
+
192
+ MiniProfiler.deauthorize_request if @config.authorization_mode == :whitelist
177
193
  if env["QUERY_STRING"] =~ /pp=no-backtrace/
178
194
  current['skip-backtrace'] = true
195
+ elsif env["QUERY_STRING"] =~ /pp=full-backtrace/
196
+ current['full-backtrace'] = true
179
197
  end
180
-
198
+
181
199
  done_sampling = false
182
200
  quit_sampler = false
183
201
  backtraces = nil
@@ -212,15 +230,15 @@ module Rack
212
230
  end
213
231
  end
214
232
 
215
- skip_it = current['discard']
216
- if @config.post_authorize_cb && !@config.post_authorize_cb.call(env)
217
- self.class.remove_profiling_cookie(headers)
233
+ skip_it = current[:discard]
234
+ if (config.authorization_mode == :whitelist && !MiniProfiler.request_authorized?)
235
+ MiniProfiler.remove_profiling_cookie(headers)
218
236
  skip_it = true
219
237
  end
220
-
238
+
221
239
  return [status,headers,body] if skip_it
222
240
 
223
- # we must do this here, otherwise current['discard'] is not being properly treated
241
+ # we must do this here, otherwise current[:discard] is not being properly treated
224
242
  if env["QUERY_STRING"] =~ /pp=env/
225
243
  body.close if body.respond_to? :close
226
244
  return dump_env env
@@ -287,7 +305,8 @@ module Rack
287
305
  pp=help : display this screen
288
306
  pp=env : display the rack environment
289
307
  pp=skip : skip mini profiler for this request
290
- pp=no-backtrace : don't collect stack traces from all the SQL calls
308
+ pp=no-backtrace : don't collect stack traces from all the SQL executed
309
+ pp=full-backtrace : enable full backtrace for SQL executed
291
310
  pp=sample : sample stack traces and return a report isolating heavy usage (requires the stacktrace gem)
292
311
  "
293
312
  #headers['Content-Length'] = body.length
@@ -383,7 +402,7 @@ module Rack
383
402
 
384
403
  def record_sql(query, elapsed_ms)
385
404
  c = current
386
- c['current_timer'].add_sql(query, elapsed_ms, c['page_struct'], c['skip-backtrace']) if (c && c['current_timer'])
405
+ c['current_timer'].add_sql(query, elapsed_ms, c['page_struct'], c['skip-backtrace'], c['full-backtrace']) if (c && c['current_timer'])
387
406
  end
388
407
 
389
408
  end
@@ -45,8 +45,8 @@ module Rack
45
45
  @children_duration += request_timer['DurationMilliseconds']
46
46
  end
47
47
 
48
- def add_sql(query, elapsed_ms, page, skip_backtrace = false)
49
- timer = SqlTimerStruct.new(query, elapsed_ms, page, skip_backtrace)
48
+ def add_sql(query, elapsed_ms, page, skip_backtrace = false, full_backtrace = false)
49
+ timer = SqlTimerStruct.new(query, elapsed_ms, page, skip_backtrace, full_backtrace)
50
50
  timer['ParentTimingId'] = self['Id']
51
51
  self['SqlTimings'].push(timer)
52
52
  self['HasSqlTimings'] = true
@@ -5,7 +5,7 @@ module Rack
5
5
 
6
6
  # Timing system for a SQL query
7
7
  class SqlTimerStruct < TimerStruct
8
- def initialize(query, duration_ms, page, skip_backtrace = false)
8
+ def initialize(query, duration_ms, page, skip_backtrace = false, full_backtrace = false)
9
9
 
10
10
  stack_trace = nil
11
11
  unless skip_backtrace
@@ -13,8 +13,8 @@ module Rack
13
13
  stack_trace = ""
14
14
  # Clean up the stack trace if there are options to do so
15
15
  Kernel.caller.each do |ln|
16
- ln.gsub!(Rack::MiniProfiler.config.backtrace_remove, '') if Rack::MiniProfiler.config.backtrace_remove
17
- if Rack::MiniProfiler.config.backtrace_filter.nil? or ln =~ Rack::MiniProfiler.config.backtrace_filter
16
+ ln.gsub!(Rack::MiniProfiler.config.backtrace_remove, '') if Rack::MiniProfiler.config.backtrace_remove and !full_backtrace
17
+ if full_backtrace or Rack::MiniProfiler.config.backtrace_filter.nil? or ln =~ Rack::MiniProfiler.config.backtrace_filter
18
18
  stack_trace << ln << "\n"
19
19
  end
20
20
  end
@@ -6,8 +6,7 @@ module MiniProfilerRails
6
6
 
7
7
  # By default, only show the MiniProfiler in development mode, in production allow profiling if post_authorize_cb is set
8
8
  c.pre_authorize_cb = lambda { |env|
9
- Rails.env.development? ||
10
- (Rack::MiniProfiler.config.post_authorize_cb && Rack::MiniProfiler.has_profiling_cookie?(env))
9
+ Rails.env.development? || Rails.env.production?
11
10
  }
12
11
 
13
12
  if Rails.env.development?
@@ -16,6 +15,10 @@ module MiniProfilerRails
16
15
  c.skip_schema_queries = true
17
16
  end
18
17
 
18
+ if Rails.env.production?
19
+ c.authorization_mode = :whitelist
20
+ end
21
+
19
22
  # The file store is just so much less flaky
20
23
  tmp = Rails.root.to_s + "/tmp/miniprofiler"
21
24
  Dir::mkdir(tmp) unless File.exists?(tmp)
@@ -29,7 +32,7 @@ module MiniProfilerRails
29
32
  c.skip_schema_queries = Rails.env != 'production'
30
33
 
31
34
  # Install the Middleware
32
- app.middleware.insert_before 'Rack::Lock', 'Rack::MiniProfiler'
35
+ app.middleware.insert(0, Rack::MiniProfiler)
33
36
 
34
37
  # Attach to various Rails methods
35
38
  ::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"}
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rack-mini-profiler"
3
- s.version = "0.1.2"
3
+ s.version = "0.1.3"
4
4
  s.summary = "Profiles loading speed for rack applications."
5
5
  s.authors = ["Aleks Totic","Sam Saffron", "Robin Ward"]
6
6
  s.date = "2012-04-02"
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  ].concat( Dir.glob('lib/**/*').reject {|f| File.directory?(f) || f =~ /~$/ } )
13
13
  s.extra_rdoc_files = [
14
14
  "README.md",
15
- "CHANGELOG.md"
15
+ "CHANGELOG"
16
16
  ]
17
17
  s.add_runtime_dependency 'rack', '>= 1.1.3'
18
18
  if RUBY_VERSION < "1.9"
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.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -84,7 +84,7 @@ executables: []
84
84
  extensions: []
85
85
  extra_rdoc_files:
86
86
  - README.md
87
- - CHANGELOG.md
87
+ - CHANGELOG
88
88
  files:
89
89
  - rack-mini-profiler.gemspec
90
90
  - lib/mini_profiler/sql_timer_struct.rb
@@ -115,7 +115,7 @@ files:
115
115
  - lib/mini_profiler_rails/railtie.rb
116
116
  - lib/patches/sql_patches.rb
117
117
  - README.md
118
- - CHANGELOG.md
118
+ - CHANGELOG
119
119
  homepage: http://miniprofiler.com
120
120
  licenses: []
121
121
  post_install_message:
@@ -130,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
130
  version: '0'
131
131
  segments:
132
132
  - 0
133
- hash: 876564877
133
+ hash: 809318397
134
134
  required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  none: false
136
136
  requirements:
@@ -139,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
139
  version: '0'
140
140
  segments:
141
141
  - 0
142
- hash: 876564877
142
+ hash: 809318397
143
143
  requirements: []
144
144
  rubyforge_project:
145
145
  rubygems_version: 1.8.24