akka-slf4jを使って、docker-fluentd経由でS3にログを格納する

ログの運用をどうしようかなー、と[Akka Httpのページ](http://doc.akka.io/docs/akka/current/java/logging.html#SLF4J)を見ていたらSLF4J使えるよー、とのことでした。

動作確認を行いました。

## 1. アプリケーション側の設定

###Main.scala

```Main.scala
import akka.event.{Logging, LoggingAdapter}

object Main {
  implicit val system: ActorSystem  = ActorSystem("your application name")
  implicit val executor: ExecutionContextExecutor = system.dispatcher
  implicit val materializer: Materializer = ActorMaterializer()

  val logger = Logging(system, getClass)
}
```

としてあげて、routingやsupervisorのstrategy、actorのoverride def等でloggingを仕込む形になります。

### build.sbt

```build.sbt
libraryDependencies ++= {
  val akkaV       = "2.4.4"
  val akkaStreamV = "2.*.*"
  Seq(
    "com.typesafe.akka" %% "akka-actor"                           % akkaV,
    "com.typesafe.akka" %% "akka-slf4j"                           % akkaV,
    "ch.qos.logback"    %  "logback-classic"                      % "1.1.7",
    "com.typesafe.akka" %% "akka-stream....（割愛）

    "eu.inn" %% "fluentd-scala" % "0.1.20",
```

### application.conf

```src/main/resources/application.conf
akka {
  loglevel = "INFO"
  loggers = ["akka.event.slf4j.Slf4jLogger"]
}
```

### logback.xml

appenderでファイル出力とfluentdかますものの２つを用意しました。
実際にfluentdでできるのかな、、というのがわからずにひよった結果、前者を追加しました。

```src/main/resources/logback.xml
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>log/app.log</file>
        <append>true</append>
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%d,%msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="FILE" />
    </root>

    <appender name="FLUENT" class="eu.inn.fluentd.FluentdAppender">
        <tag>my-tag</tag>
        <remoteHost>localhost</remoteHost>
        <port>24224</port>
    </appender>

    <root level="INFO">
        <appender-ref ref="FLUENT"/>
    </root>
</configuration>
```

## 2. AWSの設定（S3の作成）

こちらについてはaws cliでもマネジメントコンソールでもよしなに対応できるので割愛します。

## 3. fluentd on Dockerの設定

### 参考ソース

[crowdworksさんのリポジトリ](https://github.com/crowdworks/docker-fluentd-s3)を参考にさせていただきました。

fluentdのプラグインは、forestとs3の２つを利用しているシンプルな構成になっているようでした。

* https://github.com/fluent/fluent-plugin-s3
* https://github.com/tagomoris/fluent-plugin-forest

### fluent.conf

```fluent.conf
<match pattern>
  @type s3

  aws_key_id "#{ENV['AWS_ACCESS_KEY_ID']}"
  aws_sec_key "#{ENV['AWS_SECRET_ACCESS_KEY']}"
  s3_bucket "#{ENV['FLUENTD_S3_BUCKET']}"
  s3_region "#{ENV['FLUENTD_S3_REGION']}"
  s3_object_key_format %{path}%{time_slice}_%{index}.%{file_extension}
  path logs/
  buffer_path /var/log/fluent/s3

  time_slice_format %Y%m%d-%H
  time_slice_wait 10m
  utc
</match>
```

上記のようなfluent.confファイルを含むDockerコンテナを作成しました。

### docker-composeによる起動

AWSのアクセスキー等を環境変数として利用するところだけ、instance roleに変更できないかは要確認事項となります。

Dockerコンテナをビルドし終わったら、docker-compose.ymlを用意しました。

```docker-compose.yml
fluentd-s3:
        image: local/docker-fluentd-s3
        environment:
                - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
                - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
                - FLUENTD_S3_BUCKET=${FLUENTD_S3_BUCKET}
                - FLUENTD_S3_REGION=${FLUENTD_S3_REGION}
        expose:
                - 24224 
                - 5140
        ports:
                - 24224:24224
```

これで、

```bash
docker-compose up
```

とすることで、fluentdのサービスコンテナが起動し、loggingの出力結果がS3に格納されることになりました。

お手軽かつ便利ですね！

## 4. TODO

* kubernetesに組み込みやすいように作りこみを実施する
* ログの転送がリアルタイム、というわけでもないので、fluentdの設定を見直す
* zipkin等のapplication tracingと組み合わせた時の住み分け
* elastic search/kibanaを利用した可視化までやるか、正直無駄な可視化にならないか、などの見極め
* key等の情報を環境変数で持つのがうざいのでinstance roleの利用検証を行う


---

本日は以上となります＾＾