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
72a67b39
Commit
72a67b39
authored
Aug 11, 2016
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(thresholds): more work thresholds
parent
6881db87
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
237 additions
and
82 deletions
+237
-82
public/app/features/alerting/alert_def.ts
+44
-1
public/app/features/alerting/alert_tab_ctrl.ts
+34
-73
public/app/features/alerting/partials/alert_tab.html
+4
-3
public/app/features/alerting/specs/threshold_mapper_specs.ts
+78
-0
public/app/features/alerting/threshold_mapper.ts
+72
-0
public/app/plugins/panel/graph/graph.js
+2
-2
public/app/plugins/panel/graph/specs/graph_specs.ts
+2
-2
public/app/plugins/panel/graph/tab_display.html
+1
-1
No files found.
public/app/features/alerting/alert_def.ts
View file @
72a67b39
...
...
@@ -10,6 +10,49 @@ function getSeverityIconClass(alertState) {
return
alertSeverityIconMap
[
alertState
];
}
import
{
QueryPartDef
,
QueryPart
,
}
from
'app/core/components/query_part/query_part'
;
var
alertQueryDef
=
new
QueryPartDef
({
type
:
'query'
,
params
:
[
{
name
:
"queryRefId"
,
type
:
'string'
,
options
:
[
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
]},
{
name
:
"from"
,
type
:
"string"
,
options
:
[
'1s'
,
'10s'
,
'1m'
,
'5m'
,
'10m'
,
'15m'
,
'1h'
]},
{
name
:
"to"
,
type
:
"string"
,
options
:
[
'now'
]},
],
defaultParams
:
[
'#A'
,
'5m'
,
'now'
,
'avg'
]
});
var
reducerAvgDef
=
new
QueryPartDef
({
type
:
'avg'
,
params
:
[],
defaultParams
:
[]
});
var
conditionTypes
=
[
{
text
:
'Query'
,
value
:
'query'
},
];
var
evalFunctions
=
[
{
text
:
'IS ABOVE'
,
value
:
'gt'
},
{
text
:
'IS BELOW'
,
value
:
'lt'
},
{
text
:
'IS OUTSIDE RANGE'
,
value
:
'outside_range'
},
{
text
:
'IS WITHIN RANGE'
,
value
:
'within_range'
},
{
text
:
'HAS NO VALUE'
,
value
:
'no_value'
}
];
var
severityLevels
=
[
{
text
:
'Critical'
,
value
:
'critical'
},
{
text
:
'Warning'
,
value
:
'warning'
},
];
export
default
{
getSeverityIconClass
,
alertQueryDef
:
alertQueryDef
,
reducerAvgDef
:
reducerAvgDef
,
getSeverityIconClass
:
getSeverityIconClass
,
conditionTypes
:
conditionTypes
,
evalFunctions
:
evalFunctions
,
severityLevels
:
severityLevels
,
};
public/app/features/alerting/alert_tab_ctrl.ts
View file @
72a67b39
///<reference path="../../headers/common.d.ts" />
import
_
from
'lodash'
;
import
{
QueryPartDef
,
QueryPart
,
}
from
'app/core/components/query_part/query_part'
;
var
alertQueryDef
=
new
QueryPartDef
({
type
:
'query'
,
params
:
[
{
name
:
"queryRefId"
,
type
:
'string'
,
options
:
[
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
]},
{
name
:
"from"
,
type
:
"string"
,
options
:
[
'1s'
,
'10s'
,
'1m'
,
'5m'
,
'10m'
,
'15m'
,
'1h'
]},
{
name
:
"to"
,
type
:
"string"
,
options
:
[
'now'
]},
],
defaultParams
:
[
'#A'
,
'5m'
,
'now'
,
'avg'
]
});
var
reducerAvgDef
=
new
QueryPartDef
({
type
:
'avg'
,
params
:
[],
defaultParams
:
[]
});
import
{
ThresholdMapper
}
from
'./threshold_mapper'
;
import
{
QueryPart
}
from
'app/core/components/query_part/query_part'
;
import
alertDef
from
'./alert_def'
;
export
class
AlertTabCtrl
{
panel
:
any
;
...
...
@@ -29,21 +11,11 @@ export class AlertTabCtrl {
testing
:
boolean
;
testResult
:
any
;
subTabIndex
:
number
;
handlers
=
[{
text
:
'Grafana'
,
value
:
1
},
{
text
:
'External'
,
value
:
0
}];
conditionTypes
=
[
{
text
:
'Query'
,
value
:
'query'
},
];
conditionTypes
:
any
;
alert
:
any
;
conditionModels
:
any
;
evalFunctions
=
[
{
text
:
'>'
,
value
:
'>'
},
{
text
:
'<'
,
value
:
'<'
},
];
severityLevels
=
[
{
text
:
'Critical'
,
value
:
'critical'
},
{
text
:
'Warning'
,
value
:
'warning'
},
];
evalFunctions
:
any
;
severityLevels
:
any
;
addNotificationSegment
;
notifications
;
alertNotifications
;
...
...
@@ -54,6 +26,9 @@ export class AlertTabCtrl {
this
.
panel
=
this
.
panelCtrl
.
panel
;
this
.
$scope
.
ctrl
=
this
;
this
.
subTabIndex
=
0
;
this
.
evalFunctions
=
alertDef
.
evalFunctions
;
this
.
conditionTypes
=
alertDef
.
conditionTypes
;
this
.
severityLevels
=
alertDef
.
severityLevels
;
}
$onInit
()
{
...
...
@@ -101,6 +76,27 @@ export class AlertTabCtrl {
}));
}
evaluatorTypeChanged
(
evaluator
)
{
// ensure params array is correct length
switch
(
evaluator
.
type
)
{
case
"lt"
:
case
"gt"
:
{
evaluator
.
params
=
[
evaluator
.
params
[
0
]];
break
;
}
case
"within_range"
:
case
"outside_range"
:
{
evaluator
.
params
=
[
evaluator
.
params
[
0
],
evaluator
.
params
[
1
]];
break
;
}
case
"no_value"
:
{
evaluator
.
params
=
[];
}
}
this
.
thresholdUpdated
();
}
notificationAdded
()
{
var
model
=
_
.
findWhere
(
this
.
notifications
,
{
name
:
this
.
addNotificationSegment
.
value
});
if
(
!
model
)
{
...
...
@@ -146,45 +142,10 @@ export class AlertTabCtrl {
this
.
panelCtrl
.
editingThresholds
=
true
;
}
this
.
syncThresholds
(
);
ThresholdMapper
.
alertToGraphThresholds
(
this
.
panel
);
this
.
panelCtrl
.
render
();
}
syncThresholds
()
{
if
(
this
.
panel
.
type
!==
'graph'
)
{
return
;
}
var
threshold
:
any
=
{};
if
(
this
.
panel
.
thresholds
&&
this
.
panel
.
thresholds
.
length
>
0
)
{
threshold
=
this
.
panel
.
thresholds
[
0
];
}
else
{
this
.
panel
.
thresholds
=
[
threshold
];
}
var
updated
=
false
;
for
(
var
condition
of
this
.
conditionModels
)
{
if
(
condition
.
type
===
'query'
)
{
var
value
=
condition
.
evaluator
.
params
[
0
];
if
(
!
_
.
isNumber
(
value
))
{
continue
;
}
if
(
value
!==
threshold
.
value
)
{
threshold
.
value
=
value
;
updated
=
true
;
}
if
(
condition
.
evaluator
.
type
!==
threshold
.
op
)
{
threshold
.
op
=
condition
.
evaluator
.
type
;
updated
=
true
;
}
}
}
return
updated
;
}
graphThresholdChanged
(
evt
)
{
for
(
var
condition
of
this
.
alert
.
conditions
)
{
if
(
condition
.
type
===
'query'
)
{
...
...
@@ -206,8 +167,8 @@ export class AlertTabCtrl {
buildConditionModel
(
source
)
{
var
cm
:
any
=
{
source
:
source
,
type
:
source
.
type
};
cm
.
queryPart
=
new
QueryPart
(
source
.
query
,
alertQueryDef
);
cm
.
reducerPart
=
new
QueryPart
({
params
:
[]},
reducerAvgDef
);
cm
.
queryPart
=
new
QueryPart
(
source
.
query
,
alert
Def
.
alert
QueryDef
);
cm
.
reducerPart
=
new
QueryPart
({
params
:
[]},
alertDef
.
reducerAvgDef
);
cm
.
evaluator
=
source
.
evaluator
;
return
cm
;
...
...
@@ -240,7 +201,7 @@ export class AlertTabCtrl {
}
thresholdUpdated
()
{
if
(
this
.
syncThresholds
(
))
{
if
(
ThresholdMapper
.
alertToGraphThresholds
(
this
.
panel
))
{
this
.
panelCtrl
.
render
();
}
}
...
...
public/app/features/alerting/partials/alert_tab.html
View file @
72a67b39
...
...
@@ -58,9 +58,10 @@
</query-part-editor>
</div>
<div
class=
"gf-form"
>
<span
class=
"gf-form-label"
>
Value
</span>
<metric-segment-model
property=
"conditionModel.evaluator.type"
options=
"ctrl.evalFunctions"
custom=
"false"
css-class=
"query-segment-operator"
on-change=
"ctrl.thresholdUpdated()"
></metric-segment-model>
<input
class=
"gf-form-input max-width-7"
type=
"number"
ng-model=
"conditionModel.evaluator.params[0]"
ng-change=
"ctrl.thresholdUpdated()"
></input>
<metric-segment-model
property=
"conditionModel.evaluator.type"
options=
"ctrl.evalFunctions"
custom=
"false"
css-class=
"query-keyword"
on-change=
"ctrl.evaluatorTypeChanged(conditionModel.evaluator)"
></metric-segment-model>
<input
class=
"gf-form-input max-width-7"
type=
"number"
ng-hide=
"conditionModel.evaluator.params.length === 0"
ng-model=
"conditionModel.evaluator.params[0]"
ng-change=
"ctrl.thresholdUpdated()"
></input>
<label
class=
"gf-form-label query-keyword"
ng-show=
"conditionModel.evaluator.params.length === 2"
>
TO
</label>
<input
class=
"gf-form-input max-width-7"
type=
"number"
ng-if=
"conditionModel.evaluator.params.length === 2"
ng-model=
"conditionModel.evaluator.params[1]"
ng-change=
"ctrl.thresholdUpdated()"
></input>
</div>
<div
class=
"gf-form"
>
<label
class=
"gf-form-label"
>
...
...
public/app/features/alerting/specs/threshold_mapper_specs.ts
0 → 100644
View file @
72a67b39
import
{
describe
,
beforeEach
,
it
,
sinon
,
expect
}
from
'test/lib/common'
;
import
{
ThresholdMapper
}
from
'../threshold_mapper'
;
describe
(
'ThresholdMapper'
,
()
=>
{
describe
(
'with greater than evaluator'
,
()
=>
{
it
(
'can mapp query conditions to thresholds'
,
()
=>
{
var
panel
:
any
=
{
type
:
'graph'
,
alert
:
{
conditions
:
[
{
type
:
'query'
,
evaluator
:
{
type
:
'gt'
,
params
:
[
100
],
}
}
]
}
};
var
updated
=
ThresholdMapper
.
alertToGraphThresholds
(
panel
);
expect
(
updated
).
to
.
be
(
true
);
expect
(
panel
.
thresholds
[
0
].
op
).
to
.
be
(
'gt'
);
expect
(
panel
.
thresholds
[
0
].
value
).
to
.
be
(
100
);
});
});
describe
(
'with outside range evaluator'
,
()
=>
{
it
(
'can mapp query conditions to thresholds'
,
()
=>
{
var
panel
:
any
=
{
type
:
'graph'
,
alert
:
{
conditions
:
[
{
type
:
'query'
,
evaluator
:
{
type
:
'outside_range'
,
params
:
[
100
,
200
],
}
}
]
}
};
var
updated
=
ThresholdMapper
.
alertToGraphThresholds
(
panel
);
expect
(
updated
).
to
.
be
(
true
);
expect
(
panel
.
thresholds
[
0
].
op
).
to
.
be
(
'lt'
);
expect
(
panel
.
thresholds
[
0
].
value
).
to
.
be
(
100
);
expect
(
panel
.
thresholds
[
1
].
op
).
to
.
be
(
'gt'
);
expect
(
panel
.
thresholds
[
1
].
value
).
to
.
be
(
200
);
});
});
describe
(
'with inside range evaluator'
,
()
=>
{
it
(
'can mapp query conditions to thresholds'
,
()
=>
{
var
panel
:
any
=
{
type
:
'graph'
,
alert
:
{
conditions
:
[
{
type
:
'query'
,
evaluator
:
{
type
:
'within_range'
,
params
:
[
100
,
200
],
}
}
]
}
};
var
updated
=
ThresholdMapper
.
alertToGraphThresholds
(
panel
);
expect
(
updated
).
to
.
be
(
true
);
expect
(
panel
.
thresholds
[
0
].
op
).
to
.
be
(
'gt'
);
expect
(
panel
.
thresholds
[
0
].
value
).
to
.
be
(
100
);
expect
(
panel
.
thresholds
[
1
].
op
).
to
.
be
(
'lt'
);
expect
(
panel
.
thresholds
[
1
].
value
).
to
.
be
(
200
);
});
});
});
public/app/features/alerting/threshold_mapper.ts
0 → 100644
View file @
72a67b39
export
class
ThresholdMapper
{
static
alertToGraphThresholds
(
panel
)
{
var
alert
=
panel
.
alert
;
if
(
panel
.
type
!==
'graph'
)
{
return
false
;
}
for
(
var
i
=
0
;
i
<
panel
.
alert
.
conditions
.
length
;
i
++
)
{
let
condition
=
panel
.
alert
.
conditions
[
i
];
if
(
condition
.
type
!==
'query'
)
{
continue
;
}
var
evaluator
=
condition
.
evaluator
;
var
thresholds
=
panel
.
thresholds
=
[];
switch
(
evaluator
.
type
)
{
case
"gt"
:
{
let
value
=
evaluator
.
params
[
0
];
thresholds
.
push
({
value
:
value
,
op
:
'gt'
});
break
;
}
case
"lt"
:
{
let
value
=
evaluator
.
params
[
0
];
thresholds
.
push
({
value
:
value
,
op
:
'lt'
});
break
;
}
case
"outside_range"
:
{
let
value1
=
evaluator
.
params
[
0
];
let
value2
=
evaluator
.
params
[
1
];
if
(
value1
>
value2
)
{
thresholds
.
push
({
value
:
value1
,
op
:
'gt'
});
thresholds
.
push
({
value
:
value2
,
op
:
'lt'
});
}
else
{
thresholds
.
push
({
value
:
value1
,
op
:
'lt'
});
thresholds
.
push
({
value
:
value2
,
op
:
'gt'
});
}
break
;
}
case
"within_range"
:
{
let
value1
=
evaluator
.
params
[
0
];
let
value2
=
evaluator
.
params
[
1
];
if
(
value1
>
value2
)
{
thresholds
.
push
({
value
:
value1
,
op
:
'lt'
});
thresholds
.
push
({
value
:
value2
,
op
:
'gt'
});
}
else
{
thresholds
.
push
({
value
:
value1
,
op
:
'gt'
});
thresholds
.
push
({
value
:
value2
,
op
:
'lt'
});
}
break
;
}
}
}
for
(
var
t
of
panel
.
thresholds
)
{
t
.
fill
=
true
;
t
.
line
=
true
;
t
.
colorMode
=
panel
.
alert
.
severity
;
}
var
updated
=
true
;
return
updated
;
}
}
public/app/plugins/panel/graph/graph.js
View file @
72a67b39
...
...
@@ -343,12 +343,12 @@ function (angular, $, moment, _, kbn, GraphTooltip, thresholds) {
var
limit
;
switch
(
threshold
.
op
)
{
case
'
>
'
:
{
case
'
gt
'
:
{
limit
=
gtLimit
;
gtLimit
=
threshold
.
value
;
break
;
}
case
'
<
'
:
{
case
'
lt
'
:
{
limit
=
ltLimit
;
ltLimit
=
threshold
.
value
;
break
;
...
...
public/app/plugins/panel/graph/specs/graph_specs.ts
View file @
72a67b39
...
...
@@ -115,8 +115,8 @@ describe('grafanaGraph', function() {
graphScenario
(
'grid thresholds 100, 200'
,
function
(
ctx
)
{
ctx
.
setup
(
function
(
ctrl
)
{
ctrl
.
panel
.
thresholds
=
[
{
op
:
"
>
"
,
value
:
300
,
fillColor
:
'red'
,
lineColor
:
'blue'
,
fill
:
true
,
line
:
true
},
{
op
:
"
>
"
,
value
:
200
,
fillColor
:
'#ed2e18'
,
fill
:
true
}
{
op
:
"
gt
"
,
value
:
300
,
fillColor
:
'red'
,
lineColor
:
'blue'
,
fill
:
true
,
line
:
true
},
{
op
:
"
gt
"
,
value
:
200
,
fillColor
:
'#ed2e18'
,
fill
:
true
}
];
});
...
...
public/app/plugins/panel/graph/tab_display.html
View file @
72a67b39
...
...
@@ -140,7 +140,7 @@
<div
class=
"gf-form"
>
<div
class=
"gf-form-select-wrapper"
>
<select
class=
"gf-form-input"
ng-model=
"threshold.op"
ng-options=
"f for f in ['
>', '<
']"
ng-change=
"ctrl.render()"
></select>
<select
class=
"gf-form-input"
ng-model=
"threshold.op"
ng-options=
"f for f in ['
gt', 'lt
']"
ng-change=
"ctrl.render()"
></select>
</div>
<input
type=
"number"
ng-model=
"threshold.value"
class=
"gf-form-input width-8"
ng-change=
"ctrl.render()"
placeholder=
"value"
>
</div>
...
...
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