musiclink/internal/matrixbot/health.go

84 lines
2.3 KiB
Go

package matrixbot
import (
"context"
"encoding/json"
"log"
"net/http"
"time"
)
type healthResponse struct {
Status string `json:"status"`
Mode string `json:"mode"`
Rooms int `json:"rooms"`
LastSync string `json:"last_sync,omitempty"`
LastEvent string `json:"last_event,omitempty"`
LastSend string `json:"last_send,omitempty"`
LastSendError string `json:"last_send_error,omitempty"`
Received int64 `json:"received"`
Responded int64 `json:"responded"`
Dropped int64 `json:"dropped"`
RateLimited int64 `json:"rate_limited"`
EncryptedSkipped int64 `json:"encrypted_skipped"`
}
func (b *Bot) startHealthServer(ctx context.Context) {
mux := http.NewServeMux()
mux.HandleFunc("/healthz", b.handleHealth)
mux.HandleFunc("/metrics", b.handleHealth)
srv := &http.Server{
Addr: b.cfg.HealthAddr,
Handler: mux,
}
go func() {
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(shutdownCtx); err != nil {
log.Printf("Matrix health server shutdown error: %v", err)
}
}()
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Printf("Matrix health server error: %v", err)
}
}
func (b *Bot) handleHealth(w http.ResponseWriter, _ *http.Request) {
snapshot := b.stats.Snapshot()
mode := "active"
if b.cfg.Shadow {
mode = "shadow"
}
payload := healthResponse{
Status: "ok",
Mode: mode,
Rooms: len(b.allowedRooms),
LastSync: formatTime(snapshot.LastSync),
LastEvent: formatTime(snapshot.LastEvent),
LastSend: formatTime(snapshot.LastSend),
LastSendError: snapshot.LastSendError,
Received: snapshot.Received,
Responded: snapshot.Responded,
Dropped: snapshot.Dropped,
RateLimited: snapshot.RateLimited,
EncryptedSkipped: snapshot.EncryptedSkipped,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(payload); err != nil {
log.Printf("Matrix health encode error: %v", err)
}
}
func formatTime(t time.Time) string {
if t.IsZero() {
return ""
}
return t.UTC().Format(time.RFC3339)
}