module Rack::MiniProfilerRails

Public Class Methods

create_engine() click to toggle source
# File lib/mini_profiler_rails/railtie.rb, line 122
def self.create_engine
  return if defined?(Rack::MiniProfilerRails::Engine)
  klass = Class.new(::Rails::Engine) do
    engine_name 'rack-mini-profiler'
    config.assets.paths << File.expand_path('../../html', __FILE__)
    config.assets.precompile << 'rack-mini-profiler.js'
    config.assets.precompile << 'rack-mini-profiler.css'
  end
  Rack::MiniProfilerRails.const_set("Engine", klass)
end
get_key(payload) click to toggle source
# File lib/mini_profiler_rails/railtie.rb, line 143
def self.get_key(payload)
  "mini_profiler_parent_timer_#{payload[:controller]}_#{payload[:action]}".to_sym
end
initialize!(app) click to toggle source

call direct if needed to do a defer init

# File lib/mini_profiler_rails/railtie.rb, line 10
def self.initialize!(app)

  raise "MiniProfilerRails initialized twice. Set `require: false' for rack-mini-profiler in your Gemfile" if defined?(@already_initialized) && @already_initialized

  c = Rack::MiniProfiler.config

  # By default, only show the MiniProfiler in development mode.
  # To use the MiniProfiler in production, call Rack::MiniProfiler.authorize_request
  # from a hook in your ApplicationController
  #
  # Example:
  #   before_action { Rack::MiniProfiler.authorize_request if current_user.is_admin? }
  #
  # NOTE: this must be set here with = and not ||=
  #  The out of the box default is "true"
  c.pre_authorize_cb = lambda { |env|
    !Rails.env.test?
  }

  c.skip_paths ||= []

  if serves_static_assets?(app)
    c.skip_paths << app.config.assets.prefix
    wp_assets_path = get_webpacker_assets_path()
    c.skip_paths << wp_assets_path if wp_assets_path
  end

  unless Rails.env.development? || Rails.env.test?
    c.authorization_mode = :allow_authorized
  end

  if Rails.logger
    c.logger = Rails.logger
  end

  # The file store is just so much less flaky
  # If the user has not changed from the default memory store then switch to the file store, otherwise keep what the user set
  if c.storage == Rack::MiniProfiler::MemoryStore && c.storage_options.nil?
    base_path = Rails.application.config.paths['tmp'].first rescue "#{Rails.root}/tmp"
    tmp       = base_path + '/miniprofiler'

    c.storage_options = { path: tmp }
    c.storage = Rack::MiniProfiler::FileStore
  end

  # Quiet the SQL stack traces
  c.backtrace_remove = Rails.root.to_s + "/"
  c.backtrace_includes =  [/^\/?(app|config|lib|test)/]
  c.skip_schema_queries = (Rails.env.development? || Rails.env.test?)

  # Install the Middleware
  app.middleware.insert(0, Rack::MiniProfiler)
  c.enable_advanced_debugging_tools = Rails.env.development?

  if ::Rack::MiniProfiler.patch_rails?
    # Attach to various Rails methods
    ActiveSupport.on_load(:action_controller) do
      ::Rack::MiniProfiler.profile_method(ActionController::Base, :process) { |action| "Executing action: #{action}" }
    end

    ActiveSupport.on_load(:action_view) do
      ::Rack::MiniProfiler.profile_method(ActionView::Template, :render) { |x, y| "Rendering: #{@virtual_path}" }
    end
  else
    subscribe("start_processing.action_controller") do |name, start, finish, id, payload|
      next if !should_measure?

      current = Rack::MiniProfiler.current
      controller_name = payload[:controller].sub(/Controller\z/, '').downcase
      description = "Executing: #{controller_name}##{payload[:action]}"
      Thread.current[get_key(payload)] = current.current_timer
      Rack::MiniProfiler.current.current_timer = current.current_timer.add_child(description)
    end

    subscribe("process_action.action_controller") do |name, start, finish, id, payload|
      next if !should_measure?

      key = get_key(payload)
      parent_timer = Thread.current[key]
      next if !parent_timer

      Thread.current[key] = nil
      Rack::MiniProfiler.current.current_timer.record_time
      Rack::MiniProfiler.current.current_timer = parent_timer
    end

    subscribe("render_partial.action_view") do |name, start, finish, id, payload|
      render_notification_handler(shorten_identifier(payload[:identifier]), finish, start)
    end

    subscribe("render_template.action_view") do |name, start, finish, id, payload|
      render_notification_handler(shorten_identifier(payload[:identifier]), finish, start)
    end

    if Rack::MiniProfiler.subscribe_sql_active_record
      # we don't want to subscribe if we've already patched a DB driver
      # otherwise we would end up with 2 records for every query
      subscribe("sql.active_record") do |name, start, finish, id, payload|
        next if !should_measure?
        next if payload[:name] =~ /SCHEMA/ && Rack::MiniProfiler.config.skip_schema_queries

        Rack::MiniProfiler.record_sql(
          payload[:sql],
          (finish - start) * 1000,
          Rack::MiniProfiler.binds_to_params(payload[:binds])
        )
      end
    end
  end
  @already_initialized = true
end
serves_static_assets?(app) click to toggle source
# File lib/mini_profiler_rails/railtie.rb, line 151
def self.serves_static_assets?(app)
  config = app.config

  if !config.respond_to?(:assets) || !config.assets.respond_to?(:prefix)
    return false
  end

  if ::Rails.version >= "5.0.0"
    ::Rails.configuration.public_file_server.enabled
  elsif ::Rails.version >= "4.2.0"
    ::Rails.configuration.serve_static_files
  else
    ::Rails.configuration.serve_static_assets
  end
end
shorten_identifier(identifier) click to toggle source
# File lib/mini_profiler_rails/railtie.rb, line 147
def self.shorten_identifier(identifier)
  identifier.split('/').last(2).join('/')
end
subscribe(event, &blk) click to toggle source
# File lib/mini_profiler_rails/railtie.rb, line 133
def self.subscribe(event, &blk)
  if ActiveSupport::Notifications.respond_to?(:monotonic_subscribe)
    ActiveSupport::Notifications.monotonic_subscribe(event) { |*args| blk.call(*args) }
  else
    ActiveSupport::Notifications.subscribe(event) do |name, start, finish, id, payload|
      blk.call(name, start.to_f, finish.to_f, id, payload)
    end
  end
end