When LogStruct Runs
LogStruct decides in each process whether to replace Rails' logger. Where it's off, the process logs exactly as it would without LogStruct: Rails' text lines, no filtering and no integrations.
The rule
- When the
LOGSTRUCT_ENABLEDenvironment variable is set, it decides:true,t,yes,yor1(in any case) turns LogStruct on, and any other value turns it off. This applies to consoles too. - Otherwise LogStruct is on when all of these are true:
- The Rails environment is in
config.enabled_environments(default[:test, :production]). - The process isn't a console (
rails consoleorrails c). - It's a server or job process LogStruct recognizes (below), or the environment is
test.
- The Rails environment is in
So with the defaults, LogStruct is off in development, on for every test process except a console, and in production on only in the processes below.
Recognized processes
- Puma, when the program's name or one of its arguments contains
puma(bundle exec puma, orpumastarted by a wrapper script). rails server, with any server.- Unicorn, Thin and Falcon, when their server class (
Unicorn::HttpServer,Thin::Server,Falcon::Server) is defined as LogStruct loads. - Sidekiq, in the
sidekiqprocess (Sidekiq.server?). - GoodJob, in
good_job start. GoodJob's async mode runs inside your web server, which is already recognized.
Everything else keeps Rails' logger in production. That includes Rake tasks (db:migrate too), rails runner, Solid Queue's bin/jobs (Rails 8's default job runner), Resque, Delayed Job, Passenger and Pitchfork.
Unicorn, Thin and Falcon are recognized by their class names. If your app loads one of these gems in every process (it's in the Gemfile without require: false), Rake tasks and other processes may count as servers too.
Turning it on for other processes
Set LOGSTRUCT_ENABLED=true in the environment of each process that should write LogStruct lines, for example in a Procfile:
web: bundle exec puma -C config/puma.rb
jobs: LOGSTRUCT_ENABLED=true bin/jobs
release: bin/rails db:migrateIf you set LOGSTRUCT_ENABLED=true for a whole container image, every process in it gets LogStruct, consoles included. Set LOGSTRUCT_ENABLED=false to turn it off in a process LogStruct would otherwise recognize.
From an initializer
LogStruct first decides when the gem is loaded (by Bundler.require), and checks again after config/initializers run. An initializer can set config.enabled, or change config.enabled_environments to apply the rule above to other environments. LOGSTRUCT_ENABLED wins over both, and config.enabled wins over enabled_environments.
LogStruct.configure do |config|
# config.enabled applies to every process that loads this initializer, in every
# environment, so limit it to the environment you mean
config.enabled = true if Rails.env.development?
endA few things are set up as the gem loads, before initializers run: Puma's boot lines in rails server and the logger that early boot lines go to. Use LOGSTRUCT_ENABLED to turn LogStruct on or off for all of the boot.
In development
Start the server with LOGSTRUCT_ENABLED=true bin/rails server to see the lines your app writes in production. They're JSON by default; set prefer_json_in_development = false and enable_color_output = true for colored text instead (see Logger Settings).
Where lines go
| Environment | Output |
|---|---|
| production (and others) | STDOUT only, unbuffered. No log file. |
| development | STDOUT and log/development.log |
| test | log/test.log only, so test output stays clean |
| RAILS_LOG_TO_STDOUT set | STDOUT only, in any environment |
The environments that also write the log file are config.local_environments (default [:development, :test]). LogStruct honors config.log_level. A config.logger you set yourself applies only where LogStruct is off. Appenders your app adds to SemanticLogger in an initializer are kept. They write with the formatter you give them, so give them LogStruct::SemanticLogger::Formatter.new for filtered lines (see Where filtering applies).
Forking servers
LogStruct writes lines through SemanticLogger, which writes them from a background thread. A forked child doesn't inherit its parent's threads, so LogStruct hooks Process._fork, which Ruby calls for every fork, and starts a new writer thread in each child. This covers Puma's cluster mode, Unicorn, Passenger, Pitchfork, Resque and anything else that forks, with no on_worker_boot code of your own.
When it's off
- Rails' logger, Lograge's settings and Sidekiq's logger are left alone.
- Nothing is filtered or scrubbed: LogStruct's filters apply only to the lines it writes.
- Mailers still have
log_and_ignore_error,log_and_report_errorandlog_and_reraise_error, so arescue_fromthat names one of them works everywhere. They log a plain text line to the mailer's logger (see ActionMailer). LogStruct.infoand the other logging methods still work, through Rails' logger.