Giả định log do pipeline Vector đẩy vào Loki: label job="syslog", source (hostname thiết bị), site, severity; nội dung mỗi dòng là JSON có message, appname, mnemonic. Một query LogQL luôn bắt đầu bằng stream selector {...}, sau đó là chuỗi pipeline nối bằng |.
Stream selector
| Mục đích | Query |
|---|---|
| Một thiết bị | {job="syslog", source="pe1-hni"} |
| Regex | {job="syslog", source=~"pe[0-9]+-hni"} |
| Loại trừ | {job="syslog", severity!="debug"} |
| Loại trừ regex | {job="syslog", source!~"lab-.*"} |
| Biến Grafana nhiều giá trị | {job="syslog", source=~"$device"} |
Selector phải có ít nhất một matcher không khớp chuỗi rỗng ({source=~".*"} đơn lẻ bị từ chối).
Line filter (lọc nhanh nhất, đặt ngay sau selector)
| Mục đích | Query |
|---|---|
| Chứa chuỗi | {job="syslog"} |= "ADJCHANGE" |
| Không chứa | {job="syslog"} != "LINK-3-UPDOWN" |
| Regex (RE2) | {job="syslog"} |~ "BGP.*(Down|Idle)" |
| Regex không khớp | {job="syslog"} !~ "SSH|sshd" |
| Không phân biệt hoa thường | {job="syslog"} |~ "(?i)error" |
| Nhiều điều kiện (AND) | {job="syslog"} |= "BGP" |= "203.0.113.1" |
| Tìm IP trong một dải | {job="syslog"} |= ip("198.51.100.0/24") |
Parser và label filter
| Mục đích | Query |
|---|---|
| Tách field JSON thành label | {job="syslog"} | json |
| Chỉ lấy vài field JSON | {job="syslog"} | json mnemonic="mnemonic", app="appname" |
Log dạng key=value |
{job="app"} | logfmt |
Pattern (<_> bỏ qua) |
{job="raw"} | pattern "<_> <host> <program>[<pid>]: <msg>" |
| Regex với named group | {job="raw"} | regexp "neighbor (?P<peer>\\S+) (?P<state>Up|Down)" |
| Lọc theo label sau parse | {job="syslog"} | json | mnemonic="ADJCHANGE" |
| So sánh số / duration | | json | status >= 500 / | logfmt | duration > 2s |
| Kết hợp điều kiện | | json | severity="err" or severity="crit" |
| Bỏ dòng parse lỗi | | json | __error__="" |
| In lại dòng gọn hơn | | json | line_format "{{.source}} {{.mnemonic}} {{.message}}" |
| Đổi tên / tạo label | | label_format device=source |
| Bỏ / giữ label | | drop appname, procid / | keep source, mnemonic |
Luôn đặt line filter (|=) trước parser: Loki lọc chuỗi rẻ hơn nhiều so với parse JSON từng dòng.
Metric query
| Mục đích | Query |
|---|---|
| Số dòng log mỗi 5 phút | count_over_time({job="syslog"}[5m]) |
| Dòng/giây theo thiết bị | sum by (source) (rate({job="syslog"}[1m])) |
| Top 10 thiết bị nhiều log nhất | topk(10, sum by (source) (count_over_time({job="syslog"}[1h]))) |
| Đếm BGP flap theo peer | sum by (source, peer) (count_over_time({job="syslog"} |= "ADJCHANGE" | regexp "neighbor (?P<peer>\\S+)" [15m])) |
Đếm theo mnemonic (label sinh từ json) |
sum by (mnemonic) (count_over_time({job="syslog"} | json | __error__="" [1h])) |
| Byte log mỗi giây | sum by (source) (bytes_rate({job="syslog"}[5m])) |
| Cảnh báo thiết bị ngừng gửi log | absent_over_time({job="syslog", source="pe1-hni"}[15m]) |
| Có lỗi critical trong 5 phút | sum by (source) (count_over_time({job="syslog", severity=~"emerg|alert|crit"}[5m])) > 0 |
Dùng giá trị số trong log (unwrap):
quantile_over_time(0.95,
{job="app"} | logfmt | unwrap duration_seconds(latency) | __error__="" [5m]
) by (source)unwrap biến một label thành giá trị mẫu; duration_seconds() / bytes() chuyển 2s, 10KB thành số. Hàm dùng được: sum_over_time, avg_over_time, max_over_time, quantile_over_time, rate...
logcli
| Mục đích | Lệnh |
|---|---|
| Đặt địa chỉ Loki | export LOKI_ADDR=http://loki.example.net:3100 |
| Query 1 giờ gần nhất | logcli query --since=1h --limit=200 '{job="syslog", source="pe1-hni"}' |
| Theo dõi trực tiếp | logcli query --tail '{job="syslog"} |= "ADJCHANGE"' |
| Chỉ in nội dung dòng | logcli query -o raw --since=30m '{job="syslog"}' |
| Liệt kê label / giá trị | logcli labels / logcli labels source |
| Liệt kê stream khớp selector | logcli series '{job="syslog"}' |
| Metric query tại một thời điểm | logcli instant-query 'sum by (source) (count_over_time({job="syslog"}[5m]))' |
Không đưa giá trị động (IP peer, interface, nội dung message) vào label của stream. Mỗi tổ hợp label là một stream riêng; nhiều stream nhỏ làm Loki chậm và báo maximum active stream limit exceeded. Giá trị động để trong nội dung dòng và tách bằng parser lúc query.