miniprofiler 0.1.7.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.
- data/.gitignore +4 -0
 - data/CHANGELOG +32 -0
 - data/Gemfile +15 -0
 - data/Gemfile.lock +64 -0
 - data/README.md +110 -0
 - data/Rakefile +40 -0
 - data/autotest/discover.rb +2 -0
 - data/lib/mini_profiler/body_add_proxy.rb +45 -0
 - data/lib/mini_profiler/client_timer_struct.rb +76 -0
 - data/lib/mini_profiler/config.rb +52 -0
 - data/lib/mini_profiler/context.rb +10 -0
 - data/lib/mini_profiler/page_timer_struct.rb +53 -0
 - data/lib/mini_profiler/profiler.rb +405 -0
 - data/lib/mini_profiler/profiling_methods.rb +73 -0
 - data/lib/mini_profiler/request_timer_struct.rb +96 -0
 - data/lib/mini_profiler/sql_timer_struct.rb +48 -0
 - data/lib/mini_profiler/storage/abstract_store.rb +27 -0
 - data/lib/mini_profiler/storage/file_store.rb +108 -0
 - data/lib/mini_profiler/storage/memory_store.rb +68 -0
 - data/lib/mini_profiler/storage/redis_store.rb +44 -0
 - data/lib/mini_profiler/timer_struct.rb +31 -0
 - data/lib/mini_profiler_rails/railtie.rb +84 -0
 - data/lib/patches/sql_patches.rb +185 -0
 - data/lib/rack-mini-profiler.rb +6 -0
 - data/rack-mini-profiler.gemspec +23 -0
 - data/spec/components/body_add_proxy_spec.rb +90 -0
 - data/spec/components/client_timer_struct_spec.rb +165 -0
 - data/spec/components/file_store_spec.rb +47 -0
 - data/spec/components/memory_store_spec.rb +40 -0
 - data/spec/components/page_timer_struct_spec.rb +33 -0
 - data/spec/components/profiler_spec.rb +126 -0
 - data/spec/components/redis_store_spec.rb +44 -0
 - data/spec/components/request_timer_struct_spec.rb +148 -0
 - data/spec/components/sql_timer_struct_spec.rb +63 -0
 - data/spec/components/timer_struct_spec.rb +47 -0
 - data/spec/fixtures/simple_client_request.yml +17 -0
 - data/spec/fixtures/weird_client_request.yml +13 -0
 - data/spec/integration/mini_profiler_spec.rb +142 -0
 - data/spec/spec_helper.rb +31 -0
 - data/spec/support/expand_each_to_matcher.rb +8 -0
 - data/test_old/config.ru +41 -0
 - metadata +155 -0
 
| 
         @@ -0,0 +1,108 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rack
         
     | 
| 
      
 2 
     | 
    
         
            +
              class MiniProfiler
         
     | 
| 
      
 3 
     | 
    
         
            +
                class FileStore < AbstractStore
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  class FileCache
         
     | 
| 
      
 6 
     | 
    
         
            +
                    def initialize(path, prefix)
         
     | 
| 
      
 7 
     | 
    
         
            +
                      @path = path
         
     | 
| 
      
 8 
     | 
    
         
            +
                      @prefix = prefix
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    def [](key)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      begin 
         
     | 
| 
      
 13 
     | 
    
         
            +
                        data = ::File.open(path(key),"rb") {|f| f.read}
         
     | 
| 
      
 14 
     | 
    
         
            +
                        return Marshal.load data
         
     | 
| 
      
 15 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 16 
     | 
    
         
            +
                        return nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                      end
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    def []=(key,val)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      ::File.open(path(key), "wb+") {|f| f.write Marshal.dump(val)}
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    private
         
     | 
| 
      
 25 
     | 
    
         
            +
                    def path(key)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      @path + "/" + @prefix  + "_" + key
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  EXPIRE_TIMER_CACHE = 3600 * 24
         
     | 
| 
      
 31 
     | 
    
         
            +
                 
         
     | 
| 
      
 32 
     | 
    
         
            +
                  def initialize(args)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @path = args[:path]
         
     | 
| 
      
 34 
     | 
    
         
            +
                    raise ArgumentError.new :path unless @path
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @timer_struct_cache = FileCache.new(@path, "mp_timers")
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @timer_struct_lock = Mutex.new
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @user_view_cache = FileCache.new(@path, "mp_views")
         
     | 
| 
      
 38 
     | 
    
         
            +
                    @user_view_lock = Mutex.new
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    me = self
         
     | 
| 
      
 41 
     | 
    
         
            +
                    Thread.new do
         
     | 
| 
      
 42 
     | 
    
         
            +
                      while true do
         
     | 
| 
      
 43 
     | 
    
         
            +
                        me.cleanup_cache if MiniProfiler.instance
         
     | 
| 
      
 44 
     | 
    
         
            +
                        sleep(3600)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def save(page_struct)
         
     | 
| 
      
 50 
     | 
    
         
            +
            		  	@timer_struct_lock.synchronize {
         
     | 
| 
      
 51 
     | 
    
         
            +
            			  	@timer_struct_cache[page_struct['Id']] = page_struct
         
     | 
| 
      
 52 
     | 
    
         
            +
            			  }
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  def load(id)
         
     | 
| 
      
 56 
     | 
    
         
            +
            			  @timer_struct_lock.synchronize {
         
     | 
| 
      
 57 
     | 
    
         
            +
                      @timer_struct_cache[id]
         
     | 
| 
      
 58 
     | 
    
         
            +
                    }
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def set_unviewed(user, id)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @user_view_lock.synchronize {
         
     | 
| 
      
 63 
     | 
    
         
            +
                      current = @user_view_cache[user]
         
     | 
| 
      
 64 
     | 
    
         
            +
                      current = [] unless Array === current
         
     | 
| 
      
 65 
     | 
    
         
            +
                      current << id
         
     | 
| 
      
 66 
     | 
    
         
            +
                      @user_view_cache[user] = current.uniq
         
     | 
| 
      
 67 
     | 
    
         
            +
                    }
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  def set_viewed(user, id)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    @user_view_lock.synchronize {
         
     | 
| 
      
 72 
     | 
    
         
            +
                      @user_view_cache[user] ||= []
         
     | 
| 
      
 73 
     | 
    
         
            +
                      current = @user_view_cache[user]
         
     | 
| 
      
 74 
     | 
    
         
            +
                      current = [] unless Array === current
         
     | 
| 
      
 75 
     | 
    
         
            +
                      current.delete(id)
         
     | 
| 
      
 76 
     | 
    
         
            +
                      @user_view_cache[user] = current.uniq
         
     | 
| 
      
 77 
     | 
    
         
            +
                    }
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def get_unviewed_ids(user)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    @user_view_lock.synchronize {
         
     | 
| 
      
 82 
     | 
    
         
            +
                      @user_view_cache[user]
         
     | 
| 
      
 83 
     | 
    
         
            +
                    }
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  private 
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  def cleanup_cache
         
     | 
| 
      
 91 
     | 
    
         
            +
                    files = Dir.entries(@path)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    @timer_struct_lock.synchronize {
         
     | 
| 
      
 93 
     | 
    
         
            +
                      files.each do |f|
         
     | 
| 
      
 94 
     | 
    
         
            +
                        f = @path + '/' + f
         
     | 
| 
      
 95 
     | 
    
         
            +
                        File.delete f if f =~ /^mp_timers/ and (Time.now - File.mtime(f)) > EXPIRE_TIMER_CACHE
         
     | 
| 
      
 96 
     | 
    
         
            +
                      end
         
     | 
| 
      
 97 
     | 
    
         
            +
                    }
         
     | 
| 
      
 98 
     | 
    
         
            +
                    @user_view_lock.synchronize {
         
     | 
| 
      
 99 
     | 
    
         
            +
                      files.each do |f|
         
     | 
| 
      
 100 
     | 
    
         
            +
                        f = @path + '/' + f
         
     | 
| 
      
 101 
     | 
    
         
            +
                        File.delete f if f =~ /^mp_views/ and (Time.now - File.mtime(f)) > EXPIRE_TIMER_CACHE
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    }
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
                
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rack
         
     | 
| 
      
 2 
     | 
    
         
            +
              class MiniProfiler
         
     | 
| 
      
 3 
     | 
    
         
            +
                class MemoryStore < AbstractStore
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  EXPIRE_TIMER_CACHE = 3600 * 24
         
     | 
| 
      
 6 
     | 
    
         
            +
                 
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(args)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @timer_struct_lock = Mutex.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @timer_struct_cache = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @user_view_lock = Mutex.new
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @user_view_cache = {}
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    # TODO: fix it to use weak ref, trouble is may be broken in 1.9 so need to use the 'ref' gem
         
     | 
| 
      
 14 
     | 
    
         
            +
                    me = self
         
     | 
| 
      
 15 
     | 
    
         
            +
                    Thread.new do
         
     | 
| 
      
 16 
     | 
    
         
            +
                      while true do
         
     | 
| 
      
 17 
     | 
    
         
            +
                        me.cleanup_cache
         
     | 
| 
      
 18 
     | 
    
         
            +
                        sleep(3600)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def save(page_struct)
         
     | 
| 
      
 24 
     | 
    
         
            +
            		  	@timer_struct_lock.synchronize {
         
     | 
| 
      
 25 
     | 
    
         
            +
            			  	@timer_struct_cache[page_struct['Id']] = page_struct
         
     | 
| 
      
 26 
     | 
    
         
            +
            			  }
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def load(id)
         
     | 
| 
      
 30 
     | 
    
         
            +
            			  @timer_struct_lock.synchronize {
         
     | 
| 
      
 31 
     | 
    
         
            +
                      @timer_struct_cache[id]
         
     | 
| 
      
 32 
     | 
    
         
            +
                    }
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def set_unviewed(user, id)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @user_view_lock.synchronize {
         
     | 
| 
      
 37 
     | 
    
         
            +
                      @user_view_cache[user] ||= []
         
     | 
| 
      
 38 
     | 
    
         
            +
                      @user_view_cache[user] << id
         
     | 
| 
      
 39 
     | 
    
         
            +
                    }
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def set_viewed(user, id)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @user_view_lock.synchronize {
         
     | 
| 
      
 44 
     | 
    
         
            +
                      @user_view_cache[user] ||= []
         
     | 
| 
      
 45 
     | 
    
         
            +
                      @user_view_cache[user].delete(id)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    }
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def get_unviewed_ids(user)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @user_view_lock.synchronize {
         
     | 
| 
      
 51 
     | 
    
         
            +
                      @user_view_cache[user]
         
     | 
| 
      
 52 
     | 
    
         
            +
                    }
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  private 
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  def cleanup_cache
         
     | 
| 
      
 60 
     | 
    
         
            +
                    expire_older_than = ((Time.now.to_f - MiniProfiler::MemoryStore::EXPIRE_TIMER_CACHE) * 1000).to_i
         
     | 
| 
      
 61 
     | 
    
         
            +
                    @timer_struct_lock.synchronize {
         
     | 
| 
      
 62 
     | 
    
         
            +
                      @timer_struct_cache.delete_if { |k, v| v['Root']['StartMilliseconds'] < expire_older_than }
         
     | 
| 
      
 63 
     | 
    
         
            +
                    }
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rack
         
     | 
| 
      
 2 
     | 
    
         
            +
              class MiniProfiler
         
     | 
| 
      
 3 
     | 
    
         
            +
                class RedisStore < AbstractStore
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  EXPIRE_SECONDS = 60 * 60 * 24
         
     | 
| 
      
 6 
     | 
    
         
            +
                 
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(args)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    args ||= {}
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @prefix = args[:prefix] || 'MPRedisStore'
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def save(page_struct)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    redis.setex "#{@prefix}#{page_struct['Id']}", EXPIRE_SECONDS, Marshal::dump(page_struct) 
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def load(id)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    raw = redis.get "#{@prefix}#{id}"
         
     | 
| 
      
 18 
     | 
    
         
            +
                    if raw
         
     | 
| 
      
 19 
     | 
    
         
            +
                      Marshal::load raw
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def set_unviewed(user, id)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    redis.sadd "#{@prefix}-#{user}-v", id
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def set_viewed(user, id)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    redis.srem "#{@prefix}-#{user}-v", id
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def get_unviewed_ids(user)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    redis.smembers "#{@prefix}-#{user}-v"
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  private 
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def redis
         
     | 
| 
      
 38 
     | 
    
         
            +
                    require 'redis' unless defined? Redis
         
     | 
| 
      
 39 
     | 
    
         
            +
                    Redis.new 
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rack
         
     | 
| 
      
 2 
     | 
    
         
            +
              class MiniProfiler
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                # A base class for timing structures
         
     | 
| 
      
 5 
     | 
    
         
            +
                class TimerStruct
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(attrs={})
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @attributes = attrs
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def attributes
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @attributes ||= {}
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def [](name)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    attributes[name]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def []=(name, val)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    attributes[name] = val
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def to_json(*a)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    ::JSON.generate(@attributes, a[0])
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,84 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module MiniProfilerRails
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              class Railtie < ::Rails::Railtie
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                initializer "rack_mini_profiler.configure_rails_initialization" do |app|
         
     | 
| 
      
 8 
     | 
    
         
            +
                  c = Rack::MiniProfiler.config
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  # By default, only show the MiniProfiler in development mode, in production allow profiling if post_authorize_cb is set
         
     | 
| 
      
 11 
     | 
    
         
            +
                  c.pre_authorize_cb = lambda { |env|
         
     | 
| 
      
 12 
     | 
    
         
            +
                    Rails.env.development? || Rails.env.production?  
         
     | 
| 
      
 13 
     | 
    
         
            +
                  }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  if Rails.env.development?
         
     | 
| 
      
 16 
     | 
    
         
            +
                    c.skip_paths ||= []
         
     | 
| 
      
 17 
     | 
    
         
            +
                    c.skip_paths << "/assets/"
         
     | 
| 
      
 18 
     | 
    
         
            +
                    c.skip_schema_queries = true
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  if Rails.env.production? 
         
     | 
| 
      
 22 
     | 
    
         
            +
                    c.authorization_mode = :whitelist
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  # The file store is just so much less flaky
         
     | 
| 
      
 26 
     | 
    
         
            +
                  tmp = Rails.root.to_s + "/tmp/miniprofiler"
         
     | 
| 
      
 27 
     | 
    
         
            +
                  FileUtils.mkdir_p(tmp) unless File.exists?(tmp)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  c.storage_options = {:path => tmp}
         
     | 
| 
      
 30 
     | 
    
         
            +
                  c.storage = Rack::MiniProfiler::FileStore
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  # Quiet the SQL stack traces
         
     | 
| 
      
 33 
     | 
    
         
            +
                  c.backtrace_remove = Rails.root.to_s + "/"
         
     | 
| 
      
 34 
     | 
    
         
            +
                  c.backtrace_filter =  /^\/?(app|config|lib|test)/
         
     | 
| 
      
 35 
     | 
    
         
            +
                  c.skip_schema_queries =  Rails.env != 'production'
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  # Install the Middleware
         
     | 
| 
      
 38 
     | 
    
         
            +
                  app.middleware.insert(0, Rack::MiniProfiler)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  # Attach to various Rails methods
         
     | 
| 
      
 41 
     | 
    
         
            +
                  ::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"}
         
     | 
| 
      
 42 
     | 
    
         
            +
                  ::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{@virtual_path}"}
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                # TODO: Implement something better here
         
     | 
| 
      
 47 
     | 
    
         
            +
                # config.after_initialize do 
         
     | 
| 
      
 48 
     | 
    
         
            +
                #   
         
     | 
| 
      
 49 
     | 
    
         
            +
                #   class ::ActionView::Helpers::AssetTagHelper::JavascriptIncludeTag 
         
     | 
| 
      
 50 
     | 
    
         
            +
                #     alias_method :asset_tag_orig, :asset_tag
         
     | 
| 
      
 51 
     | 
    
         
            +
                #     def asset_tag(source,options)
         
     | 
| 
      
 52 
     | 
    
         
            +
                #       current = Rack::MiniProfiler.current 
         
     | 
| 
      
 53 
     | 
    
         
            +
                #       return asset_tag_orig(source,options) unless current 
         
     | 
| 
      
 54 
     | 
    
         
            +
                #       wrapped = ""
         
     | 
| 
      
 55 
     | 
    
         
            +
                #       unless current.mpt_init
         
     | 
| 
      
 56 
     | 
    
         
            +
                #         current.mpt_init = true
         
     | 
| 
      
 57 
     | 
    
         
            +
                #         wrapped << Rack::MiniProfiler::ClientTimerStruct.init_instrumentation 
         
     | 
| 
      
 58 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 59 
     | 
    
         
            +
                #       name = source.split('/')[-1]
         
     | 
| 
      
 60 
     | 
    
         
            +
                #       wrapped << Rack::MiniProfiler::ClientTimerStruct.instrument(name, asset_tag_orig(source,options)).html_safe
         
     | 
| 
      
 61 
     | 
    
         
            +
                #       wrapped
         
     | 
| 
      
 62 
     | 
    
         
            +
                #     end
         
     | 
| 
      
 63 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                #   class ::ActionView::Helpers::AssetTagHelper::StylesheetIncludeTag  
         
     | 
| 
      
 66 
     | 
    
         
            +
                #     alias_method :asset_tag_orig, :asset_tag
         
     | 
| 
      
 67 
     | 
    
         
            +
                #     def asset_tag(source,options)
         
     | 
| 
      
 68 
     | 
    
         
            +
                #       current = Rack::MiniProfiler.current 
         
     | 
| 
      
 69 
     | 
    
         
            +
                #       return asset_tag_orig(source,options) unless current 
         
     | 
| 
      
 70 
     | 
    
         
            +
                #       wrapped = ""
         
     | 
| 
      
 71 
     | 
    
         
            +
                #       unless current.mpt_init
         
     | 
| 
      
 72 
     | 
    
         
            +
                #         current.mpt_init = true
         
     | 
| 
      
 73 
     | 
    
         
            +
                #         wrapped << Rack::MiniProfiler::ClientTimerStruct.init_instrumentation 
         
     | 
| 
      
 74 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 75 
     | 
    
         
            +
                #       name = source.split('/')[-1]
         
     | 
| 
      
 76 
     | 
    
         
            +
                #       wrapped << Rack::MiniProfiler::ClientTimerStruct.instrument(name, asset_tag_orig(source,options)).html_safe
         
     | 
| 
      
 77 
     | 
    
         
            +
                #       wrapped
         
     | 
| 
      
 78 
     | 
    
         
            +
                #     end
         
     | 
| 
      
 79 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                # end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,185 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class SqlPatches
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              def self.patched?
         
     | 
| 
      
 4 
     | 
    
         
            +
                @patched
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              def self.patched=(val)
         
     | 
| 
      
 8 
     | 
    
         
            +
                @patched = val
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            	def self.class_exists?(name)
         
     | 
| 
      
 12 
     | 
    
         
            +
            		eval(name + ".class").to_s.eql?('Class')
         
     | 
| 
      
 13 
     | 
    
         
            +
            	rescue NameError
         
     | 
| 
      
 14 
     | 
    
         
            +
            		false
         
     | 
| 
      
 15 
     | 
    
         
            +
            	end
         
     | 
| 
      
 16 
     | 
    
         
            +
            	
         
     | 
| 
      
 17 
     | 
    
         
            +
              def self.module_exists?(name)
         
     | 
| 
      
 18 
     | 
    
         
            +
            		eval(name + ".class").to_s.eql?('Module')
         
     | 
| 
      
 19 
     | 
    
         
            +
            	rescue NameError
         
     | 
| 
      
 20 
     | 
    
         
            +
            		false
         
     | 
| 
      
 21 
     | 
    
         
            +
            	end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            # The best kind of instrumentation is in the actual db provider, however we don't want to double instrument
         
     | 
| 
      
 25 
     | 
    
         
            +
            if SqlPatches.class_exists? "Mysql2::Client"
         
     | 
| 
      
 26 
     | 
    
         
            +
              
         
     | 
| 
      
 27 
     | 
    
         
            +
              class Mysql2::Result
         
     | 
| 
      
 28 
     | 
    
         
            +
                alias_method :each_without_profiling, :each
         
     | 
| 
      
 29 
     | 
    
         
            +
                def each(*args, &blk)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  return each_without_profiling(*args, &blk) unless @miniprofiler_sql_id
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  start = Time.now
         
     | 
| 
      
 33 
     | 
    
         
            +
                  result = each_without_profiling(*args,&blk) 
         
     | 
| 
      
 34 
     | 
    
         
            +
                  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  @miniprofiler_sql_id.report_reader_duration(elapsed_time) 
         
     | 
| 
      
 37 
     | 
    
         
            +
                  result
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              class Mysql2::Client
         
     | 
| 
      
 42 
     | 
    
         
            +
                alias_method :query_without_profiling, :query
         
     | 
| 
      
 43 
     | 
    
         
            +
                def query(*args,&blk)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  current = ::Rack::MiniProfiler.current
         
     | 
| 
      
 45 
     | 
    
         
            +
                  return query_without_profiling(*args,&blk) unless current
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  start = Time.now
         
     | 
| 
      
 48 
     | 
    
         
            +
                  result = query_without_profiling(*args,&blk)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(args[0], elapsed_time))
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  result
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
                
         
     | 
| 
      
 57 
     | 
    
         
            +
              SqlPatches.patched = true
         
     | 
| 
      
 58 
     | 
    
         
            +
            end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            # PG patches, keep in mind exec and async_exec have a exec{|r| } semantics that is yet to be implemented 
         
     | 
| 
      
 62 
     | 
    
         
            +
            if SqlPatches.class_exists? "PG::Result"
         
     | 
| 
      
 63 
     | 
    
         
            +
              
         
     | 
| 
      
 64 
     | 
    
         
            +
              class PG::Result
         
     | 
| 
      
 65 
     | 
    
         
            +
                alias_method :each_without_profiling, :each
         
     | 
| 
      
 66 
     | 
    
         
            +
                alias_method :values_without_profiling, :values
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def values(*args, &blk)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  return values_without_profiling(*args, &blk) unless @miniprofiler_sql_id
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                  start = Time.now
         
     | 
| 
      
 72 
     | 
    
         
            +
                  result = values_without_profiling(*args,&blk) 
         
     | 
| 
      
 73 
     | 
    
         
            +
                  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  @miniprofiler_sql_id.report_reader_duration(elapsed_time) 
         
     | 
| 
      
 76 
     | 
    
         
            +
                  result
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def each(*args, &blk)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  return each_without_profiling(*args, &blk) unless @miniprofiler_sql_id
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  start = Time.now
         
     | 
| 
      
 83 
     | 
    
         
            +
                  result = each_without_profiling(*args,&blk) 
         
     | 
| 
      
 84 
     | 
    
         
            +
                  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  @miniprofiler_sql_id.report_reader_duration(elapsed_time) 
         
     | 
| 
      
 87 
     | 
    
         
            +
                  result
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              class PG::Connection
         
     | 
| 
      
 92 
     | 
    
         
            +
                alias_method :exec_without_profiling, :exec
         
     | 
| 
      
 93 
     | 
    
         
            +
                alias_method :async_exec_without_profiling, :async_exec
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                def exec(*args,&blk)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  current = ::Rack::MiniProfiler.current
         
     | 
| 
      
 97 
     | 
    
         
            +
                  return exec_without_profiling(*args,&blk) unless current
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  start = Time.now
         
     | 
| 
      
 100 
     | 
    
         
            +
                  result = exec_without_profiling(*args,&blk)
         
     | 
| 
      
 101 
     | 
    
         
            +
                  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(args[0], elapsed_time))
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  result
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                def async_exec(*args,&blk)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  current = ::Rack::MiniProfiler.current
         
     | 
| 
      
 109 
     | 
    
         
            +
                  return exec_without_profiling(*args,&blk) unless current
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                  start = Time.now
         
     | 
| 
      
 112 
     | 
    
         
            +
                  result = exec_without_profiling(*args,&blk)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(args[0], elapsed_time))
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  result
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
                
         
     | 
| 
      
 119 
     | 
    
         
            +
                alias_method :query, :exec
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
                
         
     | 
| 
      
 122 
     | 
    
         
            +
              SqlPatches.patched = true
         
     | 
| 
      
 123 
     | 
    
         
            +
            end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
            # Fallback for sequel
         
     | 
| 
      
 128 
     | 
    
         
            +
            if SqlPatches.class_exists?("Sequel::Database") && !SqlPatches.patched?
         
     | 
| 
      
 129 
     | 
    
         
            +
            	module Sequel
         
     | 
| 
      
 130 
     | 
    
         
            +
            		class Database
         
     | 
| 
      
 131 
     | 
    
         
            +
            			alias_method :log_duration_original, :log_duration
         
     | 
| 
      
 132 
     | 
    
         
            +
            			def log_duration(duration, message)
         
     | 
| 
      
 133 
     | 
    
         
            +
            				::Rack::MiniProfiler.record_sql(message, duration)
         
     | 
| 
      
 134 
     | 
    
         
            +
            				log_duration_original(duration, message)
         
     | 
| 
      
 135 
     | 
    
         
            +
            			end
         
     | 
| 
      
 136 
     | 
    
         
            +
            		end
         
     | 
| 
      
 137 
     | 
    
         
            +
            	end
         
     | 
| 
      
 138 
     | 
    
         
            +
            end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            ## based off https://github.com/newrelic/rpm/blob/master/lib/new_relic/agent/instrumentation/active_record.rb
         
     | 
| 
      
 142 
     | 
    
         
            +
            ## fallback for alls sorts of weird dbs
         
     | 
| 
      
 143 
     | 
    
         
            +
            if SqlPatches.module_exists?('ActiveRecord')
         
     | 
| 
      
 144 
     | 
    
         
            +
              module Rack
         
     | 
| 
      
 145 
     | 
    
         
            +
                class MiniProfiler  
         
     | 
| 
      
 146 
     | 
    
         
            +
                  module ActiveRecordInstrumentation
         
     | 
| 
      
 147 
     | 
    
         
            +
                    def self.included(instrumented_class)
         
     | 
| 
      
 148 
     | 
    
         
            +
                      instrumented_class.class_eval do
         
     | 
| 
      
 149 
     | 
    
         
            +
                        unless instrumented_class.method_defined?(:log_without_miniprofiler)
         
     | 
| 
      
 150 
     | 
    
         
            +
                          alias_method :log_without_miniprofiler, :log
         
     | 
| 
      
 151 
     | 
    
         
            +
                          alias_method :log, :log_with_miniprofiler
         
     | 
| 
      
 152 
     | 
    
         
            +
                          protected :log
         
     | 
| 
      
 153 
     | 
    
         
            +
                        end
         
     | 
| 
      
 154 
     | 
    
         
            +
                      end
         
     | 
| 
      
 155 
     | 
    
         
            +
                    end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                    def log_with_miniprofiler(*args, &block)
         
     | 
| 
      
 158 
     | 
    
         
            +
                      current = ::Rack::MiniProfiler.current
         
     | 
| 
      
 159 
     | 
    
         
            +
                      return log_without_miniprofiler(*args, &block) unless current
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                      sql, name, binds = args
         
     | 
| 
      
 162 
     | 
    
         
            +
                      t0 = Time.now
         
     | 
| 
      
 163 
     | 
    
         
            +
                      rval = log_without_miniprofiler(*args, &block)
         
     | 
| 
      
 164 
     | 
    
         
            +
                      
         
     | 
| 
      
 165 
     | 
    
         
            +
                      # Don't log schema queries if the option is set
         
     | 
| 
      
 166 
     | 
    
         
            +
                      return rval if Rack::MiniProfiler.config.skip_schema_queries and name =~ /SCHEMA/
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                      elapsed_time = ((Time.now - t0).to_f * 1000).round(1)
         
     | 
| 
      
 169 
     | 
    
         
            +
                      Rack::MiniProfiler.record_sql(sql, elapsed_time)
         
     | 
| 
      
 170 
     | 
    
         
            +
                      rval
         
     | 
| 
      
 171 
     | 
    
         
            +
                    end
         
     | 
| 
      
 172 
     | 
    
         
            +
                  end
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                def self.insert_instrumentation 
         
     | 
| 
      
 176 
     | 
    
         
            +
                  ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
         
     | 
| 
      
 177 
     | 
    
         
            +
                    include ::Rack::MiniProfiler::ActiveRecordInstrumentation
         
     | 
| 
      
 178 
     | 
    
         
            +
                  end
         
     | 
| 
      
 179 
     | 
    
         
            +
                end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                if defined?(::Rails) && !SqlPatches.patched?
         
     | 
| 
      
 182 
     | 
    
         
            +
                  insert_instrumentation
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
              end
         
     | 
| 
      
 185 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,6 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path('mini_profiler/profiler', File.dirname(__FILE__) )
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.expand_path('patches/sql_patches', File.dirname(__FILE__) )
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            if defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3
         
     | 
| 
      
 5 
     | 
    
         
            +
              require File.expand_path('mini_profiler_rails/railtie', File.dirname(__FILE__) )
         
     | 
| 
      
 6 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 2 
     | 
    
         
            +
              s.name = "miniprofiler"
         
     | 
| 
      
 3 
     | 
    
         
            +
              s.version = "0.1.7.1"
         
     | 
| 
      
 4 
     | 
    
         
            +
              s.summary = "Profiles loading speed for rack applications."
         
     | 
| 
      
 5 
     | 
    
         
            +
              s.authors = ["Aleks Totic","Sam Saffron", "Robin Ward"]
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.description = "Page loading speed displayed on every page. Optimize while you develop, performance is a feature."
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.email = "sam.saffron@gmail.com"
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.homepage = "http://miniprofiler.com"
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.extra_rdoc_files = [
         
     | 
| 
      
 12 
     | 
    
         
            +
                "README.md",
         
     | 
| 
      
 13 
     | 
    
         
            +
                "CHANGELOG"
         
     | 
| 
      
 14 
     | 
    
         
            +
              ]
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.add_runtime_dependency 'rack', '>= 1.1.3'
         
     | 
| 
      
 16 
     | 
    
         
            +
              if RUBY_VERSION < "1.9"
         
     | 
| 
      
 17 
     | 
    
         
            +
                s.add_runtime_dependency 'json', '>= 1.6'
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              s.add_development_dependency 'rake'
         
     | 
| 
      
 21 
     | 
    
         
            +
              s.add_development_dependency 'rack-test'
         
     | 
| 
      
 22 
     | 
    
         
            +
              s.add_development_dependency 'activerecord', '~> 3.0'
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mini_profiler/body_add_proxy'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe Rack::MiniProfiler::BodyAddProxy do
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              context 'body as an array' do
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                before do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @proxy = Rack::MiniProfiler::BodyAddProxy.new(%w(a b c), 'd')
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                it 'contains the appended value' do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @proxy.should expand_each_to %w(a b c d)
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                it 'has a correct value in to_str' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @proxy.to_str.should == "abcd"
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                describe 'delegation' do
         
     | 
| 
      
 21 
     | 
    
         
            +
                  it 'delegates respond to <<' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @proxy.respond_to?('<<').should be_true
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  it 'delegates respond to first' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @proxy.respond_to?(:first).should be_true
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end    
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  it 'delegates method_missing' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                    @proxy.first.should == 'a'
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              context 'body as a custom object' do
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                # A class and a super class to help us test appending to a custom object, such as 
         
     | 
| 
      
 39 
     | 
    
         
            +
                # Rails' ActionDispatch::Response
         
     | 
| 
      
 40 
     | 
    
         
            +
                class Band
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def style
         
     | 
| 
      
 42 
     | 
    
         
            +
                    'rock'
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end    
         
     | 
| 
      
 45 
     | 
    
         
            +
                
         
     | 
| 
      
 46 
     | 
    
         
            +
                class Beatles < Band
         
     | 
| 
      
 47 
     | 
    
         
            +
                  def each
         
     | 
| 
      
 48 
     | 
    
         
            +
                    yield 'john'
         
     | 
| 
      
 49 
     | 
    
         
            +
                    yield 'paul'
         
     | 
| 
      
 50 
     | 
    
         
            +
                    yield 'george'
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def fake_method; nil; end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  def method_missing(*args, &block)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    'yoko'
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                before do
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @proxy = Rack::MiniProfiler::BodyAddProxy.new(Beatles.new, 'ringo')
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                it 'contains the appended value' do
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @proxy.should expand_each_to %w(john paul george ringo)
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                it 'has a correct value in to_str' do
         
     | 
| 
      
 69 
     | 
    
         
            +
                  @proxy.to_str.should == "johnpaulgeorgeringo"
         
     | 
| 
      
 70 
     | 
    
         
            +
                end    
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                describe 'delegation' do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  it 'delegates respond to fake_method' do
         
     | 
| 
      
 74 
     | 
    
         
            +
                    @proxy.respond_to?(:fake_method).should be_true
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  it 'delegates respond to a super class' do
         
     | 
| 
      
 78 
     | 
    
         
            +
                    @proxy.respond_to?(:style).should be_true
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end      
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  it 'delegates method_missing' do
         
     | 
| 
      
 82 
     | 
    
         
            +
                    @proxy.doesnt_exist.should == 'yoko'
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            end
         
     |