バッチの起動監視（Java×PushGateway×Prometheus）

# この記事の概要
- バッチの起動監視をどうしようかと悩んでいた時にPushGatewayというものを見つけた
- 導入からPrometheusでメトリクスが見れるところまでをまとめてみた

# 構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/8b11710d-a962-234f-6052-7cd31a915033.png)

- PushGatewayとPrometheusはDockerで起動
- 仕組みとしては
    - BatchがPushGatewayにメトリクスを送信
    - PrometheusがPushGatewayからメトリクスを取得
- すべてローカルに存在するものとして進めます

# PushGateway構築
※Dockerが使える環境は整っている前提です

## 起動
```bash
docker pull prom/pushgateway
docker run -d \
    -p 9091:9091 \
    --name pushgateway \
    prom/pushgateway
```
> -d : デタッチドモードで起動。あまり詳しくないのでバックグラウンドで実行しれくれるくらいの認識
> -p : ポートフォワードの設定
> -name : コンテナ名の指定

## 動作確認
- `http://localhost:9091`にアクセス
<img width="992" alt="スクリーンショット 2019-09-21 22.14.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/69d8a67a-36f5-6ac6-d4a0-54d6d817b0cc.png">
- まだ真っ白な画面が表示されるだけだが、バッチからメトリクスが通知されるとこの画面に表示される
- ちなみにPrometheusからメトリクエスを取得させるときに使用するエンドポイントは`/metrics`
    - http://localhost:9091/metrics

# バッチ（雑）の作成

```groovy:build.gradle
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile('io.prometheus:simpleclient_pushgateway:0.6.0')
}
```

```java:SampleBatch.java
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class SampleBatch {
    public static void main(String[] args) {
        String url = "localhost:9091";
        PushGateway pushGateway = new PushGateway(url);

        long now = System.currentTimeMillis();

        // メトリクスを収集（ここでは起動時間としてシステムミリ秒をセット）
        CollectorRegistry registry = new CollectorRegistry();
        Gauge lastStartAt = Gauge.build()
                .name("batch_start_time")
                .help("batch start time")
                .register(registry);
        lastStartAt.set(now);

        // メトリクスにタグを設定
        Map<String, String> key = new HashMap<>();
        key.put("tagName", "tagValue");

        try {
            // メトリクスを登録
            pushGateway.pushAdd(registry, "sample-batch", key);
        } catch (IOException e) {
            // 例外処理
            e.printStackTrace();
        }
    }
}
```

## 実行！

- 実行後、PushGatewayのUIを見てみると、、、
<img width="1183" alt="スクリーンショット 2019-09-21 22.36.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/aedba16b-17b3-3adc-cee8-df0225c76225.png">
- 確かに登録されてる！

# Prometheusの構築

## 起動

```yaml:prometheus.yml
# /etc/prometheus/prometheus.yml

global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
alerting:
  alertmanagers:
  - static_configs:
    - targets:

rule_files:

scrape_configs:
- job_name: 'pushgateway'
  scrape_interval: 1m
  metrics_path: /metrics
  static_configs:
  - targets: ['localhost:9091']

```

```bash
docker pull prom/prometheus
docker run -d \
  -p 9090:9090 \
  -v prometheus.yml:/etc/prometheus/prometheus.yml \
  --name prometheus \
  prom/prometheus
```

## 動作確認
- UI(`http://localhost:9090`)で確認
<img width="1421" alt="スクリーンショット 2019-09-21 23.22.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/fde9ac4c-974f-57d8-0c82-29781369c497.png">
- ベターな方法はありそうだが、`changes(batch_start_time[2m])`というPromQLでバッチが起動したタイミングがわかる！

# 実際の運用
- 現場ではGrafanaを用いて可視化＆アラートを飛ばしている