Encapsulate context values in package.
Setting and getting of context values are done via helper methods in the notifier package. The used keys are unexported. Thus, we ensure that external code cannot overwrite the values and the type is always correct.
This commit is contained in:
parent
638b3f9f40
commit
0a5a7691fe
13
dispatch.go
13
dispatch.go
|
@ -208,14 +208,13 @@ func (ag *aggrGroup) run(nf notifyFunc) {
|
|||
// point of time reference for the subsequent notification pipeline.
|
||||
// Calculating the current time directly is prone to avoid flaky behavior,
|
||||
// which usually only becomes apparent in tests.
|
||||
ctx = context.WithValue(ctx, notify.NotifyTime, now)
|
||||
ctx = notify.WithNow(ctx, now)
|
||||
|
||||
// Populate context with the destination name and group identifier.
|
||||
ctx = context.WithValue(ctx, notify.NotifyName, ag.opts.SendTo)
|
||||
ctx = context.WithValue(ctx, notify.NotifyGroup, ag.String())
|
||||
|
||||
ctx = context.WithValue(ctx, notify.NotifyRepeatInterval, ag.opts.RepeatInterval)
|
||||
ctx = context.WithValue(ctx, notify.NotifySendResolved, ag.opts.SendResolved)
|
||||
// Populate context with information needed along the pipeline.
|
||||
ctx = notify.WithDestination(ctx, ag.opts.SendTo)
|
||||
ctx = notify.WithGroup(ctx, ag.String())
|
||||
ctx = notify.WithRepeatInterval(ctx, ag.opts.RepeatInterval)
|
||||
ctx = notify.WithSendResolved(ctx, ag.opts.SendResolved)
|
||||
|
||||
// Wait the configured interval before calling flush again.
|
||||
ag.next.Reset(ag.opts.GroupInterval)
|
||||
|
|
|
@ -17,13 +17,58 @@ import (
|
|||
type notifyKey int
|
||||
|
||||
const (
|
||||
NotifyName notifyKey = iota
|
||||
NotifyRepeatInterval
|
||||
NotifySendResolved
|
||||
NotifyGroup
|
||||
NotifyTime
|
||||
keyDestination notifyKey = iota
|
||||
keyRepeatInterval
|
||||
keySendResolved
|
||||
keyGroup
|
||||
keyNow
|
||||
)
|
||||
|
||||
func WithDestination(ctx context.Context, dest string) context.Context {
|
||||
return context.WithValue(ctx, keyDestination, dest)
|
||||
}
|
||||
|
||||
func WithRepeatInterval(ctx context.Context, t time.Duration) context.Context {
|
||||
return context.WithValue(ctx, keyRepeatInterval, t)
|
||||
}
|
||||
|
||||
func WithSendResolved(ctx context.Context, b bool) context.Context {
|
||||
return context.WithValue(ctx, keySendResolved, b)
|
||||
}
|
||||
|
||||
func WithGroup(ctx context.Context, g string) context.Context {
|
||||
return context.WithValue(ctx, keyGroup, g)
|
||||
}
|
||||
|
||||
func WithNow(ctx context.Context, t time.Time) context.Context {
|
||||
return context.WithValue(ctx, keyNow, t)
|
||||
}
|
||||
|
||||
func Destination(ctx context.Context) (string, bool) {
|
||||
v, ok := ctx.Value(keyDestination).(string)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func RepeatInterval(ctx context.Context) (time.Duration, bool) {
|
||||
v, ok := ctx.Value(keyRepeatInterval).(time.Duration)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func SendResolved(ctx context.Context) (bool, bool) {
|
||||
v, ok := ctx.Value(keySendResolved).(bool)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func Group(ctx context.Context) (string, bool) {
|
||||
v, ok := ctx.Value(keyGroup).(string)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func Now(ctx context.Context) (time.Time, bool) {
|
||||
v, ok := ctx.Value(keyNow).(time.Time)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
type Notifier interface {
|
||||
Notify(context.Context, ...*types.Alert) error
|
||||
}
|
||||
|
@ -64,22 +109,22 @@ func NewDedupingNotifier(notifies provider.Notifies, n Notifier) *DedupingNotifi
|
|||
}
|
||||
|
||||
func (n *DedupingNotifier) Notify(ctx context.Context, alerts ...*types.Alert) error {
|
||||
name, ok := ctx.Value(NotifyName).(string)
|
||||
name, ok := Destination(ctx)
|
||||
if !ok {
|
||||
return fmt.Errorf("notifier name missing")
|
||||
}
|
||||
|
||||
repeatInterval, ok := ctx.Value(NotifyRepeatInterval).(time.Duration)
|
||||
repeatInterval, ok := RepeatInterval(ctx)
|
||||
if !ok {
|
||||
return fmt.Errorf("repeat interval missing")
|
||||
}
|
||||
|
||||
sendResolved, ok := ctx.Value(NotifySendResolved).(bool)
|
||||
sendResolved, ok := SendResolved(ctx)
|
||||
if !ok {
|
||||
return fmt.Errorf("send resolved missing")
|
||||
}
|
||||
|
||||
now, ok := ctx.Value(NotifyTime).(time.Time)
|
||||
now, ok := Now(ctx)
|
||||
if !ok {
|
||||
return fmt.Errorf("now time missing")
|
||||
}
|
||||
|
@ -185,7 +230,7 @@ func NewRoutedNotifier(build func([]*config.NotificationConfig) map[string]Notif
|
|||
}
|
||||
|
||||
func (n *RoutedNotifier) Notify(ctx context.Context, alerts ...*types.Alert) error {
|
||||
name, ok := ctx.Value(NotifyName).(string)
|
||||
name, ok := Destination(ctx)
|
||||
if !ok {
|
||||
return fmt.Errorf("notifier name missing")
|
||||
}
|
||||
|
|
|
@ -39,10 +39,10 @@ func TestDedupingNotifier(t *testing.T) {
|
|||
)
|
||||
now := time.Now()
|
||||
|
||||
ctx = context.WithValue(ctx, NotifyName, "name")
|
||||
ctx = context.WithValue(ctx, NotifyRepeatInterval, time.Duration(100*time.Minute))
|
||||
ctx = context.WithValue(ctx, NotifySendResolved, true)
|
||||
ctx = context.WithValue(ctx, NotifyTime, now)
|
||||
ctx = WithDestination(ctx, "name")
|
||||
ctx = WithRepeatInterval(ctx, time.Duration(100*time.Minute))
|
||||
ctx = WithSendResolved(ctx, true)
|
||||
ctx = WithNow(ctx, now)
|
||||
|
||||
alerts := []*types.Alert{
|
||||
{
|
||||
|
@ -237,7 +237,7 @@ func TestRoutedNotifier(t *testing.T) {
|
|||
|
||||
for _, route := range []string{"3", "2", "1"} {
|
||||
var (
|
||||
ctx = context.WithValue(context.Background(), NotifyName, route)
|
||||
ctx = WithDestination(context.Background(), route)
|
||||
alert = &types.Alert{
|
||||
Alert: model.Alert{
|
||||
Labels: model.LabelSet{"route": model.LabelValue(route)},
|
||||
|
|
Loading…
Reference in New Issue