Logging to STDOUT (12‑Factor)
LogStruct embraces The Twelve‑Factor App approach to logs: write events as unbuffered lines to STDOUT
and let the environment aggregate, ship, and store them. This section explains how Rails logs by default, how LogStruct integrates, and what to configure for a predictable developer experience.
Rails Defaults vs. LogStruct
- Rails (development): writes to
log/development.log
by default; the server console shows Puma boot lines, not application logs. - Rails (test): most test runners capture logs; default logger often writes to a file.
- Rails (production): many deploy targets set
RAILS_LOG_TO_STDOUT=1
, so logs go to STDOUT. - LogStruct: when enabled, replaces the logger with SemanticLogger and emits JSON to STDOUT in test/production by default. In development, you can opt‑in to the same JSON to avoid surprises.
Make Development Match Test/Production
Opt‑in locally so development behaves like test/production:
# One-off
LOGSTRUCT_ENABLED=true RAILS_LOG_TO_STDOUT=1 rails s
# Or set in your shell env for the session
export LOGSTRUCT_ENABLED=true
export RAILS_LOG_TO_STDOUT=1
rails s
You can also force STDOUT + debug in development via code (useful for teams):
# config/environments/development.rb (or in your application template)
config.log_level = :debug
logger = ActiveSupport::Logger.new($stdout)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
Production Recommendations
- Ensure
RAILS_LOG_TO_STDOUT=1
(many platforms set this by default). - Keep LogStruct enabled in production (default) to emit structured JSON for all integrations.
- Ship logs to your log aggregation system (e.g., CloudWatch, ELK, Datadog) as line‑delimited JSON.