Open Liberty の 下記 blog に、「JSON を System.out にラッピングなしで出力できるようになった」とあるが、説明が今一つ分かりにくい(?)ので、検証ついでに投稿します。
今までは、JSON 形式で出力できなかったのか?
Liberty の標準出力(console.log)の形式は、環境変数、bootstrap.properties、server.xml の何れかで JSON 形式に変更できました。
- 環境変数:
WLP_LOGGING_CONSOLE_FORMAT=JSON
- bootstrap.properties:
com.ibm.ws.logging.console.format=JSON
- server.xml:
<logging consoleFormat="JSON"/>
しかし、この状態でアプリケーションが System.out に JSON 形式のメッセージを出力しても、残念ながら、メッセージが文字列としてラッピングされて出力されていました。
例えば、アプリケーションが以下のメッセージを出力すると、
{"level" : "WARN",
"message" : "連携先システムの応答が悪化しています。"}
標準出力(console.log)には、以下の様にラッピングされて出力されていました。
{"type":"liberty_message","host":"9.85.48.106","ibm_userDir":"C:\/opt\/wlp\/usr\/","ibm_serverName":"open-liberty","message":"{\"level\" : \"WARN\",\n \"message\" : \"連携先システムの応答が悪化しています。\"}","ibm_threadId":"0000002e","ibm_datetime":"2020-09-01T09:01:12.162+0900","module":"SystemOut","loglevel":"SystemOut","ibm_methodName":"","ibm_className":"","ibm_sequence":"1598918472162_0000000000048","ext_thread":"Default Executor-thread-1"}
分かりにくいので、jq で整形すると以下の様になります。
{
"type": "liberty_message",
"host": "9.85.48.106",
"ibm_userDir": "C:/opt/wlp/usr/",
"ibm_serverName": "open-liberty",
"message": "{\"level\" : \"WARN\",\n \"message\" : \"連携先システムの応答が悪化しています。\"}",
"ibm_threadId": "0000002e",
"ibm_datetime": "2020-09-01T09:01:12.162+0900",
"module": "SystemOut",
"loglevel": "SystemOut",
"ibm_methodName": "",
"ibm_className": "",
"ibm_sequence": "1598918472162_0000000000048",
"ext_thread": "Default Executor-thread-1"
}
アプリケーションが出力した JSON データが、Liberty のログ出力の message 要素としてラッピングされて出力されています。これを、JSON として処理するには、ひと手間必要になってしまいます。
JSON 形式での直接出力を試してみる
Open Liberty 20.0.0.8 で追加された機能を試してみます。bootstrap.properties または server.xml に以下の指定を追加すると、この機能が有効になります。
- bootstrap.properties:
com.ibm.ws.logging.apps.write.json=true
- server.xml:
<logging appsWriteJson="true"/>
先ほどと同じメッセージをアプリケーションが出力すると、アプリケーションが出力したそのままの形式で、 標準出力 (console.log) に出力されます。
Liberty が出力するメッセージの message 要素として出力されるわけではなく、本当にそのまま出力されます。
{"level" : "WARN",
"message" : "連携先システムの応答が悪化しています。"}
少し脱線しますが、出力メッセージが "{" で始まっていると、JSON 形式のデータとして判断され、そのまま標準出力 (console.log) に出力され、それ以外の時は従来と同じ扱いのようです。
不要な要素を Liberty の JSON 形式の標準出力(console.log)から除去する
ついでに、JSON 形式の標準出力(console.log)から不要な要素を除去する方法を試してみました。こちらは、Open Liberty 20.0.0.5 で追加された機能です。
JSON 形式の標準出力(console.log)には、あまり役に立ちそうにない要素が入っています。上記の出力例でも確認できますが、例えば、以下のような要素です。特に、Liberty をコンテナとして稼働させている場合は、全てのコンテナから同じ情報が出力されることになるので、まったく意味がない情報となります。
- ibm_userDir
- ibm_serverName
このような不要な要素は、bootstrap.properties に以下のような指定を追加すると出力を抑止できます。
- bootstrap.properties:
com.ibm.ws.logging.json.field.mappings=message:ibm_userDir:,ibm_serverName:
終わりに
内容としては、冒頭で紹介した blog の内容の確認だけなのですが、いかがでしたでしょうか。
Liberty をコンテナ環境で稼働させる場合、アプリケーションのログを JSON 形式で System.out (コンテナの標準出力) に書き出し、Logstash や fluentd で JSON としてパースして Elasticsearch に JSON 形式で転送したくなります。今回の機能は、このような時にぴったりの機能です。
なぜ、今まで、できなかったんでしょうか???