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
c1763508
Unverified
Commit
c1763508
authored
Sep 28, 2018
by
Marcus Efraimsson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
handle pending and completed state for alert notifications
parent
2bf399d3
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
96 additions
and
82 deletions
+96
-82
pkg/models/alert_notifications.go
+1
-3
pkg/services/alerting/notifier.go
+21
-8
pkg/services/alerting/notifiers/base_test.go
+0
-26
pkg/services/sqlstore/alert_notification.go
+16
-5
pkg/services/sqlstore/alert_notification_test.go
+58
-40
No files found.
pkg/models/alert_notifications.go
View file @
c1763508
...
...
@@ -100,9 +100,7 @@ type SetAlertNotificationStateToPendingCommand struct {
}
type
SetAlertNotificationStateToCompleteCommand
struct
{
Id
int64
Version
int64
SentAt
int64
State
*
AlertNotificationState
}
type
GetNotificationStateQuery
struct
{
...
...
pkg/services/alerting/notifier.go
View file @
c1763508
...
...
@@ -8,6 +8,7 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/imguploader"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/metrics"
"github.com/grafana/grafana/pkg/services/rendering"
"github.com/grafana/grafana/pkg/setting"
...
...
@@ -58,20 +59,32 @@ func (n *notificationService) SendIfNeeded(context *EvalContext) error {
}
func
(
n
*
notificationService
)
sendAndMarkAsComplete
(
evalContext
*
EvalContext
,
notifierState
*
NotifierState
)
error
{
err
:=
notifierState
.
notifier
.
Notify
(
evalContext
)
not
:=
notifierState
.
notifier
n
.
log
.
Debug
(
"Sending notification"
,
"type"
,
not
.
GetType
(),
"id"
,
not
.
GetNotifierId
(),
"isDefault"
,
not
.
GetIsDefault
())
metrics
.
M_Alerting_Notification_Sent
.
WithLabelValues
(
not
.
GetType
())
.
Inc
()
err
:=
not
.
Notify
(
evalContext
)
if
err
!=
nil
{
n
.
log
.
Error
(
"failed to send notification"
,
"id"
,
not
.
GetNotifierId
())
}
else
{
notifierState
.
state
.
SentAt
=
time
.
Now
()
.
Unix
()
}
if
evalContext
.
IsTestRun
{
return
nil
}
cmd
:=
&
m
.
SetAlertNotificationStateToCompleteCommand
{
Id
:
notifierState
.
state
.
Id
,
Version
:
notifierState
.
state
.
Version
,
SentAt
:
time
.
Now
()
.
Unix
(),
State
:
notifierState
.
state
,
}
err
=
bus
.
DispatchCtx
(
evalContext
.
Ctx
,
cmd
)
if
err
=
bus
.
DispatchCtx
(
evalContext
.
Ctx
,
cmd
);
err
!=
nil
{
if
err
==
m
.
ErrAlertNotificationStateVersionConflict
{
n
.
log
.
Error
(
"notification state out of sync"
,
"id"
,
not
.
GetNotifierId
())
return
nil
}
if
err
!=
nil
{
return
err
}
...
...
@@ -79,8 +92,7 @@ func (n *notificationService) sendAndMarkAsComplete(evalContext *EvalContext, no
}
func
(
n
*
notificationService
)
sendNotification
(
evalContext
*
EvalContext
,
notifierState
*
NotifierState
)
error
{
n
.
log
.
Debug
(
"trying to send notification"
,
"id"
,
notifierState
.
notifier
.
GetNotifierId
())
if
!
evalContext
.
IsTestRun
{
setPendingCmd
:=
&
m
.
SetAlertNotificationStateToPendingCommand
{
State
:
notifierState
.
state
,
}
...
...
@@ -93,6 +105,7 @@ func (n *notificationService) sendNotification(evalContext *EvalContext, notifie
if
err
!=
nil
{
return
err
}
}
return
n
.
sendAndMarkAsComplete
(
evalContext
,
notifierState
)
}
...
...
pkg/services/alerting/notifiers/base_test.go
View file @
c1763508
...
...
@@ -121,32 +121,6 @@ func TestShouldSendAlertNotification(t *testing.T) {
}
}
func
TestShouldNotifyWhenNoJournalingIsFound
(
t
*
testing
.
T
)
{
Convey
(
"base notifier"
,
t
,
func
()
{
//bus.ClearBusHandlers()
//
//notifier := NewNotifierBase(&m.AlertNotification{
// Id: 1,
// Name: "name",
// Type: "email",
// Settings: simplejson.New(),
//})
//evalContext := alerting.NewEvalContext(context.TODO(), &alerting.Rule{})
//
//Convey("should not notify query returns error", func() {
// bus.AddHandlerCtx("", func(ctx context.Context, q *m.GetNotificationStateQuery) error {
// return errors.New("some kind of error unknown error")
// })
//
// if notifier.ShouldNotify(context.Background(), evalContext) {
// t.Errorf("should not send notifications when query returns error")
// }
//})
t
.
Error
(
"might not need this anymore, at least not like this, control flow has changedd"
)
})
}
func
TestBaseNotifier
(
t
*
testing
.
T
)
{
Convey
(
"default constructor for notifiers"
,
t
,
func
()
{
bJson
:=
simplejson
.
New
()
...
...
pkg/services/sqlstore/alert_notification.go
View file @
c1763508
...
...
@@ -255,20 +255,26 @@ func InsertAlertNotificationState(ctx context.Context, cmd *m.InsertAlertNotific
func
SetAlertNotificationStateToCompleteCommand
(
ctx
context
.
Context
,
cmd
*
m
.
SetAlertNotificationStateToCompleteCommand
)
error
{
return
withDbSession
(
ctx
,
func
(
sess
*
DBSession
)
error
{
version
:=
cmd
.
State
.
Version
var
current
m
.
AlertNotificationState
sess
.
ID
(
cmd
.
State
.
Id
)
.
Get
(
&
current
)
cmd
.
State
.
State
=
m
.
AlertNotificationStateCompleted
cmd
.
State
.
Version
++
sql
:=
`UPDATE alert_notification_state SET
state = ?,
version = ?
WHERE
id = ?`
res
,
err
:=
sess
.
Exec
(
sql
,
m
.
AlertNotificationStateCompleted
,
cmd
.
Id
,
cmd
.
Version
+
1
)
_
,
err
:=
sess
.
Exec
(
sql
,
cmd
.
State
.
State
,
cmd
.
State
.
Version
,
cmd
.
State
.
Id
)
if
err
!=
nil
{
return
err
}
affected
,
_
:=
res
.
RowsAffected
()
if
affected
==
0
{
if
current
.
Version
!=
version
{
return
m
.
ErrAlertNotificationStateVersionConflict
}
...
...
@@ -278,6 +284,10 @@ func SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *m.SetA
func
SetAlertNotificationStateToPendingCommand
(
ctx
context
.
Context
,
cmd
*
m
.
SetAlertNotificationStateToPendingCommand
)
error
{
return
withDbSession
(
ctx
,
func
(
sess
*
DBSession
)
error
{
currentVersion
:=
cmd
.
State
.
Version
cmd
.
State
.
State
=
m
.
AlertNotificationStatePending
cmd
.
State
.
Version
++
sql
:=
`UPDATE alert_notification_state SET
state = ?,
version = ?
...
...
@@ -285,7 +295,8 @@ func SetAlertNotificationStateToPendingCommand(ctx context.Context, cmd *m.SetAl
id = ? AND
version = ?`
res
,
err
:=
sess
.
Exec
(
sql
,
m
.
AlertNotificationStatePending
,
cmd
.
State
.
Version
+
1
,
cmd
.
State
.
Id
,
cmd
.
State
.
Version
)
res
,
err
:=
sess
.
Exec
(
sql
,
cmd
.
State
.
State
,
cmd
.
State
.
Version
,
cmd
.
State
.
Id
,
currentVersion
)
if
err
!=
nil
{
return
err
}
...
...
pkg/services/sqlstore/alert_notification_test.go
View file @
c1763508
...
...
@@ -25,6 +25,7 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So
(
err
,
ShouldBeNil
)
So
(
query
.
Result
,
ShouldNotBeNil
)
So
(
query
.
Result
.
State
,
ShouldEqual
,
"unknown"
)
So
(
query
.
Result
.
Version
,
ShouldEqual
,
0
)
Convey
(
"Get existing state should not create a new state"
,
func
()
{
query2
:=
&
models
.
GetNotificationStateQuery
{
AlertId
:
alertID
,
OrgId
:
orgID
,
NotifierId
:
notifierID
}
...
...
@@ -33,49 +34,66 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So
(
query2
.
Result
,
ShouldNotBeNil
)
So
(
query2
.
Result
.
Id
,
ShouldEqual
,
query
.
Result
.
Id
)
})
Convey
(
"Update existing state to pending with correct version should update database"
,
func
()
{
s
:=
*
query
.
Result
cmd
:=
models
.
SetAlertNotificationStateToPendingCommand
{
State
:
&
s
,
}
err
:=
SetAlertNotificationStateToPendingCommand
(
context
.
Background
(),
&
cmd
)
So
(
err
,
ShouldBeNil
)
So
(
cmd
.
State
.
Version
,
ShouldEqual
,
1
)
So
(
cmd
.
State
.
State
,
ShouldEqual
,
models
.
AlertNotificationStatePending
)
query2
:=
&
models
.
GetNotificationStateQuery
{
AlertId
:
alertID
,
OrgId
:
orgID
,
NotifierId
:
notifierID
}
err
=
GetAlertNotificationState
(
context
.
Background
(),
query2
)
So
(
err
,
ShouldBeNil
)
So
(
query2
.
Result
.
Version
,
ShouldEqual
,
1
)
So
(
query2
.
Result
.
State
,
ShouldEqual
,
models
.
AlertNotificationStatePending
)
Convey
(
"Update existing state to completed should update database"
,
func
()
{
s
:=
*
cmd
.
State
cmd
:=
models
.
SetAlertNotificationStateToCompleteCommand
{
State
:
&
s
,
}
err
:=
SetAlertNotificationStateToCompleteCommand
(
context
.
Background
(),
&
cmd
)
So
(
err
,
ShouldBeNil
)
query3
:=
&
models
.
GetNotificationStateQuery
{
AlertId
:
alertID
,
OrgId
:
orgID
,
NotifierId
:
notifierID
}
err
=
GetAlertNotificationState
(
context
.
Background
(),
query3
)
So
(
err
,
ShouldBeNil
)
So
(
query3
.
Result
.
Version
,
ShouldEqual
,
2
)
So
(
query3
.
Result
.
State
,
ShouldEqual
,
models
.
AlertNotificationStateCompleted
)
})
Convey
(
"Update existing state to completed should update database, but return version mismatch"
,
func
()
{
cmd
.
State
.
Version
=
1000
s
:=
*
cmd
.
State
cmd
:=
models
.
SetAlertNotificationStateToCompleteCommand
{
State
:
&
s
,
}
err
:=
SetAlertNotificationStateToCompleteCommand
(
context
.
Background
(),
&
cmd
)
So
(
err
,
ShouldEqual
,
models
.
ErrAlertNotificationStateVersionConflict
)
query3
:=
&
models
.
GetNotificationStateQuery
{
AlertId
:
alertID
,
OrgId
:
orgID
,
NotifierId
:
notifierID
}
err
=
GetAlertNotificationState
(
context
.
Background
(),
query3
)
So
(
err
,
ShouldBeNil
)
So
(
query3
.
Result
.
Version
,
ShouldEqual
,
1001
)
So
(
query3
.
Result
.
State
,
ShouldEqual
,
models
.
AlertNotificationStateCompleted
)
})
})
//Convey("Can insert new state for alert notifier", func() {
// createCmd := &models.InsertAlertNotificationCommand{
// AlertId: alertId,
// NotifierId: notifierId,
// OrgId: orgId,
// SentAt: 1,
// State: models.AlertNotificationStateCompleted,
// }
//
// err := InsertAlertNotificationState(context.Background(), createCmd)
// So(err, ShouldBeNil)
//
// err = InsertAlertNotificationState(context.Background(), createCmd)
// So(err, ShouldEqual, models.ErrAlertNotificationStateAlreadyExist)
//
// Convey("should be able to update alert notifier state", func() {
// updateCmd := &models.SetAlertNotificationStateToPendingCommand{
// State: models.AlertNotificationState{
// Id: 1,
// SentAt: 1,
// Version: 0,
// }
// }
//
// err := SetAlertNotificationStateToPendingCommand(context.Background(), updateCmd)
// So(err, ShouldBeNil)
//
// Convey("should not be able to set pending on old version", func() {
// err = SetAlertNotificationStateToPendingCommand(context.Background(), updateCmd)
// So(err, ShouldEqual, models.ErrAlertNotificationStateVersionConflict)
// })
//
// Convey("should be able to set state to completed", func() {
// cmd := &models.SetAlertNotificationStateToCompleteCommand{Id: 1}
// err = SetAlertNotificationStateToCompleteCommand(context.Background(), cmd)
// So(err, ShouldBeNil)
// })
// })
// })
//})
Convey
(
"Update existing state to pending with incorrect version should return version mismatch error"
,
func
()
{
s
:=
*
query
.
Result
s
.
Version
=
1000
cmd
:=
models
.
SetAlertNotificationStateToPendingCommand
{
State
:
&
s
,
}
err
:=
SetAlertNotificationStateToPendingCommand
(
context
.
Background
(),
&
cmd
)
So
(
err
,
ShouldEqual
,
models
.
ErrAlertNotificationStateVersionConflict
)
})
})
})
Convey
(
"Alert notifications should be empty"
,
func
()
{
cmd
:=
&
models
.
GetAlertNotificationsQuery
{
...
...
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