Преглед изворни кода

feat(alerting): added validation that checks valid data source and checks for template variables in graphite query, #5841

Torkel Ödegaard пре 9 година
родитељ
комит
75a6c2b612

+ 0 - 1
pkg/services/sqlstore/alert.go

@@ -87,7 +87,6 @@ func HandleAlertsQuery(query *m.GetAlertsQuery) error {
 		sql.WriteString(")")
 		sql.WriteString(")")
 	}
 	}
 
 
-	sqlog.Error(sql.String(), "params", params)
 	alerts := make([]*m.Alert, 0)
 	alerts := make([]*m.Alert, 0)
 	if err := x.Sql(sql.String(), params...).Find(&alerts); err != nil {
 	if err := x.Sql(sql.String(), params...).Find(&alerts); err != nil {
 		return err
 		return err

+ 56 - 5
public/app/features/alerting/alert_tab_ctrl.ts

@@ -4,6 +4,7 @@ import _ from 'lodash';
 import {ThresholdMapper} from './threshold_mapper';
 import {ThresholdMapper} from './threshold_mapper';
 import {QueryPart} from 'app/core/components/query_part/query_part';
 import {QueryPart} from 'app/core/components/query_part/query_part';
 import alertDef from './alert_def';
 import alertDef from './alert_def';
+import config from 'app/core/config';
 
 
 export class AlertTabCtrl {
 export class AlertTabCtrl {
   panel: any;
   panel: any;
@@ -19,9 +20,17 @@ export class AlertTabCtrl {
   addNotificationSegment;
   addNotificationSegment;
   notifications;
   notifications;
   alertNotifications;
   alertNotifications;
+  error: string;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private $scope, private $timeout, private backendSrv, private dashboardSrv, private uiSegmentSrv, private $q) {
+  constructor(private $scope,
+              private $timeout,
+              private backendSrv,
+              private dashboardSrv,
+              private uiSegmentSrv,
+              private $q,
+              private datasourceSrv,
+              private templateSrv) {
     this.panelCtrl = $scope.ctrl;
     this.panelCtrl = $scope.ctrl;
     this.panel = this.panelCtrl.panel;
     this.panel = this.panelCtrl.panel;
     this.$scope.ctrl = this;
     this.$scope.ctrl = this;
@@ -35,6 +44,7 @@ export class AlertTabCtrl {
     this.addNotificationSegment = this.uiSegmentSrv.newPlusButton();
     this.addNotificationSegment = this.uiSegmentSrv.newPlusButton();
 
 
     this.initModel();
     this.initModel();
+    this.validateModel();
 
 
     // set panel alert edit mode
     // set panel alert edit mode
     this.$scope.$on("$destroy", () => {
     this.$scope.$on("$destroy", () => {
@@ -144,6 +154,47 @@ export class AlertTabCtrl {
     };
     };
   }
   }
 
 
+  validateModel() {
+    let firstTarget;
+    var fixed = false;
+    let foundTarget = null;
+
+    for (var condition of this.alert.conditions) {
+      if (condition.type !== 'query') {
+        continue;
+      }
+
+      for (var target of this.panel.targets) {
+        if (!firstTarget) {
+          firstTarget = target;
+        }
+        if (condition.query.params[0] === target.refId) {
+          foundTarget = target;
+          break;
+        }
+      }
+
+      if (!foundTarget) {
+        if (firstTarget) {
+          condition.query.params[0] = firstTarget.refId;
+          foundTarget = firstTarget;
+          fixed = true;
+        } else {
+          this.error = "Could not find any metric queries";
+        }
+      }
+
+      var datasourceName = foundTarget.datasource || this.panel.datasource;
+      this.datasourceSrv.get(datasourceName).then(ds => {
+        if (ds.meta.id !== 'graphite') {
+          this.error = 'Currently the alerting backend only supports Graphite queries';
+        } else if (this.templateSrv.variableExists(foundTarget.target)) {
+          this.error = 'Template variables are not supported in alert queries';
+        }
+      });
+    }
+  }
+
   buildConditionModel(source) {
   buildConditionModel(source) {
     var cm: any = {source: source, type: source.type};
     var cm: any = {source: source, type: source.type};
 
 
@@ -187,7 +238,7 @@ export class AlertTabCtrl {
   addCondition(type) {
   addCondition(type) {
     var condition = this.buildDefaultCondition();
     var condition = this.buildDefaultCondition();
     // add to persited model
     // add to persited model
-    this.panelCtrl.conditions.push(condition);
+    this.alert.conditions.push(condition);
     // add to view model
     // add to view model
     this.conditionModels.push(this.buildConditionModel(condition));
     this.conditionModels.push(this.buildConditionModel(condition));
   }
   }
@@ -198,7 +249,7 @@ export class AlertTabCtrl {
   }
   }
 
 
   delete() {
   delete() {
-    this.panel.alert = {enabled: false};
+    this.alert = this.panel.alert = {enabled: false};
     this.panel.thresholds = [];
     this.panel.thresholds = [];
     this.conditionModels = [];
     this.conditionModels = [];
     this.panelCtrl.render();
     this.panelCtrl.render();
@@ -223,12 +274,12 @@ export class AlertTabCtrl {
     // ensure params array is correct length
     // ensure params array is correct length
     switch (evaluator.type) {
     switch (evaluator.type) {
       case "lt":
       case "lt":
-      case "gt": {
+        case "gt": {
         evaluator.params = [evaluator.params[0]];
         evaluator.params = [evaluator.params[0]];
         break;
         break;
       }
       }
       case "within_range":
       case "within_range":
-      case "outside_range": {
+        case "outside_range": {
         evaluator.params = [evaluator.params[0], evaluator.params[1]];
         evaluator.params = [evaluator.params[0], evaluator.params[1]];
         break;
         break;
       }
       }

+ 4 - 0
public/app/features/alerting/partials/alert_tab.html

@@ -20,6 +20,10 @@
 
 
 	<div class="edit-tab-content">
 	<div class="edit-tab-content">
 		<div ng-if="ctrl.subTabIndex === 0">
 		<div ng-if="ctrl.subTabIndex === 0">
+			<div class="alert alert-error m-b-2" ng-show="ctrl.error">
+				<i class="fa fa-warning"></i> {{ctrl.error}}
+			</div>
+
 			<div class="gf-form-group">
 			<div class="gf-form-group">
 				<h5 class="section-heading">Alert Config</h5>
 				<h5 class="section-heading">Alert Config</h5>
 				<div class="gf-form">
 				<div class="gf-form">

+ 1 - 1
public/sass/components/_alerts.scss

@@ -9,7 +9,7 @@
 
 
 
 
 .alert {
 .alert {
-  padding: 8px 35px 13px 14px;
+  padding: 0.5rem 2rem 0.5rem 1rem;
   margin-bottom: $line-height-base;
   margin-bottom: $line-height-base;
   text-shadow: 0 1px 0 rgba(255,255,255,.5);
   text-shadow: 0 1px 0 rgba(255,255,255,.5);
   background-color: $state-warning-bg;
   background-color: $state-warning-bg;

+ 2 - 2
public/sass/components/_panel_graph.scss

@@ -392,10 +392,10 @@
     z-index: 0;
     z-index: 0;
     position: relative;
     position: relative;
 
 
-    &--crit {
+    &--critical {
       background-color: rgba(237, 46, 24, 0.60);
       background-color: rgba(237, 46, 24, 0.60);
     }
     }
-    &--warn {
+    &--warning {
       background-color: rgba(247, 149, 32, 0.60);
       background-color: rgba(247, 149, 32, 0.60);
     }
     }
   }
   }