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:
Fabian Reinartz 2015-10-09 08:43:39 +02:00
parent 638b3f9f40
commit 0a5a7691fe
3 changed files with 66 additions and 22 deletions

View File

@ -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)

View File

@ -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")
}

View File

@ -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)},