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

L3 - Monitoring Platform - Agent - Collectors (Bộ thu số liệu) ​

Trạng thái
Bản nháp
Phiên bản
0.1, ngày 30/09/2026

Ghi chú: khi tài liệu và mã khác nhau, mã thắng

Đã làm nghĩa là có mã và kiểm thử trong repo. Chỉ thiết kế nghĩa là có trong tài liệu nhưng chưa có mã. Chỗ lệch được ghi ở mục nợ kỹ thuật.

Thông tin tài liệu đầy đủ
TrườngGiá trị
Tên trangL3 - Monitoring Platform - Agent - Collectors
Trạng tháiBẢN NHÁP (tài liệu chưa sẵn sàng trình thẩm định)
Phiên bảnv0.1, 2026-09-30: bản nháp đầu tiên, dựng từ mã tại commit a23f929 (internal/collector/**, internal/stats, internal/cli/collectonce.go) và docs/03-metrics-catalog.md
Tên dự ánMonitoring Platform (Access Hub Monitoring)
Bên thẩm định / Phê duyệtchưa chỉ định. Chưa ai sign-off
Tài liệu tầng trên (Parent)L2 - Monitoring Platform - Agent - SAD, thành phần CMP-2 Collector Engine (mục 2.3), FR-04 đến FR-07, FR-22 đến FR-24, L2-NFR-01, 02, 09, 16. Truy vết tiếp lên L1: L1 HLD mục 2 (Mục tiêu 2, 3), mục 3 (T1, T2), mục 4
Tài liệu anh emL3 WAL và Sender, L3 Enroll, Credentials, Config, L3 Service và Packaging
Mục lục0 Governance, 1 Phạm vi, 2 Yêu cầu, 3 Kiến trúc, 4 Domain model, 5 Hợp đồng API, 6 Dữ liệu vật lý, 7 Thuật toán, 8 Xử lý lỗi, 9 Suy thoái, 10 Đồng thời, 11 Bảo mật, 12 Cấu hình, 13 Telemetry, 14 Kiểm thử, 15 Trình tự xây dựng, Phụ lục A, B, C

Quy ước nhãn trạng thái (giống L2): ĐÃ HIỆN THỰC (đã xác minh trong mã), THIẾT KẾ, CHƯA XÂY (chỉ có trong tài liệu thiết kế), MỘT PHẦN, ĐỀ XUẤT. Khi mã và tài liệu khác nhau, mã thắng và sai lệch được nêu trong tài liệu này và gom về L2 mục 16.2.


0. Front Matter & Approvals ​

Governance metadata

TrườngGiá trị
ComponentCMP-2 Collector Engine (L2 mục 2.3). Package internal/collector, internal/collector/linux, internal/collector/host
Truy vết L2L2-SAD-agent.md mục 2.3, 3 (FR-04, FR-05, FR-06, FR-07), 4 (L2-NFR-01, 02, 09, 16), 7.3
Phân loại rủi roĐề xuất, chưa xác nhận: Tier 3, kế thừa System Tier của L2 mục 14. Thành phần này không giữ bí mật và không nhận đầu vào từ mạng
Data classificationNội bộ (số liệu vận hành máy chủ, không PII). Nhãn mount và iface có thể tiết lộ cấu trúc máy nhưng không chứa dữ liệu người dùng (L2 mục 7.3)
Blast radiusMột máy chủ. Bộ thu lỗi chỉ làm mất số liệu của chính nó (bulkhead theo bộ thu). Lỗi nặng nhất theo mã: một cuộc gọi statfs treo (ví dụ NFS hỏng, chỉ khi bật include_network_fs) có thể chặn cả vòng thu, xem mục 8.3 và OQ-C1

Sign-off gate

Vai tròTênTrách nhiệm duyệtTrạng tháiNgày
Tech lead thành phầnchưa chỉ địnhĐúng đắn của thuật toán thu, giới hạn cardinalityChưa duyệtchưa có
SA hệ thống Agentchưa chỉ địnhNhất quán với L2 và giao thứcChưa duyệtchưa có
Bảo mậtchưa chỉ địnhDanh sách trắng nhãn, đọc /procChưa duyệtchưa có

1. Component Scope & Non-Goals ​

Vai trò: Collector Engine là bộ gom số liệu theo mẫu pipeline nhiều bộ thu cắm được (plugin collectors) với một bộ chuẩn hóa chặn ở cổng (catalog-guarded normalizer). Mỗi bộ thu là một đối tượng độc lập cài đặt interface Collector, đọc một nguồn của hệ điều hành và trả về các mẫu gauge. Engine chạy tuần tự các bộ thu, cách ly lỗi từng bộ thu, rồi ép mọi mẫu qua danh sách trắng tên chỉ số và nhãn, loại NaN, Inf, trùng, và cắt theo giới hạn series trước khi giao cho Sender.

Sơ đồ ngữ cảnh

mermaid
flowchart LR
  classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
  classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
  classDef infra fill:#444,stroke:#aaa,color:#fff

  OS(["Hệ điều hành: /proc và statfs"]):::infra
  CLI(["CLI collect-once"]):::infra

  subgraph BC["Collector Engine"]
    ENG["Engine: gom và chuẩn hóa"]:::owned
    COLS["Bộ thu Linux"]:::owned
  end

  RT["Runtime Core: vòng chu kỳ"]:::bc
  SND["Sender: đóng lô và gửi"]:::bc
  CFGL["Config Loader"]:::bc

  RT -->|"yêu cầu thu một chu kỳ"| ENG
  CLI -->|"thu hai lần in JSON"| ENG
  ENG -->|"gọi từng bộ thu"| COLS
  COLS -->|"đọc số liệu thô"| OS
  ENG -->|"trả mẫu đã chuẩn hóa"| RT
  RT -->|"chuyển mẫu để gửi"| SND
  CFGL -.->|"cấp cờ bật tắt và bộ lọc"| ENG

Mô tả quan hệ

ChiềuBênNội dung
VàoRuntime Core (internal/agent/agent.go)Gọi Engine.Collect(ctx, now) mỗi chu kỳ, một lần khởi động để mồi các bộ thu dạng tốc độ (kết quả bị bỏ)
VàoCLI collect-once (internal/cli/collectonce.go)Gọi Collect hai lần cách nhau -gap (mặc định 1 s, 100 ms đến 1 phút) rồi in mẫu lần hai dưới dạng JSON, không gửi
RaHệ điều hànhĐọc /proc/stat, /proc/loadavg, /proc/meminfo, /proc/self/mountinfo, /proc/net/dev, /proc/uptime, thư mục số của /proc, /proc/self/statm, /proc/self/stat, và statfs(2) cho từng mount. Chỉ đọc
RaRuntime CoreResult{Samples, Dropped, Errors, Duration}. Runtime tự chuyển mẫu cho Sender (BuildBatch thuộc L3 WAL và Sender)
Vào (lúc dựng)Config LoaderCờ metrics.*, limits.max_series, collect_timeout, labels. Cấu hình được đọc một lần khi dựng engine. Đổi cấu hình bằng SIGHUP không dựng lại engine (xem mục 12.1)
RaThống kê dùng chung (internal/stats)Ghi số bộ thu lỗi, thời lượng thu, số mẫu bị loại. Bộ thu tự thân đọc lại để phát agent_*

Trong phạm vi (bao phủ)

Trong phạm viGhi chú
Interface Collector, kiểu Sample, SeriesKeyinternal/collector/collector.go. ĐÃ HIỆN THỰC
Engine: chạy tuần tự, timeout chung, cách ly panic, chuẩn hóa, giới hạn series, dự trữ cho tự thâninternal/collector/engine.go. ĐÃ HIỆN THỰC
Danh mục chỉ số (nguồn sự thật) và danh sách trắng AllowedDanh mục nằm ở internal/catalog/catalog.go (nhóm, đơn vị, nhãn, bộ thu, nền tảng, mặc định, bắt buộc, mô tả vi và en), Allowed trong internal/collector/catalog.go sinh từ đó. ĐÃ HIỆN THỰC (có các chỉ số planned chưa phát, xem 5.2)
Chọn chỉ số (metrics.include, metrics.exclude, glob theo tên)internal/catalog/select.go, áp trong Engine.selected. Chỉ số bị loại không tạo ra, không tính là bỏ. Bộ thu có mọi chỉ số bị loại thì không chạy (host.go). ĐÃ HIỆN THỰC, xem ADR 0006
Bộ thu Linux: cpu, memory (gồm swap và chi tiết bộ nhớ), disk, net, uptime (gồm boot time, số tiến trình), pressure (PSI)internal/collector/linux/*.go. ĐÃ HIỆN THỰC
Bộ thu tự thân agent_*internal/collector/linux/self.go. ĐÃ HIỆN THỰC. Đọc /proc/self, nên chỉ có trên Linux
Bộ lọc mount và giao diện mạng mặc định và theo cấu hìnhinternal/collector/linux/filter.go. ĐÃ HIỆN THỰC
Dựng engine từ cấu hình hiệu lựcinternal/collector/host/host.go. ĐÃ HIỆN THỰC
Hành vi trên nền tảng không phải LinuxChỉ trả chỉ số agent (thực tế engine rỗng, không có bộ thu tự thân). ĐÃ HIỆN THỰC ở mức khung, xem 8.2
Dịch vụ Windows (internal/winsvc, ADR 0008)ĐÃ XÂY (SCM, ACL, mã thoát), chưa chạy trên Windows thật
Bộ thu Windows (API trực tiếp, ADR 0007)ĐÃ XÂY MỘT PHẦN (AGT-7, internal/collector/windows), chưa chạy trên Windows thật. PDH (ADR 0004) chỉ còn cho I/O đĩa, chưa làm

Ngoài phạm vi

Không thuộc BCThuộc về
Đóng lô protobuf, gán seq, AgentStats, gửi, backoffL3 WAL và Sender
Đọc, kiểm tra cấu hình YAML, cờ, env, SIGHUPL3 Enroll, Credentials, Config
Quyền tệp, tài khoản, unit systemdL3 Service và Packaging
Checks service, port, tcp, http, cert (service_up, port_up, tcp_connect_*, http_*, cert_days_left)ĐÃ XÂY (AGT-8): internal/collector/checks, chạy nền, trả kết quả lần chạy gần nhất
Kiểm kê phần cứng và hệ điều hànhĐÃ XÂY (AGT-9): ReadHostFacts trong inventory.go dùng lại bộ phân tích /proc và bộ lọc mount, interface của bộ thu. Phần mềm cài đặt không thu
Tốc độ I/O đĩa, open_fds_percent (disk_read_bytes_per_sec, disk_write_bytes_per_sec, disk_io_util_percent, open_fds_percent)Chưa có bộ thu (L2 D-03). docs/03 xếp vào giai đoạn 2
Container, cgroup v2Ngoài phạm vi giai đoạn này theo docs/03
Lưu, đánh giá, cảnh báo trên số liệuCollector (L2 Collector)

2. Detailed Requirements & Acceptance Criteria ​

Functional Requirements

#Trách nhiệmGiải thíchHiện thực ở
FR-C01Định nghĩa hợp đồng bộ thuMỗi bộ thu có Name() và Collect(ctx, now). Bộ thu dạng tốc độ giữ trạng thái giữa các lần gọi và không trả mẫu tốc độ ở lần đầucollector.go. ĐÃ HIỆN THỰC
FR-C02Thu CPUcpu_usage_percent, cpu_mode_percent{mode} (đủ 8 chế độ: user, nice, system, idle, iowait, irq, softirq, steal), cpu_load1/5/15, load_per_core_5m, cpu_coreslinux/cpu.go. ĐÃ HIỆN THỰC
FR-C03Thu bộ nhớ và swapmem_total/used/available_bytes, mem_used_percent, mem_free/cached/buffers/slab/page_tables_bytes, swap_total/used/cached_bytes, swap_used_percent. Dự phòng MemAvailable cho kernel cũlinux/memory.go. ĐÃ HIỆN THỰC
FR-C04Thu đĩadisk_total_bytes, disk_used_bytes, disk_used_percent, disk_inodes_used_percent theo {mount, fstype}. Loại pseudo fs, network fs mặc định, mount trùng thiết bị. Tối đa 40 mountlinux/disk.go, filter.go. ĐÃ HIỆN THỰC
FR-C05Thu mạng6 chỉ số tốc độ theo {iface} (bytes, errors, drops, chiều rx và tx). Tối đa 20 giao diện. Xử lý tràn bộ đếm 32 bitlinux/net.go, helpers.go. ĐÃ HIỆN THỰC
FR-C06Thu uptimeuptime_seconds, boot_time_seconds, procs_total (chỉ đếm thư mục số, không đọc cmdline)linux/uptime.go. ĐÃ HIỆN THỰC
FR-C07Thu tự thânagent_* (11 tên, xem 13.1). Bộ thu tự thân chạy sau cùng và được miễn cắt serieslinux/self.go, engine.go. ĐÃ HIỆN THỰC
FR-C08Cách ly lỗiLỗi hoặc panic ở một bộ thu được ghi vào Result.Errors, không dừng các bộ thu khácengine.go (safeCollect). ĐÃ HIỆN THỰC
FR-C09Chuẩn hóa mẫuLoại mẫu có tên ngoài danh sách trắng, nhãn ngoài danh sách của chỉ số đó, nhãn dành riêng, NaN, Inf, series trùng. Cắt giá trị nhãn 128 byte theo ranh giới UTF-8. Gắn nhãn tĩnh labelsengine.go (sanitize). ĐÃ HIỆN THỰC
FR-C10Giới hạn seriesCắt phần dư quá max_series trừ dự trữ tự thân (tối đa 16), cảnh báo một lần cho tới khi trở lại dưới ngưỡngengine.go. ĐÃ HIỆN THỰC
FR-C11Bật tắt và lọc theo cấu hìnhBật tắt từng bộ thu, include_iowait_in_usage, bộ lọc fstype, mount, giao diện bằng RE2. Regex sai làm dựng engine thất bạihost/host.go, linux/filter.go. ĐÃ HIỆN THỰC
FR-C12Thu một lần để chẩn đoáncollect-once thu hai lần rồi in JSON đã sắp xếpcli/collectonce.go. ĐÃ HIỆN THỰC (thuộc CLI, ghi ở đây vì dùng engine)
FR-C13Checks, kiểm kê, WindowsXem mục 1 Ngoài phạm viTHIẾT KẾ, CHƯA XÂY

Non-Functional Requirements

NFRTarget (Ý nghĩa)Parent L2-NFR (Kiểu)Satisfied-by (Tactic → Mục)
NFR-C01CPU và RAM của agent nằm trong ngân sách: đọc tệp /proc nhỏ, không đọc theo tiến trình, không thư viện bên thứ baL2-NFR-01, L2-NFR-02 (Allocated một phần)Cắt cardinality (7.4.1), đọc chỉ /proc tổng (7.4.5). Số đo thật chưa có (L2 D-16)
NFR-C02Số series không vượt max_series (cứng 500), tự thân luôn được dự trữL2-NFR-16 (Allocated)Cắt series và dự trữ (7.4.1), giới hạn MaxMounts 40 và MaxInterfaces 20 (7.4.3, 7.4.4), tham số ở 12.1
NFR-C03Một bộ thu lỗi hoặc panic không làm mất số liệu của bộ thu khác và không dừng agentL2-NFR-09 (Allocated)Bulkhead theo bộ thu (7.2, luồng 3), recover trong safeCollect
NFR-C04Một chu kỳ thu hoàn tất trong collect_timeout (mặc định 5 s, nhỏ hơn interval)Không có tương ứng trực tiếp trong L2. Kế thừa ANFR (khởi động và chu kỳ) (Owned)Timeout chung qua ngữ cảnh (7.2.2). Chỉ số agent_collect_duration_seconds (13.1). Tham số collect_timeout (12.1). Giới hạn: xem 8.3
NFR-C05Chỉ số và nhãn phát ra luôn khớp catalog và giao thức (không nhãn dành riêng)L2-NFR-18 (Inherited, tương thích giao thức)Danh sách trắng (7.4.1), TestCatalogConformance
NFR-C06Đọc không để lại dấu vết và không tăng đặc quyền: chỉ đọc /proc, statfsL2-NFR-12 (Inherited)Không ghi tệp, không exec. Xem 11
NFR-C07Tốc độ không sinh giá trị vô lý khi tràn hoặc đặt lại bộ đếmKhông có tương ứng trong L2 (Owned)counterDelta, maxRatePerSec (7.4.2). Đo bằng TestCounterDelta

Acceptance Criteria

ACKịch bản đặc tả (Given / When / Then)Truy vết → Test ID
AC-C01Given bộ thu CPU vừa dựng, When gọi Collect lần đầu, Then không có mẫu tốc độ (chỉ cpu_cores và tải)TestCPUFirstSampleHasNoRates
AC-C02Given hai lần đọc /proc/stat có delta, When gọi Collect lần hai, Then cpu_usage_percent và cpu_mode_percent tính đúng theo deltaTestCPURatesFromDeltas
AC-C03Given bộ đếm CPU đi lùi (hotplug), When thu, Then bỏ mẫu tốc độ chu kỳ đó, không lỗiTestCPUCounterGoingBackwardsSkipsSample
AC-C04Given kernel cũ thiếu cột hoặc thiếu MemAvailable, When thu, Then vẫn ra số liệu hợp lệTestCPULegacyStatColumns, TestMemoryLegacyWithoutMemAvailable
AC-C05Given tệp /proc thiếu hoặc sai, When thu, Then trả lỗi mô tả, không panicTestCPUMissingFilesReportError, TestMemoryNoSwapAndBadData
AC-C06Given bộ đếm mạng 32 bit tràn, When thu, Then tốc độ đúng. Given bộ đếm 64 bit đi lùi, Then bỏ mẫuTestNetCounterWrapAndReset, TestCounterDelta
AC-C07Given hơn 20 giao diện, When thu, Then chỉ 20 giao diện x 8 seriesTestNetInterfaceLimit
AC-C08Given danh sách mount có tmpfs, overlay, bind mount, When thu, Then chỉ mount thật, mỗi thiết bị một lầnTestDiskDefaultFilters, TestDiskRealHostFixture
AC-C09Given statfs lỗi ở một mount, When thu, Then các mount khác vẫn có số liệuTestDiskStatfsErrorIsReportedButOthersSurvive
AC-C10Given hơn 40 mount, When thu, Then dừng ở 40 và báo lỗiTestDiskMountLimit
AC-C11Given ngữ cảnh đã hủy, When thu đĩa, Then dừng sớmTestDiskContextCancelled
AC-C12Given mẫu có tên lạ, nhãn lạ, NaN, nhãn dành riêng, When chuẩn hóa, Then bị loại và đếmTestSanitizeDropsInvalidSamples, TestStaticLabelCannotOverrideReserved
AC-C13Given một bộ thu lỗi và một bộ thu panic, When Collect, Then bộ thu còn lại vẫn ra mẫu, lỗi ghi theo tênTestEngineIsolatesFailingAndPanickingCollectors
AC-C14Given số mẫu vượt giới hạn, When Collect, Then cắt phần thường nhưng giữ mẫu tự thânTestSeriesLimitTrimsMainButKeepsSelf
AC-C15Given collect_timeout, When Collect, Then ngữ cảnh truyền cho bộ thu có hạnTestEngineTimeoutIsAppliedToContext
AC-C16Given mọi bộ thu chạy hai lần, When kiểm, Then mọi tên và nhãn phát ra đều trong AllowedTestCatalogConformance
AC-C17Given cờ tắt một bộ thu, When dựng engine, Then không có bộ thu đó. Given regex sai, Then dựng thất bạiTestEngineHonorsCollectorToggles, TestBadRegexFailsEngineBuild
AC-C18Given /proc thật của máy chạy kiểm thử, When thu, Then không lỗi và có mẫuTestRealProcSmoke
AC-C19Given collect-once, When chạy, Then in JSON và không chứa URL giữ chỗ, -gap ngoài khoảng bị từ chốiTestCollectOncePrintsJSON, TestCollectOnceRejectsBadGapAndConfig

Quality Attribute Scenarios

Mã kịch bản / NFRNguồn & Kích thíchMôi trườngPhản hồi của hệ thống (Tactic)Thước đo chất lượng (Measure)
QAS-C01 / NFR-C03Một bộ thu gặp lỗi phân tích (/proc/meminfo hỏng) hoặc panicChạy bình thườngEngine ghi lỗi theo tên bộ thu, tiếp tục các bộ thu khác, Sender vẫn nhận số liệu còn lại và tự thânagent_collector_errors{collector} bằng 1 ở chu kỳ đó, các chỉ số khác vẫn hiện diện
QAS-C02 / NFR-C02Máy có rất nhiều mount hoặc giao diệnChạy bình thườngGiới hạn 40 mount, 20 giao diện, cắt theo max_series, cảnh báo một lầnSố series khi gửi không vượt max_series. Số mẫu bị loại thấy ở agent_dropped_samples_total
QAS-C03 / NFR-C07Bộ đếm mạng bị đặt lại (bơm lại driver)Chạy bình thườngBỏ mẫu tốc độ nếu bộ đếm 64 bit giảm, loại tốc độ trên 1e12 mỗi giâyKhông có điểm tốc độ vô lý trong lô. Giới hạn của cách làm: xem 7.4.2
QAS-C04 / NFR-C04Đọc /proc chậm hoặc statfs chậmTải cao, đĩa chậmNgữ cảnh có hạn collect_timeout. Bộ thu đĩa kiểm ngữ cảnh giữa các mountagent_collect_duration_seconds dưới collect_timeout. Ngoại lệ ở 8.3

3. Kiến trúc ứng dụng ​

3.1. Kiến trúc runtime ​

Engine chạy trong cùng tiến trình và cùng goroutine với vòng chu kỳ của Runtime Core (không có goroutine riêng cho bộ thu). Đây là quyết định ngầm của mã (xem D-06 ở L2 và ADR-C02 ở Phụ lục B).

mermaid
flowchart LR
  classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
  classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
  classDef datastore fill:#3a2d4a,stroke:#a06fd9,color:#fff

  RT["Runtime Core · vòng chu kỳ"]:::bc
  ENG["Engine · gom, chuẩn hóa, cắt"]:::bc
  CPU["Bộ thu CPU · tải và tốc độ"]:::bc
  MEM["Bộ thu bộ nhớ · RAM và swap"]:::bc
  DSK["Bộ thu đĩa · mount và statfs"]:::bc
  NET["Bộ thu mạng · tốc độ"]:::bc
  UPT["Bộ thu uptime · tiến trình"]:::bc
  SELF["Bộ thu tự thân · agent_*"]:::bc
  ST[("Thống kê · bộ đếm chung")]:::datastore
  OS(["Hệ điều hành · /proc, statfs"]):::owned

  RT -->|"yêu cầu thu một chu kỳ"| ENG
  ENG -->|"gọi tuần tự"| CPU & MEM & DSK & NET & UPT
  CPU & MEM & DSK & NET & UPT -->|"đọc số liệu thô"| OS
  ENG -->|"gọi sau cùng"| SELF
  SELF -->|"đọc RSS và CPU tiến trình"| OS
  ENG -.->|"ghi lỗi, thời lượng, số loại"| ST
  SELF -.->|"đọc bộ đếm chung"| ST

Chú giải: nét liền là lời gọi đồng bộ trong cùng tiến trình, nét đứt là truy cập trạng thái dùng chung trong bộ nhớ.

Bảng connector

ConnectorTừTớiCơ chếĐồng bộGhi chú
CN-1Runtime CoreEngineGọi hàm Collect(ctx, now)Đồng bộ, chặn vòng chu kỳKhông có goroutine riêng. Thời gian thu cộng vào chu kỳ
CN-2EngineBộ thuInterface CollectorĐồng bộ, tuần tự theo thứ tự cấu hình: cpu, memory, disk, net, uptimesafeCollect bọc recover
CN-3Bộ thuHệ điều hànhĐọc tệp qua fs.FS (os.DirFS("/proc")) và syscall.StatfsĐồng bộChỉ đọc. Có thể thay bằng fstest.MapFS khi kiểm thử
CN-4EngineBộ thu tự thânGiống CN-2Đồng bộ, chạy sau cắt seriesMiễn cắt series
CN-5Engine, Bộ thu tự thânThống kêatomic và sync.MutexĐồng bộCùng goroutine với Sender nên không tranh chấp thực tế, nhưng an toàn cho gọi đồng thời (Sender đọc Stats cùng luồng)

3.2. Kiến trúc module ​

mermaid
flowchart TB
  classDef pub fill:#1f3a5f,stroke:#4a90d9,color:#fff
  classDef intn fill:#3a3a3a,stroke:#888,color:#fff
  classDef ext fill:#3a3a3a,stroke:#888,color:#fff

  subgraph L1["Lớp lắp ráp: host"]
    HOST["NewEngine, NewEngineFS"]:::pub
  end
  subgraph L2["Lớp hiện thực: linux"]
    CTOR["Hàm dựng NewCPU, NewMemory, NewDisk, NewNet, NewUptime, NewSelf"]:::pub
    PARSE["procfs: bộ phân tích tệp /proc"]:::intn
    FILT["filter: lọc mount và giao diện"]:::intn
    HELP["helpers: tốc độ, chặn phần trăm"]:::intn
  end
  subgraph L3["Lớp hợp đồng: collector"]
    ENGN["Engine, EngineConfig, Result"]:::pub
    CONTRACT["Collector, Sample, SeriesKey"]:::pub
    CAT["Allowed: danh sách trắng"]:::pub
  end
  STATS(["stats, config, version"]):::ext

  HOST --> ENGN
  HOST --> CTOR
  HOST -.-> STATS
  CTOR --> PARSE & FILT & HELP
  CTOR --> CONTRACT
  ENGN --> CONTRACT
  ENGN --> CAT
  CTOR -.-> STATS

Chú giải: xanh dương là bề mặt công khai của gói, xám là nội bộ hoặc bên ngoài. Mũi tên liền là phụ thuộc biên dịch. Mũi tên đứt là phụ thuộc vào gói dùng chung. Không có phụ thuộc ngược từ collector sang linux (gói hợp đồng không biết gói hiện thực).

3.2.1. Cấu trúc: gói collector (Engine và hợp đồng) ​

Giao diệnNgười dùngHợp đồng
Collector (Name() string, Collect(ctx, now) ([]Sample, error))Engine, kiểm thửBộ thu trả mẫu gauge. Bộ thu tốc độ giữ trạng thái và không trả mẫu tốc độ lần đầu. Có thể trả cả mẫu lẫn lỗi (errors.Join), Engine giữ cả hai
Sample{Name, Labels, Value}Mọi bênMột giá trị gauge kèm nhãn
Engine.Collect(ctx, now) ResultRuntime Core, collect-onceKhông trả lỗi. Lỗi nằm trong Result.Errors[tên bộ thu]
EngineConfig{Collectors, Self, MaxSeries, Selection, StaticLabels, Timeout, Stats, Log}hostSelection (có thể nil) lọc chỉ số theo include, exclude. Self chạy cuối và được miễn cắt. Timeout bằng 0 nghĩa là không giới hạn
Allowed (map tên chỉ số tới danh sách nhãn)Engine, kiểm thửSinh từ internal/catalog, nguồn sự thật tên và nhãn phía Agent. Kiểm thử docs_sync_test.go giữ đồng bộ với docs/03, cần đồng bộ thêm với catalog của Collector
SeriesKey(name, labels), SortSamplesEngine, collect-onceKhóa ổn định theo tên và nhãn đã sắp xếp. Phân cách bằng byte 0xff

3.2.2. Cấu trúc: gói collector/linux (bộ thu Linux) ​

Thành phầnTệpNguồn dữ liệuTrạng thái giữa các lần gọi
cpuCollectorcpu.go/proc/stat, /proc/loadavgGiữ prev cpuTimes và cờ havePrev
memCollectormemory.go/proc/meminfoKhông
diskCollectordisk.go, filter.go/proc/self/mountinfo, statfs(2)Không (bộ lọc dựng sẵn)
netCollectornet.go/proc/net/devGiữ prev map[iface]counters và prevTime
uptimeCollectoruptime.go/proc/uptime, đếm thư mục số trong /procKhông
selfCollectorself.goStats, runtime.NumGoroutine, /proc/self/statm, /proc/self/statGiữ prevCPU, prevAt
Bộ phân tíchprocfs.goPhân tích stat, meminfo, mountinfo, net/dev, loadavgKhông
Bộ lọcfilter.goBộ lọc mount, fstype, giao diệnKhông
Tiện íchhelpers.goclampPercent, counterDelta, ratePerSecKhông
statfs_linux.go, statfs_other.gosyscall.Statfs. Ngoài Linux trả lỗi "statfs is only available on Linux"Không

Bộ thu Windows (ĐÃ XÂY MỘT PHẦN, AGT-7, ADR 0007): gói internal/collector/windows gồm cpu.go (GetSystemTimes), memory.go (GlobalMemoryStatusEx), disk.go (ổ có ký tự), net.go (GetIfTable2), uptime.go (GetTickCount64), self.go, ports.go (phân tích bảng TCP/UDP owner có giới hạn đọc). Logic chỉ thấy cấu trúc API (hàm thay được), lớp gọi hệ thống ở api_windows.go (thư viện chuẩn syscall, không x/sys), api_other.go trả lỗi ngoài Windows. host.NewEngineFS gọi NewEngineWindows khi chạy trên Windows, kiểm tra service và port nhận hàm từ API qua checks.Options.ServiceUp, PortListening. Không có tải trung bình trên Windows. Chưa chạy trên Windows thật.

3.2.3. Cấu trúc thành phần dùng chung: stats, config ​

Thành phầnVai trò với thành phần nàyGhi chú
internal/stats.StatsBộ đếm nguyên tử chia sẻ giữa Engine, Sender, WAL: SendFailures, DroppedSamples, WALBytes, WALBatches, RSSBytes và các giá trị ghi bằng setter (collectNanos, clockSkew, cpuPercent, collectorErrors theo sync.Mutex)Engine ghi ba giá trị của nó ở cuối phần chính, trước khi chạy bộ thu tự thân
internal/config.ConfigCấp Metrics, Limits.MaxSeries, CollectTimeout, Labels cho host.NewEngine. Cờ checks được phân tích nhưng không có bộ thu (L2 D-02)Đọc một lần khi dựng
internal/versionVersion, ProtoVersion cho agent_info

4. Domain model ​

mermaid
classDiagram
  namespace Vung_Thu_So_Lieu {
    class Engine {
      <<Aggregate Root>>
      +MaxSeries int
      +Timeout duration
      +StaticLabels map
    }
    class Collector {
      <<Entity>>
      +Name string
    }
    class RateBaseline {
      <<Entity>>
      +PrevCounters map
      +PrevTime time
    }
    class Sample {
      <<ValueObject>>
      +Name string
      +Labels map
      +Value float
    }
    class Result {
      <<ValueObject>>
      +Dropped int
      +Errors map
      +Duration duration
    }
    class MetricDef {
      <<ValueObject>>
      +Name string
      +AllowedLabels list
    }
  }
  Engine "1" *-- "1..*" Collector : chạy tuần tự
  Collector "1" o-- "0..1" RateBaseline : giữ
  Collector ..> Sample : tạo
  Engine ..> MetricDef : kiểm theo
  Engine ..> Result : trả về
  Result "1" *-- "0..*" Sample : chứa

Bất biến (invariants) của Aggregate Engine

MãBất biếnNơi bảo đảm
INV-1Mọi Sample trong Result.Samples có Name thuộc Allowed và mọi khóa nhãn thuộc danh sách của tên đósanitize
INV-2Không có nhãn company_id, server_id, agent_id trong mẫu phát ra (nhãn tĩnh cũng không thể đặt chúng)sanitize (reserved)
INV-3Giá trị mẫu là số hữu hạn (không NaN, không Inf)sanitize
INV-4Không có hai mẫu cùng SeriesKey trong một chu kỳsanitize (seen)
INV-5Giá trị nhãn không dài quá 128 byte và luôn là UTF-8 hợp lệtruncate
INV-6Số mẫu chính không vượt MaxSeries trừ min(16, MaxSeries/2) khi có bộ thu tự thân. Mẫu tự thân được nối sau khi cắt, nên tổng có thể tới MaxSeries cộng số mẫu tự thân dư (xem lưu ý dưới)Collect
INV-7Bộ thu tốc độ không phát mẫu tốc độ ở lần gọi đầu và khi bộ đếm đi lùi không hợp lệTừng bộ thu (cpu, net, self)

Lưu ý INV-6: các bộ thu chính bị cắt về MaxSeries - min(16, MaxSeries/2), bộ thu tự thân được nối sau. Bộ thu tự thân phát 8 series cố định (agent_goroutines, agent_wal_bytes, agent_wal_batches, agent_send_failures_total, agent_dropped_samples_total, agent_collect_duration_seconds, agent_clock_skew_seconds, agent_info), cộng agent_rss_bytes và agent_cpu_percent khi đọc được, cộng một series agent_collector_errors cho mỗi bộ thu chính đang lỗi (tối đa 5). Tối đa 15 series, nằm trong dự trữ 16. Đây là suy luận từ mã, TestSeriesLimitTrimsMainButKeepsSelf dùng bộ thu tự thân giả nên không khẳng định trực tiếp con số 15.


5. API Contract Specification ​

Thành phần này không có API mạng. Hợp đồng công khai của nó là interface Go trong tiến trình và lệnh CLI collect-once. Các mục 5.1 đến 5.5 được điền theo hình thức này (xem Phụ lục C).

5.1. Operations (Public API) ​

#Operation / Kênh EventLoại hìnhHướng gọi (Caller → BC)Ngữ nghĩa nghiệp vụ
1Engine.Collect(ctx, now) ResultLời gọi hàm đồng bộRuntime Core, CLI collect-once → EngineThu một chu kỳ, trả mẫu đã chuẩn hóa và cắt, số mẫu bị loại, lỗi theo bộ thu
2Collector.Collect(ctx, now) ([]Sample, error)Lời gọi hàm đồng bộEngine → Bộ thuĐọc một nguồn, trả mẫu thô. Engine chịu trách nhiệm chuẩn hóa
3Collector.Name() stringLời gọi hàmEngine → Bộ thuTên trong cấu hình (cpu, memory, disk, net, uptime, self), dùng làm khóa lỗi
4host.NewEngine(cfg, stats, log), host.NewEngineFS(..., proc fs.FS)Lời gọi hàmRuntime Core, CLI → hostDựng engine từ cấu hình hiệu lực. NewEngineFS cho phép tiêm /proc giả
5accesshub-agent collect-once [-gap d] [-config f] [-collector u] [-state-dir d] [-log-level l]CLI, in JSON ra stdoutQuản trị viên → CLIThu hai lần cách nhau -gap, in mẫu lần hai. Không gửi, không cần enroll
6Kênh sự kiện raKhông cóThành phần không phát sự kiện

5.2. Request / Response Schema ​

[Engine.Collect]

FieldKiểuGhi chú
Reqctxcontext.Context!Hủy hoặc quá hạn collect_timeout (Engine tự bọc)
Reqnowtime.Time!Thời điểm của chu kỳ, dùng tính tốc độ và boot_time_seconds
RespSamples[]Sample!Đã chuẩn hóa. Có thể rỗng. Chưa sắp xếp (dùng SortSamples khi cần)
RespDroppedint!Mẫu bị loại bởi chuẩn hóa, trùng, cắt series (không tính mẫu tự thân bị loại nếu có, xem lưu ý dưới bảng)
RespErrorsmap[string]error!Khóa là tên bộ thu. Kể cả self
RespDurationtime.Duration!Từ đầu đến khi xong các bộ thu chính (không gồm bộ thu tự thân)
Errors có thểKhông trả lỗi ra ngoài. Xem 5.3 cho lỗi trong Errors

Lưu ý: Duration và agent_collect_duration_seconds được đo trước khi chạy bộ thu tự thân. Errors["self"] được thêm sau khi ghi SetCollectorErrors, nên lỗi của bộ thu tự thân không xuất hiện ở agent_collector_errors (chỉ ở Result.Errors và log không có). Mẫu tự thân bị loại sau đó được cộng vào Result.Dropped nhưng không vào Stats.DroppedSamples. Đây là sai lệch nhỏ của mã (OQ-C4).

[Sample]

FieldKiểuGhi chú
ReqNamestring!Thuộc Allowed. Không tiền tố ah_
ReqValuefloat64!Hữu hạn
ReqLabelsmap[string]string?Khóa thuộc danh sách của chỉ số, giá trị tối đa 128 byte

[collect-once output]

FieldKiểuGhi chú
ResptimeRFC 3339 UTC!Thời điểm in
Respsamples[]{name, labels?, value}!Sắp xếp theo tên rồi khóa series
Respdroppedint!
Resperrorsmap[string]string?Có khi có bộ thu lỗi
Respdurationstring!Ví dụ 1.2ms
Errors có thểMã thoát 2 (-gap ngoài khoảng), 3 (cấu hình sai), 1 (dựng bộ thu lỗi, hoặc bị hủy)

Header và định danh người dùng cuối: không áp dụng (không có yêu cầu mạng, không có người dùng cuối).

Danh sách chỉ số đã phát (ĐÃ HIỆN THỰC) và chỉ đăng ký trong danh sách trắng (CHƯA PHÁT)

Trạng tháiTên chỉ số
Đã phát (Linux)cpu_usage_percent, cpu_mode_percent{mode}, cpu_load1, cpu_load5, cpu_load15, load_per_core_5m, cpu_cores, mem_total_bytes, mem_used_bytes, mem_available_bytes, mem_used_percent, mem_free_bytes, mem_cached_bytes, mem_buffers_bytes, mem_slab_bytes, mem_page_tables_bytes, swap_total_bytes, swap_used_bytes, swap_used_percent, swap_cached_bytes, disk_total_bytes{mount,fstype}, disk_used_bytes, disk_used_percent, disk_inodes_used_percent, net_rx_bytes_per_sec{iface}, net_tx_bytes_per_sec, net_rx_packets_per_sec, net_tx_packets_per_sec, net_rx_errors_per_sec, net_tx_errors_per_sec, net_rx_drops_per_sec, net_tx_drops_per_sec, uptime_seconds, boot_time_seconds, procs_total, psi_cpu_some_percent, psi_memory_some_percent, psi_io_some_percent, và 11 chỉ số agent_*
Chỉ có trong danh sách trắng, CHƯA XÂYdisk_read_bytes_per_sec, disk_write_bytes_per_sec, disk_io_util_percent (giai đoạn 2), open_fds_percent (giai đoạn 2), service_up, port_up, tcp_connect_up, tcp_connect_seconds, http_up, http_duration_seconds, http_status_code, cert_days_left (AGT-8)

5.3. Error Codes ​

Không có mã lỗi HTTP. Lỗi trả về trong Result.Errors là chuỗi Go, không có mã ổn định. Bảng dưới liệt kê các lỗi đặc thù để runbook nhận diện.

Mã lỗi (chuỗi)HTTP/gRPCĐiều kiện phát sinh
collector panic: <giá trị>Không áp dụngBộ thu panic, safeCollect bắt
meminfo: missing MemTotalKhông áp dụng/proc/meminfo không có MemTotal hợp lệ
stat: no aggregate cpu line, stat: cpu line has N columns, need at least 4, stat: bad cpu counter "..."Không áp dụng/proc/stat hỏng
uptime: bad value "...", uptime: empty fileKhông áp dụng/proc/uptime hỏng
self/statm: unexpected format, self/stat: no command field, self/stat: too few fields, self/stat: bad cpu fieldsKhông áp dụng/proc/self/* hỏng
disk: mount limit reached, extra mounts ignoredKhông áp dụngCó mount thứ 41 đủ điều kiện
statfs is only available on LinuxKhông áp dụngBộ thu đĩa chạy ngoài Linux (không đến được vì NewEngineFS không dựng bộ thu ngoài Linux)
Lỗi context deadline exceeded hoặc context canceledKhông áp dụngHết collect_timeout hoặc dừng agent giữa chừng khi thu đĩa
exclude_mounts "<biểu thức>": ..., net.include "...", net.exclude "..."Không áp dụngRegex không biên dịch được lúc dựng engine, host.NewEngine trả lỗi và agent không khởi động (build collectors: ...)
Lỗi từ statfs cho từng mountKhông áp dụngMount không đọc được. Các mount khác vẫn được thu

5.4. Versioning ​

Không có API mạng nên không có phiên bản API riêng. Điểm hợp đồng có phiên bản là danh mục chỉ số: Allowed phản ánh docs/03-metrics-catalog.md và catalog máy đọc được của Collector (internal/catalog/metrics.yaml theo docs/03, chưa được đối chiếu trong bản nháp này). Thêm chỉ số mới chỉ cần thêm vào Allowed và bộ thu, nhưng phải cập nhật catalog phía Collector trước, nếu không Collector sẽ loại mẫu (hành vi chính xác của Collector xem L2 Collector).

Sai lệch đã biết: docs/03 mô tả nhãn catalog_version của agent_info nhưng mã chỉ có version, proto, os (L2 D-03). Không có cơ chế dò lệch catalog lúc chạy. Gợi ý: kiểm bằng scripts/check-proto-drift.sh chỉ áp dụng cho proto, không cho catalog (ĐỀ XUẤT: thêm kiểm tra tương tự cho catalog).

5.5. Authz - shared responsibility & permission matrix ​

Không có lớp phân quyền ứng dụng: thành phần không nhận yêu cầu từ bên ngoài, chỉ được gọi từ trong tiến trình. Quyền truy cập dữ liệu là quyền hệ điều hành của tài khoản accesshub-agent.

Phân định trách nhiệm Auth

LớpAi sở hữuGồm
Nhận diện tiến trìnhHệ điều hành và systemdChạy dưới tài khoản accesshub-agent, không capability (L3 Service và Packaging)
Quyền đọc /proc, statfsHệ điều hànhMọi tiến trình đọc được /proc/stat, meminfo, net/dev, self/*. statfs cần quyền duyệt tới điểm mount. Unit có ProtectSystem=strict và ProtectProc (theo L2 mục 10.4, xem L3 Service và Packaging để biết thông số chính xác)
Kiểm soát nội dung thuThành phần nàyDanh sách trắng tên và nhãn, không đọc cmdline, không đọc nội dung tệp

Permission matrix

Public API (5.1)service-principaluser-role
Mọi thao tác 1 đến 4Chỉ mã trong cùng tiến trìnhKhông áp dụng
CLI collect-onceNgười dùng chạy lệnh (không cần root, không cần enroll)Không áp dụng, không có vai trò ứng dụng

6. Data Schema (Physical) ​

Thành phần không có cơ sở dữ liệu và không ghi đĩa. Trạng thái duy nhất là các biến trong bộ nhớ của từng bộ thu. Mục này được điền ở dạng thu gọn (Phụ lục C).

6.1. Cài đặt vật lý ​

Bảng ánh xạ

Phân hệ (3.2)Aggregate (4)CSDL (Store)Cấu trúc vật lý cốt lõi
collectorEngineKhông (bộ nhớ tiến trình)Struct Engine với cờ warnedTrim. Không có trạng thái giữa các chu kỳ ngoài cờ cảnh báo
collector/linux (cpu)RateBaselineBộ nhớ tiến trìnhprev cpuTimes, havePrev bool
collector/linux (net)RateBaselineBộ nhớ tiến trìnhprev map[string]netCounters, prevTime time.Time
collector/linux (self)RateBaselineBộ nhớ tiến trìnhprevCPU float64, prevAt time.Time, havePrev bool

Lược đồ (trạng thái trong bộ nhớ)

mermaid
classDiagram
  namespace Trang_Thai_Bo_Nho {
    class engineState {
      warnedTrim bool
    }
    class cpuState {
      prev cpuTimes
      havePrev bool
    }
    class cpuTimes {
      user uint64
      nice uint64
      system uint64
      idle uint64
      iowait uint64
      irq uint64
      softirq uint64
      steal uint64
    }
    class netState {
      prev map_iface_netCounters
      prevTime time
    }
    class netCounters {
      rxBytes uint64
      rxErrs uint64
      rxDrop uint64
      txBytes uint64
      txErrs uint64
      txDrop uint64
    }
    class selfState {
      prevCPU float64
      prevAt time
      havePrev bool
    }
  }
  cpuState *-- cpuTimes : giữ mẫu trước
  netState *-- netCounters : giữ mỗi giao diện

Ghi chú lược đồ: engineState và selfState không có quan hệ chứa. Không có khóa ngoại và không có tham chiếu chéo aggregate.

6.2. Phân loại dữ liệu & retention ​

Phần tử / Trường dữ liệuPhân lớp dữ liệuThời hạn lưu trữ (Retention)Cơ chế bảo vệ kỹ thuật
Bộ đếm mẫu trước (cpu, net, self)Nội bộChỉ trong đời tiến trình, mất khi khởi động lại (mẫu tốc độ đầu tiên bị bỏ sau mỗi lần khởi động, do đó có một chu kỳ khuyết)Chỉ ở RAM, không ghi đĩa
Mẫu trong ResultNội bộMột chu kỳ, sau đó chuyển cho Sender và vào WAL (xem L3 WAL và Sender)Không lưu ở thành phần này
Nhãn mount, ifaceNội bộNhư mẫuCắt 128 byte, danh sách trắng khóa nhãn

7. Thuật toán & Luồng nghiệp vụ ​

7.1. Luồng nghiệp vụ chính (Happy paths) ​

Luồng 1: Một chu kỳ thu (từ lần thứ hai trở đi)

mermaid
sequenceDiagram
  participant RT as Runtime Core
  participant EN as Engine
  participant BT as Bộ thu chính
  participant OS as Hệ điều hành
  participant ST as Thống kê
  participant SF as Bộ thu tự thân
  RT->>EN: Collect(ctx, now)
  loop mỗi bộ thu theo thứ tự
    EN->>BT: Collect(ctx, now)
    BT->>OS: đọc /proc hoặc statfs
    BT-->>EN: mẫu thô
  end
  EN->>EN: chuẩn hóa, loại trùng, cắt series
  EN->>ST: ghi lỗi, thời lượng, số mẫu loại
  EN->>SF: Collect(ctx, now)
  SF->>ST: đọc bộ đếm chung
  SF-->>EN: mẫu agent_*
  EN-->>RT: Result

Luồng 2: Lệnh collect-once

mermaid
sequenceDiagram
  participant OP as Quản trị viên
  participant CLI as collect-once
  participant EN as Engine
  OP->>CLI: collect-once -gap 1s
  CLI->>CLI: nạp cấu hình, URL giả nếu thiếu
  CLI->>EN: dựng engine, Stats rỗng, log bỏ
  CLI->>EN: Collect lần 1, bỏ kết quả
  CLI->>CLI: chờ -gap
  CLI->>EN: Collect lần 2
  EN-->>CLI: Result
  CLI-->>OP: JSON đã sắp xếp ra stdout

7.2. Luồng thay thế / lỗi (Alt / Error paths) ​

Luồng 3: Bộ thu lỗi hoặc panic

mermaid
sequenceDiagram
  participant EN as Engine
  participant BT as Bộ thu A
  participant BU as Bộ thu B
  participant ST as Thống kê
  EN->>BT: safeCollect
  BT--xEN: lỗi hoặc panic đã bắt
  EN->>EN: ghi Errors, log Warn "collector failed"
  EN->>BU: safeCollect (vẫn chạy)
  BU-->>EN: mẫu
  EN->>ST: agent_collector_errors A = 1

Bộ thu có thể trả cả mẫu lẫn lỗi (ví dụ đĩa có một mount lỗi), Engine giữ phần mẫu đã có.

Luồng 4: Hết hạn collect_timeout

mermaid
sequenceDiagram
  participant EN as Engine
  participant DK as Bộ thu đĩa
  participant NE as Bộ thu mạng
  EN->>EN: ctx có hạn collect_timeout chung
  EN->>DK: Collect(ctx)
  DK->>DK: kiểm ctx giữa các mount
  DK--xEN: mẫu đã có và lỗi ctx
  EN->>NE: Collect(ctx đã quá hạn)
  NE-->>EN: đọc /proc vẫn xong, không kiểm ctx
  EN->>EN: Result kèm lỗi, không hủy các bộ thu sau

Hạn là một hạn chung cho cả chu kỳ, không phải theo từng bộ thu. Bộ thu đọc tệp nhỏ trong /proc không kiểm ctx, nên chỉ bộ thu đĩa thực sự dừng sớm (xem 8.3 về statfs treo).

Luồng 5: Vượt giới hạn series

mermaid
sequenceDiagram
  participant EN as Engine
  participant LG as Log
  participant ST as Thống kê
  participant SF as Bộ thu tự thân
  EN->>EN: sau chuẩn hóa còn N mẫu chính
  EN->>EN: N lớn hơn giới hạn chính
  EN->>EN: cắt đuôi, cộng vào Dropped
  EN->>LG: Warn một lần, cờ warnedTrim
  EN->>ST: DroppedSamples cộng Dropped
  EN->>SF: chạy sau cắt, không bị cắt
  EN->>EN: N về dưới giới hạn thì xóa cờ warnedTrim

Thứ tự cắt là thứ tự bộ thu cấu hình rồi thứ tự phát của từng bộ thu, nên các bộ thu đứng sau (uptime) bị cắt trước. Không có ưu tiên theo mức quan trọng của chỉ số (OQ-C3).

7.3. State machines ​

Thực thể có vòng đời trạng thái đáng kể là đường cơ sở tốc độ (RateBaseline) của bộ thu CPU. Bộ thu mạng có trạng thái tương tự theo từng giao diện.

mermaid
stateDiagram-v2
  [*] --> KhongCoNen
  KhongCoNen --> CoNen : Collect [đọc được] / lưu bộ đếm, chỉ phát tải và số lõi
  CoNen --> CoNen : Collect [bộ đếm đi tiến, tổng khác 0] / phát tốc độ, cập nhật nền
  CoNen --> CoNen : Collect [bộ đếm đi lùi hoặc tổng bằng 0] / bỏ tốc độ, cập nhật nền, không báo lỗi
  CoNen --> CoNen : Collect [đọc lỗi] / giữ nền cũ, báo lỗi
PathĐường trên máy trạng thái
Khởi động, lần thu đầuKhongCoNen sang CoNen (Runtime Core chạy một lần thu mồi và bỏ kết quả, nên lần gửi đầu đã có tốc độ, xem L3 WAL và Sender)
Chu kỳ thườngCoNen sang CoNen phát tốc độ
Bộ đếm đi lùi (đặt lại, khởi động lại hạt nhân)CoNen sang CoNen không phát mẫu tốc độ và không trả lỗi (im lặng), nền vẫn được cập nhật
/proc/stat không đọc đượcGiữ nguyên, không đổi nền
Khởi động lại agentVề KhongCoNen, mất nền

Ghi chú: nền CPU được gán ngay sau khi đọc và phân tích thành công, trước cả khi tính hiệu (cpu.go, hàm rates), nên bộ đếm đi lùi chỉ làm khuyết đúng một chu kỳ. Khi /proc/stat đọc lỗi thì rates không được gọi và nền cũ được giữ. Chưa có kiểm thử riêng cho nhánh đọc lỗi liên tiếp (TestCPUMissingFilesReportError chỉ kiểm lỗi được báo). Với net, nhánh trạng thái thêm mức từng giao diện: giao diện mới xuất hiện vào lúc now không có nền nên bị bỏ qua đúng một chu kỳ, còn giao diện biến mất bị xóa khỏi nền.

7.4. Thuật toán cốt lõi ​

7.4.1. Chuẩn hóa mẫu và chặn cardinality ​

Vấn đề: bộ thu là mã hiện thực nhiều, dễ sai. Không được để một bộ thu lỗi làm tăng cardinality không giới hạn hoặc rò rỉ nhãn định danh đa tenant lên đường truyền.

Giải pháp: hàm sanitize chạy trên mọi mẫu, thứ tự kiểm cho từng mẫu: (1) tên phải thuộc Allowed, (2) giá trị không NaN và không Inf, (3) mỗi khóa nhãn phải hợp lệ theo regex ^[a-zA-Z_][a-zA-Z0-9_]*$, không thuộc tập dành riêng (company_id, server_id, agent_id) và thuộc danh sách nhãn cho phép của tên đó, (4) giá trị nhãn cắt 128 byte ở ranh giới UTF-8, (5) thêm nhãn tĩnh cấu hình trừ khi trùng khóa dành riêng hoặc mẫu đã có khóa đó, (6) loại mẫu có SeriesKey trùng mẫu đã giữ. Mẫu vi phạm (1) đến (3) bị loại cả mẫu, (4) chỉ cắt. Sau đó cắt đuôi về giới hạn (7.2 luồng 5).

Trade-off: loại cả mẫu thay vì bỏ nhãn sai giữ cho chuỗi thời gian nhất quán, nhưng che giấu lỗi ở bộ thu (chỉ thấy qua agent_dropped_samples_total). Regex khóa nhãn phía Agent rộng hơn quy tắc giao thức ^[a-z][a-z0-9_]{0,31}$, nhưng danh sách trắng là hàng rào thực sự nên không gây hại (OQ-C5). Cắt theo thứ tự xuất hiện đơn giản và xác định, nhưng không ưu tiên chỉ số quan trọng.

7.4.2. Tốc độ từ bộ đếm tích lũy ​

Vấn đề: /proc/net/dev và /proc/stat là bộ đếm tích lũy, cần tốc độ theo giây. Bộ đếm có thể quay vòng (32 bit ở nhân cũ) hoặc đặt lại (giao diện khởi tạo lại), và hai lần đọc có thể cách nhau bất thường.

Giải pháp: giữ nền là lần đọc trước và thời điểm. Tốc độ mạng dùng counterDelta(cur, prev): nếu cur >= prev thì hiệu thường, nếu không và prev <= MaxUint32 thì hiểu là quay vòng 32 bit và tính 2^32 - prev + cur, còn lại là đặt lại nên bỏ mẫu. ratePerSec trả không hợp lệ khi thời gian trôi bằng hoặc nhỏ hơn 0, hoặc tốc độ vượt 1e12 (ngưỡng chống số vô lý). CPU dùng diffCPU: bất kỳ bộ đếm đi lùi hoặc tổng bằng 0 thì bỏ mẫu, không báo lỗi (không phân biệt quay vòng vì bộ đếm CPU là 64 bit trên hạt nhân hiện đại).

Trade-off: giả định quay vòng khi prev nhỏ hơn hoặc bằng 2^32 có thể tính sai thành tốc độ lớn hơn thực tế nếu thực chất là đặt lại với prev nhỏ. Giới hạn 1e12 chỉ chặn trường hợp cực đoan. Tần suất thu dài (vài chục giây) làm tốc độ tức thời bị trung bình hóa, spike ngắn hơn chu kỳ không thấy được.

7.4.3. Chọn mount đĩa ​

Vấn đề: máy chủ hiện đại có rất nhiều mount ảo (tmpfs, overlay, /snap, container) không có giá trị giám sát, và cùng một thiết bị có thể được gắn nhiều lần (bind mount) gây trùng số liệu.

Giải pháp: phân tích /proc/self/mountinfo rồi lọc: bỏ mount trùng điểm gắn hoặc trùng majMin cộng fstype (giữ mount đầu tiên), áp bộ lọc fstype (mặc định bỏ nhóm ảo, chỉ thêm fs mạng khi include_network_fs), bỏ tiền tố /var/lib/docker, /var/lib/containers, /snap, /run, /sys, /proc, /dev. Nếu include_fstypes không rỗng thì thay bộ lọc mặc định. exclude_fstypes và exclude_mounts luôn áp dụng. Gọi statfs cho từng mount còn lại, bỏ mount có tổng bằng 0, dừng ở MaxMounts = 40. used = total - min(free, total) và used_percent = used / (used + avail) (cùng ngữ nghĩa df, không tính phần dành cho root). Phần trăm inode chỉ phát khi inodes > 0.

Trade-off: giới hạn 40 mount chọn theo thứ tự mountinfo nên mount thật đứng sau có thể bị bỏ sót nếu có nhiều mount hợp lệ, đổi lại chặn cardinality (mỗi mount 4 series). statfs là lời gọi hệ thống chặn, không hủy được bằng ctx, một NFS treo sẽ chặn cả vòng chu kỳ (8.3, OQ-C1).

7.4.4. Giới hạn giao diện mạng ​

Vấn đề: máy chủ container có hàng trăm cặp veth làm cardinality nổ.

Giải pháp: lọc bằng regex loại mặc định ^(lo|veth.*|docker.*|br-.*|virbr.*|cali.*|flannel.*|tunl.*|vxlan.*)$. net.include khác rỗng thì ghi đè mặc định, net.exclude luôn áp dụng. Sắp xếp tên tăng dần, giữ tối đa MaxInterfaces = 20, mỗi giao diện 8 series. Giao diện chưa có nền thì bỏ ở lần này.

Trade-off: cắt theo thứ tự chữ cái không phản ánh mức dùng thực tế, và giới hạn 20 giao diện không thông báo cho người vận hành khi có giao diện bị bỏ (không có log hay chỉ số cho việc cắt này).

7.4.5. Công thức CPU, bộ nhớ, uptime ​

Vấn đề: cần quy ước nhất quán, so sánh được với công cụ quen thuộc (top, free, df).

Giải pháp: cpu_usage_percent = 100 * (total - idle') / total, với idle' = idle + iowait khi include_iowait_in_usage là sai (mặc định), và idle' = idle khi đặt đúng. Các mode: user = user + nice, system = system + irq + softirq, iowait, steal (không phát idle và guest vì guest đã nằm trong user). load_per_core_5m = load5 / cores. Mọi phần trăm bị chặn về khoảng 0 đến 100. Bộ nhớ: used = total - available, nếu thiếu MemAvailable (nhân cũ) thì available = MemFree + Buffers + Cached. Swap: 0% khi không có swap. Uptime: boot_time_seconds = now.Unix() - uptime, procs_total đếm thư mục số trong /proc.

Mặc định iowait được xem là nhàn rỗi, đặt include_iowait_in_usage: true thì iowait tính vào mức dùng (cpu.go, biến iowaitAsBusy).

Trade-off: xem iowait là nhàn rỗi khớp top nhưng làm CPU trông thấp khi đĩa nghẽn, mà nghẽn này lại có chỉ số riêng (cpu_mode_percent{mode=iowait}).


8. Xử lý lỗi ​

8.1. Các nhánh lỗi ​

Bước lỗiNguyên nhânCơ chếTrạng thái cuối
Đọc tệp /procTệp thiếu hoặc quyềnBộ thu trả lỗi, không mẫuChỉ số nhóm đó khuyết trong chu kỳ, agent_collector_errors{collector} bằng 1
Phân tích định dạngNhân lạ, tệp hỏngTrả lỗi có mô tả (5.3)Như trên
Panic trong bộ thuLỗi lập trìnhsafeCollect bắt, thành lỗi collector panicNhư trên, các bộ thu khác vẫn chạy
Bộ đếm đi lùiKhởi động lại nhân, đặt lại giao diệnBỏ mẫu tốc độ chu kỳ đó, cập nhật nền. CPU không báo lỗi, mạng chỉ bỏ mẫu của giao diện đóKhuyết đúng một chu kỳ, không có dấu vết trong chỉ số lỗi
statfs lỗi một mountMount chết, quyềnGhi lỗi, các mount còn lại vẫn thuKhuyết chỉ mount đó
Vượt MaxMountsNhiều mount hợp lệLỗi mount limit reached và bỏ phần dưChỉ số đĩa không đủ mount
Vượt max_seriesCấu hình hoặc nhãn nổCắt đuôi, log một lầnagent_dropped_samples_total tăng
Hết collect_timeoutĐĩa chậmctx quá hạn, bộ thu đĩa dừng sớmMẫu đĩa thiếu, lỗi ghi nhận
Mẫu vi phạm danh mụcLỗi bộ thusanitize loạiDropped tăng

8.2. Fail-fast ​

Tình huốngHành viNơi kiểm
Regex exclude_mounts, net.include, net.exclude không biên dịchhost.NewEngine trả lỗi, agent thoát khi khởi động (build collectors: ...), collect-once thoát mã 1TestBadRegexFailsEngineBuild
collect_timeout ngoài 1 s đến 30 s hoặc không nhỏ hơn intervalNạp cấu hình thất bại (L3 Enroll, Credentials, Config)config.Validate
limits.max_series ngoài 1 đến 500Nạp cấu hình thất bạiconfig.Validate
Nền tảng không phải LinuxKhông thất bại: host.NewEngineFS ghi cảnh báo và dựng engine không có bộ thu và không có bộ thu tự thânhost.go

Sai lệch cần lưu ý: chú thích mã và L2 nói ngoài Linux agent "chỉ gửi chỉ số agent", nhưng engine ngoài Linux không có Self, nên chu kỳ không phát agent_* mà chỉ có AgentStats do Sender đính kèm vào gói (L2 D-13 và OQ-C7). Điều này không gây lỗi vì mã Windows chưa hỗ trợ.

8.3. Race conditions ​

Rủi roMô tảXử lý
statfs treo trên NFS hoặc thiết bị chếtLời gọi chặn trong nhân, ctx chỉ được kiểm giữa các mount, nên cả vòng chu kỳ và Sender đứng theo (cùng goroutine)Bảo vệ một phần: mặc định loại fs mạng, nên rủi ro chỉ khi bật include_network_fs hoặc đĩa cục bộ chết. Chưa có bulkhead theo bộ thu (OQ-C1, ADR-C02)
Đọc Stats từ SenderGiá trị bộ đếm nguyên tử và có mutex, không đọc ráchBảo đảm bởi stats
Hai engine cùng lúcKhông xảy ra, engine dựng một lần, gọi từ một goroutineKhông cần

9. Suy thoái dịch vụ & Khả năng phục hồi ​

9.1. Ma trận suy thoái ​

Dependency lỗiHành vi thành phầnKiểu suy thoáiHệ quả vận hành
Một tệp /proc không đọc đượcBộ thu tương ứng lỗi, còn lại chạySuy giảm từng phần (graceful degradation)Nhóm chỉ số khuyết, cảnh báo phía Collector qua agent_collector_errors
statfs chậm hoặc treoChặn vòng chu kỳ tới khi trả về, hoặc mãi mãiĐứng nghẽn (không suy giảm được)Thiếu gói dữ liệu, WAL không tăng, Collector coi là mất kết nối, cần restart agent
Hạt nhân thiếu MemAvailableDùng công thức thay thếSuy giảm chính xácSố bộ nhớ khả dụng ước lượng
Bộ thu Windows chưa kiểm trên máy thậtCấu trúc nhị phân sai bố cục đọc ra số rácCấu trúc có kiểm tra kích thước lúc biên dịch, cần chạy thử trên Windows 10, 11, ServerAGT-7 còn mở
Bộ nhớ agent cạnNgoài phạm vi thành phần nàyKhông xác địnhXem L2 mục 12

9.2. Backup, DR ​

Không áp dụng: thành phần không giữ dữ liệu bền. Mất trạng thái nền chỉ làm khuyết một chu kỳ tốc độ. RTO: một chu kỳ sau khi khởi động (giá trị đề xuất, vì Runtime Core thu mồi trước vòng lặp nên thực tế là tức thời cho chu kỳ gửi đầu). RPO: không áp dụng.


10. Đồng thời & Toàn vẹn dữ liệu ​

10.1. Ranh giới giao dịch ​

Không có giao dịch. Một lần Engine.Collect là một đơn vị nhất quán về phía bộ nhớ: kết quả gồm mẫu của một chu kỳ, và trạng thái nền chỉ được cập nhật bên trong lần gọi của từng bộ thu.

10.2. Cơ chế đồng thời ​

Cơ chếMô tảMối nguy
Thu tuần tự, một goroutineCác bộ thu chạy lần lượt trong vòng chu kỳ. Thời gian thu cộng thẳng vào chu kỳ nên chu kỳ thực là interval cộng thời gian thuMột bộ thu chậm làm trễ tất cả (8.3)
Không khóa trong bộ thuTrạng thái nền chỉ được một goroutine truy cậpSai nếu sau này song song hóa bộ thu (ĐỀ XUẤT: nếu thêm bulkhead thì phải thêm khóa)
Stats nguyên tử và mutexGhi từ Engine, Sender, WALKhông
Engine dựng một lầnKhông dựng lại khi SIGHUPĐổi metrics.*, max_series, collect_timeout, labels cần khởi động lại (L3 Enroll, Credentials, Config)

11. Bảo mật ​

11.1. Ba lớp bảo mật ​

LớpBiện pháp
Ranh giới tiến trìnhChỉ đọc /proc và statfs, không chạy lệnh ngoài, không mở cổng, không ghi đĩa
Nội dung thuDanh sách trắng tên và nhãn, không đọc cmdline, không đọc tên người dùng hay nội dung tệp
Ranh giới dữ liệuNhãn định danh đa tenant bị chặn ở gốc, nên tenant do Collector gắn từ khóa, không phải do agent khai

11.2. Pipeline authz ​

Không áp dụng năm bước authz ứng dụng vì không có yêu cầu từ ngoài. Các bước tương đương ở tầng tiến trình: xác thực hệ điều hành (chạy với tài khoản riêng), giới hạn hệ thống tệp của unit systemd, danh sách trắng nội dung. Chi tiết cách ly ở L3 Service và Packaging.

11.3. Neo zero-trust ​

Nguyên tắc (L2 mục 6)Biện pháp
Không tin nhãn từ agentcompany_id, server_id, agent_id bị loại ở sanitize, kể cả từ nhãn tĩnh
Tối thiểu đặc quyềnKhông cần root, không cần capability để đọc /proc và statfs
Không rò rỉ bí mậtKhông thu biến môi trường, đối số dòng lệnh, hay tên tiến trình. logx che bí mật trong log lỗi bộ thu
Giảm bề mặt tấn côngKhông phụ thuộc thư viện ngoài để phân tích /proc, đầu vào phân tích được kiểm bằng bảng kiểm thử (TestParsers) và fixture thật. Gói linux chưa có fuzz test (ĐỀ XUẤT, OQ-C8)

12. Cấu hình & Tinh chỉnh ​

12.1. Tunables ​

Tất cả tham số dưới đây chỉ được đọc khi dựng engine lúc khởi động (agent.Run gọi newEngine một lần). SIGHUP nạp lại tệp cấu hình cục bộ nhưng không dựng lại engine, nên mọi thay đổi ở bảng này cần khởi động lại dịch vụ.

Tham sốMặc địnhÝ nghĩaMục liên quan
collect_timeout5 s (1 s đến 30 s, phải nhỏ hơn interval)Hạn chung cho một chu kỳ thu7.2 luồng 4, NFR-C04
limits.max_series500 (1 đến 500, trần cứng HardMaxSeries)Trần số series mỗi gói. Trừ dự trữ tự thân min(16, max_series/2) khi cắt7.4.1, NFR-C02
labelsrỗng (tối đa 20 nhãn, giá trị tối đa 128 byte)Nhãn tĩnh đính vào mọi mẫu. Không thể đặt nhãn dành riêng7.4.1
metrics.cpu.enabledtrueBật bộ thu CPUFR-C02
metrics.cpu.include_iowait_in_usagefalseTính iowait vào cpu_usage_percent7.4.5
metrics.memory.enabledtrueBật bộ thu bộ nhớFR-C03
metrics.uptime.enabledtrueBật bộ thu uptimeFR-C06
metrics.pressure.enabledtrueBật bộ thu áp lực PSI (Linux, bỏ qua lặng lẽ nếu kernel không có /proc/pressure)FR-C07
metrics.includerỗngTên hoặc glob, khác rỗng thì chỉ lấy chỉ số khớp (cộng chỉ số bắt buộc). Mẫu không khớp gì là lỗi cấu hìnhADR 0006
metrics.excluderỗngTên hoặc glob loại chỉ số, thắng include. Không loại được chỉ số bắt buộc (nhóm agent), chỉ cảnh báoADR 0006
metrics.disk.enabledtrueBật bộ thu đĩaFR-C04
metrics.disk.include_fstypesrỗngKhác rỗng thì thay bộ lọc fstype mặc định7.4.3
metrics.disk.exclude_fstypesrỗngLoại thêm fstype (luôn áp dụng)7.4.3
metrics.disk.exclude_mountsrỗngRegex RE2 loại điểm gắn (luôn áp dụng)7.4.3
metrics.disk.include_network_fsfalseCho phép nfs, cifs, ceph... (kéo theo rủi ro statfs treo)7.4.3, 8.3
metrics.net.enabledtrueBật bộ thu mạngFR-C05
metrics.net.includerỗngRegex, khác rỗng thì ghi đè bộ loại mặc định7.4.4
metrics.net.excluderỗngRegex loại giao diện (luôn áp dụng)7.4.4

Hằng số biên dịch (không cấu hình được)

HằngGiá trịVai trò
MaxMounts40Số mount tối đa mỗi chu kỳ
MaxInterfaces20Số giao diện tối đa mỗi chu kỳ
SelfReserve16Chỗ dự trữ cho chỉ số tự thân
MaxLabelValueBytes128Độ dài tối đa giá trị nhãn
maxRatePerSec1e12Ngưỡng chống tốc độ vô lý

Các giá trị metrics.* được nạp từ tệp agent.yaml theo thứ tự ưu tiên của cấu hình (L3 Enroll, Credentials, Config, nơi ghi rõ khóa nào có biến môi trường AH_* tương ứng). Cấu hình từ xa (AGT-10) chưa có nên không có tham số nào đổi được lúc chạy.

12.2. Feature flags ​

Không có cờ tính năng. Tương đương duy nhất là các cờ enabled theo từng bộ thu ở 12.1. Cờ checks.* được phân tích nhưng chưa có bộ thu tương ứng (L2 D-02), bật cờ này không có hiệu ứng.


13. Telemetry & Vận hành ​

13.1. Metrics ​

Tất cả chỉ số của thành phần này là gauge do bộ thu tự thân phát vào chính luồng dữ liệu gửi đi, không có endpoint /metrics riêng. Các giá trị dạng _total được phát dưới dạng gauge chứa tổng tích lũy, phía Collector xử lý như bộ đếm.

TênKiểuNhãnNgữ nghĩa
agent_goroutinesgaugekhôngSố goroutine của tiến trình
agent_rss_bytesgaugekhôngRSS của tiến trình (self/statm nhân kích thước trang). Chỉ phát khi đọc được
agent_cpu_percentgaugekhôngCPU tiến trình (utime cộng stime chia thời gian thực, clockTicks 100). Không có ở lần đầu
agent_wal_bytesgaugekhôngByte WAL trên đĩa (do WAL cập nhật)
agent_wal_batchesgaugekhôngSố gói trong WAL
agent_send_failures_totalgaugekhôngTổng số lần gửi thất bại từ khi khởi động
agent_dropped_samples_totalgaugekhôngTổng mẫu bị Engine loại và điểm của gói bị bỏ. Không đếm việc WAL đầy loại gói cũ (L2 D-10)
agent_collect_duration_secondsgaugekhôngThời lượng thu chính của chu kỳ gần nhất (không gồm bộ thu tự thân). Chỉ số của NFR-C04
agent_collector_errorsgaugecollector1 cho mỗi bộ thu lỗi ở chu kỳ gần nhất. Không gồm lỗi của chính self
agent_clock_skew_secondsgaugekhôngLệch đồng hồ so với Collector (do Sender cập nhật)
agent_infogaugeversion, proto, osLuôn bằng 1. Chưa có nhãn catalog_version (L2 D-03)

13.2. Log schema (JSON) ​

Log dùng slog qua logx (định dạng json hoặc text, bộ che bí mật maskingHandler, xoay tệp 10 MB giữ 1 bản sao). Trường chung: time, level, msg. Các sự kiện của thành phần này:

Sự kiện (msg)MứcTrường thêmKhi nào
collector failedWarncollector, errMỗi lần một bộ thu trả lỗi hoặc panic
series limit reached, dropping the restWarnmax_seriesLần đầu vượt trần, im lặng tới khi trở lại dưới ngưỡng
Cảnh báo nền tảng không hỗ trợWarn(theo mã host.go)Dựng engine ngoài Linux
(không có log)Giao diện bị cắt ở 20, mount bị cắt ở 40 (chỉ lỗi trong Result.Errors, không log), lỗi của self

Trong collect-once, log của engine bị bỏ (slog.DiscardHandler), nên các cảnh báo trên không hiện. Người vận hành chỉ thấy trường errors trong JSON.

13.3. Alert to runbook ​

Thành phần không tự phát cảnh báo. Các điều kiện dưới đây do Collector đánh giá trên chỉ số tự thân (ĐỀ XUẤT, phụ thuộc bộ luật cảnh báo của Collector).

Điều kiện (đề xuất)Runbook
agent_collector_errors{collector} bằng 1 kéo dài nhiều chu kỳXem log collector failed, kiểm tra /proc và quyền. Chạy accesshub-agent collect-once để xem trường errors
agent_dropped_samples_total tăng liên tụcChạy collect-once, xem mẫu bị loại. Kiểm max_series, nhãn tĩnh, bộ lọc
agent_collect_duration_seconds gần collect_timeoutKiểm đĩa và mount (NFS?), xem 8.3. Cân nhắc tắt include_network_fs
Không có gói dữ liệu từ máyNghi statfs treo hoặc tiến trình đứng. Xem L3 WAL và Sender và L3 Service và Packaging

13.4. Probes ​

Không có probe riêng. Tính sống của vòng thu được suy ra ở phía Collector từ việc gói dữ liệu đến đều đặn. Không có health endpoint cục bộ trong phạm vi hiện tại (lệnh status thuộc AGT-10, chưa xây).

13.5. Trace propagation ​

Không áp dụng. Không có trace. Mã tương quan duy nhất là agent_id do Sender gắn ở tầng truyền tải.


14. Kế hoạch kiểm thử ​

Loại Test & Phạm viÁnh xạ mục tiêuMục tiêu kỹ thuậtVí dụ kịch bản (Test ID)
Unit: bộ phân tích và công thức, fixture thậtAC-C01 đến C10, NFR-C07Đúng số học trên /proc mẫu của Ubuntu 24.04 và kernel 2.6.32TestCPURatesFromDeltas, TestMemory, TestDiskRealHostFixture, TestParsers, TestCounterDelta
Unit: EngineAC-C12 đến C15, NFR-C02, NFR-C03, NFR-C05Chuẩn hóa, cắt, cách ly lỗi, hạn thời gianTestSanitizeDropsInvalidSamples, TestEngineIsolatesFailingAndPanickingCollectors, TestSeriesLimitTrimsMainButKeepsSelf, TestEngineTimeoutIsAppliedToContext, TestSeriesKeyIsStableAndDistinct
Unit: hợp đồng danh mụcAC-C16, NFR-C05Mọi chỉ số phát ra nằm trong AllowedTestCatalogConformance
Tích hợp cục bộAC-C17, AC-C18Lắp ráp engine từ cấu hình, chạy trên /proc thậtTestEngineHonorsCollectorToggles, TestBadRegexFailsEngineBuild, TestRealProcSmoke
CLIAC-C19Đầu ra JSON, từ chối tham số saiTestCollectOncePrintsJSON, TestCollectOnceRejectsBadGapAndConfig
Bảo mật logNFR-C06Bí mật không lọt vào log của bộ thuTestLoggerNeverLeaksSecrets, TestMaskFreeText
Chưa có: fuzz bộ phân tích /procNFR-C01, NFR-C03Không panic với tệp /proc méoĐỀ XUẤT: FuzzParseNetDev, FuzzParseMountinfo (OQ-C8)
Chưa có: đo CPU và RAM của vòng thuNFR-C01Kiểm chứng ngân sách (L2 D-16)ĐỀ XUẤT: benchmark một chu kỳ trên máy có 40 mount
Chưa có: statfs treoNFR-C04Mô phỏng bộ thu chặn để đo tác động lên chu kỳĐỀ XUẤT, phụ thuộc quyết định OQ-C1
Chưa có: dò lệch danh mục với CollectorNFR-C05Allowed khớp catalog phía CollectorĐỀ XUẤT: kiểm tra chéo trong CI

15. Trình tự triển khai ​

15.1. Ma trận milestone ​

MilestoneNội dungPhụ thuộcĐóng góp nghiệm thu
M1Hợp đồng Collector, Engine, danh sách trắng, bộ thu Linux (cpu, memory, disk, net, uptime, self), collect-once, host (AGT-3). ĐÃ HIỆN THỰCKhôngAC-C01 đến C19
M2Khép các nợ sai lệch: catalog_version trong agent_info (D-03), đếm lỗi của self, đếm việc cắt giao diện và mount, ưu tiên khi cắt series. ĐỀ XUẤTM1 và quyết định catalog phía CollectorAC mới (chưa có)
M3Chỉ số đĩa I/O, open_fds_percent (giai đoạn 2 của catalog). THIẾT KẾ CHƯA XÂYM1Chưa có AC
M4Bộ thu kiểm tra dịch vụ, cổng, TCP, HTTP, hạn chứng chỉ (AGT-8). ĐÃ XÂY 2026-10-02M1internal/collector/checks/checks_test.go, TestChecksRunThroughTheEngine, TestMergeCentralChecks
M5Bộ thu Windows bằng API trực tiếp theo ADR 0007 (AGT-7). ĐÃ XÂY, chưa chạy trên Windows thật. PDH cho I/O đĩa còn lạiM1Chưa có AC
M6Kiểm kê phần cứng và hệ điều hành (AGT-9). ĐÃ XÂY 2026-10-01M1TestReadHostFactsFromFixture, TestParseCPUInfoVariants, internal/inventory

Ghi chú: M4 cần trước đó có cơ chế cô lập theo bộ thu (chạy song song có hạn riêng), vì các phép kiểm tra mạng có thể chặn. Đây là quyết định thiết kế ở OQ-C1 và ADR-C02.

15.2. Sơ đồ phụ thuộc milestone ​

mermaid
flowchart LR
  M1["M1 · Engine và bộ thu Linux"]
  M2["M2 · Khép nợ sai lệch"]
  M3["M3 · Đĩa I/O, fds"]
  M4["M4 · Checks AGT-8"]
  M5["M5 · Windows AGT-7"]
  M6["M6 · Kiểm kê AGT-9"]
  M1 --> M2 --> M4
  M1 --> M3
  M1 --> M5
  M1 --> M6
  style M1 fill:#2d4a3e,stroke:#5fb37a,color:#fff
  style M2 fill:#3a3320,stroke:#d9b84a,color:#fff
  style M3 fill:#444,stroke:#aaa,color:#fff
  style M4 fill:#444,stroke:#aaa,color:#fff
  style M5 fill:#444,stroke:#aaa,color:#fff
  style M6 fill:#444,stroke:#aaa,color:#fff

Chú giải: xanh lá là đã hiện thực, vàng là đề xuất, xám là thiết kế chưa xây. Đường găng tới checks: M1, M2, M4.


Phụ lục A: Open Questions ​

#Câu hỏiHành vi tạm thờiOwnerMã theo dõi
OQ-C1statfs treo (NFS, đĩa chết) chặn cả vòng chu kỳ. Có cần chạy bộ thu đĩa trong goroutine riêng có hạn riêng, hay chấp nhận và chỉ khuyến cáo không bật include_network_fs?Chấp nhận, mặc định loại fs mạngchưa chỉ địnhL3-COL-OQ1
OQ-C2Trong container, /proc phản ánh máy chủ hay cgroup? Agent có cần biết giới hạn cgroup không?Agent thu theo /proc của môi trường chạy, chưa xử lý cgroup. Mô hình triển khai chính là máy ảo hoặc máy vật lýchưa chỉ địnhL3-COL-OQ2
OQ-C3Thứ tự cắt series hiện theo thứ tự bộ thu, uptime bị cắt trước. Có cần ưu tiên chỉ số quan trọng (cpu, mem, disk used) không?Cắt đuôi theo thứ tự cấu hình. Thực tế ít xảy ra vì trần 500 lớn hơn mức dùng thông thườngchưa chỉ địnhL3-COL-OQ3
OQ-C4Lỗi của bộ thu tự thân và mẫu tự thân bị loại không vào agent_collector_errors và agent_dropped_samples_total. Có sửa không?Không sửa. Chỉ thấy trong Result.Errorschưa chỉ địnhL3-COL-OQ4
OQ-C5Regex khóa nhãn của Agent (^[a-zA-Z_]...) rộng hơn giao thức (^[a-z][a-z0-9_]{0,31}$). Có siết cho khớp không?Giữ nguyên. Danh sách trắng nhãn là hàng rào thực sựchưa chỉ địnhL3-COL-OQ5
OQ-C6Cấu hình bộ thu không đổi lúc chạy (SIGHUP không dựng lại engine). Có cần dựng lại engine an toàn khi SIGHUP không?Cần khởi động lại để đổi metrics.*, max_series, collect_timeout, labelschưa chỉ địnhL3-COL-OQ6
OQ-C7Ngoài Linux, engine không có Self nên không phát agent_* trong chu kỳ, mâu thuẫn với chú thích mã ("chỉ gửi chỉ số agent"). Sửa mã hay sửa chú thích?Chưa ảnh hưởng vì Windows chưa hỗ trợchưa chỉ địnhL3-COL-OQ7
OQ-C8Có thêm fuzz test cho bộ phân tích /proc (giống FuzzWALScanRecords, FuzzLoadNeverPanics) không?Chỉ có bảng kiểm thử và fixturechưa chỉ địnhL3-COL-OQ8
OQ-C9Giả định bộ đếm mạng dưới 2^32 là quay vòng 32 bit có thể sinh tốc độ lớn giả khi thực ra là đặt lại. Chấp nhận hay bỏ hẳn?Chấp nhận, có chặn 1e12chưa chỉ địnhL3-COL-OQ9

Phụ lục B: ADR nội bộ ​

Mã ADRQuyết địnhTrạng tháiĐộng lực
ADR-C01Danh sách trắng tên chỉ số và nhãn đặt trong Agent (Allowed), không chỉ ở CollectorĐã hiện thựcChặn cardinality và nhãn định danh tenant ngay từ nguồn. Đánh đổi: hai nơi phải đồng bộ (OQ-C5, mục 5.4)
ADR-C02Thu tuần tự trong goroutine của vòng chu kỳ, dưới một hạn collect_timeout chung, không có bulkhead theo bộ thuĐã hiện thựcĐơn giản, xác định, ít tài nguyên. Đánh đổi: statfs treo chặn tất cả (OQ-C1). Sẽ xem lại trước khi làm AGT-8
ADR-C03Chỉ phát gauge. Tốc độ được tính ở Agent từ hai lần đọc bộ đếmĐã hiện thựcGiao thức chỉ có gauge, Collector không cần trạng thái bộ đếm. Đánh đổi: mất một chu kỳ sau mỗi lần khởi động
ADR-C04Loại cả mẫu khi vi phạm danh mục thay vì bỏ nhãn vi phạmĐã hiện thựcGiữ chuỗi thời gian nhất quán, tránh tạo series mới ngầm. Đánh đổi: che khuất lỗi bộ thu, chỉ thấy qua bộ đếm loại
ADR-C05Chỉ số tự thân chạy sau cắt và có dự trữ 16 seriesĐã hiện thựcBảo đảm quan sát được sức khỏe agent khi cardinality vượt trần
ADR-C06Windows dùng PDH với PdhAddEnglishCounter, hai mẫu cho tốc độĐã chấp nhận, cần xác nhận ở spike S1 (ADR 0004 của repo)Không CGO, tên bộ đếm độc lập ngôn ngữ. Chưa xây

Phụ lục C: Section Profile ​

Phân mụcHồ sơ quy chuẩnTrạng thái điềnGiải trình
§0 Metadata & Sign-offBắt buộcĐã điềnNgười ký để "chưa chỉ định"
§1 ScopeBắt buộcĐã điền
§2 Yêu cầuBắt buộcĐã điền
§3 Kiến trúcBắt buộcĐã điền
§4 Domain modelBắt buộcĐã điền
§5 API contractBắt buộcĐiền thu gọnKhông có API mạng. Hợp đồng là interface Go và CLI
§6 Data schemaTùy chọnĐiền thu gọnKhông có CSDL. Chỉ trạng thái trong bộ nhớ
§7 Thuật toánBắt buộcĐã điền
§8 Xử lý lỗiBắt buộcĐã điền
§9 Suy thoáiBắt buộcĐiền thu gọn9.2 không áp dụng (không dữ liệu bền)
§10 Đồng thờiBắt buộcĐiền thu gọnKhông có giao dịch
§11 Bảo mậtBắt buộcĐiền thu gọn11.2 không áp dụng (không có yêu cầu ngoài)
§12 Cấu hìnhBắt buộcĐã điềnKhông có feature flag
§13 TelemetryBắt buộcĐiền thu gọnKhông có probe, không có trace
§14 Kiểm thửBắt buộcĐã điềnCó 4 khoảng trống đề xuất
§15 Triển khaiBổ sungĐã điền
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-agent lúc 10:57, 03/10/2026. Khi tài liệu và mã khác nhau, mã thắng.