Một binary Go, một file YAML, một database SQLite: Tôi đã tự viết công cụ giám sát của riêng mình

25 tháng 8, 2026·5 phút đọc

Tác giả chia sẻ hành trình tự xây dựng Gjallar, một công cụ giám sát hạ tầng nhẹ nhàng chỉ với một binary Go tĩnh, một file cấu hình YAML và một database SQLite. Bài viết nhấn mạnh thiết kế tối giản, không CGO, pipeline thông báo không khóa (lock-free) và triết lý 'tránh biến công cụ thành nền tảng' để dễ vận hành lâu dài.

Một binary Go, một file YAML, một database SQLite: Tôi đã tự viết công cụ giám sát của riêng mình

Trong bối cảnh các hệ thống giám sát hiện đại thường cồng kềnh với hàng tá thành phần, một kỹ sư đã quyết định đi ngược xu hướng khi tự tay xây dựng Gjallar – một công cụ giám sát tối giản nhưng đầy đủ tính năng. Toàn bộ hệ thống chỉ gồm một binary Go tĩnh (khoảng 36 MB), một file YAML cấu hình và một file SQLite lưu trữ, giúp việc triển khai và vận hành trở nên cực kỳ đơn giản.

Tác giả cần theo dõi một loạt dịch vụ không đồng nhất: HTTP endpoints, PostgreSQL, vài instance Oracle, Redis, chỉ số Elasticsearch, máy chủ ping được và một số metrics Prometheus – đồng thời nhận thông báo qua Telegram, SMS và Signal. Thay vì triển khai một hệ thống giám sát phân tán thứ hai chỉ để biết hệ thống thứ nhất còn sống hay không, anh đã viết Gjallar với khoảng 3.400 dòng Go, MIT license.

Không CGO – Lựa chọn có chủ đích

Điểm mấu chốt giúp Gjallar trở thành một binary độc lập hoàn toàn là việc xây dựng với CGO_ENABLED=0. Điều này khả thi nhờ các thư viện pure-Go thay thế cho mọi dependency truyền thống ràng buộc với thư viện C:

  • pgx cho PostgreSQL – không cần libpq
  • go-ora cho Oracle – không cần Oracle Instant Client, đây chính là lý do chính khiến dự án ra đời
  • pro-bing cho ICMP echo, hỗ trợ cả privileged lẫn unprivileged
  • modernc.org/sqlite – SQLite được transpile sang Go thuần túy, không cần libsqlite3
  • Redis không cần driver nào – check giao tiếp trực tiếp qua protocol: TCP connect, AUTH tùy chọn, PING và chờ +PONG

Kết quả là một binary tự chứa (self-contained), có thể cross-compile từ laptop sang bất kỳ target nào với GOOS/GOARCH và triển khai chỉ bằng scp. Không Docker, không package manager, không shared libraries, không có chuyện "chạy được trên máy của tôi".

Pipeline thông báo không khóa (lock-free)

Các công cụ giám sát thường có tính đồng thời cao – mỗi monitor chờ network phần lớn thời gian – và đây cũng là nơi các side project thường bắt đầu mọc "rừng mutex". Gjallar không có bất kỳ lock nào quanh state của nó nhờ cách thiết kế pipeline:

một goroutine cho mỗi monitor ──▶ channel kết quả ──▶ một consumer duy nhất
                                (state machine + ghi SQLite)

Mỗi monitor chạy vòng kiểm tra trong goroutine riêng và gửi check.Result vào một channel dùng chung. Một consumer goroutine duy nhất sở hữu toàn bộ phần downstream: state machine up/down, incident rows và lịch sử ghi. Vì chỉ một goroutine chạm vào state map và database connection nên không có gì để lock – và SQLite (vốn không thích writer đồng thời) chỉ nhận đúng một writer.

State của mỗi monitor được thiết kế nhỏ và rõ ràng:

type monitorState struct {
    down         bool
    consecFails  int
    downSince    time.Time
    lastNotified time.Time
    threshold    int           // số lần fail liên tiếp trước khi bắn DOWN
    realert      time.Duration // khoảng nhắc lại khi down; 0 = tắt
    notifiers    []string
}

Hai điểm thiết kế đã chứng minh giá trị trong production:

  • State sống sót qua restart: khi khởi động, state của mỗi monitor được seed từ incident đang mở trong SQLite. Restart trong lúc sự cố đang diễn ra không bắn lại alert DOWN cũng như không bỏ lỡ thông báo recovery.
  • Thông báo bất đồng bộ: consumer không bao giờ được block – một SMTP server chậm hoặc Telegram API bị rate-limit không thể tạo back-pressure lên toàn pipeline.

Alert chỉ bắn sau N lần fail liên tiếp, không phải ở lần đầu tiên, tránh nhiễu loạn (flapping noise), kèm tùy chọn realert interval để nhắc nhở trong suốt thời gian incident còn mở.

Cấu hình tôn trọng vận hành

Mọi thứ nằm trong một file YAML duy nhất, có defaults, named notifiers và monitor groups:

defaults:
  interval: 60s
  timeout: 10s
  failure_threshold: 3
  alerts: [ops-telegram]

alerts:
  ops-telegram:
    url: "telegram://TOKEN@telegram?chats=123456789"

monitors:
  - name: app-db
    type: postgres
    dsn: "postgres://monitor:${PG_PASSWORD}@db1:5432/app"
    query: "SELECT count(*) FROM jobs WHERE status = 'stuck'"
    rule: "== 0"

Ba tính năng nhỏ giúp việc vận hành trở nên dễ chịu:

  • Hot reload qua SIGHUP: systemctl reload gjallar áp dụng config mới nhưng chỉ sau khi đã validate đầy đủ. Một YAML lỗi sẽ giữ nguyên cấu hình đang chạy và log lỗi, thay vì kéo theo hệ thống giám sát sụp đổ.
  • Khai triển biến môi trường ${VAR} cho secrets, kèm thông báo lỗi rõ ràng khi biến không tồn tại – còn dấu $ đơn (ví dụ trong regex ~ ^OPEN$) được giữ nguyên.
  • Flag -check để dry-run validation, cho phép CI lint config trước khi nó lên server.

Điều mà công cụ này cố tình không làm

Không clustering, không agents, không plugin system, không time-series dashboards, không user accounts. Lịch sử được dọn sau một khoảng retention cấu hình được (mặc định 30 ngày) để file SQLite luôn nhỏ. Khi một nhu cầu được phục vụ tốt bởi cơ chế đơn giản có sẵn – như systemd cho vòng đời service, hay shoutrrr URLs cho các dịch vụ thông báo – Gjallar chọn ủy quyền thay vì viết lại.

Đây là phần tác giả bảo vệ quyết liệt nhất: "Mọi công cụ giám sát tôi từng bỏ rơi đều chết vì cùng một căn bệnh – nó dần trở thành một nền tảng, và đến một ngày, bản thân việc giám sát lại cần được giám sát."

Một công cụ mà toàn bộ state nằm gọn trong một file SQLite và toàn bộ hành vi nằm trong một file YAML là công cụ bạn vẫn hiểu lúc 3 giờ sáng, 18 tháng sau khi viết nó.

Mã nguồn và tài liệu: github.com/brvier/Gjallar

Bài viết này đặc biệt hữu ích cho các kỹ sư DevOps và SRE tại Việt Nam – những người thường xuyên phải cân nhắc giữa việc triển khai một stack giám sát đầy đủ (Prometheus + Grafana + Alertmanager) hay một giải pháp nhẹ nhàng hơn cho các hệ thống quy mô vừa và nhỏ, nơi chi phí vận hành hạ tầng giám sát đôi khi còn lớn hơn chính hệ thống cần được theo dõi.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗