2012/07/29

[nginx] アクセスログフォーマット

nginxはアクセスログとエラーログを出力してくれます。
このログの出力フォーマットのカスタマイズ方法について書きます。

nginxのログフォーマットに関する公式ドキュメントは、HttpLogModuleにあります。

コレを拙いながらも訳すと…


log_formatディレクティブは、ログのフォーマットを表現します。 フォーマットにおいて、一般的な変数と同様に、ログ出力の瞬間のみに有効となる変数も使用出来ます。
  • $body_bytes_sent, クライアントに転送したバイト数のうち、レスポンスヘッダのバイト数を引いたもの。この変数は、Apacheのmod_log_configの%Bパラメータと互換性があります(0.3.10以前のバージョンでは、$apache_bytes_sentと呼ばれていました。)。
  • $bytes_sent, クライアントに転送したバイト数です。
  • $connection, コネクション数です。
  • $msec, ログを出力した時点の時刻(マイクロ秒の精度)です。
  • $pipe, リクエストがパイプラインによるものである場合、"p"を出力します。
  • $request_length, リクエストボディの長さです。
  • $request_time, nginxがそのリクエストを処理するのにかかった時間で、ミリ秒精度を含んだ秒数です。(0.5.19以前のバージョンでは秒数のみ)
  • $status, 応答ステータスです。
  • $time_ios8601, ISO 8601フォーマットの時刻です。例. 2011-03-21T18:52:25+03:00(バージョン0.9.6で追加)
  • $time_local, ローカル時刻です。

クライアントから転送されたヘッダについては、$sent_http_content_rangeのように"sent_http_"プレフィクスがつきます。

他のモジュールが提供する変数も、ログに出力できます。例えば、upstreamのレスポンスヘッダは、"upstream_http_"プレフィクスをつけて、ログに出力できます。

以下は、"combined"と呼ばれる、予め定義されたログフォーマットです。

log_format combined 'remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';


となっています。
したがって、
log_format 名前 フォーマット;
を定義して、"フォーマット"の部分に含める変数を必要に応じて並べてあげればいいわけです。

2013/03/03追記。
日本語のnginxの本があったんですね。知りませんでした..。

2012/07/12

[rails] rspecでDBのロールバックをテストする。

Railsアプリで、ActiveRecord::Base.transactionを使って、 トランザクションを明示的に張り、異常がある場合にロールバックする、 という実装は大いに有りますよね。

僕はRSpecを使ってテストしています。
RSpecを使って、DBがロールバックされることを確認する方法を書いておきます。

例えば、コントローラに次のような処理を書いたとします。
モデルの変更後、メールを送信する、という処理で、ここでは、メールの送信に失敗した場合は、 変更をロールバックする、という仕様とします。(その仕様は果たして妥当か?はここでは考えない。)


def save_and_send_mail(model)
  begin
    ActiveRecord::Base.tansaction do
      model.save!
      SomeMailer.something.deliver
    end
  rescue => e
    logger.error(e.message)
    logger.error(e.backtrace)
  end
end

「メールの送信に失敗したら、DBをロールバックする」という振る舞いを確認するために、 実行前後でデータを引っ張り出して比較するというのも出来なくはなさそうですが、
ちょっと面倒に思えます。

なので、「ロールバックする」メソッドが呼ばれることを確認することにました。
この「ロールバックする」メソッドとは、

  • ActiveRecord::Base.connection.rollback_db_transaction
にあたるので、

describe 'some method' do

  before do
    # 前処理
  end

  it "should rollback transaction if fail to send mail." do
    # 送信を失敗させる。
    SomeMailer.stub(:something).and_raise StandardError
    # ロールバック処理が呼ばれること
    ActiveRecord::Base.connection.should_receive(:rollback_db_transaction).once
    # 実行
    @controller.save_and_send_mail(model)
  end

end

というexampleが書けます。
これで、RSpecを使って、簡単にロールバックのテストができます。