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
f0b591b8
Commit
f0b591b8
authored
Nov 04, 2016
by
bergquist
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(alerting): extract logic state updates and notifications
ref #6444
parent
b8879113
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
160 additions
and
23 deletions
+160
-23
pkg/services/alerting/eval_context.go
+31
-0
pkg/services/alerting/eval_context_test.go
+110
-0
pkg/services/alerting/result_handler.go
+7
-12
pkg/services/alerting/rule.go
+12
-11
No files found.
pkg/services/alerting/eval_context.go
View file @
f0b591b8
...
@@ -26,6 +26,7 @@ type EvalContext struct {
...
@@ -26,6 +26,7 @@ type EvalContext struct {
ImagePublicUrl
string
ImagePublicUrl
string
ImageOnDiskPath
string
ImageOnDiskPath
string
NoDataFound
bool
NoDataFound
bool
PrevAlertState
m
.
AlertStateType
Ctx
context
.
Context
Ctx
context
.
Context
}
}
...
@@ -63,6 +64,36 @@ func (c *EvalContext) GetStateModel() *StateDescription {
...
@@ -63,6 +64,36 @@ func (c *EvalContext) GetStateModel() *StateDescription {
}
}
}
}
func
(
c
*
EvalContext
)
ShouldUpdateAlertState
()
bool
{
return
c
.
Rule
.
State
!=
c
.
PrevAlertState
}
func
(
c
*
EvalContext
)
ShouldSendNotification
()
bool
{
if
(
c
.
PrevAlertState
==
m
.
AlertStatePending
)
&&
(
c
.
Rule
.
State
==
m
.
AlertStateOK
)
{
return
false
}
alertState
:=
c
.
Rule
.
State
if
c
.
NoDataFound
{
if
c
.
Rule
.
NoDataState
==
m
.
NoDataKeepState
{
return
false
}
alertState
=
c
.
Rule
.
NoDataState
.
ToAlertState
()
}
if
c
.
Error
!=
nil
{
if
c
.
Rule
.
ExecutionErrorState
==
m
.
NoDataKeepState
{
return
false
}
alertState
=
c
.
Rule
.
ExecutionErrorState
.
ToAlertState
()
}
return
alertState
!=
c
.
PrevAlertState
}
func
(
a
*
EvalContext
)
GetDurationMs
()
float64
{
func
(
a
*
EvalContext
)
GetDurationMs
()
float64
{
return
float64
(
a
.
EndTime
.
Nanosecond
()
-
a
.
StartTime
.
Nanosecond
())
/
float64
(
1000000
)
return
float64
(
a
.
EndTime
.
Nanosecond
()
-
a
.
StartTime
.
Nanosecond
())
/
float64
(
1000000
)
}
}
...
...
pkg/services/alerting/eval_context_test.go
0 → 100644
View file @
f0b591b8
package
alerting
import
(
"context"
"fmt"
"testing"
"github.com/grafana/grafana/pkg/models"
.
"github.com/smartystreets/goconvey/convey"
)
func
TestAlertingEvalContext
(
t
*
testing
.
T
)
{
Convey
(
"Eval context"
,
t
,
func
()
{
ctx
:=
NewEvalContext
(
context
.
TODO
(),
&
Rule
{
Conditions
:
[]
Condition
{
&
conditionStub
{
firing
:
true
}}})
err
:=
fmt
.
Errorf
(
"Dummie error!"
)
Convey
(
"Should update alert state"
,
func
()
{
Convey
(
"ok -> alerting"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
State
=
models
.
AlertStateAlerting
So
(
ctx
.
ShouldUpdateAlertState
(),
ShouldBeTrue
)
})
Convey
(
"ok -> ok"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
State
=
models
.
AlertStateOK
So
(
ctx
.
ShouldUpdateAlertState
(),
ShouldBeFalse
)
})
})
Convey
(
"Should send notifications"
,
func
()
{
Convey
(
"pending -> ok"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStatePending
ctx
.
Rule
.
State
=
models
.
AlertStateOK
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeFalse
)
})
Convey
(
"ok -> alerting"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
State
=
models
.
AlertStateAlerting
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeTrue
)
})
Convey
(
"alerting -> ok"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateAlerting
ctx
.
Rule
.
State
=
models
.
AlertStateOK
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeTrue
)
})
Convey
(
"ok -> no_data(alerting)"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
NoDataState
=
models
.
NoDataSetAlerting
ctx
.
Rule
.
State
=
models
.
AlertStateAlerting
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeTrue
)
})
Convey
(
"ok -> no_data(ok)"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
NoDataState
=
models
.
NoDataSetOK
ctx
.
NoDataFound
=
true
ctx
.
Rule
.
State
=
models
.
AlertStateNoData
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeFalse
)
})
Convey
(
"ok -> no_data(keep_last)"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
NoDataState
=
models
.
NoDataKeepState
ctx
.
Rule
.
State
=
models
.
AlertStateNoData
ctx
.
NoDataFound
=
true
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeFalse
)
})
Convey
(
"ok -> execution_error(alerting)"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
State
=
models
.
AlertStateExecError
ctx
.
Rule
.
ExecutionErrorState
=
models
.
NoDataSetAlerting
ctx
.
Error
=
err
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeTrue
)
})
Convey
(
"ok -> execution_error(ok)"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
State
=
models
.
AlertStateExecError
ctx
.
Rule
.
ExecutionErrorState
=
models
.
NoDataSetOK
ctx
.
Error
=
err
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeFalse
)
})
Convey
(
"ok -> execution_error(keep_last)"
,
func
()
{
ctx
.
PrevAlertState
=
models
.
AlertStateOK
ctx
.
Rule
.
State
=
models
.
AlertStateExecError
ctx
.
Rule
.
ExecutionErrorState
=
models
.
NoDataKeepState
ctx
.
Error
=
err
So
(
ctx
.
ShouldSendNotification
(),
ShouldBeFalse
)
})
})
})
}
pkg/services/alerting/result_handler.go
View file @
f0b591b8
...
@@ -28,7 +28,7 @@ func NewResultHandler() *DefaultResultHandler {
...
@@ -28,7 +28,7 @@ func NewResultHandler() *DefaultResultHandler {
}
}
func
(
handler
*
DefaultResultHandler
)
Handle
(
evalContext
*
EvalContext
)
error
{
func
(
handler
*
DefaultResultHandler
)
Handle
(
evalContext
*
EvalContext
)
error
{
oldState
:
=
evalContext
.
Rule
.
State
evalContext
.
PrevAlertState
=
evalContext
.
Rule
.
State
executionError
:=
""
executionError
:=
""
annotationData
:=
simplejson
.
New
()
annotationData
:=
simplejson
.
New
()
...
@@ -51,8 +51,8 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
...
@@ -51,8 +51,8 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
}
}
countStateResult
(
evalContext
.
Rule
.
State
)
countStateResult
(
evalContext
.
Rule
.
State
)
if
handler
.
shouldUpdateAlertState
(
evalContext
,
oldState
)
{
if
evalContext
.
ShouldUpdateAlertState
(
)
{
handler
.
log
.
Info
(
"New state change"
,
"alertId"
,
evalContext
.
Rule
.
Id
,
"newState"
,
evalContext
.
Rule
.
State
,
"
oldState"
,
old
State
)
handler
.
log
.
Info
(
"New state change"
,
"alertId"
,
evalContext
.
Rule
.
Id
,
"newState"
,
evalContext
.
Rule
.
State
,
"
prev state"
,
evalContext
.
PrevAlert
State
)
cmd
:=
&
m
.
SetAlertStateCommand
{
cmd
:=
&
m
.
SetAlertStateCommand
{
AlertId
:
evalContext
.
Rule
.
Id
,
AlertId
:
evalContext
.
Rule
.
Id
,
...
@@ -76,7 +76,7 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
...
@@ -76,7 +76,7 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
Title
:
evalContext
.
Rule
.
Name
,
Title
:
evalContext
.
Rule
.
Name
,
Text
:
evalContext
.
GetStateModel
()
.
Text
,
Text
:
evalContext
.
GetStateModel
()
.
Text
,
NewState
:
string
(
evalContext
.
Rule
.
State
),
NewState
:
string
(
evalContext
.
Rule
.
State
),
PrevState
:
string
(
old
State
),
PrevState
:
string
(
evalContext
.
PrevAlert
State
),
Epoch
:
time
.
Now
()
.
Unix
(),
Epoch
:
time
.
Now
()
.
Unix
(),
Data
:
annotationData
,
Data
:
annotationData
,
}
}
...
@@ -86,21 +86,16 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
...
@@ -86,21 +86,16 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
handler
.
log
.
Error
(
"Failed to save annotation for new alert state"
,
"error"
,
err
)
handler
.
log
.
Error
(
"Failed to save annotation for new alert state"
,
"error"
,
err
)
}
}
if
(
oldState
==
m
.
AlertStatePending
)
&&
(
evalContext
.
Rule
.
State
==
m
.
AlertStateOK
)
{
if
evalContext
.
ShouldSendNotification
()
{
handler
.
log
.
Info
(
"Notfication not sent"
,
"oldState"
,
oldState
,
"newState"
,
evalContext
.
Rule
.
State
)
}
else
{
handler
.
notifier
.
Notify
(
evalContext
)
handler
.
notifier
.
Notify
(
evalContext
)
}
else
{
handler
.
log
.
Info
(
"Notfication not sent"
,
"prev state"
,
evalContext
.
PrevAlertState
,
"new state"
,
evalContext
.
Rule
.
State
)
}
}
}
}
return
nil
return
nil
}
}
func
(
handler
*
DefaultResultHandler
)
shouldUpdateAlertState
(
evalContext
*
EvalContext
,
oldState
m
.
AlertStateType
)
bool
{
return
evalContext
.
Rule
.
State
!=
oldState
}
func
countStateResult
(
state
m
.
AlertStateType
)
{
func
countStateResult
(
state
m
.
AlertStateType
)
{
switch
state
{
switch
state
{
case
m
.
AlertStatePending
:
case
m
.
AlertStatePending
:
...
...
pkg/services/alerting/rule.go
View file @
f0b591b8
...
@@ -11,17 +11,18 @@ import (
...
@@ -11,17 +11,18 @@ import (
)
)
type
Rule
struct
{
type
Rule
struct
{
Id
int64
Id
int64
OrgId
int64
OrgId
int64
DashboardId
int64
DashboardId
int64
PanelId
int64
PanelId
int64
Frequency
int64
Frequency
int64
Name
string
Name
string
Message
string
Message
string
NoDataState
m
.
NoDataOption
NoDataState
m
.
NoDataOption
State
m
.
AlertStateType
ExecutionErrorState
m
.
NoDataOption
Conditions
[]
Condition
State
m
.
AlertStateType
Notifications
[]
int64
Conditions
[]
Condition
Notifications
[]
int64
}
}
type
ValidationError
struct
{
type
ValidationError
struct
{
...
...
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