Merge branch 'alerting' into thresholds_v3
This commit is contained in:
@@ -24,4 +24,17 @@ brew update
|
||||
brew reinstall grafana
|
||||
```
|
||||
|
||||
-------------
|
||||
|
||||
You can also install the latest unstable grafana from git:
|
||||
|
||||
|
||||
```
|
||||
brew install --HEAD grafana/grafana/grafana
|
||||
```
|
||||
|
||||
To upgrade grafana if you've installed from HEAD:
|
||||
|
||||
```
|
||||
brew reinstall --HEAD grafana/grafana/grafana
|
||||
```
|
||||
|
||||
@@ -9,7 +9,7 @@ page_keywords: grafana, plugins, documentation
|
||||
The easiest way to install plugins is by using the CLI tool grafana-cli which is bundled with grafana. Before any modification take place after modifying plugins, grafana-server needs to be restarted.
|
||||
|
||||
### Grafana plugin directory
|
||||
On Linux systems the grafana-cli will assume that the grafana plugin directory is `/var/lib/grafana/plugins`. It's possible to override the directory which grafana-cli will operate on by specifying the --path flag. On Windows systems this parameter have to be specified for every call.
|
||||
On Linux systems the grafana-cli will assume that the grafana plugin directory is `/var/lib/grafana/plugins`. It's possible to override the directory which grafana-cli will operate on by specifying the --pluginsDir flag. On Windows systems this parameter have to be specified for every call.
|
||||
|
||||
### Grafana-cli commands
|
||||
|
||||
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
DAEMON=grafana-server
|
||||
EXECUTABLE=/usr/local/bin/grafana-server
|
||||
CONFIG=/usr/local/etc/grafana/grafana.ini
|
||||
HOMEPATH=/usr/local/share/grafana
|
||||
LOGPATH=/usr/local/var/log/grafana
|
||||
DATAPATH=/usr/local/var/lib/grafana
|
||||
PLUGINPATH=/usr/local/var/lib/grafana/plugins
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
$EXECUTABLE --config=$CONFIG --homepath=$HOMEPATH cfg:default.paths.logs=$LOGPATH cfg:default.paths.data=$DATAPATH cfg:default.paths.plugins=$PLUGINPATH 2> /dev/null &
|
||||
[ $? -eq 0 ] && echo "$DAEMON started"
|
||||
;;
|
||||
stop)
|
||||
killall $DAEMON
|
||||
[ $? -eq 0 ] && echo "$DAEMON stopped"
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 (start|stop|restart)"
|
||||
;;
|
||||
esac
|
||||
@@ -19,6 +19,29 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) float64 {
|
||||
value += point[0]
|
||||
}
|
||||
value = value / float64(len(series.Points))
|
||||
case "sum":
|
||||
for _, point := range series.Points {
|
||||
value += point[0]
|
||||
}
|
||||
case "min":
|
||||
for i, point := range series.Points {
|
||||
if i == 0 {
|
||||
value = point[0]
|
||||
}
|
||||
|
||||
if value > point[0] {
|
||||
value = point[0]
|
||||
}
|
||||
}
|
||||
case "max":
|
||||
for _, point := range series.Points {
|
||||
if value < point[0] {
|
||||
value = point[0]
|
||||
}
|
||||
}
|
||||
case "mean":
|
||||
meanPosition := int64(len(series.Points) / 2)
|
||||
value = series.Points[meanPosition][0]
|
||||
}
|
||||
|
||||
return value
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package conditions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestSimpleReducer(t *testing.T) {
|
||||
Convey("Test simple reducer by calculating", t, func() {
|
||||
Convey("avg", func() {
|
||||
result := testReducer("avg", 1, 2, 3)
|
||||
So(result, ShouldEqual, float64(2))
|
||||
})
|
||||
|
||||
Convey("sum", func() {
|
||||
result := testReducer("sum", 1, 2, 3)
|
||||
So(result, ShouldEqual, float64(6))
|
||||
})
|
||||
|
||||
Convey("min", func() {
|
||||
result := testReducer("min", 3, 2, 1)
|
||||
So(result, ShouldEqual, float64(1))
|
||||
})
|
||||
|
||||
Convey("max", func() {
|
||||
result := testReducer("max", 1, 2, 3)
|
||||
So(result, ShouldEqual, float64(3))
|
||||
})
|
||||
|
||||
Convey("mean odd numbers", func() {
|
||||
result := testReducer("mean", 1, 2, 3000)
|
||||
So(result, ShouldEqual, float64(2))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func testReducer(typ string, datapoints ...float64) float64 {
|
||||
reducer := NewSimpleReducer(typ)
|
||||
var timeserie [][2]float64
|
||||
dummieTimestamp := float64(521452145)
|
||||
|
||||
for _, v := range datapoints {
|
||||
timeserie = append(timeserie, [2]float64{v, dummieTimestamp})
|
||||
}
|
||||
|
||||
tsdb := &tsdb.TimeSeries{
|
||||
Name: "test time serie",
|
||||
Points: timeserie,
|
||||
}
|
||||
return reducer.Reduce(tsdb)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package alerting
|
||||
|
||||
type compareFn func(float64, float64) bool
|
||||
|
||||
func evalCondition(level Level, result float64) bool {
|
||||
return operators[level.Operator](result, level.Value)
|
||||
}
|
||||
|
||||
var operators = map[string]compareFn{
|
||||
">": func(num1, num2 float64) bool { return num1 > num2 },
|
||||
">=": func(num1, num2 float64) bool { return num1 >= num2 },
|
||||
"<": func(num1, num2 float64) bool { return num1 < num2 },
|
||||
"<=": func(num1, num2 float64) bool { return num1 <= num2 },
|
||||
"": func(num1, num2 float64) bool { return false },
|
||||
}
|
||||
@@ -27,10 +27,21 @@ export class AlertSrv {
|
||||
this.set(alert[0], alert[1], 'success', 3000);
|
||||
}, this.$rootScope);
|
||||
|
||||
appEvents.on('alert-error', options => {
|
||||
this.set(options[0], options[1], 'error', 7000);
|
||||
});
|
||||
|
||||
appEvents.on('confirm-modal', this.showConfirmModal.bind(this));
|
||||
}
|
||||
|
||||
set(title, text, severity, timeout) {
|
||||
if (_.isObject(text)) {
|
||||
console.log('alert error', text);
|
||||
if (text.statusText) {
|
||||
text = `HTTP Error (${text.status}) ${text.statusText}`;
|
||||
}
|
||||
}
|
||||
|
||||
var newAlert = {
|
||||
title: title || '',
|
||||
text: text || '',
|
||||
|
||||
@@ -209,7 +209,7 @@ export class DashNavCtrl {
|
||||
$scope.viewJson = function() {
|
||||
var clone = $scope.dashboard.getSaveModelClone();
|
||||
var html = angular.toJson(clone, true);
|
||||
var uri = "data:application/json," + encodeURIComponent(html);
|
||||
var uri = "data:application/json;charset=utf-8," + encodeURIComponent(html);
|
||||
var newWindow = window.open(uri);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import moment from 'moment';
|
||||
import gfunc from './gfunc';
|
||||
import {Parser} from './parser';
|
||||
import {QueryCtrl} from 'app/plugins/sdk';
|
||||
import appEvents from 'app/core/app_events';
|
||||
|
||||
export class GraphiteQueryCtrl extends QueryCtrl {
|
||||
static templateUrl = 'partials/query.editor.html';
|
||||
@@ -141,7 +142,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
|
||||
}
|
||||
}
|
||||
}).catch(err => {
|
||||
this.error = err.message || 'Failed to issue metric query';
|
||||
appEvents.emit('alert-error', ['Error', err]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -178,7 +179,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
|
||||
altSegments.unshift(this.uiSegmentSrv.newSegment('*'));
|
||||
return altSegments;
|
||||
}).catch(err => {
|
||||
this.error = err.message || 'Failed to issue metric query';
|
||||
appEvents.emit('alert-error', ['Error', err]);
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user