Sổ tay kỹ thuật

Loki – LogQL hay dùng cho syslog thiết bị

cheatsheet#loki#logql#grafana#syslog· cập nhật 2026-11-06

Tra nhanh LogQL - stream selector, line filter, parser json/logfmt/pattern, label filter và metric query đếm log theo thiết bị.

Sửa trang này
Mục lục

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.