【问题标题】:How to log Rails queries before they happen?如何在 Rails 查询发生之前记录它们?
【发布时间】:2015-09-08 10:42:17
【问题描述】:
默认情况下,Rails 记录器将在 SQL 执行后显示它。有时 - 主要是当查询需要很长时间时 - 我想将记录器配置为在执行之前输出 SQL。一旦数据库响应,它可以添加一个后续日志。
基本思路是这样的:
10:01:01 POST Load Executing "SELECT * from posts;'
10:01:03 POST Load 1712ms
如何配置 Rails 以将 SQL 日志记录分为这样的两个步骤?
【问题讨论】:
标签:
ruby-on-rails
logging
activerecord
【解决方案1】:
没有标准方法可以配置记录器以在执行之前输出 SQL 查询。
但是您仍然可以通过扩展 ActiveRecord::LogSubscriber 类来记录查询。
# initializers/extensions/active_record_logger.rb
module Extensions
module ActiveRecordLogger
IGNORE_PAYLOAD_NAMES = ActiveRecord::LogSubscriber::IGNORE_PAYLOAD_NAMES
# ActiveRecord::LogSubscriber doesn't implement this method.
# This method will be invoked before event starts processing.
# It's exactly we are looking for!
def start(name, id, payload)
super
return unless logger.debug?
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
name = payload[:name]
sql = payload[:sql]
name = color(name, nil, true)
sql = color(sql, nil, true)
debug "STARTING #{name} #{sql}"
end
end
end
ActiveRecord::LogSubscriber.include Extensions::ActiveRecordLogger
现在您将在 执行之前获得查询日志。比如查询
User.find 1
会产生
STARTING User Load SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
#<User id: 1, username: "dimakura", created_at: "2015-09-08 13:16:42", updated_at: "2015-09-08 13:16:42">
【解决方案2】:
我认为您正在搜索explain rails 方法。所以,你需要实现类似的东西:
@query = Some.model.query
Rails.logger @query.explain
ActiveRecord::Base.silence do
@query.load
end
Rails.logger "Finished"
当然,您可以添加计时器、原因、异常处理等。