rack-mini-profiler 1.0.0 → 1.0.1

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.
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