在前一章節中,我們初步認識了如何整合不同的資料來源。今天,我們將踏出關鍵的一步,將一個靜態的資訊看板,轉變為一個強大的互動式分析工具。本章節的目標是學習 Grafana 的兩大核心功能:「變數 (Variables)」與「資料轉換 (Transformations)」。
為了確保本章內容的獨立性,我們將從頭開始建立 Day 28 的所有設定。請在您的專案中建立一個 day28
資料夾,我們將在其中逐步建立所有需要的檔案。
首先,在 day28
資料夾中建立 docker-compose.yml
檔案。這個檔案定義了我們需要的所有服務:Grafana、Loki、Mimir 和 Prometheus,以及它們之間的網路和設定檔掛載。
檔案:docker-compose.yml
version: '3.8'
services:
grafana:
image: grafana/grafana:10.1.1
ports:
- "3000:3000"
volumes:
- ./grafana-provisioning:/etc/grafana/provisioning
loki:
image: grafana/loki:2.9.0
ports:
- "3100:3100"
command: -config.file=/etc/loki/loki-config.yaml
volumes:
- ./loki-config.yaml:/etc/loki/loki-config.yaml
mimir:
image: grafana/mimir:2.10.0
ports:
- "9009:9009"
command: -config.file=/etc/mimir/mimir-config.yaml
volumes:
- ./mimir-config.yaml:/etc/mimir/mimir-config.yaml
prometheus:
image: prom/prometheus:v2.47.0
ports:
- "9090:9090"
command: --config.file=/etc/prometheus/prometheus.yml
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
接下來,我們需要為 Loki、Mimir 和 Prometheus 提供基礎的設定檔。
檔案:loki-config.yaml
auth_enabled: false
server:
http_listen_port: 3100
ingester:
lifecycler:
address: 127.0.0.1
ring:
kvstore:
store: inmemory
replication_factor: 1
final_sleep: 0s
chunk_idle_period: 5m
chunk_retain_period: 1m
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
active_index_directory: /tmp/loki/index
cache_location: /tmp/loki/cache
shared_store: filesystem
filesystem:
directory: /tmp/loki/chunks
檔案:mimir-config.yaml
multitenancy_enabled: false
server:
http_listen_port: 9009
distributor:
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
ingester:
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
replication_factor: 1
檔案:prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'mimir'
static_configs:
- targets: ['mimir:9009']
remote_write:
- url: "http://mimir:9009/api/v1/push"
Grafana 的 Provisioning 功能讓我們可以透過檔案來預先設定資料來源和儀表板,無需手動操作。請在 day28
中建立對應的資料夾結構與檔案。
建立資料夾 grafana-provisioning/datasources
和 grafana-provisioning/dashboards
。
在 datasources
資料夾中,建立 datasource.yml
,定義我們需要的三個資料來源。
檔案:grafana-provisioning/datasources/datasource.yml
apiVersion: 1
datasources:
在 dashboards
資料夾中,建立 dashboard.yml
來告訴 Grafana 從哪裡載入儀表板。
檔案:grafana-provisioning/dashboards/dashboard.yml
apiVersion: 1
providers:
- name: 'Default Dashboards'
orgId: 1
folder: ''
type: file
options:
path: /etc/grafana/provisioning/dashboards
這是本章的核心。我們將直接撰寫一個包含了「變數」和「轉換」功能的儀表板 JSON 檔案。將其儲存為 grafana-provisioning/dashboards/main-dashboard.json
。
檔案:grafana-provisioning/dashboards/main-dashboard.json
{
"__inputs": [],
"__requires": [],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"title": "Mimir: HTTP Requests Total",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "mimir"
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "mimir"
},
"expr": "rate(prometheus_http_requests_total{job=\"$job\"}[5m])",
"legendFormat": "{{handler}}"
}
],
"transformations": [
{
"id": "filterByName",
"options": {
"include": {
"id": "byRegex",
"options": {
"regex": "/api/v1/push"
}
}
}
}
]
},
{
"title": "Loki: Logs",
"type": "logs",
"datasource": {
"type": "loki",
"uid": "loki"
},
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 0
},
"targets": [
{
"datasource": {
"type": "loki",
"uid": "loki"
},
"expr": "{job=\"$job\"}"
}
]
}
],
"schemaVersion": 37,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"name": "job",
"label": "Job",
"query": "label_values(job)",
"type": "query",
"datasource": {
"type": "loki",
"uid": "loki"
},
"refresh": 1,
"sort": 0,
"multi": true,
"includeAll": true
}
]
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Day 28: Advanced Dashboard",
"uid": "day28-advanced",
"version": 1,
"weekStart": ""
}
萬事俱備!在 day28
資料夾的終端機中,執行以下指令來啟動所有服務:
docker-compose up
等待所有服務啟動後,打開瀏覽器並訪問 http://localhost:3000
。您將會看到我們剛剛建立的 "Day 28: Advanced Dashboard"。
注意儀表板的左上方,您會發現一個名為 Job
的下拉式選單。這就是我們在 JSON 中 templating
區塊定義的變數。嘗試切換不同的選項(例如 mimir
),您會看到下方的圖表會根據您的選擇動態更新,只顯示對應 job 的資料。
觀察 "Mimir: HTTP Requests Total" 面板。即使 Prometheus 收集了所有 API 端點的指標,這個圖表也只顯示了 handler
為 /api/v1/push
的那一條線。這是因為我們在面板設定的 transformations
區塊中加入了一個 filterByName
的轉換規則,它在資料視覺化之前就將我們不感興趣的部份過濾掉了。
恭喜!您已經學會了如何透過撰寫設定檔來建立一個包含進階功能的 Grafana 儀表板。在本章中,我們不僅建立了完整的監控環境,更深入理解了「變數」如何提升儀表板的互動性,以及「轉換」如何讓我們更靈活地處理與呈現資料。這些技巧是在實務中建構高效、實用監控系統不可或缺的一環。