Просмотр исходного кода

Improved error handling via alertSrv service

Rashid Khan 12 лет назад
Родитель
Сommit
f4f8577d91
5 измененных файлов с 93 добавлено и 53 удалено
  1. 2 2
      index.html
  2. 3 24
      js/controllers.js
  3. 66 9
      js/services.js
  4. 15 15
      panels/dashcontrol/module.js
  5. 7 3
      partials/dasheditor.html

+ 2 - 2
index.html

@@ -32,8 +32,8 @@
     <link rel="stylesheet" href="common/css/bootstrap-responsive.min.css">
     <link rel="stylesheet" href="common/css/font-awesome.min.css">
 
-    <div ng-repeat='alert in global_alert' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last">
-      <button type="button" class="close" ng-click="clear_alert(alert)" style="padding-right:50px">&times;</button>
+    <div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last">
+      <button type="button" class="close" ng-click="dashAlerts.clear(alert)" style="padding-right:50px">&times;</button>
       <strong>{{alert.title}}</strong> <span ng-bind-html-unsafe='alert.text'></span> <div style="padding-right:10px" class='pull-right small'> {{$index + 1}} alert(s) </div>
     </div>
     <div class="navbar navbar-static-top">

+ 3 - 24
js/controllers.js

@@ -4,7 +4,7 @@
 
 angular.module('kibana.controllers', [])
 .controller('DashCtrl', function($scope, $rootScope, $http, $timeout, $route, ejsResource, 
-  fields, dashboard) {
+  fields, dashboard, alertSrv) {
 
   $scope.editor = {
     index: 0
@@ -16,11 +16,12 @@ angular.module('kibana.controllers', [])
     // Make underscore.js available to views
     $scope._ = _;
     $scope.dashboard = dashboard;
+    $scope.dashAlerts = alertSrv;
+    alertSrv.clearAll();
 
     // Provide a global list of all see fields
     $scope.fields = fields;
     $scope.reset_row();
-    $scope.clear_all_alerts();
 
     var ejs = $scope.ejs = ejsResource(config.elasticsearch);  
   };
@@ -41,28 +42,6 @@ angular.module('kibana.controllers', [])
     return { 'min-height': row.collapse ? '5px' : row.height };
   };
 
-  $scope.alert = function(title,text,severity,timeout) {
-    var alert = {
-      title: title,
-      text: text,
-      severity: severity || 'info',
-    };
-    $scope.global_alert.push(alert);
-    if (timeout > 0) {
-      $timeout(function() {
-        $scope.global_alert = _.without($scope.global_alert,alert);
-      }, timeout);
-    }
-  };
-
-  $scope.clear_alert = function(alert) {
-    $scope.global_alert = _.without($scope.global_alert,alert);
-  };
-
-  $scope.clear_all_alerts = function() {
-    $scope.global_alert = [];
-  }; 
-
   $scope.edit_path = function(type) {
     if(type) {
       return 'panels/'+type+'/editor.html';

+ 66 - 9
js/services.js

@@ -4,7 +4,36 @@
 'use strict';
 
 angular.module('kibana.services', [])
-.service('fields', function(dashboard, $rootScope, $http) {
+.service('alertSrv', function($timeout) {
+  var self = this;
+
+  // List of all alert objects
+  this.list = [];
+
+  this.set = function(title,text,severity,timeout) {
+    var _a = {
+      title: title || '',
+      text: text || '',
+      severity: severity || 'info',
+    };
+    self.list.push(_a);
+    if (timeout > 0) {
+      $timeout(function() {
+        self.list = _.without(self.list,_a);
+      }, timeout);
+    }
+  };
+
+  this.clear = function(alert) {
+    self.list = _.without(self.list,alert);
+  };
+
+  this.clearAll = function() {
+    self.list = [];
+  }; 
+
+})
+.service('fields', function(dashboard, $rootScope, $http, alertSrv) {
   // Save a reference to this
   var self = this;
 
@@ -46,6 +75,14 @@ angular.module('kibana.services', [])
     var request = $http({
       url: config.elasticsearch + "/" + indices.join(',') + "/_mapping",
       method: "GET"
+    }).error(function(data, status, headers, conf) {
+      if(status === 0) {
+        alertSrv.set('Error',"Could not contact Elasticsearch at "+config.elasticsearch+
+          ". Please ensure that Elasticsearch is reachable from your system." ,'error');
+      } else {
+        alertSrv.set('Error',"Could not find "+config.elasticsearch+"/"+indices.join(',')+"/_mapping. If you"+
+          " are using a proxy, ensure it is configured correctly",'error');
+      }
     });
 
     return request.then(function(p) {
@@ -83,7 +120,7 @@ angular.module('kibana.services', [])
   };
 
 })
-.service('kbnIndex',function($http) {
+.service('kbnIndex',function($http,alertSrv) {
 
   // returns a promise containing an array of all indices matching the index
   // pattern that exist in a given range
@@ -106,8 +143,14 @@ angular.module('kibana.services', [])
     var something = $http({
       url: config.elasticsearch + "/_aliases",
       method: "GET"
-    }).error(function(data, status, headers, config) {
-      // Handle error condition somehow?
+    }).error(function(data, status, headers, conf) {
+      if(status === 0) {
+        alertSrv.set('Error',"Could not contact Elasticsearch at "+config.elasticsearch+
+          ". Please ensure that Elasticsearch is reachable from your system." ,'error');
+      } else {
+        alertSrv.set('Error',"Could not reach "+config.elasticsearch+"/_aliases. If you"+
+          " are using a proxy, ensure it is configured correctly",'error');
+      }
     });
 
     return something.then(function(p) {
@@ -502,13 +545,14 @@ angular.module('kibana.services', [])
   self.init();
 
 })
-.service('dashboard', function($routeParams, $http, $rootScope, $injector, ejsResource, timer, kbnIndex) {
+.service('dashboard', function($routeParams, $http, $rootScope, $injector, ejsResource, timer, kbnIndex, alertSrv) {
   // A hash of defaults to use when loading a dashboard
 
   var _dash = {
     title: "",
     style: "dark",
     editable: true,
+    failover: false,
     rows: [],
     services: {},
     index: {
@@ -584,7 +628,17 @@ angular.module('kibana.services', [])
           if(p.length > 0) {
             self.indices = p;          
           } else {
-            self.indices = [self.current.index.default];
+            //TODO: Option to not failover
+            if(self.current.failover) {
+              self.indices = [self.current.index.default];
+            } else {
+              alertSrv.set('No indices matched','The pattern <i>'+self.current.index.pattern+
+                '</i> did not match any indices in your selected'+
+                ' time range.','info',5000);
+              // Do not issue refresh if no indices match. This should be removed when panels
+              // properly understand when no indices are present
+              return false;
+            }
           }
           $rootScope.$broadcast('refresh');
         });
@@ -690,22 +744,25 @@ angular.module('kibana.services', [])
       self.dash_load(_dashboard);
       return true;
     },function(result) {
+      alertSrv.set('Error',"Could not load <i>dashboards/"+file+"</i>. Please make sure it exists" ,'error');
       return false;
     });
   };
 
   this.elasticsearch_load = function(type,id) {
     var request = ejs.Request().indices(config.kibana_index).types(type);
-    var results = request.query(
+    return request.query(
       ejs.IdsQuery(id)
-    ).doSearch();
-    return results.then(function(results) {
+    ).doSearch(function(results) {
       if(_.isUndefined(results)) {
         return false;
       } else {
         self.dash_load(angular.fromJson(results.hits.hits[0]['_source']['dashboard']));
         return true;
       }
+    },
+    function(data,status) {
+      alertSrv.set('Error','Could not load '+config.elasticsearch+"/"+config.kibana_index+"/"+type+"/"+id,'error');
     });
   };
 

+ 15 - 15
panels/dashcontrol/module.js

@@ -24,7 +24,7 @@
 'use strict';
 
 angular.module('kibana.dashcontrol', [])
-.controller('dashcontrol', function($scope, $http, timer, dashboard) {
+.controller('dashcontrol', function($scope, $http, timer, dashboard, alertSrv) {
 
   $scope.panelMeta = {
     status  : "Stable",
@@ -69,17 +69,17 @@ angular.module('kibana.dashcontrol', [])
 
   $scope.set_default = function() {
     if(dashboard.set_default()) {
-      $scope.alert('Local Default Set',dashboard.current.title+' has been set as your local default','success',5000);
+      alertSrv.set('Local Default Set',dashboard.current.title+' has been set as your local default','success',5000);
     } else {
-      $scope.alert('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
+      alertSrv.set('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
     }
   };
 
   $scope.purge_default = function() {
     if(dashboard.purge_default()) {
-      $scope.alert('Local Default Clear','Your local default dashboard has been cleared','success',5000);
+      alertSrv.set('Local Default Clear','Your local default dashboard has been cleared','success',5000);
     } else {
-      $scope.alert('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
+      alertSrv.set('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
     }
   };
 
@@ -91,13 +91,13 @@ angular.module('kibana.dashcontrol', [])
       ).then(
       function(result) {
       if(!_.isUndefined(result._id)) {
-        $scope.alert('Dashboard Saved','This dashboard has been saved to Elasticsearch as "' + 
+        alertSrv.set('Dashboard Saved','This dashboard has been saved to Elasticsearch as "' + 
           result._id + '"','success',5000);
         if(type === 'temp') {
           $scope.share = dashboard.share_link(dashboard.current.title,'temp',result._id);
         }
       } else {
-        $scope.alert('Save failed','Dashboard could not be saved to Elasticsearch','error',5000);
+        alertSrv.set('Save failed','Dashboard could not be saved to Elasticsearch','error',5000);
       }
     });
   };
@@ -107,15 +107,15 @@ angular.module('kibana.dashcontrol', [])
       function(result) {
         if(!_.isUndefined(result)) {
           if(result.found) {
-            $scope.alert('Dashboard Deleted',id+' has been deleted','success',5000);
+            alertSrv.set('Dashboard Deleted',id+' has been deleted','success',5000);
             // Find the deleted dashboard in the cached list and remove it
             var toDelete = _.where($scope.elasticsearch.dashboards,{_id:id})[0];
             $scope.elasticsearch.dashboards = _.without($scope.elasticsearch.dashboards,toDelete);
           } else {
-            $scope.alert('Dashboard Not Found','Could not find '+id+' in Elasticsearch','warning',5000);
+            alertSrv.set('Dashboard Not Found','Could not find '+id+' in Elasticsearch','warning',5000);
           }
         } else {
-          $scope.alert('Dashboard Not Deleted','An error occurred deleting the dashboard','error',5000);
+          alertSrv.set('Dashboard Not Deleted','An error occurred deleting the dashboard','error',5000);
         }
       }
     );
@@ -137,10 +137,10 @@ angular.module('kibana.dashcontrol', [])
       function(link) {
       if(!_.isUndefined(link)) {
         $scope.gist.last = link;
-        $scope.alert('Gist saved','You will be able to access your exported dashboard file at '+
+        alertSrv.set('Gist saved','You will be able to access your exported dashboard file at '+
           '<a href="'+link+'">'+link+'</a> in a moment','success');
       } else {
-        $scope.alert('Save failed','Gist could not be saved','error',5000);
+        alertSrv.set('Save failed','Gist could not be saved','error',5000);
       }
     });
   };
@@ -151,12 +151,12 @@ angular.module('kibana.dashcontrol', [])
       if(files && files.length > 0) {
         $scope.gist.files = files;
       } else {
-        $scope.alert('Gist Failed','Could not retrieve dashboard list from gist','error',5000);
+        alertSrv.set('Gist Failed','Could not retrieve dashboard list from gist','error',5000);
       }
     });
   };
 })
-.directive('dashUpload', function(timer, dashboard){
+.directive('dashUpload', function(timer, dashboard, alertSrv){
   return {
     restrict: 'A',
     link: function(scope, elem, attrs) {
@@ -183,7 +183,7 @@ angular.module('kibana.dashcontrol', [])
         // Something
         document.getElementById('dashupload').addEventListener('change', file_selected, false);
       } else {
-        alert('Sorry, the HTML5 File APIs are not fully supported in this browser.');
+        alertSrv.set('Oops','Sorry, the HTML5 File APIs are not fully supported in this browser.','error');
       }
     }
   };

+ 7 - 3
partials/dasheditor.html

@@ -40,14 +40,18 @@
        </div>
     </div>
     <div class="row-fluid"> 
-      <div class="span3">
+      <div class="span2">
         <h6>Timestamping</h6><select class="input-small" ng-model="dashboard.current.index.interval" ng-options='f for f in ["none","hour","day","week","month","year"]'></select>
       </div>
-      <div class="span5" ng-show="dashboard.current.index.interval != 'none'">
+      <div class="span4" ng-show="dashboard.current.index.interval != 'none'">
         <h6>Index pattern <small>Absolutes in []</small></h6>
         <input type="text" class="input-medium" ng-model="dashboard.current.index.pattern">
       </div>
-      <div class="span4">
+      <div class="span2" ng-show="dashboard.current.index.interval != 'none'">
+        <h6>Failover <i class="icon-question-sign" bs-tooltip="'If no indices match the pattern, failover to default index *NOT RECOMMENDED*'"></i></h6>
+        <input type="checkbox" ng-model="dashboard.current.failover" ng-checked="dashboard.current.failover" />
+      </div>
+      <div class="span4" ng-show="dashboard.current.failover || dashboard.current.index.interval == 'none'">
         <h6>Default Index <small ng-show="dashboard.current.index.interval != 'none'">If index not found</small></h6>
         <input type="text" class="input-medium" ng-model="dashboard.current.index.default">
       </div>