mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 08:35:43 -06:00
* Alerting: Use a default configuration and periodically poll for new ones Use a default configuration to make sure we always start the grafana instance. Then, regularly poll for new ones. I've also made sure that failures to apply configuration do not stop the Grafana server but instead keep polling until it is a success.
189 lines
6.8 KiB
Go
189 lines
6.8 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
|
|
apimodels "github.com/grafana/alerting-api/pkg/api"
|
|
"github.com/grafana/grafana/pkg/api/response"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
)
|
|
|
|
type AlertmanagerSrv struct {
|
|
am Alertmanager
|
|
store store.AlertingStore
|
|
log log.Logger
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteCreateSilence(c *models.ReqContext, postableSilence apimodels.PostableSilence) response.Response {
|
|
silenceID, err := srv.am.CreateSilence(&postableSilence)
|
|
if err != nil {
|
|
if errors.Is(err, notifier.ErrSilenceNotFound) {
|
|
return response.Error(http.StatusNotFound, err.Error(), nil)
|
|
}
|
|
|
|
if errors.Is(err, notifier.ErrCreateSilenceBadPayload) {
|
|
return response.Error(http.StatusBadRequest, err.Error(), nil)
|
|
}
|
|
|
|
return response.Error(http.StatusInternalServerError, "failed to create silence", err)
|
|
}
|
|
return response.JSON(http.StatusAccepted, util.DynMap{"message": "silence created", "id": silenceID})
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteDeleteAlertingConfig(c *models.ReqContext) response.Response {
|
|
// not implemented
|
|
return response.Error(http.StatusNotImplemented, "", nil)
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteDeleteSilence(c *models.ReqContext) response.Response {
|
|
silenceID := c.Params(":SilenceId")
|
|
if err := srv.am.DeleteSilence(silenceID); err != nil {
|
|
if errors.Is(err, notifier.ErrSilenceNotFound) {
|
|
return response.Error(http.StatusNotFound, err.Error(), nil)
|
|
}
|
|
return response.Error(http.StatusInternalServerError, err.Error(), nil)
|
|
}
|
|
return response.JSON(http.StatusOK, util.DynMap{"message": "silence deleted"})
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteGetAlertingConfig(c *models.ReqContext) response.Response {
|
|
query := ngmodels.GetLatestAlertmanagerConfigurationQuery{}
|
|
if err := srv.store.GetLatestAlertmanagerConfiguration(&query); err != nil {
|
|
if errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
|
return response.Error(http.StatusNotFound, err.Error(), nil)
|
|
}
|
|
return response.Error(http.StatusInternalServerError, "failed to get latest configuration", err)
|
|
}
|
|
|
|
cfg, err := notifier.Load([]byte(query.Result.AlertmanagerConfiguration))
|
|
if err != nil {
|
|
return response.Error(http.StatusInternalServerError, "failed to unmarshal alertmanager configuration", err)
|
|
}
|
|
|
|
var apiReceiverName string
|
|
var receivers []*apimodels.GettableGrafanaReceiver
|
|
alertmanagerCfg := cfg.AlertmanagerConfig
|
|
if len(alertmanagerCfg.Receivers) > 0 {
|
|
apiReceiverName = alertmanagerCfg.Receivers[0].Name
|
|
receivers = make([]*apimodels.GettableGrafanaReceiver, 0, len(alertmanagerCfg.Receivers[0].PostableGrafanaReceivers.GrafanaManagedReceivers))
|
|
for _, pr := range alertmanagerCfg.Receivers[0].PostableGrafanaReceivers.GrafanaManagedReceivers {
|
|
secureFields := make(map[string]bool, len(pr.SecureSettings))
|
|
for k := range pr.SecureSettings {
|
|
secureFields[k] = true
|
|
}
|
|
gr := apimodels.GettableGrafanaReceiver{
|
|
Uid: pr.Uid,
|
|
Name: pr.Name,
|
|
Type: pr.Type,
|
|
IsDefault: pr.IsDefault,
|
|
SendReminder: pr.SendReminder,
|
|
DisableResolveMessage: pr.DisableResolveMessage,
|
|
Frequency: pr.Frequency,
|
|
Settings: pr.Settings,
|
|
SecureFields: secureFields,
|
|
}
|
|
receivers = append(receivers, &gr)
|
|
}
|
|
}
|
|
|
|
gettableApiReceiver := apimodels.GettableApiReceiver{
|
|
GettableGrafanaReceivers: apimodels.GettableGrafanaReceivers{
|
|
GrafanaManagedReceivers: receivers,
|
|
},
|
|
}
|
|
gettableApiReceiver.Name = apiReceiverName
|
|
result := apimodels.GettableUserConfig{
|
|
TemplateFiles: cfg.TemplateFiles,
|
|
AlertmanagerConfig: apimodels.GettableApiAlertingConfig{
|
|
Config: alertmanagerCfg.Config,
|
|
Receivers: []*apimodels.GettableApiReceiver{
|
|
&gettableApiReceiver,
|
|
},
|
|
},
|
|
}
|
|
|
|
return response.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteGetAMAlertGroups(c *models.ReqContext) response.Response {
|
|
groups, err := srv.am.GetAlertGroups(
|
|
c.QueryBool("active"),
|
|
c.QueryBool("silenced"),
|
|
c.QueryBool("inhibited"),
|
|
c.QueryStrings("filter"),
|
|
c.Query("receiver"),
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, notifier.ErrGetAlertGroupsBadPayload) {
|
|
return response.Error(http.StatusBadRequest, err.Error(), nil)
|
|
}
|
|
// any other error here should be an unexpected failure and thus an internal error
|
|
return response.Error(http.StatusInternalServerError, err.Error(), nil)
|
|
}
|
|
|
|
return response.JSON(http.StatusOK, groups)
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteGetAMAlerts(c *models.ReqContext) response.Response {
|
|
alerts, err := srv.am.GetAlerts(
|
|
c.QueryBool("active"),
|
|
c.QueryBool("silenced"),
|
|
c.QueryBool("inhibited"),
|
|
c.QueryStrings("filter"),
|
|
c.Query("receiver"),
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, notifier.ErrGetAlertsBadPayload) {
|
|
return response.Error(http.StatusBadRequest, err.Error(), nil)
|
|
}
|
|
// any other error here should be an unexpected failure and thus an internal error
|
|
return response.Error(http.StatusInternalServerError, err.Error(), nil)
|
|
}
|
|
|
|
return response.JSON(http.StatusOK, alerts)
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteGetSilence(c *models.ReqContext) response.Response {
|
|
silenceID := c.Params(":SilenceId")
|
|
gettableSilence, err := srv.am.GetSilence(silenceID)
|
|
if err != nil {
|
|
if errors.Is(err, notifier.ErrSilenceNotFound) {
|
|
return response.Error(http.StatusNotFound, err.Error(), nil)
|
|
}
|
|
// any other error here should be an unexpected failure and thus an internal error
|
|
return response.Error(http.StatusInternalServerError, err.Error(), nil)
|
|
}
|
|
return response.JSON(http.StatusOK, gettableSilence)
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RouteGetSilences(c *models.ReqContext) response.Response {
|
|
gettableSilences, err := srv.am.ListSilences(c.QueryStrings("filter"))
|
|
if err != nil {
|
|
if errors.Is(err, notifier.ErrListSilencesBadPayload) {
|
|
return response.Error(http.StatusBadRequest, err.Error(), nil)
|
|
}
|
|
// any other error here should be an unexpected failure and thus an internal error
|
|
return response.Error(http.StatusInternalServerError, err.Error(), nil)
|
|
}
|
|
return response.JSON(http.StatusOK, gettableSilences)
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RoutePostAlertingConfig(c *models.ReqContext, body apimodels.PostableUserConfig) response.Response {
|
|
if err := srv.am.SaveAndApplyConfig(&body); err != nil {
|
|
return response.Error(http.StatusInternalServerError, "failed to save and apply Alertmanager configuration", err)
|
|
}
|
|
|
|
return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration created"})
|
|
}
|
|
|
|
func (srv AlertmanagerSrv) RoutePostAMAlerts(c *models.ReqContext, body apimodels.PostableAlerts) response.Response {
|
|
// not implemented
|
|
return response.Error(http.StatusNotImplemented, "", nil)
|
|
}
|