package http import ( "net/http" "strings" "github.com/example/storage-appliance/internal/monitoring" ) // MetricsHandler serves Prometheus metrics func (a *App) MetricsHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() // Create collectors collectors := []monitoring.Collector{ monitoring.NewZFSCollector(a.ZFSSvc, a.Runner), monitoring.NewSMARTCollector(a.Runner), monitoring.NewServiceCollector(a.Runner), monitoring.NewHostCollector(), } // Export metrics exporter := monitoring.NewPrometheusExporter(collectors...) metrics := exporter.Export(ctx) w.Header().Set("Content-Type", "text/plain; version=0.0.4") w.WriteHeader(http.StatusOK) w.Write([]byte(metrics)) } // MonitoringHandler shows the monitoring dashboard func (a *App) MonitoringHandler(w http.ResponseWriter, r *http.Request) { data := templateData(r, map[string]interface{}{ "Title": "Monitoring", }) if err := templates.ExecuteTemplate(w, "monitoring", data); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } // HXMonitoringHandler returns HTMX partial for monitoring metrics func (a *App) HXMonitoringHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() // Create collectors collectors := []monitoring.Collector{ monitoring.NewZFSCollector(a.ZFSSvc, a.Runner), monitoring.NewSMARTCollector(a.Runner), monitoring.NewServiceCollector(a.Runner), monitoring.NewHostCollector(), } // Export for UI exporter := monitoring.NewUIExporter(collectors...) groups := exporter.Export(ctx) data := map[string]interface{}{ "Groups": groups, } if err := templates.ExecuteTemplate(w, "hx_monitoring", data); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } // HXMonitoringGroupHandler returns HTMX partial for a specific metric group func (a *App) HXMonitoringGroupHandler(w http.ResponseWriter, r *http.Request) { groupName := r.URL.Query().Get("group") if groupName == "" { http.Error(w, "group parameter required", http.StatusBadRequest) return } ctx := r.Context() // Create the specific collector (normalize group name) var collector monitoring.Collector groupLower := strings.ToLower(groupName) switch groupLower { case "zfs": collector = monitoring.NewZFSCollector(a.ZFSSvc, a.Runner) case "smart": collector = monitoring.NewSMARTCollector(a.Runner) case "services", "service": collector = monitoring.NewServiceCollector(a.Runner) case "host": collector = monitoring.NewHostCollector() default: // Try to match by collector name if strings.Contains(groupLower, "zfs") { collector = monitoring.NewZFSCollector(a.ZFSSvc, a.Runner) } else if strings.Contains(groupLower, "smart") { collector = monitoring.NewSMARTCollector(a.Runner) } else if strings.Contains(groupLower, "service") { collector = monitoring.NewServiceCollector(a.Runner) } else if strings.Contains(groupLower, "host") { collector = monitoring.NewHostCollector() } else { http.Error(w, "unknown group", http.StatusBadRequest) return } } // Export for UI exporter := monitoring.NewUIExporter(collector) groups := exporter.Export(ctx) if len(groups) == 0 { http.Error(w, "no data", http.StatusNotFound) return } data := map[string]interface{}{ "Group": groups[0], } if err := templates.ExecuteTemplate(w, "hx_monitoring_group", data); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }