さくらのクラウドの「メトリクスストレージ」にデータを送信し、「可視化サービス」と「Grafana」でモニタリングしてみた

## はじめに
さくらインターネット株式会社の「[さくらのクラウド](https://cloud.sakura.ad.jp/)」では、
続々とマネージドサービスがリリースされています。

その中でも、メトリクスストレージはPrometheus互換で、API経由で様々なメトリクスを保存することができます。
Grafanaで可視化もできますし、さくらのクラウドのモニタリングスイートでも可視化できるので、
実質マネージドPrometheusのような使い方ができるのでは　と思い今回試してみました。

**※本記事の文章には生成AIを一切使用しておらず、すべて自分の言葉で表現しています**

## 全体図
![sakura_apprun-ページ2.drawio (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/46dc8a7b-46e9-4a92-b842-7741c814daf6.png)

## 手順
### ソースチェックアウト
今回のソースはこちらにあります。事前にチェックアウトしておいて下さい。
https://github.com/HTDevelop/sakura_observability

#### ソース解説
<details><summary>展開してください</summary>

* dockerfile
シンプルなPython実行です。
```Python
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

CMD ["python", "app.py"]
```
* app.py
OpenTelemetryのライブラリを使用して、`app_requests_total`という名前のメトリクスで10秒に一回カウントアップして送信します（`counter.add(1, {"route": "/example"})`）
```Python
from opentelemetry import metrics
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.resources import Resource
import time

# Setup resource
resource = Resource(attributes={"service.name": "demo-python-service"})
reader = PeriodicExportingMetricReader(
    OTLPMetricExporter(endpoint="http://otel-collector:4317", insecure=True)
)
provider = MeterProvider(resource=resource, metric_readers=[reader])
metrics.set_meter_provider(provider)
meter = metrics.get_meter(__name__)
counter = meter.create_counter("app_requests_total", unit="1", description="Total requests")


# Run app
if __name__ == "__main__":
    while(True):
        counter.add(1, {"route": "/example"})
        time.sleep(10)
```

* docker-compose.yml
OpenTelemetryの公式イメージをサービスとして組み込んでいます（`image: otel/opentelemetry-collector-contrib:0.128.0`）
独自の設定ファイルを指定したいので、`- ./otel-collector-config.yaml:/etc/otelcol/config.yaml`と指定しています。
```bash
version: "3.9"

services:
  otel-collector:
    image: otel/opentelemetry-collector-contrib:0.128.0
    command: ["--config=/etc/otelcol/config.yaml"]
    volumes:
      - ./otel-collector-config.yaml:/etc/otelcol/config.yaml
    ports:
      - "4317:4317"   # OTLP gRPC
      - "4318:4318"   # OTLP HTTP
      - "8888:8888"   # metrics/debug
    networks:
      - otelnet

  app:
    build:
      context: ./app
    environment:
      - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
    depends_on:
      - otel-collector
    networks:
      - otelnet

networks:
  otelnet:
```
* otel-collector-config.yaml
非常にシンプルな構成です、4317でgrpcプロトコルで受け付け、prometheusremotewriteで指定したエンドポイント宛てにベーシック認証で送信します。
```bash
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

extensions:
  basicauth/remote:
    client_auth:
      username: "XXXXXX"
      password: "XXXXXX"

exporters:
  prometheusremotewrite:
    endpoint: "https://XXXXXX.metrics.monitoring.global.api.sacloud.jp/prometheus/api/v1/write"
    auth:
      authenticator: basicauth/remote

service:
  extensions: [basicauth/remote]
  pipelines:
    metrics:
      receivers: [otlp]
      processors: []
      exporters: [prometheusremotewrite]

```

</details>

### メトリクスストレージ情報取得
[メトリクスストレージ](https://secure.sakura.ad.jp/cloud/iaas/#!/monitoring/metrics/)にアクセスし、デフォルトを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/6fec0726-6c5c-403d-9394-869b94ae9ac4.png)

アクセスキー -> 追加 -> 作成を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/90ad12d2-5f42-469a-be68-7ed320b44e14.png)

ダブルクリックする詳細が表示されますので、これを控えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/eea28663-644b-4c90-ae0f-3144f99e2a1e.png)

### OpenTelemetry設定
チェックアウトしたソースの`otel-collector-config.yaml`で以下の箇所を置換します。
* extensions -> basicauth/remote -> client_auth -> username, password
* exporters -> prometheusremotewrite -> endpoint
```bash
～略～
extensions:
  basicauth/remote:
    client_auth:
      username: "XXXXXX"
      password: "XXXXXX"

exporters:
  prometheusremotewrite:
    endpoint: "https://XXXXXX.metrics.monitoring.global.api.sacloud.jp/prometheus/api/v1/write"
    auth:
      authenticator: basicauth/remote
～略～
```

### サンプル起動
それでは、いよいよdocker-composeでOpenTelemetry起動 + メトリクス送信スクリプト実行を行います。
```bash
cd sakura_observability
docker compose up --build
```

### 動作確認
[可視化サービス](https://secure.sakura.ad.jp/cloud/iaas/#!/monitoring/dashboard/)にアクセスし、ダッシュボードを表示します。
※可視化サービスの有効化方法はマニュアルなどを見てください。

メトリクスを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/bc7ec473-3ee5-4c7a-b2c3-b47be84bc47b.png)

デフォルトを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/3f12c746-aa01-412b-829c-a902bb052ffd.png)

検索画面が表示されるので、`app_requests_total{job="demo-python-service"}`と入力して検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/df7ad125-2c2d-45ba-9d76-b00cc7bf93bd.png)

そうすると、メトリクスグラフが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/81a4fdf9-9833-420e-b2d6-ca6aac784457.png)
app.pyでは10秒に一回カウントアップするようにしているので、徐々に上昇していますね。

### （おまけ）Grafanaで可視化
メトリクスストレージはPrometheus互換なので、Grafanaでも可視化できます。
※Grafanaの構築手順はここでは割愛します。私はAWSのマネージドGrafanaを使用しています。

まず、データソースでPrometheusを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/2f3f1d80-fcaa-4468-bf78-6e2769108b17.png)

Connectionの欄にはメトリクスストレージのURL,認証はベーシック認証にしてメトリクスストレージで発行済みのユーザ名、パスワードを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/2a207d85-b99e-4bd8-aff5-f74cbe976d7b.png)

追加したら、Exploreから該当のPrometheusを選択し、Codeタブに切り替えて、
可視化サービスと同様に`app_requests_total{job="demo-python-service"}`で検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/6b22a71f-1f73-4f6c-8ca3-c18e7fb36326.png)

すると同じグラフが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112783/6a7f1782-44fc-421e-a40a-ffec70045e8b.png)


## さいごに
いかがだったでしょうか？
今回は`app_requests_total`という特段意味のないメトリクスでしたが、本番運用ではCPU、メモリなどの単一メトリクスや、`http_server_duration_milliseconds_bucket`などのレスポンス情報をモニタリングします。

また、ログも「ログストレージ」というサービスで送信・可視化できるようです。
興味のある方は是非試してみてください！



以上