2012年9月5日水曜日

[AppEngine] ログ出力

Google App Engine ではファイル出力ができないので、 何か記録を残そうとしたらデータベースに書くかログに出力することになる。
App Engine ではデフォルトでは java.util.logging を使用する設定になっている。

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException, ServletException  {

        Logger logger = Logger.getLogger("SampleLogger");
        logger.info("INFOログです。");
        logger.warning("WARNINGログです。");
        resp.setContentType("text/plain; charset=utf-8");
        resp.getWriter().println("ログ出力テスト");
    }

管理ツールのLogsで見るとこんな感じに出力されている。

管理ツールのLogs画面で Timezone を選択できる。ログの時刻はここで選択した Timezone を使って表示される。


ログの設定


ログの出力設定は、war フォルダのWEB-INF/logging.properties に書いてある。

# A default java.util.logging configuration.
# (All App Engine logging is through java.util.logging by default).
#
# To use this configuration, copy it into your application's WEB-INF
# folder and add the following to your appengine-web.xml:
# 
# <system-properties>
#   <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
# </system-properties>
#
# Set the default logging level for all loggers to WARNING
.level = WARNING

デフォルトでは全ロガーで WARNING 以上のログが出力される。


標準出力


標準出力への出力もログとして記録される。

logging.properties:
...
.level = INFO

テストコード:

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException, ServletException  {
        Logger logger = Logger.getLogger("SampleLogger");
        logger.info("INFOログです。");
        logger.warning("WARNINGログです。");
        resp.setContentType("text/plain; charset=utf-8");
        resp.getWriter().println("ログ出力テスト");
        System.out.println("STDOUT print test.");
        System.out.println("標準出力への出力テスト");
    }

標準出力への出力は、INFOとして扱われている。
デフォルトの logging.properties では INFO は出力されないので、出力レベルを変えてある。
日本語の出力は文字化けするようだ。

デフォルトでは System.getProperty("file.encoding") が「ANSI_X3.4-1968」になっているので、 以下の設定(赤字の部分)を appengine-web.xml に追加してエンコーディングを UTF-8 にしてみたが文字化けは変わらず。

  <system-properties>
    <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
    <property name="file.encoding" value="UTF-8"/>
  </system-properties>

ログは日本語でも文字化けせずに出ているのだから何かの設定をすれば文字化けせずに出るのだろうが現時点では不明。

「System.out」で取得できるオブジェクトの種類を確認してみた。

System.out.println(System.out.getClass().getName());

com.google.apphosting.runtime.security.shared.intercept.java.lang.System_$LogPrintStream

謎なクラスだった。
ローカルのサーバー環境では「java.io.PrintStream」なので AppEngine 環境用の特別なクラスのようだ。

もう少しやってみる。まず明示的に Writer のエンコーディングを UTF-8 にする。

PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"));
pw.println("標準出力への出力テスト");
pw.flush();

これで文字化けせずに出力された。
次は UTF-8 のバイト列にしてから出力する。

System.out.write("標準出力への出力テスト\n".getBytes("UTF-8"));

文字化けはせずに出力されるのだが改行がされないようで次の出力と一緒のログになってしまった。
("標準出力への出力テスト" + System.getProperty("line.separator")).getBytes("UTF-8"));
でも改行がされない。 println を使ったほうがよさそう。



0 件のコメント:

コメントを投稿