Access Hub Collector
Đồng bộ từ mã nguồn lúc 10:57, 03/10/2026
Skip to content

Cảnh báo ​

Phân vai: Access Hub sở hữu luật, định tuyến thông báo, vòng đời alert và giao diện. Collector đánh giá luật trên luồng mẫu và phát sự kiện. Collector không gửi email hay webhook, việc đó do hệ thống thông báo có sẵn của Access Hub làm.

14 phút đọcCập nhật 01/10/2026access-hub-collector, docs/05-alerting.md

1. Mô hình luật ​

Luật lưu trong Access Hub (monitoring_rules), collector kéo về theo since và biên dịch.

json
{
  "id": "0d6b...",
  "version": 7,
  "company_id": "c1...",
  "name": "Đĩa gần đầy",
  "kind": "threshold",
  "scope": {
    "all": false,
    "server_ids": [],
    "tags": ["prod"],
    "environments": ["prod"],
    "roles": [],
    "datacenters": []
  },
  "metric": "disk_used_percent",
  "matchers": { "mount": "/var" },
  "operator": ">",
  "threshold": 90,
  "for_seconds": 300,
  "recover_threshold": 85,
  "recover_for_seconds": 120,
  "severity": "critical",
  "no_data": "ignore",
  "renotify_seconds": 3600,
  "enabled": true
}
TrườngÝ nghĩa
kindthreshold (GĐ 2), check (kết quả kiểm tra port, dịch vụ, cert, GĐ 2), agent_down (dựng sẵn, GĐ 1)
scopeTập máy chủ áp dụng, hợp của các điều kiện. Thuộc tính lấy từ kiểm kê Server (tags, environment, role, datacenter) và Access Hub gửi kèm trong bản đồng bộ để collector không phải tra ngược
matchersKhớp nhãn của series (ví dụ chỉ /var). Giá trị đơn hoặc danh sách, cho phép regex đã kiểm chứng an toàn
for_secondsĐiều kiện phải đúng liên tục chừng này thời gian mới mở alert
recover_threshold, recover_for_secondsTrễ phục hồi (hysteresis): phải xuống dưới ngưỡng này liên tục mới đóng, tránh nhấp nháy quanh ngưỡng
no_dataKhi máy vẫn online nhưng series biến mất: ignore, alert, resolve
renotify_secondsNhắc lại tối thiểu bao lâu một lần khi alert còn mở, 0 là không nhắc

version tăng mỗi lần sửa. Sự kiện luôn mang rule_version để truy vết luật lúc phát sự kiện.

Bộ luật mặc định (mỗi công ty, bật tắt được) ​

LuậtĐiều kiệnMức
Mất tín hiệuagent_down sau max(3 x interval, 90 s)critical
CPU caocpu_usage_percent > 90 trong 10 phút, phục hồi dưới 80warning
RAM caomem_used_percent > 90 trong 10 phút, phục hồi dưới 85warning
Đĩa đầy dầndisk_used_percent > 85 trong 5 phútwarning
Đĩa gần đầydisk_used_percent > 95 trong 5 phútcritical
Tải caoload_per_core_5m > 2 trong 15 phútwarning
Chứng chỉ sắp hết hạncert_days_left < 14 warning, < 3 criticalwarning, critical

2. Trạng thái và đánh giá ​

Mỗi cặp (rule_id, server_id, series) có máy trạng thái:

        vi phạm                 vi phạm liên tục >= for
 OK -----------------> PENDING --------------------------> FIRING
  ^  hết vi phạm          |                                  |
  '-----------------------'      thỏa recover liên tục >=    |
  ^                                recover_for               |
  '----------------------------------------------------------'
  • Đánh giá diễn ra mỗi khi mẫu của series đến, không theo đồng hồ riêng, nên độ trễ cảnh báo bám sát chu kỳ thu thập. Thời gian for tính theo timestamp của mẫu, không theo giờ nhận, để bù lại khi agent gửi bù dữ liệu tồn.
  • Mẫu quá cũ (cũ hơn max(for_seconds, 2 phút) so với mẫu mới nhất của cùng series, xem mục 2.1) không kích hoạt alert mới, chỉ dùng để lấp lịch sử.
  • Trạng thái nằm trong bộ nhớ worker theo shard, snapshot mỗi 30 giây (alerting.rules_state_interval) và khi tắt êm, vào Redis, hoặc tệp (alerting.rules_dir), hoặc bộ nhớ khi không cấu hình gì. Khởi động lại nạp snapshot, alert đang mở không bị mất hay mở trùng (NFR-13), riêng vụ sập cứng trong cửa sổ 30 giây có thể phát lại một alert.opened (Access Hub khử trùng theo seq, xem mục 5).
  • Khi luật đổi version: trạng thái đang FIRING của luật cũ được đóng với lý do rule_changed nếu metric, matchers hoặc cờ all của scope thay đổi, giữ nguyên nếu chỉ đổi thuộc tính không ảnh hưởng đánh giá (ví dụ renotify_seconds). Thêm hoặc bớt máy chủ khỏi scope không đổi chữ ký: máy chủ bị bớt đóng alert với lý do out_of_scope, các máy chủ còn lại giữ nguyên, không phát sự kiện nào.

2.1 Hiện thực COL-8 ​

Bộ đánh giá nằm trong tiến trình worker, gắn vào worker.Options.OnBatch (internal/rules). Trạng thái chia 64 shard theo bus.ShardFor(server_id), mỗi shard một mutex.

Kéo luật. Syncer gọi GET /rules?since=&limit=500 của Access Hub ngay khi khởi động, rồi mỗi alerting.rules_sync_interval (mặc định 1 phút), và khi có POST /internal/v1/reload/rules. Con trỏ since là sync_version toàn cục của Access Hub (không phải version của từng luật), đọc tiếp theo next_since và more cho đến hết. Luật tắt hoặc xóa đến dưới dạng bia mộ (enabled=false hoặc deleted=true) và bị gỡ khỏi bộ đang chạy. Cả lần đồng bộ được áp dụng nguyên khối: lỗi giữa chừng giữ nguyên bộ cũ. Bộ luật thô và since được lưu snapshot, nên khởi động lại khi Access Hub sập vẫn chạy với bộ luật cuối.

Biên dịch. Mỗi luật được kiểm tra riêng: kind (threshold, check; agent_down là luật dựng sẵn nên bỏ qua), metric thuộc catalog, nhãn của matchers được phép với metric đó, operator, threshold hữu hạn, recover_threshold đúng phía của ngưỡng, severity, no_data, các khoảng thời gian, scope. Regex chạy RE2 (thời gian tuyến tính), neo hai đầu, tối đa 128 ký tự, danh sách tối đa 64 giá trị. Luật sai bị bỏ qua: log cảnh báo, ahc_rules_rejected_total{reason}, ahc_rules_invalid, GET /status mục rules.invalid_rules. Luật sai không bao giờ làm sập collector, và không có sự kiện rule.invalid vì phong bì sự kiện bắt buộc có server_id. Nếu luật đang FIRING bị sửa thành sai, alert đóng với lý do rule_removed.

Phạm vi. Đánh giá khi company_id của luật bằng company_id của lô (cách ly tenant, sự kiện luôn mang company_id của lô) và máy nằm trong scope: scope.all, hoặc hợp của resolved_server_ids (Access Hub đã giải tag, môi trường, vai trò, trung tâm dữ liệu) và scope.server_ids.

Máy trạng thái. Khóa (rule_id, server_id, series_key), series_key dạng metric{label="value"} nhãn sắp xếp, dài quá 255 byte (giới hạn cột của Access Hub) thì cắt còn phần đầu đọc được cộng hậu tố ~ và 12 ký tự hash của khóa đầy đủ. Vi phạm lần đầu vào PENDING. Đủ for_seconds (đo bằng timestamp mẫu) thì FIRING và phát alert.opened. Với for_seconds = 0, vi phạm đầu tiên mở alert ngay. PENDING chịu được khoảng trống dữ liệu tối đa alerting.no_data_after. Trong FIRING, mẫu thỏa điều kiện phục hồi (hết vi phạm và, nếu có recover_threshold, vượt qua nó) liên tục recover_for_seconds thì phát alert.resolved (reason=recovered). Đến hạn renotify_seconds phát alert.reminder. Giá trị ở giữa ngưỡng và recover_threshold giữ nguyên trạng thái (hysteresis).

Mẫu cũ. stale = max(for_seconds, 2 phút): mẫu có newest - ts > stale (newest là mẫu mới nhất của series trong lô) không mở alert mới, để agent gửi bù dữ liệu tồn không gây báo giả.

no_data. Sweep chạy định kỳ. Series im lặng quá alerting.no_data_after (mặc định 5 phút, giờ thật) trong khi máy vẫn gửi các lô khác thì áp no_data: ignore (giữ nguyên trạng thái), alert (nếu chưa FIRING thì mở alert alert.opened với nhãn no_data="true", không có threshold, còn đang FIRING vì vi phạm thì giữ nguyên), resolve (đóng alert đang mở với reason=no_data). Alert do no_data mở sẽ đóng với reason=data_returned khi mẫu đầu tiên quay lại, rồi đánh giá bình thường. Máy mất hoàn toàn tín hiệu do agent_down lo, không tính vào no_data.

Đổi luật. Chữ ký (công ty, metric, matchers, cờ all của scope) đổi thì alert FIRING đóng với reason=rule_changed rồi đánh giá lại từ đầu. Danh sách máy chủ của scope (resolved_server_ids) không nằm trong chữ ký: một máy chủ rời scope đóng alert của riêng nó với reason=out_of_scope, máy chủ khác không bị ảnh hưởng. Sau lần nâng cấp collector đầu tiên, snapshot cũ mang chữ ký có danh sách máy chủ nên các alert đang mở của luật theo nhóm máy chủ có thể đóng một lần với rule_changed rồi mở lại (Access Hub khử trùng theo seq). Luật bị tắt, xóa hoặc thành không hợp lệ đóng với reason=rule_removed. Sửa các trường khác (threshold, for, renotify, tên, mức) giữ nguyên trạng thái. Việc đóng làm lười, ở lần đánh giá hoặc quét kế tiếp.

Hook. Engine.Suppress nhận (company, server, at) và trả (suppressed, reason). COL-9 nối nó vào suppress.Suppressor (mục 4.1), nên mọi sự kiện luật mang suppressed và suppress_reason đúng.

Mất tín hiệu (agent_down) ​

  • Bộ quét chạy mỗi 10 giây trên ah:seen, tìm agent có last_seen < now - max(3 x interval, 90 s).
  • Ra khỏi trạng thái up: ghi agent:{id}:st, phát agent.down một lần.
  • Nhận lại gói metrics hợp lệ: phát agent.up, đóng alert.
  • Máy có Server.status = maintenance hoặc decommissioned: vẫn đổi trạng thái nhưng đánh dấu suppressed: true (xem mục 4).

Kiểm tra (check) ​

Kết quả kiểm tra là series như mọi chỉ số (service_up, port_up, http_up, cert_days_left), luật kind=check đánh giá cùng cơ chế với ngưỡng.

3. Chống nhiễu ​

Cơ chếMô tả
Hysteresisrecover_threshold và recover_for_seconds (COL-8)
FlappingAlert chuyển FIRING <-> OK từ 4 lần trở lên trong 30 phút bị đánh dấu flapping, ngừng gửi thông báo chuyển trạng thái, gửi một thông báo tóm tắt, alert giữ FIRING cho đến khi ổn định 30 phút. Cấu hình được (mục 3.1)
Gom sự cố diện rộngNếu từ 5 máy trở lên và từ 30% số máy cùng subnet_id hoặc datacenter của một công ty mất tín hiệu trong cửa sổ 60 giây, collector phát một sự kiện group_down (group_key, member_server_ids) thay vì hàng trăm agent.down. Access Hub tạo một alert nhóm và gắn các alert con ở trạng thái grouped. Khi thành viên phục hồi lần lượt thì cập nhật nhóm (mục 3.2)
Nhắc lạirenotify_seconds. Không nhắc khi đang flapping
Khởi động thácSau khi collector khởi động hoặc bus tràn, giai đoạn ân hạn 2 x interval không phát agent.down để tránh báo giả do chưa kịp nhận gói

3.1 Flapping (COL-9) ​

Khóa theo (rule_id, server_id, series_key). Mỗi lần alert mở hoặc đóng (đo bằng timestamp mẫu) được ghi vào lịch sử, chỉ giữ những lần trong alerting.flap_window.

  • Dưới alerting.flap_transitions (mặc định 4) lần: phát alert.opened và alert.resolved như thường.
  • Lần chuyển thứ 4 đẩy series vào flapping: phát alert.flapping với reason=entered, transitions=<số lần>. Nếu chính lần chuyển đó là lần mở thì alert.opened vẫn đi trước, để Access Hub luôn có alert mở. Access Hub coi alert là FIRING cho đến khi ổn định.
  • Khi đang flapping: mọi alert.opened, alert.resolved tiếp theo bị giữ lại (không phát), alert.reminder bị bỏ qua. Số sự kiện bị giữ đếm ở ahc_alert_flap_events_dropped_total.
  • Ổn định: sau alerting.flap_stable (mặc định 30 phút, giờ thật) không có chuyển đổi nào, phát alert.flapping với reason=exited. Nếu lúc đó điều kiện đã hết vi phạm thì phát thêm alert.resolved (reason=recovered). Nếu vẫn vi phạm thì alert tiếp tục mở bình thường.
  • Luật đổi chữ ký, bị gỡ hoặc máy rời scope khi đang flapping: alert đóng bằng alert.resolved với lý do tương ứng, không phát exited.
  • alerting.flap_transitions: 0 tắt flapping. Trạng thái flapping nằm trong snapshot của bộ luật (khởi động lại vẫn giữ).
  • Metric: ahc_alert_flaps_total{to=entered|exited}, ahc_alerts_flapping, GET /status mục rules.flapping.

3.2 Gom sự cố diện rộng group_down (COL-9) ​

Chạy trong tiến trình worker, chỉ khi alerting.group_down.enabled (mặc định true). GroupIndex được cập nhật bởi hook của registry và phân nhóm máy theo subnet:<subnet_id> và datacenter:<datacenter> của từng công ty. Hai chiều là hai nhóm độc lập, nên máy có cả hai thuộc tính có thể sinh hai group_down (mỗi chiều một).

  • Mở. Mỗi lần quét, các agent mới bị tuyên bố mất tín hiệu được ghi vào nhóm của chúng. Một nhóm mở khi số máy mất tín hiệu trong window (mặc định 60 giây) đạt min (mặc định 5) và chiếm ít nhất ratio (mặc định 0.30) số máy của nhóm. Phát một group_down. Các agent.down riêng lẻ vẫn được phát (để Access Hub gắn chúng làm alert con, trạng thái grouped).
  • Cập nhật. Khi có thành viên hồi phục rời nhóm hoặc máy im lặng mới gia nhập, phát group_update với danh sách thành viên hiện tại.
  • Đóng. Khi không còn thành viên nào, phát group_resolved (reason=recovered, duration_seconds).
  • Hồi phục được xác định bằng cách đọc presence của agent, nên đúng cả khi ingest và worker chạy tách tiến trình. agent.up của từng thành viên vẫn phát riêng.
  • Định danh. rule_id=group_down, series_key=group_key, server_id là máy neo (thành viên có server_id nhỏ nhất lúc mở, giữ nguyên đến hết đời nhóm). seq tăng theo (server neo, group_key) nên Access Hub khử trùng như mọi sự kiện. group_total là số máy của nhóm lúc phát.
  • Tham số theo công ty, từng trường, thứ tự ưu tiên: GET /settings/{company_id} của Access Hub (trường null nghĩa là không đặt) > ghi đè trong cấu hình alerting.group_down.companies.<company_id> > mặc định. Cài đặt được cache 5 phút (30 giây sau lỗi gọi Access Hub), POST /internal/v1/reload/settings xóa cache.
  • Chặn thông báo. Nhóm suppressed khi mọi thành viên lúc mở đều bị chặn, suppress_reason lấy của thành viên đầu tiên. group_update và group_resolved thừa hưởng quyết định lúc mở.
  • Ân hạn khởi động áp dụng như agent.down: hết 2 x interval sau khi khởi động mới có nhóm.
  • Trạng thái nhóm đang mở được snapshot (Redis, tệp hoặc bộ nhớ) nên khởi động lại không mở trùng. Giới hạn: việc tuyên bố mất tín hiệu là race free giữa các worker (worker thắng SADD phát agent.down), nhưng mỗi worker chỉ thấy những máy do chính nó tuyên bố nên nhóm không được chia sẻ. Khi chạy nhiều worker, chỉ một worker nên bật alerting.group_down.enabled (các worker khác đặt false), nếu không ngưỡng min có thể không bao giờ đạt.
  • Metric: ahc_groups_open, ahc_events_emitted_total{type=group_*}.

4. Chặn thông báo ​

Collector vẫn đánh giá và phát sự kiện, kèm cờ suppressed và suppress_reason (maintenance, silence, decommissioned). Access Hub lưu alert nhưng không thông báo. Cách này giữ đủ lịch sử và cho phép gỡ chặn mà không mất dữ liệu. Cờ áp dụng cho mọi sự kiện: alert.*, agent.down, agent.up, group_*.

  • decommissioned và maintenance: Server.status của máy, đồng bộ qua bản ghi agent (server_status, xem 06 mục 4.2). Đây là trạng thái hiện tại (collector không giữ lịch sử), lấy từ agent chưa bị thu hồi mới nhất của máy, cache 5 giây.
  • silence: khoảng thời gian tắt tiếng theo phạm vi do người dùng tạo trong Access Hub, đồng bộ như luật (mục 4.1).
  • Thứ tự ưu tiên khi nhiều lý do cùng đúng: decommissioned > maintenance > silence.

4.1 Silence (COL-9) ​

suppress.Syncer kéo GET /silences?since=&limit= theo đúng mẫu của Syncer luật: chạy lúc khởi động, mỗi alerting.silences_sync_interval (mặc định 1 phút) và khi có POST /internal/v1/reload/silences (tách tiến trình thì qua bộ đếm Redis <prefix>silences:reload). Con trỏ là sync_version toàn cục, bia mộ (deleted=true) gỡ silence, cả lần đồng bộ áp nguyên khối, lỗi giữa chừng giữ bộ cũ. Bộ thô và since được snapshot nên Access Hub sập lúc khởi động vẫn dùng bộ cuối.

  • Cách ly tenant. Silence chỉ áp cho sự kiện cùng company_id. Silence của công ty khác, dù scope.all, không bao giờ khớp.
  • Phạm vi. scope.all, hoặc máy thuộc scope.server_ids hoặc resolved_server_ids (ở trong scope hoặc ở cấp trên cùng).
  • Thời điểm. Silence được so với timestamp của sự kiện, không phải giờ phát, theo khoảng [starts_at, ends_at). Ví dụ alert.resolved của một alert mở trước khi silence bắt đầu mà đóng trong silence thì suppressed=true, còn sự kiện trước starts_at phát muộn thì không. Silence đã hết hạn không còn khớp sự kiện mới. Collector giữ bản thô thêm 24 giờ sau khi hết hạn (để khớp sự kiện trễ) rồi dọn.
  • Metric: ahc_events_suppressed_total{reason}, ahc_silences_sync_total{result}, ahc_silences_last_sync_timestamp_seconds, ahc_silences_since, ahc_silences_active. GET /status mục silences (active, loaded, since, last_sync_at, last_sync_error).

5. Sự kiện gửi về Access Hub ​

json
{
  "event_id": "018f2c1e-7b6a-7d3e-8b8e-2f2f6d1e9c11",
  "type": "alert.opened",
  "seq": 42,
  "occurred_at": "2026-09-30T02:15:30Z",
  "company_id": "c1...",
  "server_id": "s1...",
  "rule_id": "0d6b...",
  "rule_version": 7,
  "series_key": "disk_used_percent{mount=\"/var\"}",
  "severity": "critical",
  "value": 93.4,
  "threshold": 90,
  "suppressed": false,
  "suppress_reason": null,
  "group_key": null,
  "labels": { "mount": "/var" }
}
typeKhi nào
alert.openedChuyển PENDING -> FIRING
alert.resolvedChuyển FIRING -> OK, có duration_seconds, peak_value, reason (recovered, no_data, data_returned, rule_changed, out_of_scope, rule_removed)
alert.reminderĐến hạn renotify_seconds
alert.flappingVào (reason=entered, transitions) hoặc ra (reason=exited) trạng thái flapping
agent.down, agent.upMất và có lại tín hiệu
group_down, group_update, group_resolvedSự cố diện rộng: mang group_key, member_server_ids, group_total. group_resolved có duration_seconds và reason=recovered
agent.seen_snapshotKhông phải sự kiện cảnh báo, xem endpoint seen

Access Hub xử lý theo quy tắc: bỏ nếu event_id đã thấy, bỏ nếu seq không lớn hơn seq đã xử lý của cặp (server_id, rule_id, series_key), còn lại áp dụng vào bảng monitoring_alerts và kích hoạt thông báo (trừ khi suppressed).

6. Kiểm thử cảnh báo (tóm tắt) ​

  • Bảng quyết định đơn vị cho máy trạng thái (vào PENDING, đủ for, hysteresis, no_data).
  • Mô phỏng tái phát: phát lại chuỗi mẫu đã ghi để đảm bảo cùng chuỗi mẫu cho ra cùng chuỗi sự kiện (xác định).
  • Kiểm thử khởi động lại giữa PENDING và FIRING: không mở trùng, không mất.
  • Kiểm thử gom sự cố với 500 agent mất đồng loạt: đúng một sự kiện nhóm. Chi tiết ở 12-testing.
Trang này có giúp được bạn không?
Sửa trang này

Nội dung đồng bộ từ kho mã access-hub-collector lúc 10:57, 03/10/2026. Khi tài liệu và mã khác nhau, mã thắng.