# Django + Grafana + Promail + Loki
Vincent大大推薦看完ELK後,可以看一下這樣的組合`(Grafana + Promail + Loki)`,所以就寫一篇文章來記錄,最後再跟`Kibana`比較一下差在哪
### 簡單介紹
- Grafana: 相當於ELK中的Kibana,用於UI的展示
- Loki: 相當於ELK中的ElasticSearch,用於存儲日誌和處理查詢
- Promail: 相當於ELK中的Logstash,用於採集日誌並將其發送給Loki
### 合併起來的運作流程
- 跟ELK的運作流程大同小異,只是框架變了而已
```mermaid
graph TD;
運行中的程式-->Promail;
Promail-->Loki;
Loki-->Grafana;
```
### 部屬方式
- 可以參考[這一篇](https://mpolinowski.github.io/docs/DevOps/Provisioning/2021-04-07--loki-prometheus-grafana/2021-04-07/),或參考這邊的範例。這邊的範例主要是監聽這個檔案`error.log`
:::spoiler docker-compose.yml
```dockerfile=
version: "3"
services:
grafana:
image: grafana/grafana:8.2.6
ports:
- "3060:3000"
networks:
- loki
restart: always
promtail:
image: grafana/promtail:2.3.0
volumes:
- ./promtail.yml:/etc/promtail/promtail-config.yml
- ./error.log:/opt/nginx_access.log # 掛載進yml裡面指定的路徑
command: -config.file=/etc/promtail/promtail-config.yml
networks:
- loki
restart: always
loki:
image: grafana/loki:2.3.0
volumes:
- ./loki-config.yml:/etc/loki/loki-config.yml
command: -config.file=/etc/loki/loki-config.yml
ports:
- "3100:3100"
networks:
- loki
restart: always
networks:
loki:
```
:::
:::spoiler promtail.yml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: nginx_log
static_configs:
- targets:
- loki
labels:
job: varlogs # 指定監測的label,在Grafana上面選的選項
__path__: /opt/nginx_access.log # 指定監測的檔案,接受正規表達式
:::
### Django實作直接發送log給Loki(django_loki)
- 使用`django_loki`套件可不用部屬`Promail`,會直接透過`Loki`傳送給`Grafana`
1. 設定logging
```python
LOGGING = {
...
'formatters': {
'loki': {
'class': 'django_loki.LokiFormatter',
'format': '[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] [%(funcName)s] %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
},
'handlers': {
'loki': {
'level': 'DEBUG',
'class': 'django_loki.LokiHttpHandler',
'host': '192.168.223.127',
'formatter': 'loki',
'port': 3100,
'timeout': 0.5,
'protocol': 'http',
'source': 'Loki', # 標籤名,在Grafana上選擇該label
'src_host': 'localhost',
'tz': 'UTC',
},
},
'loggers': {
'loki': {
'handlers': ['loki'],
'level': 'INFO',
'propagate': False,
}
},
...
}
```
2. 在`urls.py`中設定對外的接口
```python
urlpatterns = [
path('test', views.test, name="test"),
]
```
3. 在`views.py`中撰寫對應的程式
```python=
import logging
from django.http import JsonResponse
logger = logging.getLogger('loki')
def test(request):
logger.warning("test warning")
logger.error("test error")
logger.critical("test critical")
return JsonResponse({"status": 200})
```
4. 再到`Grafana`中設定`Data Sources`

5. 把程式跑起來,並觸發對應的url(`http://localhost:8080/test`)
6. 來觀察log是否有被記錄到

### Grafana VS Kibana
| | 目的 | 數據來源 | 是否支援全文搜尋 | 訪問控制和身份驗證 | 警報 |
| - | --- | ------- | ------------- | --------------- | --- |
| Grafana | 分析和可視化CPU、內存、I/O等指標 | 多(ES、Loki、prometheus...) | 否 | 內建用戶控制和身份驗證機制 | 內建警報功能 |
| Kibana | 分析日誌消息 | ES | 是 | 需要配置X-Pack安全角色 | Kibana Alerts |
### 參考資料
- https://www.readfog.com/a/1642167415174434816
- https://github.com/zepc007/django-loki
- https://mpolinowski.github.io/docs/DevOps/Provisioning/2021-04-07--loki-prometheus-grafana/2021-04-07/