Rails Octopus Gem - Log which database queried - ruby-on-rails

Does anyone have a way to check which database is being queried from ActiveRecord using Octopus Gem?
I want to check whether the read requests are actually hitting slave database and not master database.

Looking into the gem source code, I believe that Octopus already logs the current shard it sends the ActiveRecord query against, by default. You need to set your Rails logger to the :debug level and then you should see a green prefix [Shard: the_db] ... on each debug line, including the SQL printings.
See also this gem's spec for using the logging feature.

Related

Rails Middleware in console?

I want to run some code around a rails console session (e.g. add log tagging, set database connection). For the rails server I can do this using middle ware, but can this also be done for the console?
see also: Rails7 MultiDB switch shard for console

Create an audit log from irb or rails console?

As part of the security procedures for our Rails application, we want to have an audit log of the commands that were run from rails console in our production environment.
This audit log should be persisted somewhere, such as a database, a file in an S3 bucket, or similar. If it could be written to the standard rails log, that might be OK too, as we already have a way to persist that.
We're currently hosted on Heroku. Heroku will log the event of firing up a console, but (a) Heroku provides no functionality for logging commands run from an active console, and (b) we'd like a more general-purpose solution.
Are there any pre-existing solutions for this out there?
If there is none, I'm trying to figure out how to monkey-patch IRB or Rails Console.
I've discovered that the data I need is already in
Readline::HISTORY
but I'm struggling to figure out where/how to hook into it.
Ideally, I'd like to capture each entry as (before?) it is sent to the interpreter, and quickly persist it somewhere (we already have Resque, so that may be a good solution). FWIW, sending the contents of Readline::HISTORY on Kernel.exit seems like it may be unreliable. For example, if a SIGKILL stops the process, then the history contents wouldn't be saved.

Turn off active record logging in production

How can I turn off the verbose active record logging in production? (Like every SQL statement is logged)
My logs are filling up really fast because I have background jobs running loads of queries. This is fine on my development server but I don't need this logged in production.
To turn off completely, just add this to your environment file (i.e. production.rb):
config.active_record.logger = nil
See AR guide (section 3.6):
config.active_record.logger accepts a logger conforming to the
interface of Log4r or the default Ruby Logger class, which is then
passed on to any new database connections made. You can retrieve this
logger by calling logger on either an Active Record model class or an
Active Record model instance. Set to nil to disable logging.
There's more options (like selectively turning on / off) documented in other posts. See Disable Rails SQL logging in console as a starting point.

Re-initialize ActiveRecord after rails startup

I'm building a system which allows the user to modify the database.yml contents via an admin frontend interface.
That changes to database.yml obviously don't have any affect until the application is restarted. Rather than forcing the user (who may not have SSH access to the physical box) to restar the application manually, I'd like a way to force ActiveRecord to reload the config post startup.
Rather than requiring them to restart the server, is there a way to force ActiveRecord to re-initialize after initial startup?
Rationale
There are two use cases for this - a) initial setup wizard b) moving from sqlite evaluation database to production supported database.
Initial Setup Wizard
After installing our application and starting it for the first time the user will be presented with a setup wizard, which amongst other things, allows the user to choose between the built in evaluation database using sqlite or to specify a production supported database. They need to specify the database properties. Rather than asking users to edit yml files on the server we wish the present a frontend to do so during initial setup.
Moving from sqlite evaluation database to production supported database
If the user opted to go with the built in evaluation database, but alter wants to migrate to a production database they need to update the database settings to reflect this change. Same reasons as above, a front end rather than requiring the user to edit config files is desired, especially since we can validate connectivity, permissions etc from the application rather than the user finding out it didn't work when they try to start the application and they get an activerecord exception.
Restart your Rails stack on the next request just as you would if you had access to the server.
system("touch #{File.join(Rails.root,'tmp','restart.txt')")
Building on #wless1's answer in order to get ERB-like ENV vars (e.g. <%= ENV['DB_HOST'] %>) working try this:
YAML::load(ERB.new(File.read(File.join(Rails.root, "config/database.yml"))).result)
ActiveRecord::Base.establish_connection config[Rails.env]
Theoretically, you could achieve this with the following:
config = YAML::load File.read(File.join(Rails.root, "config/database.yml"))
ActiveRecord::Base.establish_connection config[Rails.env]
You'd have to execute the reconnection code in every rails process you're running for it to be effective. There's a bunch of dangerous things to worry about here though - race conditions when changing the database config, syntax problems in the new database.yml, etc.

Using Octopus gem with Rails SQL Caching

We are using octopus in our rails app to forward read queries directly to our slave boxes, and writes to our master. Have to say its a great gem, but we noticed that queries to the slaves forgoes Active Record's default SQL caching. Kind of defeats the purpose to scale the DB servers horizontally only to lose out on the caching layer that would help scale.
Does anyone have an idea on how to fix this, or is there a better gem to use. We don't need the sharding functionality that octopus gives; just the replication.
thanks ahead of time
The way SQL caching is turned on for a connection is by doing something like
ActiveRecord::Base.connection.cache do
# the query cache is used here
end
# and turned off by here
For the main activerecord connection rails has a rack middleware that sets this up for each request. If you want this to happen for your slave connection then you'll need to do something similar yourself to enable caching for your second connection (slightly easier than a rack middleware would be an around_filter)
I'm not very familiar with octopus, but it seems likely that these two connections will be independant - activerecord won't know to invalidate its cache on your read connection just because you've done some writes on your other connection

Resources