JaegerでSpringBootアプリケーションをトレーシング

# 概要

Jeagerを触ってみたので導入方法をメモしておきます

トレーシング対象のアプリケーションはSpringBootです。

# 導入

## Jaeger起動

今回はお試しということでall in oneで起動します

[公式ドキュメント](https://www.jaegertracing.io/docs/1.32/getting-started/)を参考にdocker-composeで起動できるようにします。

```yaml:docker-compose.yml
version: '2'
services:
  jeager:
    image: jaegertracing/all-in-one:1.32
    ports:
      - "6831:6831/udp" # accept jaeger.thrift over compact thrift protocol
      - "6832:6832/udp" # accept jaeger.thrift over binary thrift protocol
      - "5778:5778"     # serve configs
      - "16686:16686"   # serve frontend
      - "14250:14250"   # accept model.proto
      - "14268:14268"   # accept jaeger.thrift directly from clients
      - "14269:14269"   #
      - "9411:9411"     # Zipkin compatible endpoint (optional)
    environment:
      COLLECTOR_ZIPKIN_HOST_PORT: ":9411"
```

起動!

```
docker-compose up -d
```

http://localhost:16686/ にアクセスしたらUIが表示されます🎉

![スクリーンショット 2022-03-12 18.15.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/6d7ea855-5c73-64e2-da01-21887e9d5702.png)

## アプリケーション実装

SpringBootアプリケーションのベースは https://start.spring.io/ で作成します。
ここではSpring Webのみ追加してベースを作成します。

Zipをダウンロード＆解答したらJeagerとの連携に必要なライブラリを追加します。

```groovy:build.gradle
dependencies {
    implementation 'io.opentracing.contrib:opentracing-spring-jaeger-web-starter:3.3.1'
    implementation 'io.opentracing.contrib:opentracing-spring-web-starter:4.1.0'
}
```

> 補足: 追加するライブラリは以下から探します
※ここは結構試行錯誤必要かも。。。

https://opentracing.io/registry

サンプルで動作させるAPIを実装します。

```java
@RestController
@RequiredArgsConstructor
public class SampleController {
    private final RestTemplate restTemplate;

    @GetMapping("/proxy/hello")
    public String proxyToHello() {
        return restTemplate.getForObject("/hello", String.class);
    }

    @GetMapping("/hello")
    public String hello() {
        return "Hello, jaeger.";
    }
}
```

RestTemplateはBean登録している必要があるので、コンストラクタインジェクションで注入するようにしています。

最後にRestTemplateのBean登録です。

```java
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplateBuilder()
                .rootUri("http://localhost:8080")
                .build();
    }
```

## 動作確認

APIにリクエストを送って

```sh
$ curl localhost:8080/proxy/hello
Hello, jaeger.
```

UIで検索してみると

![スクリーンショット 2022-03-12 21.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/040082ce-4044-2324-c941-3abaa1abc45f.png)

トレーシングできてる！！！🎉🎉🎉

# DBもトレーシング

DBまでトレースできるようにしてみます。

DBとしてH2DBを使い、jpaが使えるよう依存を追加します。
またDBのトレースができるよう依存を追加します。

```groovy:bui;d.gralde
dependencies {
    implementation 'io.opentracing.contrib:opentracing-jdbc:0.2.15'

    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.h2database:h2'
}
```

DBのトレースをするには、Driverとurlの指定を普段を変える必要があります。

```yaml:application.yml
spring:
  datasource:
    # driver-class-name: "org.h2.Driver"
    driver-class-name: "io.opentracing.contrib.jdbc.TracingDriver"
    # url: "jdbc:h2:./h2db/sample"
    url: "jdbc:tracing:h2:./h2db/sample"
```

APIをDBアクセスしてidに紐づくnameに対して挨拶するような感じにしてみます
※DB、jpa周りは省略🙏

```java
@RestController
@RequiredArgsConstructor
public class SampleController {
    private final RestTemplate restTemplate;
    private final UserRepository userRepository;

    @GetMapping("/proxy/hello/{id}")
    public String proxyToHello(@PathVariable String id) {
        return restTemplate.getForObject("/hello/{id}", String.class, id);
    }

    @GetMapping("/hello/{id}")
    public String hello(@PathVariable String id) {
        var user = userRepository.findById(id);
        return "Hello, " + user.map(User::getName).orElse("jaeger") + ".";
    }
}
```

curlでAPIにリクエストを送ってみると

```
$ curl localhost:8080/proxy/hello/1
Hello, Ryo.
```

UIでDBの情報も見れるようになりました🎉🎉🎉

![スクリーンショット 2022-03-12 22.06.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/a9dc1fa7-e4de-ffd5-02aa-e56ae05ace82.png)