Log every SQL query to database in Rails
SQL logging in rails -
In brief - you need to override ActiveRecord execute method. There you can add any logic for logging.
Log every SQL query to database in Rails 3
Put it in config/initializers. Most likely it's because of reloading classes each time in dev env. This code need to be executed only once though.
Ruby on Rails SQL Logging
If you use active record, you can overwrite the active record logger :
ActiveRecord::Base.logger = Logger.new("#{Rails.root}/log/sql_log.log")
Display SQL queries in log with Rails 4
the rails console never writes to the log file, but you can achieve it quite easily, for example, if you execute following after starting the rails console
ActiveRecord::Base.logger = Logger.new STDOUT
rails will log all SQL statements to stdout, thus display them in your terminal. and since Logger.new accepts any stream as first argument, you could just let it write to the rails development.log:
ActiveRecord::Base.logger = Logger.new File.open('log/development.log', 'a')
How to show SQL queries run in the Rails console?
Rails 3+
Enter this line in the console:
ActiveRecord::Base.logger = Logger.new(STDOUT)
Rails 2
Enter this line in the console:
ActiveRecord::Base.connection.instance_variable_set :@logger, Logger.new(STDOUT)
ActiveRecord log which query went to which database
As I know you can't do it with ActiveRecord natively. But you can override log
method in AbstractAdapter
if you really need it:
class ActiveRecord::ConnectionAdapters::AbstractAdapter
alias :original_log :log
def log(sql, name = "SQL", binds = [], statement_name = nil)
#add info that you want to display to name
name = "#{name} #{@connection.hash}"
original_log(sql, name, binds, statement_name) { yield }
end
end
The output:
D, [2017-03-15T20:55:59.200533 #73440] DEBUG -- : -4111614587995646180 (0.5ms) create table foo(i int)
D, [2017-03-15T20:55:59.201178 #73440] DEBUG -- : -4097137311320758185 (0.1ms) create table foo(i int)
D, [2017-03-15T20:55:59.201298 #73440] DEBUG -- : -4111614587995646180 (0.0ms) insert into foo(i) values (1)
D, [2017-03-15T20:55:59.201426 #73440] DEBUG -- : -4097137311320758185 (0.1ms) insert into foo(i) values (2)
D, [2017-03-15T20:55:59.202229 #73440] DEBUG -- : -4111614587995646180 (0.7ms) select * from foo
D, [2017-03-15T20:55:59.202360 #73440] DEBUG -- : -4097137311320758185 (0.0ms) select * from foo
Being more human-friendly
The above code logs the connection hash, and that's enough to tell one connection from another. If you want to log something more human-friendly than that, you'll need to get a little tricky.
What we can do is to decorate the abstract adapter with a method to return a human-friendly connection name. During your program's initialization, add a #log_name method to each connection adapter:
Base1.connection.define_singleton_method(:log_name) { "one" }
Base2.connection.define_singleton_method(:log_name) { "two" }
The monkey-patch can now use the #log_name method:
class ActiveRecord::ConnectionAdapters::AbstractAdapter
alias :original_log :log
def log(sql, name = "SQL", binds = [], statement_name = nil)
connection_name = respond_to?(:log_name) ? log_name : nil
name = [connection_name, name].compact.join(" ")
original_log(sql, name, binds, statement_name) { yield }
end
end
The output:
D, [2017-03-21T10:10:53.330021 #22147] DEBUG -- : one (0.3ms) create table foo(i int)
D, [2017-03-21T10:10:53.330380 #22147] DEBUG -- : two (0.2ms) create table foo(i int)
D, [2017-03-21T10:10:53.330464 #22147] DEBUG -- : one (0.0ms) insert into foo(i) values (1)
D, [2017-03-21T10:10:53.330536 #22147] DEBUG -- : two (0.0ms) insert into foo(i) values (2)
D, [2017-03-21T10:10:53.331002 #22147] DEBUG -- : one (0.4ms) select * from foo
D, [2017-03-21T10:10:53.331104 #22147] DEBUG -- : two (0.0ms) select * from foo
Rails Logs: Only show Create, Update, and Destroy SQL statements in Logs and nothing else
You can disable logging of ActiveRecord
database queries by setting the log_level
to :info
.
Then use Rails' ActiveSupport::Instrumentation
and subscribe to the sql.active_record
event.
Just add the following code into an initializer:
# in `config/initializers/query_logger.rb`
class QueryLogger
def call(name, started, finished, unique_id, payload)
query = payload[:sql]
Rails.logger.info("SQL Query: #{query}") unless query.start_with?('SELECT')
end
end
ActiveSupport::Notifications.subscribe('sql.active_record', QueryLogger.new)
Rails 2.3 log all database queries separatly
You don't need to monkey-patch ActiveRecord to get logging (which you're doing incorrectly here anyway). I assume you want this in production, since in development all queries are already logged. Simply set this in config/environments/production.rb
:
config.log_level = :debug
Or if you want to restrict this to SQL queries only, without the other verbosity, try this:
ActiveRecord::Base.logger.level = Logger::DEBUG
Or if your goal is to write the SQL queries to a dedicated logfile, check out this question: Rails3 SQL logging output in a separate file
Log SQL queries during rake tasks
Depending on your environment, Rake will log sql queries just like any Rails process will & in the same logfile. So on your dev box, check your log/development.log file - it will contain your Rake task's queries. If you want queries logged in production, set the log level in your Rake task to DEBUG, and make sure the rake task depends on :environment.
desc "Task with SQL logging"
task :test_log => :environment do
Rails.logger.level = Logger::DEBUG
Your code here...
end
Related Topics
How to Use a Calculated Column to Calculate Another Column in the Same View
When or Why Would You Use a Right Outer Join Instead of Left
Storing Money in a Decimal Column - What Precision and Scale
How to Store a List in a Column of a Database Table
How to Convert an Integer (Time) to Hh:Mm:Ss::00 in SQL Server 2008
How to Include a PHP Variable Inside a MySQL Statement
Run All SQL Files in a Directory
The Maximum Recursion 100 Has Been Exhausted Before Statement Completion
Delete All Rows in a Table Based on Another Table
Fastest Way to Update 120 Million Records
Using 'Case Expression Column' in Where Clause
Split Column into Multiple Rows in Postgres
SQL Runs Fast in Ssms Slow in ASP.NET