Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to log Rails queries before they happen?

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.

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?

like image 457
mahemoff Avatar asked Sep 08 '15 10:09

mahemoff


People also ask

Where does rails logger write to?

By default it puts these log files in the log/ directory of your project. So if you open up that folder you'll see a development.

What is the log to check for errors in rails?

Rails uses six different log levels: debug, info, warn, error, fatal, and unknown. Each level defines how much information your application will log: Debug: diagnostic information for developers and system administrators, including database calls or inspecting object attributes.

What is rails logger debugging?

logger. debug , or in short logger. debug writes the parameter text to a log file. This log file is by default environment specific. If you are currently running rails in development environment then the log file in use is log/development.


1 Answers

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

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

# 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">
like image 185
dimakura Avatar answered Oct 11 '22 04:10

dimakura