如何在Rails查询发生之前记录它们?

时间:2022-05-05 00:20:24

Rails logger by default will show the SQL after it's been executed. Sometimes - mainly when a query takes a long time - I want to configure the logger to output the SQL before it executes. Then it can add a follow-up log once the database has responded.

默认情况下,Rails记录器将在执行后显示SQL。有时 - 主要是在查询需要很长时间的时候 - 我想配置记录器在执行之前输出SQL。然后,一旦数据库响应,它就可以添加后续日志。

Basic idea is something like:

基本想法是这样的:

10:01:01 POST Load Executing "SELECT * from posts;'
10:01:03 POST Load 1712ms

How can Rails be configured to break the SQL logging into 2 steps like this?

如何配置Rails以将SQL登录分成两个这样的步骤?

2 个解决方案

#1


3  

There is no standard way you can configure logger to output SQL query before execution.

没有标准方法可以配置记录器在执行之前输出SQL查询。

But you can still log queries this way by extending ActiveRecord::LogSubscriber class.

但您仍然可以通过扩展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

Now you will get query log before execution. For instance, querying

现在,您将在执行前获得查询日志。例如,查询

User.find 1

will produce

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


2  

I think you are searching for explain rails method. So, you need to implement something like that:

我想你正在寻找解释rails方法。所以,你需要实现类似的东西:

@query = Some.model.query
Rails.logger @query.explain
ActiveRecord::Base.silence do
  @query.load
end
Rails.logger "Finished"

Of course, you can add timers, causes, exception handling et.c.

当然,你可以添加定时器,原因,异常处理等。

#1


3  

There is no standard way you can configure logger to output SQL query before execution.

没有标准方法可以配置记录器在执行之前输出SQL查询。

But you can still log queries this way by extending ActiveRecord::LogSubscriber class.

但您仍然可以通过扩展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

Now you will get query log before execution. For instance, querying

现在,您将在执行前获得查询日志。例如,查询

User.find 1

will produce

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


2  

I think you are searching for explain rails method. So, you need to implement something like that:

我想你正在寻找解释rails方法。所以,你需要实现类似的东西:

@query = Some.model.query
Rails.logger @query.explain
ActiveRecord::Base.silence do
  @query.load
end
Rails.logger "Finished"

Of course, you can add timers, causes, exception handling et.c.

当然,你可以添加定时器,原因,异常处理等。