GeekFactory

int128.hatenablog.com

Springでリクエストとレスポンスのログを出力する

Spring MVCでリクエストとレスポンスのログを出力する方法を説明します。

リクエストログだけなら CommonsRequestLoggingFilter もしくは AbstractRequestLoggingFilter を使う方法が簡単です。詳しくは下記の記事で説明しています。

int128.hatenablog.com

一方で、レスポンスログを出力するには一工夫が必要です。通常、レスポンスボディはストリームに書き込まれてメモリから消えてしまうため、メモリに一時的に保持する必要があります。Springで用意されている ContentCachingResponseWrapper というクラスを使うと、レスポンスボディをバイト配列で取り出すことができます。

実装例

AbstractRequestLoggingFilter を参考にしてフィルタを実装してみました。

  • ContentCachingRequestWrapper でリクエストオブジェクトをラップする。
  • ContentCachingResponseWrapper でレスポンスオブジェクトをラップする。
  • 前処理で、リクエストオブジェクトからヘッダとボディを取り出してログに出力する。
  • 後処理で、レスポンスオブジェクトからヘッダとボディを取り出してログに出力する。

なお、後処理では必ず ContentCachingResponseWrapper#copyBodyToResponse() を実行する必要があります。そうしないとレスポンスボディがストリームに書き込まれないため、Tomcatの場合は待ち状態になってしまいます。Jettyでは insufficient content written というエラーが返されます。

Java 8 + Lombokで書くとこんな感じです。

このフィルタを適用するとレスポンスボディが一時的にメモリに保持されるため、メモリの消費量が大きくなります。また、大きいレスポンスを返す場合はパフォーマンスが悪化します。そのため、デバッグ用途に限定した方がよいでしょう。