How to get the line of code that triggers a query?

这一生的挚爱 提交于 2019-12-31 10:24:14

问题


is there a way (a gem, a plugin or something else) in rails 3.2 to know which line of code triggers a database query? For example in my log I have:

User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 5 LIMIT 1

How can I know the line of code that triggers the query? Thx...


回答1:


I've found this solution:

module QueryTrace
  def self.enable!
    ::ActiveRecord::LogSubscriber.send(:include, self)
  end

  def self.append_features(klass)
    super
    klass.class_eval do
      unless method_defined?(:log_info_without_trace)
        alias_method :log_info_without_trace, :sql
        alias_method :sql, :log_info_with_trace
      end
    end
  end

  def log_info_with_trace(event)
    log_info_without_trace(event)
    trace_log = Rails.backtrace_cleaner.clean(caller).first
    if trace_log && event.payload[:name] != 'SCHEMA'
      logger.debug("   \\_ \e[33mCalled from:\e[0m " + trace_log)
    end
  end
end

In some initializer add QueryTrace.enable!




回答2:


Using the active-record-query-trace gem:

In Gemfile:

gem 'active_record_query_trace'

Then bundle, then in config/environments/development.rb:

ActiveRecordQueryTrace.enabled = true



回答3:


Add this to your config/environments/test.rb or whatever environment you want to have the lines in. I am testing on rails 5.

  ActiveRecord::Base.verbose_query_logs = true

You'll get the file and the line.




回答4:


You can monkey patch the BufferedLogger to do what you want. Put this file in your config/initializers path:

require 'active_support/buffered_logger'

class ActiveSupport::BufferedLogger

  def add(severity, message = nil, progname = nil, &block)
    add_debugging_details(severity)
    @log.add(severity, message, progname, &block)
  end

  private

  EXCLUDE_CALLERS = Gem.paths.path.clone << 'script/rails' << RbConfig::CONFIG['rubylibdir'] << __FILE__

  def add_debugging_details(severity)
    caller_in_app = caller.select do |line|
      EXCLUDE_CALLERS.detect { |gem_path| line.starts_with?(gem_path) }.nil?
    end

    return if caller_in_app.empty?

    @log.add(severity, "Your code in \e[1;33m#{caller_in_app.first}\e[0;0m triggered:")
  end

end if Rails.env.development?


来源:https://stackoverflow.com/questions/10911371/how-to-get-the-line-of-code-that-triggers-a-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!