はじめに
Railsアプリケーションを開発している際に、デバッグやエラーの特定は日常的な作業です。Railsのログはデータベースのトランザクションやリクエスト処理の詳細を提供しますが、バリデーションエラーのようなアプリケーションレベルのイベントは標準のログには詳細が記録されないことがあります。この記事では、Railsのログがどのように機能しているかを解説し、カスタムログを活用してデバッグ情報を充実させる方法を紹介します。
Railsのログが出る場合と出ない場合
Railsのログが出る場合:
1. リクエストログ:
これはHTTPリクエストを処理するたびに生成されます。リクエストメソッド、パス、完了ステータス、所要時間などが含まれます。
2. データベースクエリログ:
ActiveRecordを通じてデータベースに発行される各クエリの詳細が記録されます。これにはSQL文とクエリの実行時間が含まれます。たとえば、以下のバリデーションにおけるエラーログなどがそれにあたります。
def unique_future_reservation_per_customer_and_company
return if date.blank? || customer_id.blank? || company_id.blank? || date < Date.today
future_reservations = Reservation.where(customer_id: customer_id, company_id: company_id).where('date >= ?', Date.today)
future_reservations = future_reservations.where(deleted_at: nil)
future_reservations = future_reservations.where.not(id: id) unless new_record?
if future_reservations.exists?
errors.add(:base, "予約は1つしか作成できません")
end
end
↳ app/models/reservation.rb:36:in `unique_future_reservation_per_customer_and_company'
TRANSACTION (0.8ms) ROLLBACK
↳ app/controllers/reservations_controller.rb:104:in `toggle_approval'
3. エラーログ:
システムのエラーや例外が発生した場合に生成されます。これにはエラーメッセージとスタックトレースが含まれることが多いです。
Railsのログが出ない場合:
4. モデルバリデーションエラー:
モデルのバリデーションはデータベースレベルの処理ではなく、オブジェクトがデータベースに保存される前のメモリ内で処理されます。そのため、標準のログにはこれらの詳細は記録されません。たとえば、以下のバリデーションではログが出力されません。
def date_cannot_be_in_the_past
if date.present? && date < Date.today
errors.add(:date, "は今日以降の日付を選択してください")
end
end
以下はログです。エラーが生じてロールバックしているが、エラーに関する情報が記載されていません。
Customer Load (1.1ms) SELECT "customers".* FROM "customers" WHERE "customers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/reservations_controller.rb:104:in `toggle_approval'
TRANSACTION (0.6ms) ROLLBACK
↳ app/controllers/reservations_controller.rb:104:in `toggle_approval'
Redirected to http://localhost:3000/reservations
Completed 302 Found in 27ms (ActiveRecord: 7.4ms | Allocations: 9009)
対策: カスタムログの実装
アプリケーションレベルの処理においてログを出力するにはカスタムログを設定する必要があります。アプリケーションの特定の処理でカスタムログを記録することで、デバッグが容易になり、運用時の問題解析が迅速に行えるようになります。例として、モデルバリデーションのカスタムログを追加する方法を示します:
class Reservation < ApplicationRecord
validate :date_cannot_be_in_the_past
def date_cannot_be_in_the_past
if date.present? && date < Date.today
Rails.logger.info "Validation Failed - Date cannot be in the past: #{date}"
errors.add(:date, "は今日以降の日付を選択してください")
end
end
end
このコードは、Reservation
モデルにカスタムバリデーションを追加し、バリデーションが失敗するたびにログに記録します。こうすることで、開発中はもちろん、本番環境での問題発生時にも、ログから迅速に情報を得ることができます。
ログレベルの管理
Railsでは、環境ごとにログレベルを設定することができます。例えば、開発環境ではdebug
レベルで詳細な情報を出力し、本番環境ではinfo
レベルに設定して情報量を制限することが一般的です。
# config/environments/production.rb
config.log_level = :info
まとめ
Railsのログは強力なデバッグと監視のツールですが、すべての情報が自動的に記録されるわけではありません。カスタムログを適切に実装することで、アプリケーションの挙動をより詳細に把握し、開発と運用の効率を大幅に向上させることができます。