Files
storage-appliance/internal/http/monitoring_handlers.go

122 lines
3.4 KiB
Go

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)
}
}