rack-mini-profiler 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +10 -0
  3. data/README.md +2 -1
  4. data/lib/html/includes.css +5 -5
  5. data/lib/html/includes.js +38 -3
  6. data/lib/html/includes.scss +1 -1
  7. data/lib/html/includes.tmpl +5 -0
  8. data/lib/html/profile_handler.js +1 -1
  9. data/lib/mini_profiler/asset_version.rb +1 -1
  10. data/lib/mini_profiler/client_settings.rb +11 -12
  11. data/lib/mini_profiler/config.rb +17 -17
  12. data/lib/mini_profiler/context.rb +3 -3
  13. data/lib/mini_profiler/gc_profiler.rb +15 -16
  14. data/lib/mini_profiler/profiler.rb +50 -54
  15. data/lib/mini_profiler/profiling_methods.rb +4 -4
  16. data/lib/mini_profiler/storage/file_store.rb +10 -7
  17. data/lib/mini_profiler/storage/memcache_store.rb +4 -5
  18. data/lib/mini_profiler/storage/memory_store.rb +2 -3
  19. data/lib/mini_profiler/storage/redis_store.rb +2 -2
  20. data/lib/mini_profiler/timer_struct/base.rb +2 -2
  21. data/lib/mini_profiler/timer_struct/client.rb +6 -7
  22. data/lib/mini_profiler/timer_struct/custom.rb +4 -4
  23. data/lib/mini_profiler/timer_struct/page.rb +26 -25
  24. data/lib/mini_profiler/timer_struct/request.rb +25 -24
  25. data/lib/mini_profiler/timer_struct/sql.rb +20 -20
  26. data/lib/mini_profiler/version.rb +1 -1
  27. data/lib/mini_profiler_rails/railtie.rb +3 -3
  28. data/lib/patches/db/activerecord.rb +2 -2
  29. data/lib/patches/db/moped.rb +2 -2
  30. data/lib/patches/db/mysql2.rb +5 -5
  31. data/lib/patches/db/nobrainer.rb +1 -1
  32. data/lib/patches/db/pg.rb +34 -16
  33. data/lib/patches/db/riak.rb +11 -11
  34. data/lib/patches/db/rsolr.rb +2 -2
  35. data/rack-mini-profiler.gemspec +5 -4
  36. metadata +18 -4
@@ -41,7 +41,7 @@ module Rack
41
41
  self.current.discard = true if current
42
42
  end
43
43
 
44
- def create_current(env={}, options={})
44
+ def create_current(env = {}, options = {})
45
45
  # profiling the request
46
46
  context = Context.new
47
47
  context.inject_js = config.auto_inject && (!env['HTTP_X_REQUESTED_WITH'].eql? 'XMLHttpRequest')
@@ -102,11 +102,11 @@ module Rack
102
102
  # If we're an XMLHttpRequest, serve up the contents as JSON
103
103
  if request.xhr?
104
104
  result_json = page_struct.to_json
105
- [200, { 'Content-Type' => 'application/json'}, [result_json]]
105
+ [200, { 'Content-Type' => 'application/json' }, [result_json]]
106
106
  else
107
107
  # Otherwise give the HTML back
108
108
  html = generate_html(page_struct, env)
109
- [200, {'Content-Type' => 'text/html'}, [html]]
109
+ [200, { 'Content-Type' => 'text/html' }, [html]]
110
110
  end
111
111
  end
112
112
 
@@ -131,11 +131,10 @@ module Rack
131
131
  resources_env = env.dup
132
132
  resources_env['PATH_INFO'] = file_name
133
133
 
134
- rack_file = Rack::File.new(MiniProfiler.resources_root, {'Cache-Control' => 'max-age:86400'})
134
+ rack_file = Rack::File.new(MiniProfiler.resources_root, 'Cache-Control' => 'max-age:86400')
135
135
  rack_file.call(resources_env)
136
136
  end
137
137
 
138
-
139
138
  def current
140
139
  MiniProfiler.current
141
140
  end
@@ -144,12 +143,10 @@ module Rack
144
143
  MiniProfiler.current = c
145
144
  end
146
145
 
147
-
148
146
  def config
149
147
  @config
150
148
  end
151
149
 
152
-
153
150
  def call(env)
154
151
 
155
152
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -164,7 +161,7 @@ module Rack
164
161
  env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME'] = ENV['PASSENGER_BASE_URI'] || env['SCRIPT_NAME']
165
162
 
166
163
  skip_it = (@config.pre_authorize_cb && !@config.pre_authorize_cb.call(env)) ||
167
- (@config.skip_paths && @config.skip_paths.any?{ |p| path.start_with?(p) }) ||
164
+ (@config.skip_paths && @config.skip_paths.any? { |p| path.start_with?(p) }) ||
168
165
  query_string =~ /pp=skip/
169
166
 
170
167
  if skip_it || (
@@ -189,9 +186,9 @@ module Rack
189
186
  end
190
187
 
191
188
  if skip_it || !config.enabled
192
- status,headers,body = @app.call(env)
189
+ status, headers, body = @app.call(env)
193
190
  client_settings.disable_profiling = true
194
- return client_settings.handle_cookie([status,headers,body])
191
+ return client_settings.handle_cookie([status, headers, body])
195
192
  else
196
193
  client_settings.disable_profiling = false
197
194
  end
@@ -206,13 +203,13 @@ module Rack
206
203
  if query_string =~ /pp=profile-memory/
207
204
  query_params = Rack::Utils.parse_nested_query(query_string)
208
205
  options = {
209
- :ignore_files => query_params['memory_profiler_ignore_files'],
210
- :allow_files => query_params['memory_profiler_allow_files'],
206
+ ignore_files: query_params['memory_profiler_ignore_files'],
207
+ allow_files: query_params['memory_profiler_allow_files'],
211
208
  }
212
- options[:top]= Integer(query_params['memory_profiler_top']) if query_params.key?('memory_profiler_top')
209
+ options[:top] = Integer(query_params['memory_profiler_top']) if query_params.key?('memory_profiler_top')
213
210
  result = StringIO.new
214
211
  report = MemoryProfiler.report(options) do
215
- _,_,body = @app.call(env)
212
+ _, _, body = @app.call(env)
216
213
  body.close if body.respond_to? :close
217
214
  end
218
215
  report.pretty_print(result)
@@ -236,8 +233,7 @@ module Rack
236
233
  flamegraph = nil
237
234
 
238
235
  trace_exceptions = query_string =~ /pp=trace-exceptions/ && defined? TracePoint
239
- status, headers, body, exceptions,trace = nil
240
-
236
+ status, headers, body, exceptions, trace = nil
241
237
 
242
238
  if trace_exceptions
243
239
  exceptions = []
@@ -264,7 +260,7 @@ module Rack
264
260
  unless defined?(Flamegraph) && Flamegraph.respond_to?(:generate)
265
261
 
266
262
  flamegraph = "Please install the flamegraph gem and require it: add gem 'flamegraph' to your Gemfile"
267
- status,headers,body = @app.call(env)
263
+ status, headers, body = @app.call(env)
268
264
  else
269
265
  # do not sully our profile with mini profiler timings
270
266
  current.measure = false
@@ -277,12 +273,12 @@ module Rack
277
273
  else
278
274
  sample_rate = config.flamegraph_sample_rate
279
275
  end
280
- flamegraph = Flamegraph.generate(nil, :fidelity => sample_rate, :embed_resources => query_string =~ /embed/, :mode => mode) do
281
- status,headers,body = @app.call(env)
276
+ flamegraph = Flamegraph.generate(nil, fidelity: sample_rate, embed_resources: query_string =~ /embed/, mode: mode) do
277
+ status, headers, body = @app.call(env)
282
278
  end
283
279
  end
284
280
  else
285
- status,headers,body = @app.call(env)
281
+ status, headers, body = @app.call(env)
286
282
  end
287
283
  ensure
288
284
  trace.disable if trace
@@ -295,7 +291,7 @@ module Rack
295
291
  skip_it = true
296
292
  end
297
293
 
298
- return client_settings.handle_cookie([status,headers,body]) if skip_it
294
+ return client_settings.handle_cookie([status, headers, body]) if skip_it
299
295
 
300
296
  # we must do this here, otherwise current[:discard] is not being properly treated
301
297
  if trace_exceptions
@@ -335,7 +331,6 @@ module Rack
335
331
  return client_settings.handle_cookie(self.flamegraph(flamegraph))
336
332
  end
337
333
 
338
-
339
334
  begin
340
335
  @storage.save(page_struct)
341
336
  # no matter what it is, it should be unviewed, otherwise we will miss POST
@@ -343,7 +338,7 @@ module Rack
343
338
 
344
339
  # inject headers, script
345
340
  if status >= 200 && status < 300
346
- result = inject_profiler(env,status,headers,body)
341
+ result = inject_profiler(env, status, headers, body)
347
342
  return client_settings.handle_cookie(result) if result
348
343
  end
349
344
  rescue Exception => e
@@ -359,7 +354,7 @@ module Rack
359
354
  self.current = nil
360
355
  end
361
356
 
362
- def inject_profiler(env,status,headers,body)
357
+ def inject_profiler(env, status, headers, body)
363
358
  # mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
364
359
  # Rack::ETag has already inserted some nonesense in the chain
365
360
  content_type = headers['Content-Type']
@@ -382,7 +377,7 @@ module Rack
382
377
  script = self.get_profile_script(env)
383
378
 
384
379
  if String === body
385
- response.write inject(body,script)
380
+ response.write inject(body, script)
386
381
  else
387
382
  body.each { |fragment| response.write inject(fragment, script) }
388
383
  end
@@ -420,7 +415,7 @@ module Rack
420
415
 
421
416
  body << "\nBacktraces\n"
422
417
  exceptions.each_with_index do |e, i|
423
- body << "##{i+1}: #{e.class} - \"#{e.message}\"\n #{e.backtrace.join("\n ")}\n\n"
418
+ body << "##{i + 1}: #{e.class} - \"#{e.message}\"\n #{e.backtrace.join("\n ")}\n\n"
424
419
  end
425
420
  end
426
421
  text_result(body)
@@ -428,12 +423,12 @@ module Rack
428
423
 
429
424
  def dump_env(env)
430
425
  body = "Rack Environment\n---------------\n".dup
431
- env.each do |k,v|
426
+ env.each do |k, v|
432
427
  body << "#{k}: #{v}\n"
433
428
  end
434
429
 
435
430
  body << "\n\nEnvironment\n---------------\n"
436
- ENV.each do |k,v|
431
+ ENV.each do |k, v|
437
432
  body << "#{k}: #{v}\n"
438
433
  end
439
434
 
@@ -449,9 +444,9 @@ module Rack
449
444
  end
450
445
 
451
446
  def trim_strings(strings, max_size)
452
- strings.sort!{|a,b| b[1] <=> a[1]}
447
+ strings.sort! { |a, b| b[1] <=> a[1] }
453
448
  i = 0
454
- strings.delete_if{|_| (i+=1) > max_size}
449
+ strings.delete_if { |_| (i += 1) > max_size }
455
450
  end
456
451
 
457
452
  def analyze_memory
@@ -470,8 +465,8 @@ module Rack
470
465
 
471
466
  unless str.valid_encoding?
472
467
  # work around bust string with a double conversion
473
- str.encode!("utf-16","utf-8",:invalid => :replace)
474
- str.encode!("utf-8","utf-16")
468
+ str.encode!("utf-16", "utf-8", invalid: :replace)
469
+ str.encode!("utf-8", "utf-16")
475
470
  end
476
471
  end
477
472
 
@@ -484,8 +479,8 @@ module Rack
484
479
  total_strings = counts[:T_STRING]
485
480
 
486
481
  body << counts
487
- .sort{|a,b| b[1] <=> a[1]}
488
- .map{|k,v| "#{k}: #{v}"}
482
+ .sort { |a, b| b[1] <=> a[1] }
483
+ .map { |k, v| "#{k}: #{v}" }
489
484
  .join("\n")
490
485
 
491
486
  strings = []
@@ -509,19 +504,19 @@ module Rack
509
504
  trim_strings(strings, max_size)
510
505
 
511
506
  body << "\n\n\n1000 Largest strings:\n\n"
512
- body << strings.map{|s,len| "#{s[0..1000]}\n(len: #{len})\n\n"}.join("\n")
507
+ body << strings.map { |s, len| "#{s[0..1000]}\n(len: #{len})\n\n" }.join("\n")
513
508
 
514
509
  body << "\n\n\n1000 Sample strings:\n\n"
515
- body << sample_strings.map{|s,len| "#{s[0..1000]}\n(len: #{len})\n\n"}.join("\n")
510
+ body << sample_strings.map { |s, len| "#{s[0..1000]}\n(len: #{len})\n\n" }.join("\n")
516
511
 
517
512
  body << "\n\n\n1000 Most common strings:\n\n"
518
- body << string_counts.sort{|a,b| b[1] <=> a[1]}[0..max_size].map{|s,len| "#{trunc.call(s)}\n(x #{len})\n\n"}.join("\n")
513
+ body << string_counts.sort { |a, b| b[1] <=> a[1] }[0..max_size].map { |s, len| "#{trunc.call(s)}\n(x #{len})\n\n" }.join("\n")
519
514
 
520
515
  text_result(body)
521
516
  end
522
517
 
523
518
  def text_result(body)
524
- headers = {'Content-Type' => 'text/plain'}
519
+ headers = { 'Content-Type' => 'text/plain' }
525
520
  [200, headers, [body]]
526
521
  end
527
522
 
@@ -531,7 +526,7 @@ module Rack
531
526
  end
532
527
 
533
528
  def help(client_settings, env)
534
- headers = {'Content-Type' => 'text/html'}
529
+ headers = { 'Content-Type' => 'text/html' }
535
530
  body = "<html><body>
536
531
  <pre style='line-height: 30px; font-size: 16px;'>
537
532
  Append the following to your query string:
@@ -560,7 +555,7 @@ Append the following to your query string:
560
555
  end
561
556
 
562
557
  def flamegraph(graph)
563
- headers = {'Content-Type' => 'text/html'}
558
+ headers = { 'Content-Type' => 'text/html' }
564
559
  [200, headers, [graph]]
565
560
  end
566
561
 
@@ -591,19 +586,20 @@ Append the following to your query string:
591
586
  path = "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}"
592
587
 
593
588
  settings = {
594
- :path => path,
595
- :version => MiniProfiler::ASSET_VERSION,
596
- :verticalPosition => @config.vertical_position,
597
- :horizontalPosition => @config.horizontal_position,
598
- :showTrivial => @config.show_trivial,
599
- :showChildren => @config.show_children,
600
- :maxTracesToShow => @config.max_traces_to_show,
601
- :showControls => @config.show_controls,
602
- :authorized => true,
603
- :toggleShortcut => @config.toggle_shortcut,
604
- :startHidden => @config.start_hidden,
605
- :collapseResults => @config.collapse_results,
606
- :htmlContainer => @config.html_container
589
+ path: path,
590
+ version: MiniProfiler::ASSET_VERSION,
591
+ verticalPosition: @config.vertical_position,
592
+ horizontalPosition: @config.horizontal_position,
593
+ showTrivial: @config.show_trivial,
594
+ showChildren: @config.show_children,
595
+ maxTracesToShow: @config.max_traces_to_show,
596
+ showControls: @config.show_controls,
597
+ showTotalSqlCount: @config.show_total_sql_count,
598
+ authorized: true,
599
+ toggleShortcut: @config.toggle_shortcut,
600
+ startHidden: @config.start_hidden,
601
+ collapseResults: @config.collapse_results,
602
+ htmlContainer: @config.html_container
607
603
  }
608
604
 
609
605
  if current && current.page_struct
@@ -617,7 +613,7 @@ Append the following to your query string:
617
613
  # TODO : cache this snippet
618
614
  script = IO.read(::File.expand_path('../html/profile_handler.js', ::File.dirname(__FILE__)))
619
615
  # replace the variables
620
- settings.each do |k,v|
616
+ settings.each do |k, v|
621
617
  regex = Regexp.new("\\{#{k.to_s}\\}")
622
618
  script.gsub!(regex, v.to_s)
623
619
  end
@@ -14,7 +14,7 @@ module Rack
14
14
  return unless current
15
15
  parent_timer = current.current_timer
16
16
  current.current_timer = current_timer = current.current_timer.add_child(name)
17
- [current_timer,parent_timer]
17
+ [current_timer, parent_timer]
18
18
  end
19
19
 
20
20
  def finish_step(obj)
@@ -63,7 +63,7 @@ module Rack
63
63
  end
64
64
 
65
65
  def profile_method(klass, method, type = :profile, &blk)
66
- default_name = type==:counter ? method.to_s : klass.to_s + " " + method.to_s
66
+ default_name = type == :counter ? method.to_s : klass.to_s + " " + method.to_s
67
67
  clean = clean_method_name(method)
68
68
 
69
69
  with_profiling = ("#{clean}_with_mini_profiler").intern
@@ -96,7 +96,7 @@ module Rack
96
96
  self.send without_profiling, *args, &orig
97
97
  ensure
98
98
  duration_ms = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start).to_f * 1000
99
- parent_timer.add_custom(name, duration_ms, Rack::MiniProfiler.current.page_struct )
99
+ parent_timer.add_custom(name, duration_ms, Rack::MiniProfiler.current.page_struct)
100
100
  end
101
101
  else
102
102
  Rack::MiniProfiler.current.current_timer = current_timer = parent_timer.add_child(name)
@@ -130,7 +130,7 @@ module Rack
130
130
  # and keeping a record of its run time.
131
131
  #
132
132
  # Returns the result of the block, or nil when no block is given.
133
- def counter(type, duration_ms=nil)
133
+ def counter(type, duration_ms = nil)
134
134
  result = nil
135
135
  if block_given?
136
136
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -16,25 +16,28 @@ module Rack
16
16
 
17
17
  def [](key)
18
18
  begin
19
- data = ::File.open(path(key),"rb") {|f| f.read}
19
+ data = ::File.open(path(key), "rb") { |f| f.read }
20
20
  return Marshal.load data
21
21
  rescue
22
22
  return nil
23
23
  end
24
24
  end
25
25
 
26
- def []=(key,val)
27
- ::File.open(path(key), "wb+") {|f| f.write Marshal.dump(val)}
26
+ def []=(key, val)
27
+ ::File.open(path(key), "wb+") do |f|
28
+ f.sync = true
29
+ f.write Marshal.dump(val)
30
+ end
28
31
  end
29
32
 
30
33
  private
31
34
  if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|cygwin|bccwin/
32
35
  def path(key)
33
- @path + "/" + @prefix + "_" + key.gsub(/:/, '_')
36
+ @path.dup << "/" << @prefix << "_" << key.gsub(/:/, '_')
34
37
  end
35
38
  else
36
39
  def path(key)
37
- @path + "/" + @prefix + "_" + key
40
+ @path.dup << "/" << @prefix << "_" << key
38
41
  end
39
42
  end
40
43
  end
@@ -158,13 +161,13 @@ module Rack
158
161
  @timer_struct_lock.synchronize {
159
162
  files.each do |f|
160
163
  f = @path + '/' + f
161
- ::File.delete f if ::File.basename(f) =~ /^mp_timers/ and (Time.now - ::File.mtime(f)) > @expires_in_seconds
164
+ ::File.delete f if ::File.basename(f) =~ (/^mp_timers/) && ((Time.now - ::File.mtime(f)) > @expires_in_seconds)
162
165
  end
163
166
  }
164
167
  @user_view_lock.synchronize {
165
168
  files.each do |f|
166
169
  f = @path + '/' + f
167
- ::File.delete f if ::File.basename(f) =~ /^mp_views/ and (Time.now - ::File.mtime(f)) > @expires_in_seconds
170
+ ::File.delete f if ::File.basename(f) =~ (/^mp_views/) && ((Time.now - ::File.mtime(f)) > @expires_in_seconds)
168
171
  end
169
172
  }
170
173
  end
@@ -10,8 +10,8 @@ module Rack
10
10
  def initialize(args = nil)
11
11
  require 'dalli' unless defined? Dalli
12
12
  args ||= {}
13
- @prefix = args[:prefix] || "MPMemcacheStore"
14
- @prefix += "-#{Rack::MiniProfiler::VERSION}"
13
+ @prefix = args[:prefix] || "MPMemcacheStore"
14
+ @prefix += "-#{Rack::MiniProfiler::VERSION}"
15
15
  @client = args[:client] || Dalli::Client.new
16
16
  @expires_in_seconds = args[:expires_in] || EXPIRES_IN_SECONDS
17
17
  end
@@ -62,15 +62,14 @@ module Rack
62
62
  token_info = @client.get("#{@prefix}-tokens")
63
63
  key1, key2, cycle_at = nil
64
64
 
65
-
66
65
  if token_info
67
- key1, key2, cycle_at = Marshal::load(token_info)
66
+ key1, key2, cycle_at = Marshal::load(token_info)
68
67
 
69
68
  key1 = nil unless key1 && key1.length == 32
70
69
  key2 = nil unless key2 && key2.length == 32
71
70
 
72
71
  if key1 && cycle_at && (cycle_at > Process.clock_gettime(Process::CLOCK_MONOTONIC))
73
- return [key1,key2].compact
72
+ return [key1, key2].compact
74
73
  end
75
74
  end
76
75
 
@@ -19,7 +19,6 @@ module Rack
19
19
  @cycle_count * @interval >= @cycle
20
20
  end
21
21
 
22
-
23
22
  # We don't want to hit the filesystem every 10s to clean up the cache so we need to do a bit of
24
23
  # accounting to avoid sleeping that entire time. We don't want to sleep for the entire period because
25
24
  # it means the thread will stay live in hot deployment scenarios, keeping a potentially large memory
@@ -67,12 +66,12 @@ module Rack
67
66
  end
68
67
 
69
68
  #FIXME: use weak ref, trouble it may be broken in 1.9 so need to use the 'ref' gem
70
- def initialize_cleanup_thread(args={})
69
+ def initialize_cleanup_thread(args = {})
71
70
  cleanup_interval = args.fetch(:cleanup_interval) { CLEANUP_INTERVAL }
72
71
  cleanup_cycle = args.fetch(:cleanup_cycle) { CLEANUP_CYCLE }
73
72
  t = CacheCleanupThread.new(cleanup_interval, cleanup_cycle, self) do
74
73
  until Thread.current[:should_exit] do
75
- CacheCleanupThread.current.sleepy_run
74
+ t.sleepy_run
76
75
  end
77
76
  end
78
77
  at_exit { t[:should_exit] = true }
@@ -10,7 +10,7 @@ module Rack
10
10
 
11
11
  def initialize(args = nil)
12
12
  @args = args || {}
13
- @prefix = @args.delete(:prefix) || 'MPRedisStore'
13
+ @prefix = @args.delete(:prefix) || 'MPRedisStore'
14
14
  @redis_connection = @args.delete(:connection)
15
15
  @expires_in_seconds = @args.delete(:expires_in) || EXPIRES_IN_SECONDS
16
16
  end
@@ -103,7 +103,7 @@ unviewed_ids: #{get_unviewed_ids(user)}
103
103
  end
104
104
 
105
105
  redis.setex "#{@prefix}-key1", timeout, key1
106
- redis.setex "#{@prefix}-key1_old", timeout*2, key1
106
+ redis.setex "#{@prefix}-key1_old", timeout * 2, key1
107
107
 
108
108
  [key1, key2].compact
109
109
  end