alerttonotify/server/server.go

93 lines
2.8 KiB
Go

package server
import (
"encoding/json"
"fmt"
"log/slog"
"net/http"
"strings"
"time"
)
type Server struct {
logger *slog.Logger
ns *NotificationService
http.Server
}
type Alert struct {
Status string `json:"status"`
Labels map[string]string `json:"labels"`
Annotations map[string]string `json:"annotations"`
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
GeneratorURL string `json:"generatorURL"`
Fingerprint string `json:"fingerprint"`
}
type AlertMessage struct {
Version string `json:"version"`
GroupKey string `json:"groupKey"`
TruncatedAlerts int `json:"truncatedAlerts"`
Status string `json:"status"`
Receiver string `json:"receiver"`
GroupLabels map[string]string `json:"groupLabels"`
CommonLabels map[string]string `json:"commonLabels"`
CommonAnnotations map[string]string `json:"commonAnnotations"`
ExternalURL string `json:"externalURL"`
Alerts []Alert `json:"alerts"`
}
func NewServer(ns *NotificationService, logger *slog.Logger) *Server {
srv := &Server{
logger: logger,
}
mux := http.NewServeMux()
mux.HandleFunc("GET /", srv.handleIndex)
mux.HandleFunc("POST /alert", srv.handleAlert)
srv.Handler = mux
return srv
}
func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
s.logger.Info("index page")
w.Write([]byte("Hello!"))
}
func (s *Server) handleAlert(w http.ResponseWriter, r *http.Request) {
s.logger.Debug("Got new alert", "remoteAddr", r.RemoteAddr)
decoder := json.NewDecoder(r.Body)
var alertMessage AlertMessage
if err := decoder.Decode(&alertMessage); err != nil {
s.logger.Error("Failed to decode alert message", "error", err)
w.WriteHeader(http.StatusBadRequest)
return
}
s.logger.Debug("Decoded alert message", "alert", alertMessage)
s.logger.Info("Incoming message", "status", alertMessage.Status)
var sb strings.Builder
for _, alert := range alertMessage.Alerts {
s.logger.Debug("Incoming alert", "status", alert.Status, "fingerprint", alert.Fingerprint)
if summary, ok := alert.Annotations["summary"]; ok {
sb.WriteString(fmt.Sprintf("[%s] %s\n", strings.ToUpper(alert.Status), summary))
} else {
sb.WriteString(fmt.Sprintf("[%s]: %s\n", strings.ToUpper(alert.Status), alert.Fingerprint))
}
}
msg := &BusNotification{
Summary: fmt.Sprintf("%d alerts %s", len(alertMessage.Alerts), alertMessage.Status),
Body: sb.String(),
}
s.logger.Debug("Sending notification", "message", msg)
if err := s.ns.Notify(msg); err != nil {
s.logger.Error("Failed to send notification", "error", err)
w.WriteHeader(http.StatusInternalServerError)
}
}