django-prometheus 使い方 prometheus を理解してみた

django-prometheus の記事があんまり見当たらなかったので やってみた。
prometheus を触ったことがないので、一緒に勉強してみた

# 概要
- django-prometheusが、暗号にしか見えない web endpoint ↓ を公開してくれる
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/4ba3bdfa-bb8c-1333-b4b6-6ce274b6a984.png)
- prometheus が、それを polling する
    - **django-prometheus がデータを prometheus に送るわけではない！** ただ html ひとつ出すだけです。
- grafana が prometheus のデータを visualize する


# 悩んだ

django-prometheus が agent だと思ってたので全然理解できなくてしばらく悩んだ。
django-prometheus はただapiを提供するだけで。prometheusが向こうからそれを取りに来る。


# django-prometheusを動かしてみる

Tutorial
https://docs.timescale.com/latest/tutorials/tutorial-howto-monitor-django-prometheus

```
mkdir django-prometheus
cd django-prometheus
python -m pip install Django
django-admin startproject mysite
cd mysite
python manage.py runserver
# ctrl + c
python -m pip install django-prometheus
```

settings.py を編集する。middlewareのところが既存の設定を挟み込むようにする。最初と最後じゃないといけない。注意。

```py:mysite/settings.py
INSTALLED_APPS = [
   ...
   'django_prometheus',
   ...
]

MIDDLEWARE = [
    'django_prometheus.middleware.PrometheusBeforeMiddleware',
    # All your other middlewares go here, including the default
    # middlewares like SessionMiddleware, CommonMiddleware,
    # CsrfViewmiddleware, SecurityMiddleware, etc.
    'django_prometheus.middleware.PrometheusAfterMiddleware',
]
```

```py:mysite/urls.py
from django.conf.urls import url, include

urlpatterns = [
    ...
    url('', include('django_prometheus.urls')),
]
```

django 起動する

```sh
python manage.py runserver 0.0.0.0:8000
curl localhost:8000/metrics
```

ブラウザで /metrics が見えればok

http://localhost:8000/metrics

# prometheus / grafana を起動する

素晴らしいcomposeがあるのでまんま使います。関係ないコンテナも起動するけど、勉強のためそのまま起動。

Refer to
https://github.com/vegasbrianc/prometheus/blob/master/docker-compose.yml

まずvolumeを外して起動する

```yml:docker-compose.yml
#https://github.com/vegasbrianc/prometheus/blob/master/docker-compose.yml
version: '3.7'

volumes:
    prometheus_data: {}
    grafana_data: {}

networks:
  front-tier:
  back-tier:

services:

  prometheus:
    image: prom/prometheus:v2.1.0
#    volumes:
#      - ./prometheus/:/etc/prometheus/
#      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
    ports:
      - 9090:9090
    links:
      - cadvisor:cadvisor
      - alertmanager:alertmanager
#      - pushgateway:pushgateway
    depends_on:
      - cadvisor
#      - pushgateway
    networks:
      - back-tier
    restart: always
#    deploy:
#      placement:
#        constraints:
#          - node.hostname == ${HOSTNAME}

  node-exporter:
    image: prom/node-exporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - --collector.filesystem.ignored-mount-points
      - "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)"
    ports:
      - 9100:9100
    networks:
      - back-tier
    restart: always
    deploy:
      mode: global

  alertmanager:
    image: prom/alertmanager
    ports:
      - 9093:9093
#    volumes:
#      - ./alertmanager/:/etc/alertmanager/
    networks:
      - back-tier
    restart: always
    command:
      - '--config.file=/etc/alertmanager/config.yml'
      - '--storage.path=/alertmanager'
#    deploy:
#      placement:
#        constraints:
#          - node.hostname == ${HOSTNAME}
  cadvisor:
    image: google/cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    ports:
      - 8080:8080
    networks:
      - back-tier
    restart: always
    deploy:
      mode: global

  grafana:
    image: grafana/grafana
    user: "472"
    depends_on:
      - prometheus
    ports:
      - 3000:3000
#    volumes:
#      - grafana_data:/var/lib/grafana
#      - ./grafana/provisioning/:/etc/grafana/provisioning/
#    env_file:
#      - ./grafana/config.monitoring
    networks:
      - back-tier
      - front-tier
    restart: always

#  pushgateway:
#    image: prom/pushgateway
#    restart: always
#    expose:
#      - 9091
#    ports:
#      - "9091:9091"
#    networks:
#      - back-tier
```


起動したら prometheus の config を変更するために、既存ファイルをcopyする

```
docker cp prometheus_prometheus_1:/etc/prometheus .
vim prometheus/prometheus.yml
```

最終行の targets  に、 django-prometheus が動いているendpoint を入れる。
/metrics は不要（全員デフォルトでそこ取るよ、って書いてある）

```yml:prometheus/prometheus.yml
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ['localhost:9090', '192.168.1.2:8000']    <------ ここにdjango-prometheusが動いてるサーバを足す
```

そしたら、その prometheus.yml を読み込むようにvolumesを変えて、recreateする。

```yml
services:

  prometheus:
    image: prom/prometheus:v2.1.0
   volumes:                                 <------------- ここだけ
     - ./prometheus/:/etc/prometheus/        <------------- 変える
#      - prometheus_data:/prometheus
```


# prometheus 動作確認

ブラウザで prometheus を開く

menuから Status > Targets を開く

http://localhost:9090/targets
*prometheusがlocalにある場合はこれで開けるはず

djangoのendpointがきちんと認識されていることを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/2a479329-8d9d-5877-1a8b-15291f82ac05.png)

ここに出る endpoint が prometheus コンテナの中から見えれば ok.

Topに戻り、 - insert metric at cursor - の select menu を開き、適当に1つ選ぶ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/c4f94163-f7e8-a087-68a7-2f0b2a4c0f86.png)


Executeを押す → value が出ればok

例えば `django_http_requests_total_by_method_total` の場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/100db0ac-1e50-33e4-6dfa-5efec13bb641.png)



# grafanaで見てみる

grafana に login する

http://localhost:3000/

id/pwは両方admin

configuration > Data sources を選ぶ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/ebc2894e-481a-7170-1780-11c5c17ea0a7.png)

Add Data Source ボタンを押し、Prometheus を select
URL に docker network でアクセスできる prometheus の URL を入れて、 Save & Test するだけ

```
http://prometheus_prometheus_1:9090
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/a9805c97-9eb8-d1a7-2065-e71ccd5dc4ab.png)
*Grafana コンテナから Prometheus コンテナにアクセスするのでこうしてます。(同じdocker networkにいれば、コンテナ名でアクセスできる）

query 叩いてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/07000572-1694-75fd-7f78-2e3993c9b57c.png)


graphがでたら成功！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/918e6e56-2500-ec31-4063-4363a0dced18.png)



# django の項目をもっと取ってみる

manual
https://github.com/korfuri/django-prometheus

基本簡単です。

## DBの状態取る場合
こういうのが欲しい場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/edf55b53-f20a-ad2e-394a-aa16eeaffeeb.png)

mysqlでもなんでも `django.` を `django_prometheus.` にするだけ

```py:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
}

↓↓↓↓↓↓↓↓↓↓↓↓↓↓

DATABASES = {
    'default': {
        'ENGINE': 'django_prometheus.db.backends.sqlite3',       <-------
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
}
```

## Modelを取る場合
こういうのが欲しい場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/88bebcad-026f-968a-9b2d-26677df7a4a5.png)

`models.Model` の前に一個足すだけ

```py:models/foovar.py
class Dog(models.Model):

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

from django_prometheus.models import ExportModelOperationsMixin
class Dog(ExportModelOperationsMixin('dog'), models.Model):
```

modelごとに動きが見えます。すごい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/ef8fca0b-5738-e08a-70a7-7ebe822a9bb5.png)


おわり！