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
44a795cb
Unverified
Commit
44a795cb
authored
Oct 16, 2020
by
Kyle Brandt
Committed by
GitHub
Oct 16, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
AlertingNG: remove warn/crit from eval prototype (#28334)
and misc cleanup
parent
4c8e4f35
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
54 additions
and
46 deletions
+54
-46
pkg/api/api.go
+1
-1
pkg/api/dtos/ngalert.go
+3
-3
pkg/api/ngalert.go
+3
-3
pkg/services/ngalert/eval.go
+47
-39
No files found.
pkg/api/api.go
View file @
44a795cb
...
...
@@ -355,7 +355,7 @@ func (hs *HTTPServer) registerRoutes() {
if
hs
.
Cfg
.
IsNgAlertEnabled
()
{
apiRoute
.
Group
(
"/alert-definitions"
,
func
(
alertDefinitions
routing
.
RouteRegister
)
{
alertDefinitions
.
Get
(
"/eval/:dashboardID/:panelID/:refID"
,
reqEditorRole
,
Wrap
(
hs
.
AlertDefinitionEval
))
alertDefinitions
.
Post
(
"/eval"
,
reqEditorRole
,
bind
(
dtos
.
EvalAlertCondition
sCommand
{}),
Wrap
(
hs
.
Conditions
Eval
))
alertDefinitions
.
Post
(
"/eval"
,
reqEditorRole
,
bind
(
dtos
.
EvalAlertCondition
Command
{}),
Wrap
(
hs
.
Condition
Eval
))
})
}
...
...
pkg/api/dtos/ngalert.go
View file @
44a795cb
...
...
@@ -6,7 +6,7 @@ import (
eval
"github.com/grafana/grafana/pkg/services/ngalert"
)
type
EvalAlertCondition
s
Command
struct
{
Condition
s
eval
.
Conditions
`json:"conditions
"`
Now
time
.
Time
`json:"now"`
type
EvalAlertConditionCommand
struct
{
Condition
eval
.
Condition
`json:"condition
"`
Now
time
.
Time
`json:"now"`
}
pkg/api/ngalert.go
View file @
44a795cb
...
...
@@ -13,7 +13,7 @@ import (
)
// POST /api/alert-definitions/eval
func
(
hs
*
HTTPServer
)
Condition
sEval
(
c
*
models
.
ReqContext
,
dto
dtos
.
EvalAlertConditions
Command
)
Response
{
func
(
hs
*
HTTPServer
)
Condition
Eval
(
c
*
models
.
ReqContext
,
dto
dtos
.
EvalAlertCondition
Command
)
Response
{
alertCtx
,
cancelFn
:=
context
.
WithTimeout
(
context
.
Background
(),
setting
.
AlertingEvaluationTimeout
)
defer
cancelFn
()
...
...
@@ -29,7 +29,7 @@ func (hs *HTTPServer) ConditionsEval(c *models.ReqContext, dto dtos.EvalAlertCon
toStr
=
"now"
}
execResult
,
err
:=
dto
.
Condition
s
.
Execute
(
alertExecCtx
,
fromStr
,
toStr
)
execResult
,
err
:=
dto
.
Condition
.
Execute
(
alertExecCtx
,
fromStr
,
toStr
)
if
err
!=
nil
{
return
Error
(
400
,
"Failed to execute conditions"
,
err
)
}
...
...
@@ -67,7 +67,7 @@ func (hs *HTTPServer) AlertDefinitionEval(c *models.ReqContext) Response {
toStr
=
"now"
}
conditions
,
err
:=
hs
.
AlertNG
.
LoadAlertCondition
s
(
dashboardID
,
panelID
,
conditionRefID
,
c
.
SignedInUser
,
c
.
SkipCache
)
conditions
,
err
:=
hs
.
AlertNG
.
LoadAlertCondition
(
dashboardID
,
panelID
,
conditionRefID
,
c
.
SignedInUser
,
c
.
SkipCache
)
if
err
!=
nil
{
return
Error
(
400
,
"Failed to load conditions"
,
err
)
}
...
...
pkg/services/ngalert/eval.go
View file @
44a795cb
// Package eval executes the condition for an alert definition, evaluates the condition results, and
// returns the alert instance states.
package
eval
import
(
...
...
@@ -24,6 +26,7 @@ type minimalDashboard struct {
}
`json:"panels"`
}
// AlertNG is the service for evaluating the condition of an alert definition.
type
AlertNG
struct
{
DatasourceCache
datasources
.
CacheService
`inject:""`
}
...
...
@@ -33,10 +36,11 @@ func init() {
}
// Init initializes the AlertingService.
func
(
e
*
AlertNG
)
Init
()
error
{
func
(
ng
*
AlertNG
)
Init
()
error
{
return
nil
}
// AlertExecCtx is the context provided for executing an alert condition.
type
AlertExecCtx
struct
{
AlertDefitionID
int64
SignedInUser
*
models
.
SignedInUser
...
...
@@ -44,55 +48,59 @@ type AlertExecCtx struct {
Ctx
context
.
Context
}
// At least Warn or Crit condition must be non-empty
type
Conditions
struct
{
Condition
string
`json:"condition"`
// Condition contains backend expressions and queries and the RefID
// of the query or expression that will be evaluated.
type
Condition
struct
{
RefID
string
`json:"refId"`
QueriesAndExpressions
[]
tsdb
.
Query
`json:"queriesAndExpressions"`
}
type
ExecutionResult
struct
{
AlertDefinitionId
int64
// ExecutionResults contains the unevaluated results from executing
// a condition.
type
ExecutionResults
struct
{
AlertDefinitionID
int64
Error
error
Results
data
.
Frames
}
type
EvalResults
[]
EvalResult
// Results is a slice of evaluated alert instances states.
type
Results
[]
Result
type
EvalResult
struct
{
// Result contains the evaluated state of an alert instance
// identified by its labels.
type
Result
struct
{
Instance
data
.
Labels
State
State
// Enum
}
// State is an enum of the evaluation state for an alert instance.
type
State
int
const
(
// Normal is the eval state for an alert instance condition
// that evaluated to false.
Normal
State
=
iota
Warning
Critical
Error
// Alerting is the eval state for an alert instance condition
// that evaluated to false.
Alerting
)
func
(
s
State
)
String
()
string
{
return
[
...
]
string
{
"Normal"
,
"
Warning"
,
"Critical"
,
"Error
"
}[
s
]
return
[
...
]
string
{
"Normal"
,
"
Alerting
"
}[
s
]
}
// IsValid checks the conditions validity
func
(
c
Conditions
)
IsValid
()
bool
{
/*
if c.WarnCondition == "" && c.CritCondition == "" {
return false
}
*/
func
(
c
Condition
)
IsValid
()
bool
{
// TODO search for refIDs in QueriesAndExpressions
return
len
(
c
.
QueriesAndExpressions
)
!=
0
}
// LoadAlertCondition
s returns a Conditions
object for the given alertDefintionId.
func
(
ng
*
AlertNG
)
LoadAlertCondition
s
(
dashboardID
int64
,
panelID
int64
,
conditionRefID
string
,
signedInUser
*
models
.
SignedInUser
,
skipCache
bool
)
(
*
Conditions
,
error
)
{
// LoadAlertCondition
returns a Condition
object for the given alertDefintionId.
func
(
ng
*
AlertNG
)
LoadAlertCondition
(
dashboardID
int64
,
panelID
int64
,
conditionRefID
string
,
signedInUser
*
models
.
SignedInUser
,
skipCache
bool
)
(
*
Condition
,
error
)
{
// get queries from the dashboard (because GEL expressions cannot be stored in alerts so far)
getDashboardQuery
:=
models
.
GetDashboardQuery
{
Id
:
dashboardID
}
if
err
:=
bus
.
Dispatch
(
&
getDashboardQuery
);
err
!=
nil
{
...
...
@@ -109,7 +117,7 @@ func (ng *AlertNG) LoadAlertConditions(dashboardID int64, panelID int64, conditi
return
nil
,
errors
.
New
(
"Failed to unmarshal dashboard JSON"
)
}
condition
s
:=
Conditions
{}
condition
:=
Condition
{}
for
_
,
p
:=
range
dash
.
Panels
{
if
p
.
ID
==
panelID
{
panelDatasource
:=
p
.
Datasource
...
...
@@ -148,8 +156,8 @@ func (ng *AlertNG) LoadAlertConditions(dashboardID int64, panelID int64, conditi
}
if
query
.
Get
(
"orgId"
)
.
MustString
()
==
""
{
// GEL requires orgID inside the query JSON
// need to decide which organi
s
ation id is expected there
// in grafana queries is passed the signed in user organi
s
ation id:
// need to decide which organi
z
ation id is expected there
// in grafana queries is passed the signed in user organi
z
ation id:
// https://github.com/grafana/grafana/blob/34a355fe542b511ed02976523aa6716aeb00bde6/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts#L60
// but I think that it should be datasource org id instead
query
.
Set
(
"orgId"
,
0
)
...
...
@@ -165,7 +173,7 @@ func (ng *AlertNG) LoadAlertConditions(dashboardID int64, panelID int64, conditi
query
.
Set
(
"intervalMs"
,
1000
)
}
condition
s
.
QueriesAndExpressions
=
append
(
conditions
.
QueriesAndExpressions
,
tsdb
.
Query
{
condition
.
QueriesAndExpressions
=
append
(
condition
.
QueriesAndExpressions
,
tsdb
.
Query
{
RefId
:
refID
,
MaxDataPoints
:
query
.
Get
(
"maxDataPoints"
)
.
MustInt64
(
100
),
IntervalMs
:
query
.
Get
(
"intervalMs"
)
.
MustInt64
(
1000
),
...
...
@@ -176,14 +184,14 @@ func (ng *AlertNG) LoadAlertConditions(dashboardID int64, panelID int64, conditi
}
}
}
condition
s
.
Condition
=
conditionRefID
return
&
condition
s
,
nil
condition
.
RefID
=
conditionRefID
return
&
condition
,
nil
}
// Execute runs the
WarnCondition and CritCondtion
expressions or queries.
func
(
c
onditions
*
Conditions
)
Execute
(
ctx
AlertExecCtx
,
fromStr
,
toStr
string
)
(
*
ExecutionResult
,
error
)
{
result
:=
ExecutionResult
{}
if
!
c
onditions
.
IsValid
()
{
// Execute runs the
Condition's
expressions or queries.
func
(
c
*
Condition
)
Execute
(
ctx
AlertExecCtx
,
fromStr
,
toStr
string
)
(
*
ExecutionResults
,
error
)
{
result
:=
ExecutionResult
s
{}
if
!
c
.
IsValid
()
{
return
nil
,
fmt
.
Errorf
(
"Invalid conditions"
)
}
...
...
@@ -192,8 +200,8 @@ func (conditions *Conditions) Execute(ctx AlertExecCtx, fromStr, toStr string) (
Debug
:
true
,
User
:
ctx
.
SignedInUser
,
}
for
i
:=
range
c
onditions
.
QueriesAndExpressions
{
request
.
Queries
=
append
(
request
.
Queries
,
&
c
onditions
.
QueriesAndExpressions
[
i
])
for
i
:=
range
c
.
QueriesAndExpressions
{
request
.
Queries
=
append
(
request
.
Queries
,
&
c
.
QueriesAndExpressions
[
i
])
}
resp
,
err
:=
plugins
.
Transform
.
Transform
(
ctx
.
Ctx
,
request
)
...
...
@@ -202,7 +210,7 @@ func (conditions *Conditions) Execute(ctx AlertExecCtx, fromStr, toStr string) (
return
&
result
,
err
}
conditionResult
:=
resp
.
Results
[
c
onditions
.
Condition
]
conditionResult
:=
resp
.
Results
[
c
.
RefID
]
if
conditionResult
==
nil
{
err
=
fmt
.
Errorf
(
"No GEL results"
)
result
.
Error
=
err
...
...
@@ -220,8 +228,8 @@ func (conditions *Conditions) Execute(ctx AlertExecCtx, fromStr, toStr string) (
// EvaluateExecutionResult takes the ExecutionResult, and returns a frame where
// each column is a string type that holds a string representing its state.
func
EvaluateExecutionResult
(
results
*
ExecutionResult
)
(
Eval
Results
,
error
)
{
evalResults
:=
make
([]
Eval
Result
,
0
)
func
EvaluateExecutionResult
(
results
*
ExecutionResult
s
)
(
Results
,
error
)
{
evalResults
:=
make
([]
Result
,
0
)
labels
:=
make
(
map
[
string
]
bool
)
for
_
,
f
:=
range
results
.
Results
{
rowLen
,
err
:=
f
.
RowLen
()
...
...
@@ -250,10 +258,10 @@ func EvaluateExecutionResult(results *ExecutionResult) (EvalResults, error) {
state
:=
Normal
val
,
err
:=
f
.
Fields
[
0
]
.
FloatAt
(
0
)
if
err
!=
nil
||
val
!=
0
{
state
=
Critical
state
=
Alerting
}
evalResults
=
append
(
evalResults
,
Eval
Result
{
evalResults
=
append
(
evalResults
,
Result
{
Instance
:
f
.
Fields
[
0
]
.
Labels
,
State
:
state
,
})
...
...
@@ -264,7 +272,7 @@ func EvaluateExecutionResult(results *ExecutionResult) (EvalResults, error) {
// AsDataFrame forms the EvalResults in Frame suitable for displaying in the table panel of the front end.
// This may be temporary, as there might be a fair amount we want to display in the frontend, and it might not make sense to store that in data.Frame.
// For the first pass, I would expect a Frame with a single row, and a column for each instance with a boolean value.
func
(
evalResults
Eval
Results
)
AsDataFrame
()
data
.
Frame
{
func
(
evalResults
Results
)
AsDataFrame
()
data
.
Frame
{
fields
:=
make
([]
*
data
.
Field
,
0
)
for
_
,
evalResult
:=
range
evalResults
{
fields
=
append
(
fields
,
data
.
NewField
(
""
,
evalResult
.
Instance
,
[]
bool
{
evalResult
.
State
!=
Normal
}))
...
...
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