feat: switch monitor client to Docker-first runtime
- remove install.sh-based deployment path - add multi-stage Dockerfile for HarborForge.Monitor - support HF_MONITER_* env vars and keep HF_MONITOR_* compatibility - add rootfs-aware host metric collection for Docker deployment
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -12,15 +13,17 @@ type Config struct {
|
||||
APIKey string `json:"apiKey"`
|
||||
ReportIntervalSec int `json:"reportIntervalSec"`
|
||||
LogLevel string `json:"logLevel"`
|
||||
RootFS string `json:"rootFs"`
|
||||
}
|
||||
|
||||
func Load(path string) (Config, error) {
|
||||
cfg := Config{
|
||||
BackendURL: getenv("HF_MONITOR_BACKEND_URL", "https://monitor.hangman-lab.top"),
|
||||
Identifier: getenv("HF_MONITOR_IDENTIFIER", hostnameOr("unknown-host")),
|
||||
APIKey: os.Getenv("HF_MONITOR_API_KEY"),
|
||||
ReportIntervalSec: getenvInt("HF_MONITOR_REPORT_INTERVAL", 30),
|
||||
LogLevel: getenv("HF_MONITOR_LOG_LEVEL", "info"),
|
||||
BackendURL: getenvAny([]string{"HF_MONITER_BACKEND_URL", "HF_MONITOR_BACKEND_URL"}, "https://monitor.hangman-lab.top"),
|
||||
Identifier: getenvAny([]string{"HF_MONITER_IDENTIFIER", "HF_MONITOR_IDENTIFIER"}, hostnameOr("unknown-host")),
|
||||
APIKey: getenvAny([]string{"HF_MONITER_API_KEY", "HF_MONITOR_API_KEY"}, ""),
|
||||
ReportIntervalSec: getenvIntAny([]string{"HF_MONITER_REPORT_INTERVAL", "HF_MONITOR_REPORT_INTERVAL"}, 30),
|
||||
LogLevel: getenvAny([]string{"HF_MONITER_LOG_LEVEL", "HF_MONITOR_LOG_LEVEL"}, "info"),
|
||||
RootFS: getenvAny([]string{"HF_MONITER_ROOTFS", "HF_MONITOR_ROOTFS"}, ""),
|
||||
}
|
||||
|
||||
if path != "" {
|
||||
@@ -32,13 +35,14 @@ func Load(path string) (Config, error) {
|
||||
}
|
||||
|
||||
// env always wins over file
|
||||
cfg.BackendURL = getenv("HF_MONITOR_BACKEND_URL", cfg.BackendURL)
|
||||
cfg.Identifier = getenv("HF_MONITOR_IDENTIFIER", cfg.Identifier)
|
||||
if v := os.Getenv("HF_MONITOR_API_KEY"); v != "" {
|
||||
cfg.BackendURL = getenvAny([]string{"HF_MONITER_BACKEND_URL", "HF_MONITOR_BACKEND_URL"}, cfg.BackendURL)
|
||||
cfg.Identifier = getenvAny([]string{"HF_MONITER_IDENTIFIER", "HF_MONITOR_IDENTIFIER"}, cfg.Identifier)
|
||||
if v := getenvAny([]string{"HF_MONITER_API_KEY", "HF_MONITOR_API_KEY"}, ""); v != "" {
|
||||
cfg.APIKey = v
|
||||
}
|
||||
cfg.ReportIntervalSec = getenvInt("HF_MONITOR_REPORT_INTERVAL", cfg.ReportIntervalSec)
|
||||
cfg.LogLevel = getenv("HF_MONITOR_LOG_LEVEL", cfg.LogLevel)
|
||||
cfg.ReportIntervalSec = getenvIntAny([]string{"HF_MONITER_REPORT_INTERVAL", "HF_MONITOR_REPORT_INTERVAL"}, cfg.ReportIntervalSec)
|
||||
cfg.LogLevel = getenvAny([]string{"HF_MONITER_LOG_LEVEL", "HF_MONITOR_LOG_LEVEL"}, cfg.LogLevel)
|
||||
cfg.RootFS = getenvAny([]string{"HF_MONITER_ROOTFS", "HF_MONITOR_ROOTFS"}, cfg.RootFS)
|
||||
|
||||
if cfg.BackendURL == "" {
|
||||
return cfg, fmt.Errorf("backendUrl is required")
|
||||
@@ -49,6 +53,7 @@ func Load(path string) (Config, error) {
|
||||
if cfg.ReportIntervalSec <= 0 {
|
||||
cfg.ReportIntervalSec = 30
|
||||
}
|
||||
applyHostFSEnv(cfg.RootFS)
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
@@ -80,20 +85,27 @@ func merge(dst *Config, src Config) {
|
||||
if src.LogLevel != "" {
|
||||
dst.LogLevel = src.LogLevel
|
||||
}
|
||||
if src.RootFS != "" {
|
||||
dst.RootFS = src.RootFS
|
||||
}
|
||||
}
|
||||
|
||||
func getenv(key, fallback string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
func getenvAny(keys []string, fallback string) string {
|
||||
for _, key := range keys {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func getenvInt(key string, fallback int) int {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
var out int
|
||||
if _, err := fmt.Sscanf(v, "%d", &out); err == nil && out > 0 {
|
||||
return out
|
||||
func getenvIntAny(keys []string, fallback int) int {
|
||||
for _, key := range keys {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
var out int
|
||||
if _, err := fmt.Sscanf(v, "%d", &out); err == nil && out > 0 {
|
||||
return out
|
||||
}
|
||||
}
|
||||
}
|
||||
return fallback
|
||||
@@ -106,3 +118,20 @@ func hostnameOr(fallback string) string {
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func applyHostFSEnv(rootFS string) {
|
||||
if rootFS == "" {
|
||||
return
|
||||
}
|
||||
setIfEmpty("HOST_PROC", filepath.Join(rootFS, "proc"))
|
||||
setIfEmpty("HOST_SYS", filepath.Join(rootFS, "sys"))
|
||||
setIfEmpty("HOST_ETC", filepath.Join(rootFS, "etc"))
|
||||
setIfEmpty("HOST_VAR", filepath.Join(rootFS, "var"))
|
||||
setIfEmpty("HOST_RUN", filepath.Join(rootFS, "run"))
|
||||
}
|
||||
|
||||
func setIfEmpty(key, value string) {
|
||||
if os.Getenv(key) == "" {
|
||||
_ = os.Setenv(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,11 @@ func BuildPayload(ctx context.Context, cfg config.Config) (Payload, error) {
|
||||
payload.MemPct = round1(vm.UsedPercent)
|
||||
}
|
||||
|
||||
diskUsage, err := disk.UsageWithContext(ctx, "/")
|
||||
diskPath := cfg.RootFS
|
||||
if diskPath == "" {
|
||||
diskPath = "/"
|
||||
}
|
||||
diskUsage, err := disk.UsageWithContext(ctx, diskPath)
|
||||
if err == nil {
|
||||
payload.DiskPct = round1(diskUsage.UsedPercent)
|
||||
}
|
||||
@@ -75,7 +79,7 @@ func BuildPayload(ctx context.Context, cfg config.Config) (Payload, error) {
|
||||
payload.UptimeSeconds = hostInfo.Uptime
|
||||
}
|
||||
|
||||
nginxInstalled, nginxSites, err := detectNginx()
|
||||
nginxInstalled, nginxSites, err := detectNginx(cfg.RootFS)
|
||||
if err == nil {
|
||||
payload.NginxInstalled = nginxInstalled
|
||||
payload.NginxSites = nginxSites
|
||||
@@ -109,12 +113,20 @@ func Send(ctx context.Context, client *http.Client, cfg config.Config, payload P
|
||||
return nil
|
||||
}
|
||||
|
||||
func detectNginx() (bool, []string, error) {
|
||||
func detectNginx(rootFS string) (bool, []string, error) {
|
||||
installed := false
|
||||
if _, err := exec.LookPath("nginx"); err == nil {
|
||||
installed = true
|
||||
if rootFS == "" {
|
||||
if _, err := exec.LookPath("nginx"); err == nil {
|
||||
installed = true
|
||||
}
|
||||
}
|
||||
for _, path := range []string{"/etc/nginx/nginx.conf", "/usr/local/etc/nginx/nginx.conf", "/opt/homebrew/etc/nginx/nginx.conf"} {
|
||||
for _, path := range []string{
|
||||
rootPath(rootFS, "/etc/nginx/nginx.conf"),
|
||||
rootPath(rootFS, "/usr/local/etc/nginx/nginx.conf"),
|
||||
rootPath(rootFS, "/opt/homebrew/etc/nginx/nginx.conf"),
|
||||
rootPath(rootFS, "/usr/sbin/nginx"),
|
||||
rootPath(rootFS, "/usr/bin/nginx"),
|
||||
} {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
installed = true
|
||||
break
|
||||
@@ -124,7 +136,7 @@ func detectNginx() (bool, []string, error) {
|
||||
return false, []string{}, nil
|
||||
}
|
||||
|
||||
dir := "/etc/nginx/sites-enabled"
|
||||
dir := rootPath(rootFS, "/etc/nginx/sites-enabled")
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@@ -155,3 +167,10 @@ func round1(v float64) float64 {
|
||||
func round2(v float64) float64 {
|
||||
return float64(int(v*100+0.5)) / 100
|
||||
}
|
||||
|
||||
func rootPath(rootFS, path string) string {
|
||||
if rootFS == "" || rootFS == "/" {
|
||||
return path
|
||||
}
|
||||
return filepath.Join(rootFS, strings.TrimPrefix(path, "/"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user