14

I want to save to a log file some SQL query rails performs, (namely the CREATE, UPDATE and DELETE ones) therefore I need to intercept all queries and then filter them maybe with some regexp and log them as needed.

Where would I put such a thing in the rails code?

6 Answers 6

15

Here a simplified version of what c0r0ner linked to, to better show it:

connection = ActiveRecord::Base.connection
class << connection
  alias :original_exec :execute
  def execute(sql, *name)
    # try to log sql command but ignore any errors that occur in this block
    # we log before executing, in case the execution raises an error
    begin
        File.open(Rails.root.join("/log/sql.txt"),'a'){|f| f.puts Time.now.to_s+": "+sql}
    rescue Exception => e
      ;
    end
    # execute original statement
    original_exec(sql, *name)
  end
end
Sign up to request clarification or add additional context in comments.

1 Comment

The post on misuse.org notes that it should be loaded by application.rb, in there you could require a file containing your override code. (On Rails 2, you're stuck with the environment config files.)
5

SQL logging in rails - In brief - you need to override ActiveRecord execute method. There you can add any logic for logging.

3 Comments

And remember to not intercept the logging queries themselves, or you'll get an infinite loop...
@DanSingerman That's assuming you're going to log the queries in SQL itself.
404 not found. link is missing
2

As a note for followers, you can "log all queries" like Rails - See generated SQL queries in Log files and then grep the files for the ones you want, if desired.

Comments

1

If you are using mysql I would look into mysqlbinlog . It is going to track everything that potentially updates data. you can grep out whatever you need from that log easily.

http://dev.mysql.com/doc/refman/5.0/en/mysqlbinlog.html

http://dev.mysql.com/doc/refman/5.0/en/binary-log.html

Comments

0

SQL Server? If so...

Actually, I'd do this at the SQL end. You could set up a trace, and collect every query that comes through a connection with a particular Application Name. If you save it to a table, you can easily query that table later.

Comments

0

Slightly updated version of @luca's answer for at least Rails 4 (and probably Rails 5)

Place this in config/initializers/sql_logger.rb:

connection = ActiveRecord::Base.connection
class << connection
  alias :original_exec :execute
  def execute(sql, *name)
    # try to log sql command but ignore any errors that occur in this block
    # we log before executing, in case the execution raises an error
    begin
      File.open(Rails.root.join("log/sql.log"), 'a') do |file|
        file.puts Time.now.to_s + ": " + sql
      end
    rescue Exception => e
      "Error logging SQL: #{e}"
    end
    # execute original statement
    original_exec(sql, *name)
  end
end

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.