rack-mini-profiler 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +59 -28
- data/lib/enable_rails_patches.rb +1 -3
- data/lib/html/includes.css +40 -9
- data/lib/html/includes.js +90 -29
- data/lib/html/includes.scss +32 -4
- data/lib/html/includes.tmpl +74 -2
- data/lib/html/profile_handler.js +1 -1
- data/lib/html/rack-mini-profiler.css +3 -0
- data/lib/html/rack-mini-profiler.js +2 -0
- data/lib/html/vendor.js +10 -2
- data/lib/mini_profiler/asset_version.rb +1 -1
- data/lib/mini_profiler/config.rb +13 -1
- data/lib/mini_profiler/profiler.rb +166 -23
- data/lib/mini_profiler/storage/abstract_store.rb +72 -0
- data/lib/mini_profiler/storage/memory_store.rb +54 -5
- data/lib/mini_profiler/storage/redis_store.rb +136 -2
- data/lib/mini_profiler/timer_struct/page.rb +4 -1
- data/lib/mini_profiler/version.rb +1 -1
- data/lib/mini_profiler_rails/railtie.rb +13 -0
- data/lib/mini_profiler_rails/railtie_methods.rb +6 -0
- data/lib/patches/net_patches.rb +19 -6
- data/lib/prepend_net_http_patch.rb +5 -0
- data/rack-mini-profiler.gemspec +4 -2
- metadata +51 -20
| @@ -41,6 +41,78 @@ module Rack | |
| 41 41 | 
             
                    raise NotImplementedError.new("allowed_tokens is not implemented")
         | 
| 42 42 | 
             
                  end
         | 
| 43 43 |  | 
| 44 | 
            +
                  def should_take_snapshot?(period)
         | 
| 45 | 
            +
                    raise NotImplementedError.new("should_take_snapshot? is not implemented")
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def push_snapshot(page_struct, config)
         | 
| 49 | 
            +
                    raise NotImplementedError.new("push_snapshot is not implemented")
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def fetch_snapshots(batch_size: 200, &blk)
         | 
| 53 | 
            +
                    raise NotImplementedError.new("fetch_snapshots is not implemented")
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  def snapshot_groups_overview
         | 
| 57 | 
            +
                    groups = {}
         | 
| 58 | 
            +
                    fetch_snapshots do |batch|
         | 
| 59 | 
            +
                      batch.each do |snapshot|
         | 
| 60 | 
            +
                        group_name = default_snapshot_grouping(snapshot)
         | 
| 61 | 
            +
                        if !groups[group_name] || groups[group_name] < snapshot.duration_ms
         | 
| 62 | 
            +
                          groups[group_name] = snapshot.duration_ms
         | 
| 63 | 
            +
                        end
         | 
| 64 | 
            +
                      end
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                    groups = groups.to_a
         | 
| 67 | 
            +
                    groups.sort_by! { |name, score| score }
         | 
| 68 | 
            +
                    groups.reverse!
         | 
| 69 | 
            +
                    groups.map! do |name, score|
         | 
| 70 | 
            +
                      { name: name, worst_score: score }
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                    groups
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  def find_snapshots_group(group_name)
         | 
| 76 | 
            +
                    data = []
         | 
| 77 | 
            +
                    fetch_snapshots do |batch|
         | 
| 78 | 
            +
                      batch.each do |snapshot|
         | 
| 79 | 
            +
                        snapshot_group_name = default_snapshot_grouping(snapshot)
         | 
| 80 | 
            +
                        if group_name == snapshot_group_name
         | 
| 81 | 
            +
                          data << {
         | 
| 82 | 
            +
                            id: snapshot[:id],
         | 
| 83 | 
            +
                            duration: snapshot.duration_ms,
         | 
| 84 | 
            +
                            timestamp: snapshot[:started_at]
         | 
| 85 | 
            +
                          }
         | 
| 86 | 
            +
                        end
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                    data.sort_by! { |s| s[:duration] }
         | 
| 90 | 
            +
                    data.reverse!
         | 
| 91 | 
            +
                    data
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  def load_snapshot(id)
         | 
| 95 | 
            +
                    raise NotImplementedError.new("load_snapshot is not implemented")
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  private
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  def default_snapshot_grouping(snapshot)
         | 
| 101 | 
            +
                    group_name = rails_route_from_path(snapshot[:request_path], snapshot[:request_method])
         | 
| 102 | 
            +
                    group_name ||= snapshot[:request_path]
         | 
| 103 | 
            +
                    "#{snapshot[:request_method]} #{group_name}"
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  def rails_route_from_path(path, method)
         | 
| 107 | 
            +
                    if defined?(Rails) && defined?(ActionController::RoutingError)
         | 
| 108 | 
            +
                      hash = Rails.application.routes.recognize_path(path, method: method)
         | 
| 109 | 
            +
                      if hash && hash[:controller] && hash[:action]
         | 
| 110 | 
            +
                        "#{hash[:controller]}##{hash[:action]}"
         | 
| 111 | 
            +
                      end
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
                  rescue ActionController::RoutingError
         | 
| 114 | 
            +
                    nil
         | 
| 115 | 
            +
                  end
         | 
| 44 116 | 
             
                end
         | 
| 45 117 | 
             
              end
         | 
| 46 118 | 
             
            end
         | 
| @@ -52,17 +52,21 @@ module Rack | |
| 52 52 | 
             
                    @expires_in_seconds = args.fetch(:expires_in) { EXPIRES_IN_SECONDS }
         | 
| 53 53 |  | 
| 54 54 | 
             
                    @token1, @token2, @cycle_at = nil
         | 
| 55 | 
            +
                    @snapshots_cycle = 0
         | 
| 56 | 
            +
                    @snapshots = []
         | 
| 55 57 |  | 
| 56 58 | 
             
                    initialize_locks
         | 
| 57 59 | 
             
                    initialize_cleanup_thread(args)
         | 
| 58 60 | 
             
                  end
         | 
| 59 61 |  | 
| 60 62 | 
             
                  def initialize_locks
         | 
| 61 | 
            -
                    @token_lock | 
| 62 | 
            -
                    @timer_struct_lock | 
| 63 | 
            -
                    @user_view_lock | 
| 64 | 
            -
                    @ | 
| 65 | 
            -
                    @ | 
| 63 | 
            +
                    @token_lock           = Mutex.new
         | 
| 64 | 
            +
                    @timer_struct_lock    = Mutex.new
         | 
| 65 | 
            +
                    @user_view_lock       = Mutex.new
         | 
| 66 | 
            +
                    @snapshots_cycle_lock = Mutex.new
         | 
| 67 | 
            +
                    @snapshots_lock       = Mutex.new
         | 
| 68 | 
            +
                    @timer_struct_cache   = {}
         | 
| 69 | 
            +
                    @user_view_cache      = {}
         | 
| 66 70 | 
             
                  end
         | 
| 67 71 |  | 
| 68 72 | 
             
                  #FIXME: use weak ref, trouble it may be broken in 1.9 so need to use the 'ref' gem
         | 
| @@ -135,6 +139,51 @@ module Rack | |
| 135 139 |  | 
| 136 140 | 
             
                    end
         | 
| 137 141 | 
             
                  end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                  def should_take_snapshot?(period)
         | 
| 144 | 
            +
                    @snapshots_cycle_lock.synchronize do
         | 
| 145 | 
            +
                      @snapshots_cycle += 1
         | 
| 146 | 
            +
                      if @snapshots_cycle % period == 0
         | 
| 147 | 
            +
                        @snapshots_cycle = 0
         | 
| 148 | 
            +
                        true
         | 
| 149 | 
            +
                      else
         | 
| 150 | 
            +
                        false
         | 
| 151 | 
            +
                      end
         | 
| 152 | 
            +
                    end
         | 
| 153 | 
            +
                  end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                  def push_snapshot(page_struct, config)
         | 
| 156 | 
            +
                    @snapshots_lock.synchronize do
         | 
| 157 | 
            +
                      @snapshots << page_struct
         | 
| 158 | 
            +
                      @snapshots.sort_by! { |s| s.duration_ms }
         | 
| 159 | 
            +
                      @snapshots.reverse!
         | 
| 160 | 
            +
                      if @snapshots.size > config.snapshots_limit
         | 
| 161 | 
            +
                        @snapshots.slice!(-1)
         | 
| 162 | 
            +
                      end
         | 
| 163 | 
            +
                    end
         | 
| 164 | 
            +
                  end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                  def fetch_snapshots(batch_size: 200, &blk)
         | 
| 167 | 
            +
                    @snapshots_lock.synchronize do
         | 
| 168 | 
            +
                      @snapshots.each_slice(batch_size) do |batch|
         | 
| 169 | 
            +
                        blk.call(batch)
         | 
| 170 | 
            +
                      end
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
                  end
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                  def load_snapshot(id)
         | 
| 175 | 
            +
                    @snapshots_lock.synchronize do
         | 
| 176 | 
            +
                      @snapshots.find { |s| s[:id] == id }
         | 
| 177 | 
            +
                    end
         | 
| 178 | 
            +
                  end
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                  private
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                  # used in tests only
         | 
| 183 | 
            +
                  def wipe_snapshots_data
         | 
| 184 | 
            +
                    @snapshots_cycle = 0
         | 
| 185 | 
            +
                    @snapshots = []
         | 
| 186 | 
            +
                  end
         | 
| 138 187 | 
             
                end
         | 
| 139 188 | 
             
              end
         | 
| 140 189 | 
             
            end
         | 
| @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            +
            require 'digest'
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            module Rack
         | 
| 4 6 | 
             
              class MiniProfiler
         | 
| 5 7 | 
             
                class RedisStore < AbstractStore
         | 
| @@ -33,7 +35,7 @@ module Rack | |
| 33 35 |  | 
| 34 36 | 
             
                  def set_unviewed(user, id)
         | 
| 35 37 | 
             
                    key = user_key(user)
         | 
| 36 | 
            -
                    if redis.exists | 
| 38 | 
            +
                    if redis.call([:exists, prefixed_id(id)]) == 1
         | 
| 37 39 | 
             
                      expire_at = Process.clock_gettime(Process::CLOCK_MONOTONIC).to_i + redis.ttl(prefixed_id(id))
         | 
| 38 40 | 
             
                      redis.zadd(key, expire_at, id)
         | 
| 39 41 | 
             
                    end
         | 
| @@ -44,7 +46,7 @@ module Rack | |
| 44 46 | 
             
                    key = user_key(user)
         | 
| 45 47 | 
             
                    redis.del(key)
         | 
| 46 48 | 
             
                    ids.each do |id|
         | 
| 47 | 
            -
                      if redis.exists | 
| 49 | 
            +
                      if redis.call([:exists, prefixed_id(id)]) == 1
         | 
| 48 50 | 
             
                        expire_at = Process.clock_gettime(Process::CLOCK_MONOTONIC).to_i + redis.ttl(prefixed_id(id))
         | 
| 49 51 | 
             
                        redis.zadd(key, expire_at, id)
         | 
| 50 52 | 
             
                      end
         | 
| @@ -108,6 +110,106 @@ unviewed_ids: #{get_unviewed_ids(user)} | |
| 108 110 | 
             
                    [key1, key2].compact
         | 
| 109 111 | 
             
                  end
         | 
| 110 112 |  | 
| 113 | 
            +
                  COUNTER_LUA = <<~LUA
         | 
| 114 | 
            +
                    if redis.call("INCR", KEYS[1]) % ARGV[1] == 0 then
         | 
| 115 | 
            +
                      redis.call("DEL", KEYS[1])
         | 
| 116 | 
            +
                      return 1
         | 
| 117 | 
            +
                    else
         | 
| 118 | 
            +
                      return 0
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
                  LUA
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  COUNTER_LUA_SHA = Digest::SHA1.hexdigest(COUNTER_LUA)
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                  def should_take_snapshot?(period)
         | 
| 125 | 
            +
                    1 == cached_redis_eval(
         | 
| 126 | 
            +
                      COUNTER_LUA,
         | 
| 127 | 
            +
                      COUNTER_LUA_SHA,
         | 
| 128 | 
            +
                      reraise: false,
         | 
| 129 | 
            +
                      keys: [snapshot_counter_key()],
         | 
| 130 | 
            +
                      argv: [period]
         | 
| 131 | 
            +
                    )
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  def push_snapshot(page_struct, config)
         | 
| 135 | 
            +
                    zset_key = snapshot_zset_key()
         | 
| 136 | 
            +
                    hash_key = snapshot_hash_key()
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                    id = page_struct[:id]
         | 
| 139 | 
            +
                    score = page_struct.duration_ms
         | 
| 140 | 
            +
                    limit = config.snapshots_limit
         | 
| 141 | 
            +
                    bytes = Marshal.dump(page_struct)
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                    lua = <<~LUA
         | 
| 144 | 
            +
                      local zset_key = KEYS[1]
         | 
| 145 | 
            +
                      local hash_key = KEYS[2]
         | 
| 146 | 
            +
                      local id = ARGV[1]
         | 
| 147 | 
            +
                      local score = tonumber(ARGV[2])
         | 
| 148 | 
            +
                      local bytes = ARGV[3]
         | 
| 149 | 
            +
                      local limit = tonumber(ARGV[4])
         | 
| 150 | 
            +
                      redis.call("ZADD", zset_key, score, id)
         | 
| 151 | 
            +
                      redis.call("HSET", hash_key, id, bytes)
         | 
| 152 | 
            +
                      if redis.call("ZCARD", zset_key) > limit then
         | 
| 153 | 
            +
                        local lowest_snapshot_id = redis.call("ZRANGE", zset_key, 0, 0)[1]
         | 
| 154 | 
            +
                        redis.call("ZREM", zset_key, lowest_snapshot_id)
         | 
| 155 | 
            +
                        redis.call("HDEL", hash_key, lowest_snapshot_id)
         | 
| 156 | 
            +
                      end
         | 
| 157 | 
            +
                    LUA
         | 
| 158 | 
            +
                    redis.eval(
         | 
| 159 | 
            +
                      lua,
         | 
| 160 | 
            +
                      keys: [zset_key, hash_key],
         | 
| 161 | 
            +
                      argv: [id, score, bytes, limit]
         | 
| 162 | 
            +
                    )
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  def fetch_snapshots(batch_size: 200, &blk)
         | 
| 166 | 
            +
                    zset_key = snapshot_zset_key()
         | 
| 167 | 
            +
                    hash_key = snapshot_hash_key()
         | 
| 168 | 
            +
                    iteration = 0
         | 
| 169 | 
            +
                    corrupt_snapshots = []
         | 
| 170 | 
            +
                    while true
         | 
| 171 | 
            +
                      ids = redis.zrange(
         | 
| 172 | 
            +
                        zset_key,
         | 
| 173 | 
            +
                        batch_size * iteration,
         | 
| 174 | 
            +
                        batch_size * iteration + batch_size - 1
         | 
| 175 | 
            +
                      )
         | 
| 176 | 
            +
                      break if ids.size == 0
         | 
| 177 | 
            +
                      batch = redis.mapped_hmget(hash_key, *ids).to_a
         | 
| 178 | 
            +
                      batch.map! do |id, bytes|
         | 
| 179 | 
            +
                        begin
         | 
| 180 | 
            +
                          Marshal.load(bytes)
         | 
| 181 | 
            +
                        rescue
         | 
| 182 | 
            +
                          corrupt_snapshots << id
         | 
| 183 | 
            +
                          nil
         | 
| 184 | 
            +
                        end
         | 
| 185 | 
            +
                      end
         | 
| 186 | 
            +
                      batch.compact!
         | 
| 187 | 
            +
                      blk.call(batch) if batch.size != 0
         | 
| 188 | 
            +
                      break if ids.size < batch_size
         | 
| 189 | 
            +
                      iteration += 1
         | 
| 190 | 
            +
                    end
         | 
| 191 | 
            +
                    if corrupt_snapshots.size > 0
         | 
| 192 | 
            +
                      redis.pipelined do
         | 
| 193 | 
            +
                        redis.zrem(zset_key, corrupt_snapshots)
         | 
| 194 | 
            +
                        redis.hdel(hash_key, corrupt_snapshots)
         | 
| 195 | 
            +
                      end
         | 
| 196 | 
            +
                    end
         | 
| 197 | 
            +
                  end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                  def load_snapshot(id)
         | 
| 200 | 
            +
                    hash_key = snapshot_hash_key()
         | 
| 201 | 
            +
                    bytes = redis.hget(hash_key, id)
         | 
| 202 | 
            +
                    begin
         | 
| 203 | 
            +
                      Marshal.load(bytes)
         | 
| 204 | 
            +
                    rescue
         | 
| 205 | 
            +
                      redis.pipelined do
         | 
| 206 | 
            +
                        redis.zrem(snapshot_zset_key(), id)
         | 
| 207 | 
            +
                        redis.hdel(hash_key, id)
         | 
| 208 | 
            +
                      end
         | 
| 209 | 
            +
                      nil
         | 
| 210 | 
            +
                    end
         | 
| 211 | 
            +
                  end
         | 
| 212 | 
            +
             | 
| 111 213 | 
             
                  private
         | 
| 112 214 |  | 
| 113 215 | 
             
                  def user_key(user)
         | 
| @@ -125,6 +227,38 @@ unviewed_ids: #{get_unviewed_ids(user)} | |
| 125 227 | 
             
                    end
         | 
| 126 228 | 
             
                  end
         | 
| 127 229 |  | 
| 230 | 
            +
                  def snapshot_counter_key
         | 
| 231 | 
            +
                    @snapshot_counter_key ||= "#{@prefix}-mini-profiler-snapshots-counter"
         | 
| 232 | 
            +
                  end
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                  def snapshot_zset_key
         | 
| 235 | 
            +
                    @snapshot_zset_key ||= "#{@prefix}-mini-profiler-snapshots-zset"
         | 
| 236 | 
            +
                  end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                  def snapshot_hash_key
         | 
| 239 | 
            +
                    @snapshot_hash_key ||= "#{@prefix}-mini-profiler-snapshots-hash"
         | 
| 240 | 
            +
                  end
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                  def cached_redis_eval(script, script_sha, reraise: true, argv: [], keys: [])
         | 
| 243 | 
            +
                    begin
         | 
| 244 | 
            +
                      redis.evalsha(script_sha, argv: argv, keys: keys)
         | 
| 245 | 
            +
                    rescue ::Redis::CommandError => e
         | 
| 246 | 
            +
                      if e.message.start_with?('NOSCRIPT')
         | 
| 247 | 
            +
                        redis.eval(script, argv: argv, keys: keys)
         | 
| 248 | 
            +
                      else
         | 
| 249 | 
            +
                        raise e if reraise
         | 
| 250 | 
            +
                      end
         | 
| 251 | 
            +
                    end
         | 
| 252 | 
            +
                  end
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                  # only used in tests
         | 
| 255 | 
            +
                  def wipe_snapshots_data
         | 
| 256 | 
            +
                    redis.pipelined do
         | 
| 257 | 
            +
                      redis.del(snapshot_counter_key())
         | 
| 258 | 
            +
                      redis.del(snapshot_zset_key())
         | 
| 259 | 
            +
                      redis.del(snapshot_hash_key())
         | 
| 260 | 
            +
                    end
         | 
| 261 | 
            +
                  end
         | 
| 128 262 | 
             
                end
         | 
| 129 263 | 
             
              end
         | 
| 130 264 | 
             
            end
         | 
| @@ -39,8 +39,11 @@ module Rack | |
| 39 39 | 
             
                        executed_scalars: 0,
         | 
| 40 40 | 
             
                        executed_non_queries: 0,
         | 
| 41 41 | 
             
                        custom_timing_names: [],
         | 
| 42 | 
            -
                        custom_timing_stats: {}
         | 
| 42 | 
            +
                        custom_timing_stats: {},
         | 
| 43 | 
            +
                        custom_fields: {}
         | 
| 43 44 | 
             
                      )
         | 
| 45 | 
            +
                      self[:request_method] = env['REQUEST_METHOD']
         | 
| 46 | 
            +
                      self[:request_path] = env['PATH_INFO']
         | 
| 44 47 | 
             
                      name = "#{env['REQUEST_METHOD']} http://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{env['SCRIPT_NAME']}#{env['PATH_INFO']}"
         | 
| 45 48 | 
             
                      self[:root] = TimerStruct::Request.createRoot(name, self)
         | 
| 46 49 | 
             
                    end
         | 
| @@ -30,6 +30,8 @@ module Rack::MiniProfilerRails | |
| 30 30 |  | 
| 31 31 | 
             
                if serves_static_assets?(app)
         | 
| 32 32 | 
             
                  c.skip_paths << app.config.assets.prefix
         | 
| 33 | 
            +
                  wp_assets_path = get_webpacker_assets_path()
         | 
| 34 | 
            +
                  c.skip_paths << wp_assets_path if wp_assets_path
         | 
| 33 35 | 
             
                end
         | 
| 34 36 |  | 
| 35 37 | 
             
                unless Rails.env.development? || Rails.env.test?
         | 
| @@ -116,6 +118,17 @@ module Rack::MiniProfilerRails | |
| 116 118 | 
             
                @already_initialized = true
         | 
| 117 119 | 
             
              end
         | 
| 118 120 |  | 
| 121 | 
            +
              def self.create_engine
         | 
| 122 | 
            +
                return if defined?(Rack::MiniProfilerRails::Engine)
         | 
| 123 | 
            +
                klass = Class.new(::Rails::Engine) do
         | 
| 124 | 
            +
                  engine_name 'rack-mini-profiler'
         | 
| 125 | 
            +
                  config.assets.paths << File.expand_path('../../html', __FILE__)
         | 
| 126 | 
            +
                  config.assets.precompile << 'rack-mini-profiler.js'
         | 
| 127 | 
            +
                  config.assets.precompile << 'rack-mini-profiler.css'
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
                Rack::MiniProfilerRails.const_set("Engine", klass)
         | 
| 130 | 
            +
              end
         | 
| 131 | 
            +
             | 
| 119 132 | 
             
              def self.subscribe(event, &blk)
         | 
| 120 133 | 
             
                if ActiveSupport::Notifications.respond_to?(:monotonic_subscribe)
         | 
| 121 134 | 
             
                  ActiveSupport::Notifications.monotonic_subscribe(event) { |*args| blk.call(*args) }
         | 
| @@ -51,5 +51,11 @@ module Rack::MiniProfilerRailsMethods | |
| 51 51 | 
             
                child[start] + child[duration] <= node[start] + node[duration]
         | 
| 52 52 | 
             
              end
         | 
| 53 53 |  | 
| 54 | 
            +
              def get_webpacker_assets_path
         | 
| 55 | 
            +
                if defined?(Webpacker) && Webpacker.config.config_path.exist?
         | 
| 56 | 
            +
                  Webpacker.config.public_output_path.to_s.gsub(Webpacker.config.public_path.to_s, "")
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 54 60 | 
             
              extend self
         | 
| 55 61 | 
             
            end
         | 
    
        data/lib/patches/net_patches.rb
    CHANGED
    
    | @@ -1,13 +1,26 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            if (defined?(Net) && defined?(Net::HTTP))
         | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 4 | 
            +
             | 
| 5 | 
            +
              if defined?(Rack::MINI_PROFILER_PREPEND_NET_HTTP_PATCH)
         | 
| 6 | 
            +
                module NetHTTPWithMiniProfiler
         | 
| 7 | 
            +
                  def request(request, *args, &block)
         | 
| 8 | 
            +
                    Rack::MiniProfiler.step("Net::HTTP #{request.method} #{request.path}") do
         | 
| 9 | 
            +
                      super
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
                Net::HTTP.prepend(NetHTTPWithMiniProfiler)
         | 
| 14 | 
            +
              else
         | 
| 15 | 
            +
                Net::HTTP.class_eval do
         | 
| 16 | 
            +
                  def request_with_mini_profiler(*args, &block)
         | 
| 17 | 
            +
                    request = args[0]
         | 
| 18 | 
            +
                    Rack::MiniProfiler.step("Net::HTTP #{request.method} #{request.path}") do
         | 
| 19 | 
            +
                      request_without_mini_profiler(*args, &block)
         | 
| 20 | 
            +
                    end
         | 
| 8 21 | 
             
                  end
         | 
| 22 | 
            +
                  alias request_without_mini_profiler request
         | 
| 23 | 
            +
                  alias request request_with_mini_profiler
         | 
| 9 24 | 
             
                end
         | 
| 10 25 | 
             
              end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
              Net::HTTP.prepend(NetHTTPWithMiniProfiler)
         | 
| 13 26 | 
             
            end
         | 
    
        data/rack-mini-profiler.gemspec
    CHANGED
    
    | @@ -21,7 +21,7 @@ Gem::Specification.new do |s| | |
| 21 21 | 
             
                "CHANGELOG.md"
         | 
| 22 22 | 
             
              ]
         | 
| 23 23 | 
             
              s.add_runtime_dependency 'rack', '>= 1.2.0'
         | 
| 24 | 
            -
              s.required_ruby_version = '>= 2. | 
| 24 | 
            +
              s.required_ruby_version = '>= 2.4.0'
         | 
| 25 25 |  | 
| 26 26 | 
             
              s.metadata = {
         | 
| 27 27 | 
             
                'source_code_uri' => 'https://github.com/MiniProfiler/rack-mini-profiler',
         | 
| @@ -30,7 +30,6 @@ Gem::Specification.new do |s| | |
| 30 30 |  | 
| 31 31 | 
             
              s.add_development_dependency 'rake', '< 11'
         | 
| 32 32 | 
             
              s.add_development_dependency 'rack-test'
         | 
| 33 | 
            -
              s.add_development_dependency 'activerecord', '~> 3.0'
         | 
| 34 33 | 
             
              s.add_development_dependency 'dalli'
         | 
| 35 34 | 
             
              s.add_development_dependency 'rspec', '~> 3.6.0'
         | 
| 36 35 | 
             
              s.add_development_dependency 'redis'
         | 
| @@ -40,6 +39,9 @@ Gem::Specification.new do |s| | |
| 40 39 | 
             
              s.add_development_dependency 'mini_racer'
         | 
| 41 40 | 
             
              s.add_development_dependency 'nokogiri'
         | 
| 42 41 | 
             
              s.add_development_dependency 'rubocop-discourse'
         | 
| 42 | 
            +
              s.add_development_dependency 'listen'
         | 
| 43 | 
            +
              s.add_development_dependency 'webpacker', '~> 5.1'
         | 
| 44 | 
            +
              s.add_development_dependency 'rails', '~> 5.1'
         | 
| 43 45 |  | 
| 44 46 | 
             
              s.require_paths = ["lib"]
         | 
| 45 47 | 
             
            end
         |