SKILL.md
唯讀
名稱
loki
描述
Grafana Loki 日誌聚合與 LogQL 查詢語言。涵蓋 LogQL 語法(日誌查詢、指標查詢、標籤匹配、行過濾器、解析器:json/logfmt/pattern/regexp/unpack、標籤過濾器、line_format)、Loki 架構、透過 Alloy/Promtail/Fluent Bit 進行日誌擷取、結構化中繼資料,以及 Logs Drilldown。適用於撰寫 LogQL 查詢、設定 Loki、排錯日誌管線或分析日誌時使用。
Grafana Loki - 日誌聚合
僅索引中繼資料(標籤),而非完整日誌內容——比全文檢索系統便宜許多。
LogQL 快速參考
日誌串流選擇器(每個查詢必填)
{app="nginx"} # 精確比對
{app!="nginx"} # 不等於
{app=~"nginx|apache"} # 正規表示式比對
{app!~"debug.*"} # 正規表示式不匹配
{app="nginx", env="prod"} # AND(多個標籤)
行過濾器(管線階段 1 - 為效能應優先放置)
{app="nginx"} |= "error" # 包含字串
{app="nginx"} != "info" # 不包含
{app="nginx"} |~ "error|warn" # 正規表示式比對
{app="nginx"} !~ "health.*check" # 正規表示式不匹配
{app="nginx"} |= `"status":5` # 反引號避免跳脫
解析器
# JSON
{app="api"} | json
{app="api"} | json status="http_status", path="request.path"
# Logfmt
{app="api"} | logfmt
{app="api"} | logfmt --strict
{app="api"} | logfmt --keep-empty
# Pattern(位置式,_ 表示捨棄)
{app="nginx"} | pattern `<ip> - - <_> "<method> <uri> <_>" <status> <bytes>`
# Regexp(具名捕獲群組)
{app="nginx"} | regexp `(?P<method>\w+) (?P<path>\S+) HTTP/(?P<version>\S+)`
# Unpack(解開 Promtail 打包的標籤)
{app="api"} | unpack
標籤過濾器(解析器之後)
{app="api"} | json | status >= 500
{app="api"} | json | status == 200 and method != "OPTIONS"
{app="api"} | logfmt | duration > 1s
{app="api"} | json | level =~ "error|warn"
{app="api"} | json | bytes > 20MB
{app="api"} | json | path != "/healthz"
行格式
{app="api"} | json | line_format "{{.method}} {{.path}} -> {{.status}} ({{.duration}})"
{app="api"} | logfmt | line_format `{{.level | upper}}: {{.msg}}`
標籤格式
{app="api"} | logfmt | label_format new_name=old_name
{app="api"} | logfmt | label_format severity=level, svc=app
{app="api"} | logfmt | label_format msg=`{{.level}}: {{.message}}`
捨棄/保留標籤
{app="api"} | json | drop filename, level="debug"
{app="api"} | json | keep level, status, method
去除顏色碼
{app="cli-tool"} | decolorize
指標查詢
日誌範圍聚合
# 每秒請求數
rate({app="nginx"}[5m])
# 時間視窗內的日誌行總數
count_over_time({app="nginx"}[1h])
# 每秒位元組數
bytes_rate({app="nginx"}[5m])
# 總位元組數
bytes_over_time({app="nginx"}[1h])
# 若範圍內無日誌則回傳 1(用於缺失告警)
absent_over_time({app="nginx"}[5m])
聚合
# 依服務的錯誤率
sum(rate({env="prod"} |= "error" [5m])) by (app)
# 前 5 名最活躍服務
topk(5, sum(rate({env="prod"}[5m])) by (app))
# 所有服務的錯誤總數
sum(count_over_time({env="prod"} |= "error" [5m]))
解包範圍聚合(從日誌中提取數值)
# 從 logfmt 取得的平均請求持續時間
avg_over_time({app="api"} | logfmt | unwrap duration [5m])
# 第 95 百分位延遲
quantile_over_time(0.95, {app="api"} | logfmt | unwrap duration [5m]) by (app)
# 從 JSON 日誌取得的位元組總和
sum_over_time({app="api"} | json | unwrap bytes [5m])
# 含轉換(持續時間字串 → 秒)
avg_over_time({app="api"} | logfmt | unwrap duration | duration_seconds [5m])
偏移修飾符
# 比較當前速率與 1 小時前
rate({app="nginx"}[5m]) / rate({app="nginx"}[5m] offset 1h)
實用範例
錯誤率告警查詢
sum(rate({env="prod"} |= "error" [5m])) by (service)
/
sum(rate({env="prod"}[5m])) by (service)
> 0.05
慢請求
{app="api"} | logfmt | duration > 1s | line_format "SLOW: {{.method}} {{.path}} {{.duration}}"
HTTP 5xx 錯誤含詳細資訊
{app="nginx"} | pattern `<ip> - - <_> "<method> <uri> <_>" <status> <bytes>` | status >= 500
憑證外洩偵測
{namespace="prod"} |~ `https?://\w+:\w+@`
傳送日誌到 Loki
透過 Grafana Alloy
loki.source.file "app" {
targets = [{__path__ = "/var/log/app/*.log", job = "app"}]
forward_to = [loki.process.parse.receiver]
}
loki.process "parse" {
forward_to = [loki.write.cloud.receiver]
stage.json {
expressions = { level = "level", msg = "message" }
}
stage.labels {
values = { level = "" }
}
stage.drop {
expression = ".*healthcheck.*"
}
}
loki.write "cloud" {
endpoint {
url = "https://logs-xxx.grafana.net/loki/api/v1/push"
basic_auth {
username = sys.env("LOKI_USER")
password = sys.env("GRAFANA_API_KEY")
}
}
external_labels = { cluster = "prod" }
}
透過 Kubernetes(Alloy DaemonSet)
discovery.kubernetes "pods" {
role = "pod"
}
loki.source.kubernetes "pods" {
targets = discovery.kubernetes.pods.targets
forward_to = [loki.write.cloud.receiver]
}
Loki HTTP Push API
curl -X POST https://logs-xxx.grafana.net/loki/api/v1/push \
-u "user:apikey" \
-H 'Content-Type: application/json' \
-d '{
"streams": [{
"stream": { "app": "myapp", "env": "prod" },
"values": [
["1609459200000000000", "log line here"]
]
}]
}'
架構
推送路徑: Client → Distributor → Ingester (WAL) → Object Storage (chunks)
讀取路徑: Query → Query Frontend → Querier → Ingester + Store (chunks)
元件:
- Distributor:驗證並雜湊傳入的日誌串流
- Ingester:在記憶體中緩衝區塊,並刷新到物件儲存
- Querier:執行 LogQL 查詢
- Query Frontend:快取、分割並平行化查詢
- Compactor:管理保留與重複資料刪除






