ActiveRecord::ModSqlLogSubscriber
An ActiveRecord::LogSubscriber which records only mod-SQL logs.
The mod-SQL is shown as follows.
- INSERT
- UPDATE
- DELETE
- TRUNCATE
- BEGIN
- COMMIT
- ROLLBACK
- SAVEPOINT
- RELEASE SAVEPOINT
- ROLLBACK TO SAVEPOINT
Motivation
- SQL logs are useful for trouble shooging.
- Especialy, mod-SQL(INSERT, UPDATE, DELETE, ...) logs are very important to know what occurred in app.
- Rails provides SQL logging feature only by settings
Rails.logger
log level to:debug
. - But this settings writes a lot of
SELECT
statement SQL logs. These logs are very noisy and use many disk space. - I want to write logs only mod-SQL(INSERT, UPDATE, DELETE, ...) and transaction SQL(BEGIN, COMMIT, ROLLBACK, ...). So I create this gem.
Requirements
- Rails >= 5.1.5
Installation
Add this line to your application's Gemfile:
gem 'active_record-mod_sql_log_subscriber'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install active_record-mod_sql_log_subscriber
Usage
Create a file underconfig/initializer
, configure log subscriber,
and attach to :active_record namespace.
require 'active_record/mod_sql_log_subscriber'
::ActiveRecord::ModSqlLogSubscriber.configure do |config|
config.disable = ::ActiveRecord::Base.logger.debug? # Recommended
end
::ActiveRecord::ModSqlLogSubscriber.attach_to(:active_record)
Next restart your app, then your app starts to log mod-SQLs.
Here is rails console examples.
$ rails c
> ActiveRecord::Base.logger = Logger.new(STDOUT)
> user = User.find(1); nil # Do not logging
> user.update_attributes(name: 'New name'); nil # Do logging
# => "UPDATE users SET name = 'New name' WHERE id = $1 {:id=>1}"
Try console
You can try this gem by cloning this repo and run bin/setup
and bin/console
.
$ git clone https://github.com/ryu39/active_record-mod_sql_log_subscriber.git
$ cd active_record-mod_sql_log_subscriber
# Run bundle install and create sqlite3 database.
$ bin/setup
# Connect sqlite3 database and start IRB.
$ bin/console
> User.count # => no log
> User.create!(name: 'name', age: 20, birth_date: Date.new(2000, 1, 1))
# => I, [2019-02-05T11:04:07.489057 #42019] INFO -- : begin transaction
# I, [2019-02-05T11:04:07.490495 #42019] INFO -- : INSERT INTO "users" ("name", "age", "birth_date", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) ["name", 20, "2000-01-01", "2019-02-20 05:00:13.175405", "2019-02-20 05:00:13.175405"]
# I, [2019-02-05T11:04:07.492610 #42019] INFO -- : commit transaction
> user = User.last # => no log
> user.update!(name: 'new name')
# => I, [2019-02-05T11:04:52.971503 #42019] INFO -- : begin transaction
# I, [2019-02-05T11:04:52.973071 #42019] INFO -- : UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ? ["new name", "2019-02-20 05:00:37.983816", 2]
# I, [2019-02-05T11:04:52.974081 #42019] INFO -- : commit transaction
> user.destroy!
# => I, [2019-02-05T11:05:13.765564 #42019] INFO -- : begin transaction
# I, [2019-02-05T11:05:13.775460 #42019] INFO -- : DELETE FROM "users" WHERE "users"."id" = ? [2]
# I, [2019-02-05T11:05:13.776722 #42019] INFO -- : commit transaction
Configuration
You can configure this subscriber before attaching to :active_record namespace
::ActiveRecord::ModSqlLogSubscriber.configure do |config|
config.disable = true
config.log_level = :warn
config.log_format = :json
# config.log_format = ->(sql, binds) { 'your code here' }
config.target_statements << 'merge'
end
# You must attach subscriber after configuraton.
::ActiveRecord::ModSqlLogSubscriber.attach_to(:active_record)
Enable/Disable
You can make log subscriber enbaled/disabled via config. Default is enabled. This is useful in development/test env because duplicated sql logs are written in log in this env.
::ActiveRecord::ModSqlLogSubscriber.configure do |config|
config.disable = false # enabled
config.disable = true # disabled
config.disable = ::ActiveRecord::Base.logger.debug? # Recommended
end
Log level
You can change log level. Default is :info.
::ActiveRecord::ModSqlLogSubscriber.configure do |config|
config.log_level = :warn
# config.log_level = :error
# config.log_level = :fatal
end
Log format
You can select log format as follows, or use a custom Proc object.
-
:text
(Default) :json
:hash
- Proc object
Target statement
You can add/change/remove target SQL statements.
::ActiveRecord::ModSqlLogSubscriber.configure do |config|
# Add MERGE SQL
config.target_statements << 'merge'
# Remove BEGIN SQL
config.target_stagements.delete('begin')
# Orverwite your target statements
config.target_statements = %w(insert update delete)
end
Development
After checking out the repo, run bin/setup
to install dependencies.
You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
.
To release a new version, update the version number in mod_sql_log_subscriber.r
,
and then run bundle exec rake release
, which will create a git tag for the version,
push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/ryu39/active_record-mod_sql_log_subscriber. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the ActiveRecord::ModSqlLogSubscriber project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.