Skip to content

Commit 8e302d2

Browse files
Merge pull request #46 from grafana/grobinson/cherry-pick-errors-notifications
Capture and expose notification delivery errors (#31)
2 parents e1e5992 + d59154b commit 8e302d2

File tree

12 files changed

+469
-66
lines changed

12 files changed

+469
-66
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@
2020
!/.travis.yml
2121
!/.promu.yml
2222
!/api/v2/openapi.yaml
23+
24+
# Editor
25+
.vscode
26+
.DS_Store

api/api.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/prometheus/alertmanager/cluster"
3131
"github.com/prometheus/alertmanager/config"
3232
"github.com/prometheus/alertmanager/dispatch"
33+
"github.com/prometheus/alertmanager/notify"
3334
"github.com/prometheus/alertmanager/provider"
3435
"github.com/prometheus/alertmanager/silence"
3536
"github.com/prometheus/alertmanager/types"
@@ -195,9 +196,9 @@ func (api *API) Register(r *route.Router, routePrefix string) *http.ServeMux {
195196

196197
// Update config and resolve timeout of each API. APIv2 also needs
197198
// setAlertStatus to be updated.
198-
func (api *API) Update(cfg *config.Config, setAlertStatus func(model.LabelSet)) {
199+
func (api *API) Update(cfg *config.Config, receivers []*notify.Receiver, setAlertStatus func(model.LabelSet)) {
199200
api.v1.Update(cfg)
200-
api.v2.Update(cfg, setAlertStatus)
201+
api.v2.Update(cfg, setAlertStatus, receivers)
201202
}
202203

203204
func (api *API) limitHandler(h http.Handler) http.Handler {

api/v2/api.go

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import (
3232
"github.com/prometheus/common/version"
3333
"github.com/rs/cors"
3434

35-
"github.com/prometheus/alertmanager/api/metrics"
3635
open_api_models "github.com/prometheus/alertmanager/api/v2/models"
3736
"github.com/prometheus/alertmanager/api/v2/restapi"
3837
"github.com/prometheus/alertmanager/api/v2/restapi/operations"
@@ -41,9 +40,12 @@ import (
4140
general_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/general"
4241
receiver_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/receiver"
4342
silence_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/silence"
43+
44+
"github.com/prometheus/alertmanager/api/metrics"
4445
"github.com/prometheus/alertmanager/cluster"
4546
"github.com/prometheus/alertmanager/config"
4647
"github.com/prometheus/alertmanager/dispatch"
48+
"github.com/prometheus/alertmanager/notify"
4749
"github.com/prometheus/alertmanager/pkg/labels"
4850
"github.com/prometheus/alertmanager/provider"
4951
"github.com/prometheus/alertmanager/silence"
@@ -71,7 +73,8 @@ type API struct {
7173
logger log.Logger
7274
m *metrics.Alerts
7375

74-
Handler http.Handler
76+
Handler http.Handler
77+
receivers []*notify.Receiver
7578
}
7679

7780
type (
@@ -153,13 +156,14 @@ func (api *API) requestLogger(req *http.Request) log.Logger {
153156
}
154157

155158
// Update sets the API struct members that may change between reloads of alertmanager.
156-
func (api *API) Update(cfg *config.Config, setAlertStatus setAlertStatusFn) {
159+
func (api *API) Update(cfg *config.Config, setAlertStatus setAlertStatusFn, receivers []*notify.Receiver) {
157160
api.mtx.Lock()
158161
defer api.mtx.Unlock()
159162

160163
api.alertmanagerConfig = cfg
161164
api.route = dispatch.NewRoute(cfg.Route, nil)
162165
api.setAlertStatus = setAlertStatus
166+
api.receivers = receivers
163167
}
164168

165169
func (api *API) getStatusHandler(params general_ops.GetStatusParams) middleware.Responder {
@@ -220,11 +224,40 @@ func (api *API) getStatusHandler(params general_ops.GetStatusParams) middleware.
220224

221225
func (api *API) getReceiversHandler(params receiver_ops.GetReceiversParams) middleware.Responder {
222226
api.mtx.RLock()
223-
defer api.mtx.RUnlock()
227+
configReceivers := api.receivers
228+
api.mtx.RUnlock()
229+
230+
receivers := make([]*open_api_models.Receiver, 0, len(configReceivers))
231+
for _, r := range configReceivers {
232+
integrations := make([]*open_api_models.Integration, 0, len(r.Integrations()))
233+
234+
for _, integration := range r.Integrations() {
235+
notify, duration, err := integration.GetReport()
236+
iname := integration.String()
237+
sendResolved := integration.SendResolved()
238+
integrations = append(integrations, &open_api_models.Integration{
239+
Name: &iname,
240+
SendResolved: &sendResolved,
241+
LastNotifyAttempt: strfmt.DateTime(notify.UTC()),
242+
LastNotifyAttemptDuration: duration.String(),
243+
LastNotifyAttemptError: func() string {
244+
if err != nil {
245+
return err.Error()
246+
}
247+
return ""
248+
}(),
249+
})
250+
}
251+
252+
rName := r.Name()
253+
active := r.Active()
254+
model := &open_api_models.Receiver{
255+
Name: &rName,
256+
Active: &active,
257+
Integrations: integrations,
258+
}
224259

225-
receivers := make([]*open_api_models.Receiver, 0, len(api.alertmanagerConfig.Receivers))
226-
for i := range api.alertmanagerConfig.Receivers {
227-
receivers = append(receivers, &open_api_models.Receiver{Name: &api.alertmanagerConfig.Receivers[i].Name})
260+
receivers = append(receivers, model)
228261
}
229262

230263
return receiver_ops.NewGetReceiversOK().WithPayload(receivers)

api/v2/models/integration.go

Lines changed: 122 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v2/models/receiver.go

Lines changed: 51 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v2/openapi.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,36 @@ definitions:
508508
properties:
509509
name:
510510
type: string
511+
active:
512+
type: boolean
513+
integrations:
514+
type: array
515+
items:
516+
$ref: '#/definitions/integration'
517+
required:
518+
- name
519+
- active
520+
- integrations
521+
integration:
522+
type: object
523+
properties:
524+
name:
525+
type: string
526+
sendResolved:
527+
type: boolean
528+
lastNotifyAttempt:
529+
description: A timestamp indicating the last attempt to deliver a notification regardless of the outcome.
530+
type: string
531+
format: date-time
532+
lastNotifyAttemptDuration:
533+
description: Duration of the last attempt to deliver a notification in humanized format (`1s` or `15ms`, etc).
534+
type: string
535+
lastNotifyAttemptError:
536+
description: Error string for the last attempt to deliver a notification. Empty if the last attempt was successful.
537+
type: string
511538
required:
512539
- name
540+
- sendResolved
513541
labelSet:
514542
type: object
515543
additionalProperties:

0 commit comments

Comments
 (0)