
2026/08/26 6:43
Go バイナリ、YAML ファイル、SQLite データベース:監視ツールを作成しました
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Gjallar は、Go で記述された自己完結型で KISS(Keep It Simple, Stupid)な監視サービスです(約 3,400 行、MIT ライセンス)。HTTP エンドポイント、PostgreSQL、Oracle、Redis、Elasticsearch、ICMP ping、Prometheus メトリクスなどの多様なサービスを追跡します。CGO_ENABLED=0 の設定および純粋な Go 製置き換え(PostgreSQL: pgx、Oracle: go-ora、ICMP: pro-bing、ストレージ: modernc.org/sqlite、Redis: 直接の TCP プロトコル実装)により、クロスコンパイル可能(GOOS/GOARCH フラグ使用)、scp を介して展開でき、Docker、パッケージマネージャー、共有ライブラリ、外部依存関係は不要となる単一静的バイナリ(約 36 MB)が構築されます。
ロックフリーなアーキテクチャにより、各モニターは独自の goroutine で実行され、結果をチャンネルを通じて、状態管理、SQLite の書き込み処理、アップ/ダウンの状態機械を維持する単一の goroutine が消費します。モニターの状態(ダウンステータス、連続失敗回数、最後の通知日時、閾値、再アラート間隔、ノティファヤーリスト)は明示的に保存され、SQLite を介して再起動後も永続化されます。起動時にインシデントが復元されるため、回復時や展開中に DOWN アラートが再発火することはありません。通知は非同期で配信され、送信あたり 15 秒のタイムアウトを設け、SMTP や Telegram API など遅延するノティファヤーによるパイプラインブロックを防ぎます。
アラートロジックは初回の一時的な異常ではなく、N 回の連続失敗後に発火し、リマインダー用のオプションの再アラート間隔を含みます。設定は単一の YAML ファイルで、デフォルト値(interval、timeout、failure_threshold)、命名されたノティファヤー、DSN・クエリー・ルール付きのモニターグループをサポートします。運用機能としては、SIGHUP によるホットリロード(適用前に完全なバリデーション実行)、シークレット用の ${VAR} 環境変数展開、CI レンティング用ドライランチェック用の -check フラグが備わります。
このツールは意図的にクラスターリング、エージェント、プラグインシステム、時系列ダッシュボード、ユーザーアカウントを排除しており、コンフィギュラブルな保留期間(デフォルト 30 日)後の履歴を削減して SQLite を小さく保ちます。ライフサイクル管理には systemd、通知には shoutrrr URL という既存の機構を活用し、作成から数ヶ月経っても理解可能で単純であるよう心がけています。
本文
Gjallar:KISS 精神に基づいた自立型監視ツール
多様なインフラの監視と通知を一元管理したい場合に、過剰な機能や依存関係を持たない軽量な解決策を提供します。Gjallar はその理念を体現した単一バイナリです。
🎯 何をするべきか:多様なサービスの監視と通知
以下のコンポーネントやプロトコルを一括で監視し、問題発生時に即時通知を行います。
- 監視対象
- HTTP エンドポイント
- PostgreSQL データベース
- Oracle インスタンス(複数)
- Redis クライアント
- Elasticsearch インデックス(常に最新の状態維持チェック)
- ICMP ping 対応マシン
- Prometheus メトリクス
- 通知チャネル
- Telegram
- SMS
- Signal
⚙️ なぜ Gjallar か:軽量で自立型の設計思想
既存の監視プラットフォーム(Prometheus + Alertmanager + Grafana など)や複雑なコンテナ構成には以下の理由から、このプロジェクトは採用されませんでした。
- 分散システムの回避
- チェック項目が数十個程度でも、「システム稼働状態を確認するために別の分散システムを運用したくない」という意図があります。
- 依存関係の削減
- 軽量なオプションでは、Oracle クライアントライブラリのインストールや共有ライブラリへの依存など、環境構築の手間が課題でした。
Gjallar は以下の構成で動作します:
- 静的バイナリ 1 つ
- YAML 設定ファイル 1 つ
- SQLite ファイル 1 つ
全コードは Go で約 3,400 行、MIT ライセンスを採用しています。
🚫 CGO の使用を意図的に排除した点
ビルドコマンドには
CGO_ENABLED=0 フラグを使用し、純粋な Go のライブラリのみで動作するよう設計されています。これにより、C ライブラリ依存(インストール困難)を解消できます。
採用された純粋な Go ライブラリ
- pgx:PostgreSQL 用接続(libpq 不要)
- go-ora:Oracle 用接続(Oracle Instant Client 不要)
- 過去に最小限のリソースサーバーで Oracle クライアントをデプロイした経験があれば、その難しさを理解できるでしょう。
- pro-bing:ICMP echo ping(特権・非特権環境どちらでも動作)
- modernc.org/sqlite:SQLite ストレージ(libsqlite3 不要)
- Redis:ドライバなし。TCP プロトコルを直接話しかける方式を採用しています。
結果としての利点
- 単一バイナリ化:約 36 MB(主要部分は SQLite と Oracle ドライバ)
- クロスコンパイル対応:
を指定し、scp で任意のターゲットにデプロイ可能。GOOS/GOARCH - 環境依存なし:Docker、パッケージマネージャー、共有ライブラリ不要。「私のマシンでは動かない」という問題がありません。
🔒 ロックフリーなアラートパイプライン
監視ツールは並行処理が必要ですが、互斥量(ミュテックス)による競合回避を避けることで、パフォーマンスと安定性を確保しています。ステート管理にロックは一切使用していません。
処理の流れ
[各モニタ] (独立したゴルーチン) ↓ チェック実行 → 結果送信 [共有チャンネル] ↓ リクエストプッシュ [単一コンシューマ] (状態機械化処理 + SQLite 書き込み)
- 各モニタ:独自のゴルーチン内でチェックループを実行し、結果をチャンネルに流します。
- 下流処理:ステート更新、インシデント記録、履歴書き込みはすべて単一のコンシューマゴルーチンが管理します。
- 状態マップや DB 接続へのアクセスは常に「一つ」のゴルーチンのみなのでロック不要。
- 並行書き込みを嫌う SQLite も正確に一つで済み、性能劣化を防ぎます。
ステート構造 (monitorState
)
monitorStatetype monitorState struct { down bool consecFails int // DOWN アラート発火までの連続失敗数 downSince time.Time // ダウン開始時刻 lastNotified time.Time // 最終通知時刻 threshold int // アラート発火閾値 realert time.Duration // ダウン中の再通知間隔(0 で無効) notifiers []string // 通知先リスト }
運用で重要な 2 つの特性
- ステートの永続化
- SQLite に記録された未解決インシデントから起動時にステートを再構成。
- ダウン中に再起動しても、アラート重複や復旧通知欠落は発生しません。
- バージョン更新時にも、動作不連続を防止します。
- 非同期な通知配信
- SMTP の遅延や Telegram API のレート制限に対し、システム全体がブロックされません。
- 専用のゴルーチンで処理し、15 秒のタイムアウトを設定しています。
ノイズ抑制と再通知
- フラッピング防止:初回異常検知ではなく、設定された回数(N 回)の連続失敗後にアラートを発火。
- 再通知機能:インシデントが開状態の間に、オプションの実行間隔設定により再度通知可能。
⚙️ オペレーションを尊重した設定方式
すべての設定は単一の YAML ファイルに統合されています。
設定例
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"
運用を快適にする機能
- ホットリロード(SIGHUP)
で新しい設定を読み込み。systemctl reload gjallar- 完全に検証されるまで適用されず、構文エラー時は実行中の設定を維持しログに記録。監視担当者が障害を負うことを防ぎます。
- 環境変数展開
形式で展開されます。未定義の場合は明確な起動失敗エラーが発生します。${VAR}
- CI 検証(DRY_RUN)
フラグを伴って設定を検証可能。デプロイ前にコードチェックできます。-check
🙅♂️ 意図的に行わないこと
以下のような機能を実装していません。システムライフサイクルには systemd を使用します。通知サービスは shoutrrr URL で 20 種超をサポートしていますが、私が使用するものは限定的です。
- ❌ クラスタリング
- ❌ エージェントモード
- ❌ プラグインシステム
- ❌ 時系列ダッシュボード
- ❌ ユーザーアカウント管理
データの維持性
- 履歴剪定:設定可能な保持期間(デフォルト 30 日)後に自動削除され、SQLite ファイルは永久に小さく保たれます。
なぜこれらを実装していないか?
私が数年来廃棄していった監視ツールは、「プラットフォーム化」し、「監視自体を監視する」必要が生じるという病気で死んでいます。
Gjallar は以下のシンプルさを目指します:
- 全体状態は 1 つの SQLite ファイル に収まる。
- 全体挙動は 1 つの YAML ファイル に記述される。
- 作成後 18 ヶ月経過しても、真夜中の 3 時にその仕組みを理解できるレベルです。
すでに単純なメカニズムで十分賄えるため、複雑な機能を再実装せず、外部ツール(shoutrrr など)へ委譲します。