GAEのログを見やすくする方法

最近業務上でGAEを使ってサイトを公開することが増えてきた。このIT TRICKもGAE上で公開している。GAEとは限らず、システムでエラーが発生した場合はまずログをみますよね!?でもGAEは「Logs Stored Data」という項目でログの容量に対して課金をしているため、デフォルトでは必要なリクエスト情報はまったく含まれていない。

必要な情報をGAEのアクセスログに表示させるためにはアプリで実装しなければならない。今回はサーブレットのフィルターを使って、すべてのアクセスの共通ログを見やすく出力する方法をみていこう。

サーブレットフィルタークラスの作成

まず、サーブレットフィルタークラスAccessFilter.class(名前は任意)を作成し、javax.servlet.Filterをインプリメントする。

package com.appspot.trick.it.common.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class AccessFilter implements Filter {

    public void init(FilterConfig arg0) throws ServletException {}

    public void doFilter(ServletRequest request, ServletResponse Response,
            FilterChain chain) throws IOException, ServletException {

    }

    public void destroy() {
    }

}

HttpServletRequest

サーブレットのフィルターの引数はjavax.servlet.ServletRequestになっているが、必要な情報を取得するためにはこれをjavax.servlet.http.HttpServletRequestでキャストし、HttpServletRequestのオブジェクトを取得しなければならないので、以下のように取得する。

// リクエスト
		HttpServletRequest req = (HttpServletRequest)request;


日本時間の出力

GAEの時間はデフォルトではアメリカ時間になっているので、現在時刻を日本時間に変更して出力するには以下のように現在時刻を+9時間にする。

		// 日本時間に変更するため、現在のタイムスタンプ + 9時間する
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.HOUR, 9);
		SimpleDateFormat sdf = new SimpleDateFormat(
				"yyyy'年'MM'月'dd'日' HH'時'mm'分'ss'秒'");

		// 日本時間の出力
		StringBuffer sb = new StringBuffer();
		sb.append("¥n");
		sb.append("【日本時間】:" + sdf.format(calendar.getTime()));
		sb.append("¥n");


リクエストパラメーターの出力

リクエストヘッダー情報をUTF-8でデコードしてから出力する。

これは例えばYahooで検索して、Yahooの検索ページからサイトにアクセスしてきた場合、Yahooの検索ページのURLは遷移元URLとして出力される。この遷移元URLに含まれる日本語キーワードが日本語として表示させるため、ここでUTF-8にデコードしている。

		// ヘッダーの数だけ繰り返す
		Enumeration headernames = req.getHeaderNames();
	    while (headernames.hasMoreElements()){
	      String name = (String)headernames.nextElement();
	      Enumeration headervals = req.getHeaders(name);
	      while (headervals.hasMoreElements()){
	        String val = (String)headervals.nextElement();
	        sb.append("【" + name + "】");
	        sb.append(" :   ");
	        // UTF-8でデコード
	        String strD = URLDecoder.decode(val,"utf-8");
	        sb.append(strD);
	        sb.append("¥n");
	      }
	    }


ソース全体

package com.appspot.trick.it.common.filter;

import java.io.IOException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.logging.Logger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class AccessFilter implements Filter {

    public void init(FilterConfig arg0) throws ServletException {}

    @SuppressWarnings("rawtypes")
    public void doFilter(ServletRequest request, ServletResponse Response,
            FilterChain chain) throws IOException, ServletException {
        
        Logger logger = Logger.getLogger(this.getClass().getName());

        // リクエスト
        HttpServletRequest req = (HttpServletRequest)request;

        // 日本時間に変更するため、現在のタイムスタンプ + 9時間する
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR, 9);
        SimpleDateFormat sdf = new SimpleDateFormat(
                "yyyy'年'MM'月'dd'日' HH'時'mm'分'ss'秒'");

        // 日本時間の出力
        StringBuffer sb = new StringBuffer();
        sb.append("¥n");
        sb.append("【日本時間】:" + sdf.format(calendar.getTime()));
        sb.append("¥n");

        // ヘッダーの数だけ繰り返す
        Enumeration headernames = req.getHeaderNames();
        while (headernames.hasMoreElements()){
          String name = (String)headernames.nextElement();
          Enumeration headervals = req.getHeaders(name);
          while (headervals.hasMoreElements()){
            String val = (String)headervals.nextElement();
            sb.append("【" + name + "】");
            sb.append(" :   ");
            // UTF-8でデコード
            String strD = URLDecoder.decode(val,"utf-8");
            sb.append(strD);
            sb.append("¥n");
          }
        }

        logger.info(sb.toString());

        chain.doFilter(request, Response);
    }

    public void destroy() {
    }

}


フィルターの適用

まずフィルターの定義をweb.xmlに追加する。

    <filter>
        <filter-name>AccessFilter</filter-name>
        <filter-class>com.appspot.trick.it.common.filter.AccessFilter</filter-class>
    </filter>

つぎに今回作成したフィルターのマッピングをweb.xmlに追加する。

    <filter-mapping>
        <filter-name>AccessFilter</filter-name>
        <url-pattern>/</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>AccessFilter</filter-name>
        <url-pattern>*.html</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

あとはデプロイしてログを確認するだけ。

ログの出力結果

以下はYahooでキーワード「it trick 技術メモ」で検索して、Yahooの検索結果ページから遷移してきた場合のログ表示例。

com.appspot.trick.it.common.filter.AccessFilter doFilter: 
【日本時間】:2014年01月15日 14時19分57秒
【Host】 :   it--trick.appspot.com
【Accept】 :   text/html,application/xhtml xml,application/xml;q=0.9,image/webp,*/*;q=0.8
【Referer】 :   http://search.yahoo.co.jp/search?p=it trick 技術メモ&aq=-1&oq=&ei=UTF-8&fr=top_ga1_sa&x=wrt
【Accept-Language】 :   ja,en-US;q=0.8,en;q=0.6
【User-Agent】 :   Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
【X-AppEngine-Country】 :   JP
【X-AppEngine-Region】 :   40
【X-AppEngine-City】 :   fukuoka
【X-AppEngine-CityLatLong】 :   33.590355,130.401715

このログをみると、検索日時・検索キーワード、検索エンジン、検索ユーザーの情報、使用ブラウザやOSなどの情報が一目瞭然。


終わり

最後まで読んで頂き、誠にありがとうございます。この記事はお役に立てましたでしょうか?

もしよければ下にあるGoogleプラグインを使って、IT TRICKのGoogle+ページをフォローして頂けるとうれしいです。

  • 2GAEのログを見やすくする方法

<