package main import ( "database/sql" "encoding/json" "log" "net/http" "os" "strings" _ "github.com/lib/pq" ) type Config struct { Port string `json:"port"` DBUrl string `json:"db_url"` } func loadConfig() Config { cfg := Config{ Port: "8080", DBUrl: "postgres://monitor:monitorpassword@localhost:5432/vdimonitor?sslmode=disable", } file, err := os.Open("config.json") if err == nil { defer file.Close() decoder := json.NewDecoder(file) if err := decoder.Decode(&cfg); err != nil { log.Printf("Warning: Failed to parse config.json: %v", err) } } if envPort := os.Getenv("PORT"); envPort != "" { cfg.Port = envPort } if envDB := os.Getenv("DB_URL"); envDB != "" { cfg.DBUrl = envDB } return cfg } type MetricPayload struct { Hostname string `json:"hostname"` TotalCpuPercent float64 `json:"total_cpu_percent"` TotalMemPercent float64 `json:"total_mem_percent"` DpcInterruptPercent float64 `json:"dpc_interrupt_percent"` TopCpuProcesses json.RawMessage `json:"top_cpu_processes"` TopMemProcesses json.RawMessage `json:"top_mem_processes"` TopIoProcesses json.RawMessage `json:"top_io_processes"` NetworkConnections json.RawMessage `json:"network_connections"` HungProcesses json.RawMessage `json:"hung_processes"` } var db *sql.DB func main() { cfg := loadConfig() var err error db, err = sql.Open("postgres", cfg.DBUrl) if err != nil { log.Fatalf("Failed to connect to db: %v", err) } defer db.Close() http.HandleFunc("/api/metrics", handleMetrics) port := cfg.Port if !strings.HasPrefix(port, ":") { port = ":" + port } log.Printf("Server starting on %s\n", port) log.Fatal(http.ListenAndServe(port, nil)) } func handleMetrics(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } var payload MetricPayload if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { http.Error(w, "Bad request", http.StatusBadRequest) return } _, err := db.Exec( `INSERT INTO client_metrics (hostname, total_cpu_percent, total_mem_percent, dpc_interrupt_percent, top_cpu_processes, top_mem_processes, top_io_processes, network_connections, hung_processes) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, payload.Hostname, payload.TotalCpuPercent, payload.TotalMemPercent, payload.DpcInterruptPercent, payload.TopCpuProcesses, payload.TopMemProcesses, payload.TopIoProcesses, payload.NetworkConnections, payload.HungProcesses, ) if err != nil { log.Printf("DB insert error: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) }