JavaアプリケーションからAmazon Kinesis Firehoseにログを直接出力する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Kinesis StreamとKinesis Firehoseは、フルマネージドなストリーミングサービスとして提供されており、大規模なデータの収集・処理に使うことができます。

その一つの活用法として、Kinesis Logback Appenderを紹介したいと思います。

Guardian社が開発しているLogbackのAppenderで、READMEの記載によるとawslabs/kinesis-log4j-appender: GithubのLogback実装とのことです。

READMEに記載の通り、Kinesis StreamとKinesis Firehoseの両方に対応しています。今回はFirehoseAppenderを利用してKinesis Firehoseにログを送信し、S3に出力されていることを確認します。

AWS側の設定

Kinesis Firehoseの作成手順詳細は、別記事にかかれていますのでそちらを併せて参照ください。

今回は以下の点を特筆する点として挙げておきます。

  • Stream Nameはlogback-firehoseとした
  • Destinationには同じAWSアカウントにある適当なS3バケットを指定した

それ以外はデフォルトの設定でDelivery Streamを作成し、ステータスがACTIVEになることを確認します。

Javaアプリケーションの設定

まず、ライブラリのダウンロードをしましょう。私の環境ではGradleを使っているため、以下をbuild.gradleに追加しました。

compile('com.gu:kinesis-logback-appender:1.4.0')

logback.xmlに以下の記載を足します。

<configuration>
    <appender name="KINESIS" class="com.gu.logback.appender.kinesis.FirehoseAppender">
        <region>ap-northeast-1</region>
        <streamName>logback-firehose</streamName>
        <encoding>UTF-8</encoding>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%msg%n</pattern>
        </layout>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="KINESIS"/>
    </root>
</configuration>

必須なのはregion(またはendpoint)とstreamNameです。その他、bufferSizemaxRetryなどのオプションもlogback.xmlから設定可能です。詳細はGithubのREADMEのサンプルを参照ください。

今回の例では、streamNameの設定値を上の手順で作成したlogback-firehoseとしています。

実際にログを出力するアプリケーションコードはこんな感じで雑に書きました。Lombokの@Slf4jアノテーションを利用しています。

@Slf4j
public class KinesisLogRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        while(true) {
            log.debug("debug log");
            log.info("info log");
            log.warn("warn log");
            log.error("error log");
            Thread.sleep(1000L);
        }
    }
}

動作確認

このJavaプログラムをしばらく流したままにしておき、先ほどKinesis FirehoseのDestinationとして登録したS3バケットにデータが登録されているかを確認してみましょう。

S3_Management_Console

対象S3バケットのyyyy/mm/dd/hhのPrefix以下に、Kinesis Firehoseからのデータが書き込まれていました!中身を見てみましょう。中身の確認はAWS CLIを利用すると簡単に行なえます。

$ aws s3 cp s3://sample-firehose-bucket/2017/10/23/07/logback-firehose-1-2017-10-23-07-33-05-ce946ccf-f2c2-47a8-8aa1-39bf5183fff0 - | head -n 10
info log
warn log
debug log
error log
debug log
warn log
error log
info log
error log

今回は簡易化のためにMessageのみをFirehoseに送るようにしていますが、当然LogbackのLayout次第で送る内容は調整可能です。

Logbackに設定を追加するだけで、簡単にFirehoseへとログを送ることができました!

まとめ

アプリケーション開発をする中で(気づかないうちに)規模・容量が大きくなっているのがアプリケーションログではないでしょうか。様々なログが肥大化してディスクフルになった、という経験はサーバ運用に関わった方は誰しも持っているかと思います。

サーバのクラウド化が進み、近年のコンテナ技術の流行もあり、ログはサーバ上に吐き出したままにしてはいけない。必ず外部のストレージに保存すべしという認識はそれなりに進んでいるのではないかと思います。では具体的にどういう方法でアプリケーションログを外部に保存すればよいのでしょうか。

一つの案は、FluentdLogstashのようなログ収集ミドルウェアを利用することです。これらのプロダクトは様々な形式のinput/outputに対応しており、柔軟な設定を行うことが可能です。

一方で、それほど高機能でなくても良い、ただ単にログを保管しておきたいだけという要望もあるかと思います。そういった場合にはlogback-kinesis-appenderのようなライブラリを使うことを検討してみてはいかがでしょうか?非常に簡単に外部へのログ送信が行なえます。

今回の検証に使ったアプリケーションはGithubに置いてあります。clone後、src/main/resources/logback.xmlのStreamNameを書き換えた後に以下のコマンドで皆様の環境でも実行可能です。お試しください。

$ cd path/to/project && ./gradlew bootRun