github.com/wtfutil/wtf@v0.43.0/modules/grafana/client.go (about) 1 package grafana 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "net/http" 9 "sort" 10 11 "github.com/wtfutil/wtf/utils" 12 ) 13 14 type AlertState int 15 16 const ( 17 Alerting AlertState = iota 18 Pending 19 NoData 20 Paused 21 Ok 22 ) 23 24 var toString = map[AlertState]string{ 25 Alerting: "alerting", 26 Pending: "pending", 27 NoData: "no_data", 28 Paused: "paused", 29 Ok: "ok", 30 } 31 32 var toID = map[string]AlertState{ 33 "alerting": Alerting, 34 "pending": Pending, 35 "no_data": NoData, 36 "paused": Paused, 37 "ok": Ok, 38 } 39 40 // MarshalJSON marshals the enum as a quoted json string 41 func (s AlertState) MarshalJSON() ([]byte, error) { 42 buffer := bytes.NewBufferString(`"`) 43 buffer.WriteString(toString[s]) 44 buffer.WriteString(`"`) 45 return buffer.Bytes(), nil 46 } 47 48 // UnmarshalJSON unmashals a quoted json string to the enum value 49 func (s *AlertState) UnmarshalJSON(b []byte) error { 50 var j string 51 err := json.Unmarshal(b, &j) 52 if err != nil { 53 return err 54 } 55 // if we somehow get an invalid value we'll end up in the alerting state 56 *s = toID[j] 57 return nil 58 } 59 60 type Alert struct { 61 Name string `json:"name"` 62 State AlertState `json:"state"` 63 URL string `json:"url"` 64 } 65 66 type Client struct { 67 apiKey string 68 baseURI string 69 } 70 71 func NewClient(settings *Settings) *Client { 72 return &Client{ 73 apiKey: settings.apiKey, 74 baseURI: settings.baseURI, 75 } 76 } 77 78 func (client *Client) Alerts() ([]Alert, error) { 79 // query the alerts API of Grafana https://grafana.com/docs/grafana/latest/http_api/alerting/ 80 req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/alerts", client.baseURI), http.NoBody) 81 if err != nil { 82 return nil, err 83 } 84 85 if client.apiKey != "" { 86 req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", client.apiKey)) 87 } 88 89 res, err := http.DefaultClient.Do(req) 90 if err != nil { 91 return nil, err 92 } 93 defer func() { _ = res.Body.Close() }() 94 95 if res.StatusCode != 200 { 96 msg := struct { 97 Msg string `json:"message"` 98 }{} 99 err = utils.ParseJSON(&msg, res.Body) 100 if err != nil { 101 return nil, err 102 } 103 return nil, errors.New(msg.Msg) 104 } 105 106 var out []Alert 107 err = utils.ParseJSON(&out, res.Body) 108 if err != nil { 109 return nil, err 110 } 111 112 sort.SliceStable(out, func(i, j int) bool { 113 return out[i].State < out[j].State 114 }) 115 116 return out, nil 117 }