github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/alertmanager/alertmanager_http.go (about) 1 package alertmanager 2 3 import ( 4 "net/http" 5 "text/template" 6 7 "github.com/go-kit/log/level" 8 "github.com/grafana/dskit/services" 9 10 util_log "github.com/cortexproject/cortex/pkg/util/log" 11 ) 12 13 var ( 14 ringStatusPageTemplate = template.Must(template.New("ringStatusPage").Parse(` 15 <!DOCTYPE html> 16 <html> 17 <head> 18 <meta charset="UTF-8"> 19 <title>Cortex Alertmanager Ring</title> 20 </head> 21 <body> 22 <h1>Cortex Alertmanager Ring</h1> 23 <p>{{ .Message }}</p> 24 </body> 25 </html>`)) 26 27 statusTemplate = template.Must(template.New("statusPage").Parse(` 28 <!doctype html> 29 <html> 30 <head><title>Cortex Alertmanager Status</title></head> 31 <body> 32 <h1>Cortex Alertmanager Status</h1> 33 {{ if not .ClusterInfo }} 34 <p>Alertmanager gossip-based clustering is disabled.</p> 35 {{ else }} 36 <h2>Node</h2> 37 <dl> 38 <dt>Name</dt><dd>{{.ClusterInfo.self.Name}}</dd> 39 <dt>Addr</dt><dd>{{.ClusterInfo.self.Addr}}</dd> 40 <dt>Port</dt><dd>{{.ClusterInfo.self.Port}}</dd> 41 </dl> 42 <h3>Members</h3> 43 {{ with .ClusterInfo.members }} 44 <table> 45 <tr><th>Name</th><th>Addr</th></tr> 46 {{ range . }} 47 <tr><td>{{ .Name }}</td><td>{{ .Addr }}</td></tr> 48 {{ end }} 49 </table> 50 {{ else }} 51 <p>No peers</p> 52 {{ end }} 53 {{ end }} 54 </body> 55 </html>`)) 56 ) 57 58 func writeRingStatusMessage(w http.ResponseWriter, message string) { 59 w.WriteHeader(http.StatusOK) 60 err := ringStatusPageTemplate.Execute(w, struct { 61 Message string 62 }{Message: message}) 63 if err != nil { 64 level.Error(util_log.Logger).Log("msg", "unable to serve alertmanager ring page", "err", err) 65 } 66 } 67 68 func (am *MultitenantAlertmanager) RingHandler(w http.ResponseWriter, req *http.Request) { 69 if !am.cfg.ShardingEnabled { 70 writeRingStatusMessage(w, "Alertmanager has no ring because sharding is disabled.") 71 return 72 } 73 74 if am.State() != services.Running { 75 // we cannot read the ring before the alertmanager is in Running state, 76 // because that would lead to race condition. 77 writeRingStatusMessage(w, "Alertmanager is not running yet.") 78 return 79 } 80 81 am.ring.ServeHTTP(w, req) 82 } 83 84 // GetStatusHandler returns the status handler for this multi-tenant 85 // alertmanager. 86 func (am *MultitenantAlertmanager) GetStatusHandler() StatusHandler { 87 return StatusHandler{ 88 am: am, 89 } 90 } 91 92 // StatusHandler shows the status of the alertmanager. 93 type StatusHandler struct { 94 am *MultitenantAlertmanager 95 } 96 97 // ServeHTTP serves the status of the alertmanager. 98 func (s StatusHandler) ServeHTTP(w http.ResponseWriter, _ *http.Request) { 99 var clusterInfo map[string]interface{} 100 if s.am.peer != nil { 101 clusterInfo = s.am.peer.Info() 102 } 103 err := statusTemplate.Execute(w, struct { 104 ClusterInfo map[string]interface{} 105 }{ 106 ClusterInfo: clusterInfo, 107 }) 108 if err != nil { 109 level.Error(util_log.Logger).Log("msg", "unable to serve alertmanager status page", "err", err) 110 http.Error(w, err.Error(), http.StatusInternalServerError) 111 } 112 }