Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
f001815d
Unverified
Commit
f001815d
authored
May 07, 2019
by
Carl Bergquist
Committed by
GitHub
May 07, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
alerting: no notification when going from nodata -> pending (#16905)
ref #16496
parent
b8674f4e
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
76 additions
and
62 deletions
+76
-62
pkg/services/alerting/eval_context_test.go
+6
-6
pkg/services/alerting/notifiers/base.go
+17
-11
pkg/services/alerting/notifiers/base_test.go
+53
-45
No files found.
pkg/services/alerting/eval_context_test.go
View file @
f001815d
...
@@ -6,6 +6,8 @@ import (
...
@@ -6,6 +6,8 @@ import (
"testing"
"testing"
"time"
"time"
"github.com/stretchr/testify/assert"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/models"
)
)
...
@@ -195,12 +197,10 @@ func TestGetStateFromEvalContext(t *testing.T) {
...
@@ -195,12 +197,10 @@ func TestGetStateFromEvalContext(t *testing.T) {
}
}
for
_
,
tc
:=
range
tcs
{
for
_
,
tc
:=
range
tcs
{
ctx
:=
NewEvalContext
(
context
.
TODO
(),
&
Rule
{
Conditions
:
[]
Condition
{
&
conditionStub
{
firing
:
true
}}})
evalContext
:=
NewEvalContext
(
context
.
Background
(),
&
Rule
{
Conditions
:
[]
Condition
{
&
conditionStub
{
firing
:
true
}}})
tc
.
applyFn
(
ctx
)
tc
.
applyFn
(
evalContext
)
have
:=
ctx
.
GetNewState
()
newState
:=
evalContext
.
GetNewState
()
if
have
!=
tc
.
expected
{
assert
.
Equal
(
t
,
tc
.
expected
,
newState
,
"failed: %s
\n
expected '%s' have '%s'
\n
"
,
tc
.
name
,
tc
.
expected
,
string
(
newState
))
t
.
Errorf
(
"failed: %s
\n
expected '%s' have '%s'
\n
"
,
tc
.
name
,
tc
.
expected
,
string
(
have
))
}
}
}
}
}
pkg/services/alerting/notifiers/base.go
View file @
f001815d
...
@@ -48,12 +48,15 @@ func NewNotifierBase(model *models.AlertNotification) NotifierBase {
...
@@ -48,12 +48,15 @@ func NewNotifierBase(model *models.AlertNotification) NotifierBase {
// ShouldNotify checks this evaluation should send an alert notification
// ShouldNotify checks this evaluation should send an alert notification
func
(
n
*
NotifierBase
)
ShouldNotify
(
ctx
context
.
Context
,
context
*
alerting
.
EvalContext
,
notiferState
*
models
.
AlertNotificationState
)
bool
{
func
(
n
*
NotifierBase
)
ShouldNotify
(
ctx
context
.
Context
,
context
*
alerting
.
EvalContext
,
notiferState
*
models
.
AlertNotificationState
)
bool
{
prevState
:=
context
.
PrevAlertState
newState
:=
context
.
Rule
.
State
// Only notify on state change.
// Only notify on state change.
if
context
.
PrevAlertState
==
context
.
Rule
.
State
&&
!
n
.
SendReminder
{
if
prevState
==
new
State
&&
!
n
.
SendReminder
{
return
false
return
false
}
}
if
context
.
PrevAlertState
==
context
.
Rule
.
State
&&
n
.
SendReminder
{
if
prevState
==
new
State
&&
n
.
SendReminder
{
// Do not notify if interval has not elapsed
// Do not notify if interval has not elapsed
lastNotify
:=
time
.
Unix
(
notiferState
.
UpdatedAt
,
0
)
lastNotify
:=
time
.
Unix
(
notiferState
.
UpdatedAt
,
0
)
if
notiferState
.
UpdatedAt
!=
0
&&
lastNotify
.
Add
(
n
.
Frequency
)
.
After
(
time
.
Now
())
{
if
notiferState
.
UpdatedAt
!=
0
&&
lastNotify
.
Add
(
n
.
Frequency
)
.
After
(
time
.
Now
())
{
...
@@ -61,32 +64,35 @@ func (n *NotifierBase) ShouldNotify(ctx context.Context, context *alerting.EvalC
...
@@ -61,32 +64,35 @@ func (n *NotifierBase) ShouldNotify(ctx context.Context, context *alerting.EvalC
}
}
// Do not notify if alert state is OK or pending even on repeated notify
// Do not notify if alert state is OK or pending even on repeated notify
if
context
.
Rule
.
State
==
models
.
AlertStateOK
||
context
.
Rule
.
State
==
models
.
AlertStatePending
{
if
newState
==
models
.
AlertStateOK
||
new
State
==
models
.
AlertStatePending
{
return
false
return
false
}
}
}
}
// Do not notify when we become OK for the first time.
unknownOrNoData
:=
prevState
==
models
.
AlertStateUnknown
||
prevState
==
models
.
AlertStateNoData
if
context
.
PrevAlertState
==
models
.
AlertStateUnknown
&&
context
.
Rule
.
State
==
models
.
AlertStateOK
{
okOrPending
:=
newState
==
models
.
AlertStatePending
||
newState
==
models
.
AlertStateOK
// Do not notify when new state is ok/pending when previous is unknown or no_data
if
unknownOrNoData
&&
okOrPending
{
return
false
return
false
}
}
// Do not notify when we become
OK for the first time.
// Do not notify when we become
Pending for the first
if
context
.
PrevAlertState
==
models
.
AlertStateUnknown
&&
context
.
Rule
.
State
==
models
.
AlertStatePending
{
if
prevState
==
models
.
AlertStateNoData
&&
new
State
==
models
.
AlertStatePending
{
return
false
return
false
}
}
// Do not notify when we become OK from pending
// Do not notify when we become OK from pending
if
context
.
PrevAlertState
==
models
.
AlertStatePending
&&
context
.
Rule
.
State
==
models
.
AlertStateOK
{
if
prevState
==
models
.
AlertStatePending
&&
new
State
==
models
.
AlertStateOK
{
return
false
return
false
}
}
// Do not notify when we OK -> Pending
// Do not notify when we OK -> Pending
if
context
.
PrevAlertState
==
models
.
AlertStateOK
&&
context
.
Rule
.
State
==
models
.
AlertStatePending
{
if
prevState
==
models
.
AlertStateOK
&&
new
State
==
models
.
AlertStatePending
{
return
false
return
false
}
}
// Do not notif
u
if state pending and it have been updated last minute
// Do not notif
y
if state pending and it have been updated last minute
if
notiferState
.
State
==
models
.
AlertNotificationStatePending
{
if
notiferState
.
State
==
models
.
AlertNotificationStatePending
{
lastUpdated
:=
time
.
Unix
(
notiferState
.
UpdatedAt
,
0
)
lastUpdated
:=
time
.
Unix
(
notiferState
.
UpdatedAt
,
0
)
if
lastUpdated
.
Add
(
1
*
time
.
Minute
)
.
After
(
time
.
Now
())
{
if
lastUpdated
.
Add
(
1
*
time
.
Minute
)
.
After
(
time
.
Now
())
{
...
@@ -95,7 +101,7 @@ func (n *NotifierBase) ShouldNotify(ctx context.Context, context *alerting.EvalC
...
@@ -95,7 +101,7 @@ func (n *NotifierBase) ShouldNotify(ctx context.Context, context *alerting.EvalC
}
}
// Do not notify when state is OK if DisableResolveMessage is set to true
// Do not notify when state is OK if DisableResolveMessage is set to true
if
context
.
Rule
.
State
==
models
.
AlertStateOK
&&
n
.
DisableResolveMessage
{
if
new
State
==
models
.
AlertStateOK
&&
n
.
DisableResolveMessage
{
return
false
return
false
}
}
...
...
pkg/services/alerting/notifiers/base_test.go
View file @
f001815d
...
@@ -5,8 +5,10 @@ import (
...
@@ -5,8 +5,10 @@ import (
"testing"
"testing"
"time"
"time"
"github.com/stretchr/testify/assert"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/components/simplejson"
m
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/alerting"
.
"github.com/smartystreets/goconvey/convey"
.
"github.com/smartystreets/goconvey/convey"
)
)
...
@@ -16,76 +18,76 @@ func TestShouldSendAlertNotification(t *testing.T) {
...
@@ -16,76 +18,76 @@ func TestShouldSendAlertNotification(t *testing.T) {
tcs
:=
[]
struct
{
tcs
:=
[]
struct
{
name
string
name
string
prevState
m
.
AlertStateType
prevState
m
odels
.
AlertStateType
newState
m
.
AlertStateType
newState
m
odels
.
AlertStateType
sendReminder
bool
sendReminder
bool
frequency
time
.
Duration
frequency
time
.
Duration
state
*
m
.
AlertNotificationState
state
*
m
odels
.
AlertNotificationState
expect
bool
expect
bool
}{
}{
{
{
name
:
"pending -> ok should not trigger an notification"
,
name
:
"pending -> ok should not trigger an notification"
,
newState
:
m
.
AlertStateOK
,
newState
:
m
odels
.
AlertStateOK
,
prevState
:
m
.
AlertStatePending
,
prevState
:
m
odels
.
AlertStatePending
,
sendReminder
:
false
,
sendReminder
:
false
,
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"ok -> alerting should trigger an notification"
,
name
:
"ok -> alerting should trigger an notification"
,
newState
:
m
.
AlertStateAlerting
,
newState
:
m
odels
.
AlertStateAlerting
,
prevState
:
m
.
AlertStateOK
,
prevState
:
m
odels
.
AlertStateOK
,
sendReminder
:
false
,
sendReminder
:
false
,
expect
:
true
,
expect
:
true
,
},
},
{
{
name
:
"ok -> pending should not trigger an notification"
,
name
:
"ok -> pending should not trigger an notification"
,
newState
:
m
.
AlertStatePending
,
newState
:
m
odels
.
AlertStatePending
,
prevState
:
m
.
AlertStateOK
,
prevState
:
m
odels
.
AlertStateOK
,
sendReminder
:
false
,
sendReminder
:
false
,
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"ok -> ok should not trigger an notification"
,
name
:
"ok -> ok should not trigger an notification"
,
newState
:
m
.
AlertStateOK
,
newState
:
m
odels
.
AlertStateOK
,
prevState
:
m
.
AlertStateOK
,
prevState
:
m
odels
.
AlertStateOK
,
sendReminder
:
false
,
sendReminder
:
false
,
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"ok -> ok with reminder should not trigger an notification"
,
name
:
"ok -> ok with reminder should not trigger an notification"
,
newState
:
m
.
AlertStateOK
,
newState
:
m
odels
.
AlertStateOK
,
prevState
:
m
.
AlertStateOK
,
prevState
:
m
odels
.
AlertStateOK
,
sendReminder
:
true
,
sendReminder
:
true
,
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"alerting -> ok should trigger an notification"
,
name
:
"alerting -> ok should trigger an notification"
,
newState
:
m
.
AlertStateOK
,
newState
:
m
odels
.
AlertStateOK
,
prevState
:
m
.
AlertStateAlerting
,
prevState
:
m
odels
.
AlertStateAlerting
,
sendReminder
:
false
,
sendReminder
:
false
,
expect
:
true
,
expect
:
true
,
},
},
{
{
name
:
"alerting -> ok should trigger an notification when reminders enabled"
,
name
:
"alerting -> ok should trigger an notification when reminders enabled"
,
newState
:
m
.
AlertStateOK
,
newState
:
m
odels
.
AlertStateOK
,
prevState
:
m
.
AlertStateAlerting
,
prevState
:
m
odels
.
AlertStateAlerting
,
frequency
:
time
.
Minute
*
10
,
frequency
:
time
.
Minute
*
10
,
sendReminder
:
true
,
sendReminder
:
true
,
state
:
&
m
.
AlertNotificationState
{
UpdatedAt
:
tnow
.
Add
(
-
time
.
Minute
)
.
Unix
()},
state
:
&
m
odels
.
AlertNotificationState
{
UpdatedAt
:
tnow
.
Add
(
-
time
.
Minute
)
.
Unix
()},
expect
:
true
,
expect
:
true
,
},
},
{
{
name
:
"alerting -> alerting with reminder and no state should trigger"
,
name
:
"alerting -> alerting with reminder and no state should trigger"
,
newState
:
m
.
AlertStateAlerting
,
newState
:
m
odels
.
AlertStateAlerting
,
prevState
:
m
.
AlertStateAlerting
,
prevState
:
m
odels
.
AlertStateAlerting
,
frequency
:
time
.
Minute
*
10
,
frequency
:
time
.
Minute
*
10
,
sendReminder
:
true
,
sendReminder
:
true
,
...
@@ -93,78 +95,84 @@ func TestShouldSendAlertNotification(t *testing.T) {
...
@@ -93,78 +95,84 @@ func TestShouldSendAlertNotification(t *testing.T) {
},
},
{
{
name
:
"alerting -> alerting with reminder and last notification sent 1 minute ago should not trigger"
,
name
:
"alerting -> alerting with reminder and last notification sent 1 minute ago should not trigger"
,
newState
:
m
.
AlertStateAlerting
,
newState
:
m
odels
.
AlertStateAlerting
,
prevState
:
m
.
AlertStateAlerting
,
prevState
:
m
odels
.
AlertStateAlerting
,
frequency
:
time
.
Minute
*
10
,
frequency
:
time
.
Minute
*
10
,
sendReminder
:
true
,
sendReminder
:
true
,
state
:
&
m
.
AlertNotificationState
{
UpdatedAt
:
tnow
.
Add
(
-
time
.
Minute
)
.
Unix
()},
state
:
&
m
odels
.
AlertNotificationState
{
UpdatedAt
:
tnow
.
Add
(
-
time
.
Minute
)
.
Unix
()},
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"alerting -> alerting with reminder and last notifciation sent 11 minutes ago should trigger"
,
name
:
"alerting -> alerting with reminder and last notifciation sent 11 minutes ago should trigger"
,
newState
:
m
.
AlertStateAlerting
,
newState
:
m
odels
.
AlertStateAlerting
,
prevState
:
m
.
AlertStateAlerting
,
prevState
:
m
odels
.
AlertStateAlerting
,
frequency
:
time
.
Minute
*
10
,
frequency
:
time
.
Minute
*
10
,
sendReminder
:
true
,
sendReminder
:
true
,
state
:
&
m
.
AlertNotificationState
{
UpdatedAt
:
tnow
.
Add
(
-
11
*
time
.
Minute
)
.
Unix
()},
state
:
&
m
odels
.
AlertNotificationState
{
UpdatedAt
:
tnow
.
Add
(
-
11
*
time
.
Minute
)
.
Unix
()},
expect
:
true
,
expect
:
true
,
},
},
{
{
name
:
"OK -> alerting with notifciation state pending and updated 30 seconds ago should not trigger"
,
name
:
"OK -> alerting with notifciation state pending and updated 30 seconds ago should not trigger"
,
newState
:
m
.
AlertStateAlerting
,
newState
:
m
odels
.
AlertStateAlerting
,
prevState
:
m
.
AlertStateOK
,
prevState
:
m
odels
.
AlertStateOK
,
state
:
&
m
.
AlertNotificationState
{
State
:
m
.
AlertNotificationStatePending
,
UpdatedAt
:
tnow
.
Add
(
-
30
*
time
.
Second
)
.
Unix
()},
state
:
&
m
odels
.
AlertNotificationState
{
State
:
models
.
AlertNotificationStatePending
,
UpdatedAt
:
tnow
.
Add
(
-
30
*
time
.
Second
)
.
Unix
()},
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"OK -> alerting with notifciation state pending and updated 2 minutes ago should trigger"
,
name
:
"OK -> alerting with notifciation state pending and updated 2 minutes ago should trigger"
,
newState
:
m
.
AlertStateAlerting
,
newState
:
m
odels
.
AlertStateAlerting
,
prevState
:
m
.
AlertStateOK
,
prevState
:
m
odels
.
AlertStateOK
,
state
:
&
m
.
AlertNotificationState
{
State
:
m
.
AlertNotificationStatePending
,
UpdatedAt
:
tnow
.
Add
(
-
2
*
time
.
Minute
)
.
Unix
()},
state
:
&
m
odels
.
AlertNotificationState
{
State
:
models
.
AlertNotificationStatePending
,
UpdatedAt
:
tnow
.
Add
(
-
2
*
time
.
Minute
)
.
Unix
()},
expect
:
true
,
expect
:
true
,
},
},
{
{
name
:
"unknown -> ok"
,
name
:
"unknown -> ok"
,
prevState
:
m
.
AlertStateUnknown
,
prevState
:
m
odels
.
AlertStateUnknown
,
newState
:
m
.
AlertStateOK
,
newState
:
m
odels
.
AlertStateOK
,
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"unknown -> pending"
,
name
:
"unknown -> pending"
,
prevState
:
m
.
AlertStateUnknown
,
prevState
:
m
odels
.
AlertStateUnknown
,
newState
:
m
.
AlertStatePending
,
newState
:
m
odels
.
AlertStatePending
,
expect
:
false
,
expect
:
false
,
},
},
{
{
name
:
"unknown -> alerting"
,
name
:
"unknown -> alerting"
,
prevState
:
m
.
AlertStateUnknown
,
prevState
:
m
odels
.
AlertStateUnknown
,
newState
:
m
.
AlertStateAlerting
,
newState
:
m
odels
.
AlertStateAlerting
,
expect
:
true
,
expect
:
true
,
},
},
{
name
:
"no_data -> pending"
,
prevState
:
models
.
AlertStateNoData
,
newState
:
models
.
AlertStatePending
,
expect
:
false
,
},
}
}
for
_
,
tc
:=
range
tcs
{
for
_
,
tc
:=
range
tcs
{
evalContext
:=
alerting
.
NewEvalContext
(
context
.
TODO
(),
&
alerting
.
Rule
{
evalContext
:=
alerting
.
NewEvalContext
(
context
.
Background
(),
&
alerting
.
Rule
{
State
:
tc
.
prevState
,
State
:
tc
.
prevState
,
})
})
if
tc
.
state
==
nil
{
if
tc
.
state
==
nil
{
tc
.
state
=
&
m
.
AlertNotificationState
{}
tc
.
state
=
&
m
odels
.
AlertNotificationState
{}
}
}
evalContext
.
Rule
.
State
=
tc
.
newState
evalContext
.
Rule
.
State
=
tc
.
newState
nb
:=
&
NotifierBase
{
SendReminder
:
tc
.
sendReminder
,
Frequency
:
tc
.
frequency
}
nb
:=
&
NotifierBase
{
SendReminder
:
tc
.
sendReminder
,
Frequency
:
tc
.
frequency
}
if
nb
.
ShouldNotify
(
evalContext
.
Ctx
,
evalContext
,
tc
.
state
)
!=
tc
.
expect
{
r
:=
nb
.
ShouldNotify
(
evalContext
.
Ctx
,
evalContext
,
tc
.
state
)
t
.
Errorf
(
"failed test %s.
\n
expected
\n
%+v
\n
to return: %v"
,
tc
.
name
,
tc
,
tc
.
expect
)
assert
.
Equal
(
t
,
r
,
tc
.
expect
,
"failed test %s. expected %+v to return: %v"
,
tc
.
name
,
tc
,
tc
.
expect
)
}
}
}
}
}
...
@@ -172,7 +180,7 @@ func TestBaseNotifier(t *testing.T) {
...
@@ -172,7 +180,7 @@ func TestBaseNotifier(t *testing.T) {
Convey
(
"default constructor for notifiers"
,
t
,
func
()
{
Convey
(
"default constructor for notifiers"
,
t
,
func
()
{
bJson
:=
simplejson
.
New
()
bJson
:=
simplejson
.
New
()
model
:=
&
m
.
AlertNotification
{
model
:=
&
m
odels
.
AlertNotification
{
Uid
:
"1"
,
Uid
:
"1"
,
Name
:
"name"
,
Name
:
"name"
,
Type
:
"email"
,
Type
:
"email"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment