Next.js + Rails APIでSPA開発中の話。
ECS Fargate + Railsの本番環境で500エラーが出たが解決に時間がかかりました。
かなり苦労したので記事化。技術記事初投稿です。
1. 前提
- 本番環境の500エラーを解消したいがCloudWatchにRailsログが出ない
- リバースプロキシのNginxでは500エラーとだけ出る
- Railsログには情報なし
- 本番インフラ: Route53 → ALB → ECS Fargate (Nginx/Rails)
- Ruby 3.3.7 Rails API 7.2.2.1
500エラーという情報だけで力技で解決しようとしてました。。
2. 詳しい状況
Devise Token Authのメール内リンク押下によるアカウント認証時に500エラー。
認証も失敗するし、リダイレクト先で500と出る。
なお、開発環境では成功済み。
コード:
# puma.rb
stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true
# production.rb
config.logger = ActiveSupport::Logger.new(STDOUT)
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
.then { |logger| ActiveSupport::TaggedLogging.new(logger) }
config.log_level = :debug
加えて、RAILS_LOG_TO_STDOUT=true
をタスク定義の環境変数で渡していました。
これは.env.production
への設定でもOK。
Devise Token AuthのOSSコードを追ったりして原因特定しようと思ったができず。
3. 解決法
結論、pumaのログ設定を下記に修正してCloudWatchでRailsログが出ました。
# puma.rb
if ENV.fetch("RAILS_ENV", "development") == "production"
stdout_redirect(nil, nil, true)
else
stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true
end
stdout_redirect
でログ出力先を指定。本番ではSTDOUTもSTDERRもnil
に。
これでコンテナのSTDOUT/STDERRを収集してCloudWatchに流れます。
修正後にRailsログを見るとActionController::Redirecting::UnsafeRedirectErrorでした。500エラーの具体的内容さえわかれば対処は難しくない。10分で解決しました。
最後に
- 500エラーは具体的内容が不明だと解決は非常に難しい(OSS依存の内容なら尚更)
- デプロイ後は本番用ログが正常に出るかを早めに確認すべき
以上を思いました。
同じような問題にぶつかった方の参考になれば幸いです。