Commit 6881db87 by Torkel Ödegaard

Merge branch 'alerting' into thresholds_v3

parents fbb8f8e6 8878a55d
......@@ -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
......
#!/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
......
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)
}
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 [];
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment