浏览代码

Merge branch 'alerting' into thresholds_v3

Torkel Ödegaard 9 年之前
父节点
当前提交
6881db87bb

+ 13 - 0
docs/sources/installation/mac.md

@@ -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
+```

+ 1 - 1
docs/sources/plugins/installation.md

@@ -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
 

+ 26 - 0
packaging/mac/bin/grafana

@@ -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

+ 23 - 0
pkg/services/alerting/conditions/reducer.go

@@ -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

+ 54 - 0
pkg/services/alerting/conditions/reducer_test.go

@@ -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)
+}

+ 0 - 15
pkg/services/alerting/evaluator.go

@@ -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 },
-}

+ 11 - 0
public/app/core/services/alert_srv.ts

@@ -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 || '',

+ 1 - 1
public/app/features/dashboard/dashnav/dashnav.ts

@@ -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);
     };
 

+ 3 - 2
public/app/plugins/datasource/graphite/query_ctrl.ts

@@ -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 [];
     });
   }