Dockerで動かすTomcatとElasticのAPMを繋いでパフォーマンスを可視化する

# 概要

2018年7月9日に[Elastic APM Java Agent Beta Released](https://www.elastic.co/blog/elastic-apm-java-agent-beta-released)として、Elastic APMにつなぐJavaのエージェント（ベータ版）が公開されました。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/111676/2a16f0a7-5dfd-b807-af77-c11034517d1b.png)


各種ログやメトリクスをElasticsearchに入れている場合、APMのデータもあわせて入れておくことで、調査や問題発生時の解決速度向上に寄与することが期待できそうです。

上記の記事ではSpringの例となっていますが、Docker上で動くTomcatだともっと簡単に試せます。

今回はそれを紹介する内容となります。試した環境は以下の通りです。

|product|version|
|----|----|
| Elasticsearch | 6.3.1(Docker) |
| Kibana        | 6.3.1(Docker) |
| APM Server    | 6.3.1(Docker) |
| Tomcat        | 8系の最新(Docker) |
| JavaAgent     | 0.6.0 |

# Tomcatでの設定

## 必要となる資材の入手

必要となるのはjavaagentのjarファイルです。

[Maven Central](http://search.maven.org/#search|ga|1|a%3A"elastic-apm-agent")からjarファイルを取得しましょう。
2018/07/11時点では、バージョンは0.6.0となっていました。


## javaagentの設定

上記のβリリースのブログでは、Springでの設定例としてこのように書かれています。

```shell

java -javaagent:/path/to/elastic-apm-agent-<version>.jar \
     -Delastic.apm.server_url=http://localhost:8200 \
     -Delastic.apm.service_name=my-application \
     -Delastic.apm.application_packages=org.example \
     -jar my-spring-boot-application.jar
```

これをDockerのtomcatで動かす場合の設定だと、このような感じになります。
docker-composeのyamlの例です。

```yaml
version: '2'
services:
  tomcat:
    image: tomcat:8
    container_name: tomcat
    ports:
      - 8080:8080
    links:
      - apm:apm
    networks:
      - esnet
    volumes:
      - ./elastic-apm-agent-0.6.0.jar:/tmp/elastic-apm-agent-0.6.0.jar
    # ここでElastic APMで必要な設定を渡している。
    environment:
      - "JAVA_OPTS=-javaagent:/tmp/elastic-apm-agent-0.6.0.jar -Delastic.apm.server_url=http://apm:8200 -Delastic.apm.service_name=hogehoge -
Delastic.apm.application_packages=jp.co.fuga.piyo"

networks:
  esnet:
```

(手抜き)ポイントはコンテナ開始時に渡す環境変数（JAVA_OPTS）にjavaagent、apmの設定を含めておくことです。
こうすることで、開始時に実行されるcatalina.sh startで、JAVA_OPTSの値がTomcatのVM引数としてつかわれます。

既存のイメージを再度ビルドしなおすことなく、APMの対象にできる、というのは大変手軽に感じるところです。

javaagentが指定でき、apmサーバの場所を正しく示せればTomcat側の作業は終わりです。
あとはTomcat上のアプリを動かして、DBアクセスなりを発生させAPMの画面で確認しましょう。

もし、tomcatをベースイメージにした独自のイメージであったとしても、catalina.shを使って起動する部分を変えていないなら、同じアプローチで動くでしょう。

## 確認

無事にAPMサーバにJavaAgentからデータが飛んでいれば、Kibanaの画面より確認することができます。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/111676/8c484f99-7662-641d-f308-8d6846a0563f.png)

![2.png](https://qiita-image-store.s3.amazonaws.com/0/111676/00e1a420-c746-9f32-121d-4d8e1995bc0c.png)


# その他

APMサーバそのものもDockerイメージが配布されていますので、これを利用することで、より簡易に動作を確認することができます。

検証用でESからKibana,Tomcat,APMまでまとめて起動していたdocker-compose.ymlの一部です。

```yml

version: '2'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:6.3.1
    container_name: elasticsearch
    environment:
      - cluster.name=docker-cluster
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata630:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - esnet

  kibana:
    image: docker.elastic.co/kibana/kibana:6.3.1
    container_name: kibana
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch
    links:
      - elasticsearch:elasticsearch
    networks:
      - esnet

  apm:
    image: docker.elastic.co/apm/apm-server:6.3.1
    container_name: apm
    ports:
      - 8200:8200
    environment:
      - output.elasticsearch.hosts=elasticsearch:9200
    depends_on:
      - elasticsearch
    links:
      - elasticsearch:elasticsearch
    networks:
      - esnet

  tomcat:
    image: tomcat:8
    # 本当は自分のアプリが入ったDockerイメージを指定
    container_name: tomcat
    ports:
      - 80:8080
    links:
      - apm:apm
    networks:
      - esnet
    volumes:
      - ./elastic-apm-agent-0.6.0.jar:/tmp/elastic-apm-agent-0.6.0.jar
    environment:
      - "JAVA_OPTS=-javaagent:/tmp/elastic-apm-agent-0.6.0.jar -Delastic.apm.server_url=http://apm:8200 -Delastic.apm.service_name=rooms -Delastic.apm.application_packages=jp.co"

volumes:
  esdata630:
    driver: local

networks:
  esnet:

```


# まとめ

公式の記述では、「Minimal Overhead」とあり、オーバーヘッドも、平均して１マイクロ秒以下とのこと。

外部のサービスを使っていると、「データの保持期間が～」ということもあろうかと思いますが、
他のElasticsearchのインデックスと同じように自分で決められる、というのは良いところだと思います。
既にElasticsearchを入れていて、もっと便利に使っていきたい！利用用途を増やしていきたい！　といった人には向いているでしょう。

APMのデータと、他のログや各種メトリクスと組み合わせて、「Elasticsearchに入れていたから、問題解決が早かったぜ！」といったユースケースが今後出てくることと期待しています。

おまけ
https://discuss.elastic.co/t/next-apm-agent/99900

ここで、次のAgent候補に投票することができます。.NETに一票入れましたっと！