Elastic APMとアプリケーションログの連携

# はじめに

前回、以下の投稿でJavaアプリケーションのパフォーマンスをElastic APMで計測し、トレースデータをKibanaで表示するところまで試してみました。

- [JavaアプリケーションをElastic APMで計測してみる](https://qiita.com/mkyz08/items/dfcb4785f9444b04a574)

今回は、アプリケーションログをElasticsearchに送信し、APMのトレースデータとログを関連付けて表示することを試してみます。
APMのトレースデータとログを関連付けは以下のサイトを参考に実施しました。

- [Log correlation](https://www.elastic.co/guide/en/apm/agent/java/current/log-correlation.html)

APMのトレースデータとログを関連付けのために実施する作業は大きく以下の3つになります。

1. Elastic APM agentの設定変更
1. アプリケーションのログ設定変更
1. Filebeatを用いてログをElasticsearchへ送信する


# Elastic APM agentの設定変更

Elastic APM agentの設定ファイル（elasticapm.properties）に以下を追記し、ログ連携を有効にします。
（agentの設定をファイルで実施している場合）

```properties:elasticapm.properties
enable_log_correlation=true
```

JVM引数であれば以下のようになります。

```
-Delastic.apm.enable_log_correlation=true
```


# アプリケーションのログ設定変更

アプリケーションログをElasticsearchに取り込むために、Elastic Common Schema（ECS）のjson形式のログを出力するようにアプリケーションのログ設定を変更します。
以下のサイトを参考に設定していきます。

- [Java ECS logging](https://github.com/elastic/ecs-logging-java)

まずは、pom.xmlに以下を追記します。今回のアプリケーションではlog4j2を使用しているため、「log4j2-ecs-layout」を使用します。

```xml:pom.xml
<dependency>
    <groupId>co.elastic.logging</groupId>
    <artifactId>log4j2-ecs-layout</artifactId>
    <version>0.5.0</version>
</dependency>
```

次にECSログを出力するようにlog4j2.xmlに以下を追記します。これでECSログを出力することができるので、次はこのログファイルをElasticsearchへ送信するようにFilebeatを設定します。

```xml:log4j2.xml
	<Appenders>
	<File name="JsonLogFile" fileName="logs/app.log">
            <EcsLayout serviceName="my-cool-service"/>
        </File>
	</Appenders>

	<Loggers>
		<Root level="info">
			<AppenderRef ref="JsonLogFile" />
		</Root>
	</Loggers>
```

アプリケーション起動後、ログファイル（app.log）にjson形式のログが出力されていることを確認します。
ログ中の"trace.id"などが自動で挿入されたデータのようです。

```
{"@timestamp":"2020-07-24T07:22:31.607Z", "log.level": "INFO", "message":"### MyCodeProcessor process", "service.name":"my-cool-service","event.dataset":"my-cool-service.log","process.thread.name":"CamelJettyServer(0x1e92c3b6)-175","log.logger":"example.camelbegginer.restdsl.MyCodeProcessor","trace.id":"124f81c604fe9130edab2296e79bf49e","transaction.id":"482ba85dc8346d80"}
```


# Filebeatを用いてログをElasticsearchへ送信する

Filebeatは使用しているOS用のモジュールを以下のサイトからダウンロードし、インストールします。Windows版は解凍して実行するだけだったのでインストール方法は省略します。

filebeat.ymlを以下のように修正して、Filebeatを実行します。
logs以下のログファイルでERRORが出力されていなければ完了です。

```yaml:filebeat.yml
filebeat.inputs:
- type: log
  paths: /path/to/app.log
  json.keys_under_root: true
  json.overwrite_keys: true

# no further processing required, logs can directly be sent to Elasticsearch  
output.elasticsearch:
  hosts: ["http://[Elasticsearchサーバのホスト名]:9200"]
```


# Kibana APM UIでログとトレースデータを表示する

以下ではKibana APM UIでトレースデータを表示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179607/1c23100e-b5bb-5eb6-406d-82cc46ed3bca.png)

ここで、[Action]-[trace logs]を選択すると、その時のアプリケーションログを表示することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179607/9992208d-fc5e-ddcd-fc1d-d2e45862345c.png)

逆にログの表示から[Actions]-[View in APM]を選択すると、ログに該当するトレースデータを表示することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179607/6a7137f5-9249-ccc9-fecf-19594f6e1977.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179607/a185a23d-3d40-461e-47bf-6fa9dffc48ff.png)


処理が遅かったログを確認し、そこからトレースデータを表示することで処理中のどこで遅延していたのかを調査するなどの利用方法がありそうです。



# 参考

- [Log correlation](https://www.elastic.co/guide/en/apm/agent/java/current/log-correlation.html)
- [Java ECS logging](https://github.com/elastic/ecs-logging-java)