Kibana / OpenSearch Dashboards: tìm log, dashboard, alert

4 câu hỏi phỏng vấn~25 phútTừ khóa: data view, index pattern, Discover, KQL, Lucene query, saved search, Lens, dashboard, alerting rule, OpenSearch Alerting, monitor, spaces, tenants, RBAC, field-level security, APM, trace correlation

Tiếp đi: Kibana. Log shop-app vào ES đủ rồi, nhưng team mở Discover ra chỉ biết gõ "error" rồi cuộn. Dùng sao cho ra việc?

Gõ "error" là tìm full-text trên mọi field, vừa chậm vừa nhiều rác. Kibana mạnh khi bạn lọc theo field có cấu trúc mà bài 19.9 đã chuẩn bị: service.name, log.level, trace.id. Mọi thứ dưới đây cũng áp dụng cho OpenSearch Dashboards, chỉ khác tên menu.

1. Bài toán

Khách báo đơn ORD-1042 lỗi lúc 08:15. Team cần: (1) tìm log của đơn đó qua cả 3 service, (2) xem error rate từng service hôm nay, (3) được báo khi payment lỗi tăng vọt.

2. Vấn đề

3. Giải pháp

KibanaOpenSearch DashboardsDùng để
Data viewIndex patternChọn index nào, field thời gian nào
DiscoverDiscoverTìm và đọc log
Saved searchSaved searchLưu query + cột để dùng chung
Lens / VisualizeVisualizeVẽ chart
DashboardDashboardGom chart
Alerting rulesAlerting (monitor + trigger)Báo động
SpacesTenantsTách không gian theo team

4. Code từng bước

Bước 1: tạo data view bằng API

curl -s -u "admin_kibana:$KIBANA_ADMIN_PASSWORD" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' \
  -X POST "$KIBANA_URL/api/data_views/data_view" -d '{
  "data_view": { "title": "logs-shop-*", "name": "shop-app logs", "timeFieldName": "@timestamp" } }'

Bước 2: query trong Discover

CầnKQLLucene
Lỗi của paymentservice.name:payment-service and log.level:errorservice.name:payment-service AND log.level:error
Theo tracetrace.id:4bf92f3577b34da6a3ce929d0e0e4736như KQL
Một trong nhiềuservice.name:(order-service or payment-service)service.name:(order-service OR payment-service)
Loại trừnot url.path:/actuator*-url.path:\/actuator*
Khoảng sốhttp.response.status_code >= 500http.response.status_code:[500 TO 599]
Cụm từmessage:"charge failed"message:"charge failed"
Field có tồn tạierror.type:*_exists_:error.type
Regex, fuzzykhông cóorderId:/ORD-10[0-9]{2}/, messge~

KQL dễ đọc, có gợi ý field, mặc định dùng. Lucene khi cần regex, fuzzy, boost. Lọc theo keyword thì nhanh; wildcard đầu chuỗi (*failed) thì rất chậm.

Quy trình cho ORD-1042: orderId:ORD-1042 → thấy trace.id → bấm filter theo trace.id → thấy cả log order, payment, inventory xếp theo thời gian. Lưu thành saved search "Theo dõi một đơn" với cột service.name, log.level, message.

Bước 3: dashboard error rate theo service (Lens)

Chart: Line, trục X = @timestamp (auto interval)
Breakdown: service.name (top 5)
Y: Formula  count(kql='log.level:error') / count()
Thêm panel: Top 10 error.type (bar), bảng log ERROR mới nhất (saved search)

Export dashboard ra file NDJSON (Stack Management → Saved objects → Export) và commit vào git để dựng lại ở môi trường khác.

Bước 4: alert

Kibana: rule loại "Elasticsearch query":

Index: logs-shop-*      Query (KQL): service.name:payment-service and log.level:error
Threshold: count > 50 trong 5 phút, kiểm tra mỗi 1 phút
Action: webhook/Slack connector, nội dung có link Discover

OpenSearch Alerting: tạo monitor dạng query:

POST _plugins/_alerting/monitors
{
  "type": "monitor", "name": "payment-errors", "enabled": true,
  "schedule": { "period": { "interval": 1, "unit": "MINUTES" } },
  "inputs": [{ "search": { "indices": ["logs-shop-*"], "query": {
     "size": 0, "query": { "bool": { "filter": [
        { "term": { "service.name": "payment-service" } },
        { "term": { "log.level": "error" } },
        { "range": { "@timestamp": { "gte": "now-5m" } } } ] } } } } }],
  "triggers": [{ "name": "too-many", "severity": "2",
     "condition": { "script": { "source": "ctx.results[0].hits.total.value > 50" } },
     "actions": [] }]
}

Kiểm tra: curl -s -H "Authorization: ApiKey $ES_API_KEY" "$ES_URL/logs-shop-*/_count" -H 'Content-Type: application/json' -d '{"query":{"term":{"log.level":"error"}}}'.

5. Cách hoạt động

 Dashboard (10 panel) ──► Kibana server ──► 10 aggregation query ──► ES
        │ mỗi lần refresh, mỗi người xem              (scatter tới mọi shard trong khoảng thời gian)
        ▼
 Khoảng 15 phút: nhẹ        Khoảng 30 ngày: nặng → chọn khoảng ngắn, auto-refresh thưa

 Alert rule (mỗi phút) ──► query ES ──► vượt ngưỡng ──► connector (Slack/PagerDuty/webhook)

 Log có trace.id ──► Kibana APM / Jaeger / Tempo: bấm "View trace" (link field)
 Trace có span lỗi ──► "View logs" lọc trace.id

6. So sánh: alert từ log hay từ metric

Alert từ log (Kibana)Alert từ metric (Prometheus, 19.2)
Chi phí mỗi lần kiểm traQuery ES trên nhiều docĐọc vài time series
Phụ thuộcPipeline log trễ/hỏng → alert im lặngĐộc lập với log
Đo SLO/burn rateKhóTự nhiên
Hợp vớiSự kiện hiếm, cụ thể: "có log FraudRuleDisabled", lỗi bảo mậtError rate, latency, saturation

Nên page người bằng alert theo SLO từ metric (19.2); alert log để báo sự kiện cụ thể, mức ticket.

7. Khi nào nên dùng / không nên dùng

Log payment có số điện thoại và email khách. Team order chỉ nên thấy log của order. Mình phân quyền trong Kibana kiểu gì?

Bạn cần hai lớp: Space (gọn giao diện) và role (quyền dữ liệu thật). Space một mình không chặn dữ liệu.

POST _security/role/team-order-logs
{
  "indices": [{
    "names": ["logs-shop-prod"],
    "privileges": ["read", "view_index_metadata"],
    "query": { "term": { "service.name": "order-service" } },      // document-level security
    "field_security": { "grant": ["*"], "except": ["user.email", "user.phone"] }  // field-level
  }],
  "applications": [{ "application": "kibana-.kibana",
     "privileges": ["feature_discover.read", "feature_dashboard.read"], "resources": ["space:order"] }]
}

Gán role qua SSO (SAML/OIDC với Keycloak, chương 12) theo group. Lưu ý: DLS/FLS cần license trả phí của Elastic; OpenSearch có sẵn trong security plugin (tenants + document/field level security). Cách tốt hơn nữa: đừng log PII ngay từ app, hoặc mask ở ingest pipeline.

Trong Discover mình thấy cột http.response.status_code bị dấu chấm than vàng, không lọc >= 500 được. Sao vậy nhỉ?

Gần như chắc là mapping conflict: trong logs-shop-* có backing index cũ map field đó là keyword (do dynamic mapping trước khi có template), index mới là short. Data view gộp nhiều index nên thấy hai kiểu.

Phỏng vấn hỏi về Kibana, tìm log và alert từ log thì trả lời sao?

Q1. Bạn điều tra một request lỗi qua nhiều service trong Kibana thế nào?

🇻🇳 Tiếng Việt:

Tôi bắt đầu từ dấu vết có sẵn như mã đơn hoặc request id, lọc bằng KQL theo field keyword, lấy trace.id từ log đó rồi lọc theo trace.id để thấy log của mọi service theo thời gian. Từ đó nhảy sang trace trong APM hoặc Tempo để xem span nào chậm hay lỗi. Điều kiện là mọi service ghi log JSON có service.name và trace.id.

🇬🇧 English:

I start from an identifier I have, such as an order ID or request ID, filter with KQL on keyword fields, take the trace ID from that log, and filter by trace ID to see logs from every service in time order. Then I jump to the trace in APM or Tempo to see which span was slow or failed. This only works if every service emits JSON logs with service.name and trace.id.

Q2. KQL và Lucene query khác nhau thế nào?

🇻🇳 Tiếng Việt:

KQL là cú pháp mặc định của Kibana, dễ đọc, có gợi ý field, hỗ trợ and, or, not, range và wildcard. Lucene query cũ hơn nhưng có regex, fuzzy, proximity và boost. Tôi dùng KQL hằng ngày và chỉ chuyển sang Lucene hoặc query DSL khi cần các tính năng đó.

🇬🇧 English:

KQL is Kibana's default syntax: readable, with field suggestions, supporting and, or, not, ranges and wildcards. Lucene query syntax is older but adds regex, fuzzy, proximity and boosting. I use KQL day to day and switch to Lucene or the query DSL only when I need those features.

Q3. Nên alert từ log hay từ metric?

🇻🇳 Tiếng Việt:

Với error rate và latency tôi alert từ metric theo SLO, vì rẻ, nhanh và không phụ thuộc pipeline log. Alert từ log dành cho sự kiện cụ thể và hiếm, ví dụ một thông điệp bảo mật hoặc lỗi nghiệp vụ đặc biệt. Nếu alert dựa vào log thì cũng phải alert khi pipeline log ngừng đẩy dữ liệu.

🇬🇧 English:

For error rate and latency I alert on metrics against SLOs, because it is cheap, fast and independent of the log pipeline. Log-based alerts are for specific, rare events such as a security message or a particular business failure. If I rely on log alerts, I also alert when the log pipeline stops delivering data.

Cách nhớ ngắn gọn


Tự kiểm tra

Data view trong OpenSearch Dashboards gọi là gì?

Index pattern.

Viết KQL: lỗi 5xx của order-service.

service.name:order-service and http.response.status_code >= 500

Space có ngăn user đọc index khác không?

Không; cần role với index privilege (và DLS/FLS nếu cần).

Vì sao alert từ log có thể "im lặng" khi hệ thống hỏng?

Pipeline log trễ hoặc ngừng thì không có log để đếm.

Dấu chấm than vàng trên field trong Discover thường là gì?

Mapping conflict giữa các index trong data view.