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

Updated default dashboard, added filtering panel

Rashid Khan 12 лет назад
Родитель
Сommit
2c5eb8bfb4

+ 1 - 1
common/lib/shared.js

@@ -284,7 +284,7 @@ function flatten_json(object,root,array) {
         } else if(obj.length === 1 && _.isNumber(obj[0])) {
         } else if(obj.length === 1 && _.isNumber(obj[0])) {
           array[rootname] = parseFloat(obj[0]);
           array[rootname] = parseFloat(obj[0]);
         } else {
         } else {
-          array[rootname] = typeof obj === 'undefined' ? null : obj.join(',');
+          array[rootname] = typeof obj === 'undefined' ? null : obj;
         }
         }
       } else {
       } else {
         flatten_json(obj,rootname,array)
         flatten_json(obj,rootname,array)

+ 1 - 1
config.js

@@ -20,7 +20,7 @@ var config = new Settings(
   elasticsearch:    "http://"+window.location.hostname+":9200",   
   elasticsearch:    "http://"+window.location.hostname+":9200",   
   // elasticsearch: 'http://localhost:9200',
   // elasticsearch: 'http://localhost:9200',
   kibana_index:     "kibana-int", 
   kibana_index:     "kibana-int", 
-  modules:          ['histogram','map','pie','table',
+  modules:          ['histogram','map','pie','table','filtering',
                     'timepicker','text','fields','hits','dashcontrol',
                     'timepicker','text','fields','hits','dashcontrol',
                     'column','derivequeries','trends','bettermap','query'],
                     'column','derivequeries','trends','bettermap','query'],
   }
   }

+ 103 - 58
dashboards/default → dashboards/default.json

@@ -1,6 +1,38 @@
 {
 {
   "title": "Logstash Search",
   "title": "Logstash Search",
-  "services": {},
+  "services": {
+    "query": {
+      "idQueue": [],
+      "list": {
+        "0": {
+          "query": "*",
+          "alias": "",
+          "color": "#7EB26D",
+          "id": 0
+        }
+      },
+      "ids": [
+        0
+      ]
+    },
+    "filter": {
+      "idQueue": [],
+      "list": {
+        "0": {
+          "from": "2013-07-15T03:54:27.219Z",
+          "to": "2013-07-15T04:09:27.219Z",
+          "field": "@timestamp",
+          "type": "time",
+          "mandate": "must",
+          "alias": "",
+          "id": 0
+        }
+      },
+      "ids": [
+        0
+      ]
+    }
+  },
   "rows": [
   "rows": [
     {
     {
       "title": "Options",
       "title": "Options",
@@ -11,13 +43,14 @@
       "panels": [
       "panels": [
         {
         {
           "loading": false,
           "loading": false,
-          "error": false,
+          "error": "",
           "span": 5,
           "span": 5,
           "editable": true,
           "editable": true,
           "group": [
           "group": [
             "default"
             "default"
           ],
           ],
           "type": "timepicker",
           "type": "timepicker",
+          "status": "Stable",
           "mode": "relative",
           "mode": "relative",
           "time_options": [
           "time_options": [
             "5m",
             "5m",
@@ -27,18 +60,18 @@
             "12h",
             "12h",
             "24h",
             "24h",
             "2d",
             "2d",
-            "5d"
+            "7d",
+            "30d"
           ],
           ],
-          "timespan": "6h",
+          "timespan": "15m",
           "timefield": "@timestamp",
           "timefield": "@timestamp",
-          "index": "[logstash-]YYYY.MM.DD",
-          "defaultindex": "NOINDEX",
-          "index_interval": "day",
+          "timeformat": "",
           "refresh": {
           "refresh": {
             "enable": false,
             "enable": false,
             "interval": 30,
             "interval": 30,
             "min": 3
             "min": 3
-          }
+          },
+          "filter_id": 0
         },
         },
         {
         {
           "loading": false,
           "loading": false,
@@ -49,6 +82,7 @@
             "default"
             "default"
           ],
           ],
           "type": "dashcontrol",
           "type": "dashcontrol",
+          "status": "Stable",
           "save": {
           "save": {
             "gist": false,
             "gist": false,
             "elasticsearch": true,
             "elasticsearch": true,
@@ -62,7 +96,6 @@
           },
           },
           "hide_control": false,
           "hide_control": false,
           "elasticsearch_size": 20,
           "elasticsearch_size": 20,
-          "elasticsearch_saveto": "kibana-int",
           "temp": true,
           "temp": true,
           "temp_ttl": "30d"
           "temp_ttl": "30d"
         }
         }
@@ -83,16 +116,12 @@
           "group": [
           "group": [
             "default"
             "default"
           ],
           ],
-          "type": "stringquery",
+          "type": "query",
+          "status": "Experimental",
           "label": "Search",
           "label": "Search",
           "query": "*",
           "query": "*",
-          "size": 100,
-          "sort": [
-            "_score",
-            "desc"
-          ],
-          "multi": false,
-          "multi_arrange": "horizontal"
+          "history": [],
+          "remember": 10
         }
         }
       ]
       ]
     },
     },
@@ -105,61 +134,77 @@
       "panels": [
       "panels": [
         {
         {
           "loading": false,
           "loading": false,
-          "span": 12,
+          "span": 9,
           "editable": true,
           "editable": true,
           "group": [
           "group": [
             "default"
             "default"
           ],
           ],
           "type": "histogram",
           "type": "histogram",
+          "status": "Stable",
           "query": [
           "query": [
             {
             {
               "query": "*",
               "query": "*",
-              "label": "*"
+              "label": "Query"
             }
             }
           ],
           ],
-          "interval": "5m",
-          "show": [
-            "points",
-            "lines",
-            "legend",
-            "x-axis",
-            "y-axis"
-          ],
+          "mode": "count",
+          "time_field": "@timestamp",
+          "value_field": null,
+          "auto_int": true,
+          "resolution": 100,
+          "interval": "10s",
+          "fill": 3,
+          "linewidth": 3,
           "timezone": "browser",
           "timezone": "browser",
           "spyable": true,
           "spyable": true,
           "zoomlinks": true,
           "zoomlinks": true,
-          "fill": 0,
-          "linewidth": 2,
           "bars": true,
           "bars": true,
           "stack": true,
           "stack": true,
           "points": false,
           "points": false,
           "lines": false,
           "lines": false,
           "legend": true,
           "legend": true,
           "x-axis": true,
           "x-axis": true,
-          "y-axis": true
+          "y-axis": true,
+          "percentage": false,
+          "interactive": true
         },
         },
         {
         {
           "loading": false,
           "loading": false,
-          "span": 0,
+          "error": false,
+          "span": 3,
           "editable": true,
           "editable": true,
           "group": [
           "group": [
             "default"
             "default"
           ],
           ],
-          "type": "hits",
+          "type": "filtering",
+          "status": "Stable",
           "query": [
           "query": [
             {
             {
               "query": "*",
               "query": "*",
-              "label": "*"
+              "label": "Query"
             }
             }
           ],
           ],
-          "style": {
-            "font-size": "9pt"
-          },
-          "aggregate": false,
-          "arrangement": "horizontal",
-          "chart": true,
-          "counters": true,
-          "count_pos": "above"
+          "mode": "count",
+          "time_field": "@timestamp",
+          "value_field": null,
+          "auto_int": true,
+          "resolution": 100,
+          "interval": "5m",
+          "fill": 3,
+          "linewidth": 3,
+          "timezone": "browser",
+          "spyable": true,
+          "zoomlinks": true,
+          "bars": true,
+          "stack": true,
+          "points": false,
+          "lines": false,
+          "legend": true,
+          "x-axis": true,
+          "y-axis": true,
+          "percentage": false,
+          "interactive": true,
+          "title": "Filters"
         }
         }
       ]
       ]
     },
     },
@@ -179,6 +224,7 @@
             "default"
             "default"
           ],
           ],
           "type": "fields",
           "type": "fields",
+          "status": "Beta",
           "style": {},
           "style": {},
           "arrange": "vertical",
           "arrange": "vertical",
           "micropanel_position": "right",
           "micropanel_position": "right",
@@ -197,21 +243,10 @@
             "default"
             "default"
           ],
           ],
           "type": "table",
           "type": "table",
+          "status": "Stable",
           "query": "*",
           "query": "*",
-          "interval": "1y",
-          "show": [
-            "bars",
-            "y-axis",
-            "x-axis",
-            "legend"
-          ],
-          "fill": 3,
-          "overflow": "min-height",
-          "timezone": "browser",
-          "spyable": true,
-          "zoomlinks": true,
-          "size": 50,
-          "pages": 10,
+          "size": 100,
+          "pages": 5,
           "offset": 0,
           "offset": 0,
           "sort": [
           "sort": [
             "@timestamp",
             "@timestamp",
@@ -220,14 +255,24 @@
           "style": {
           "style": {
             "font-size": "9pt"
             "font-size": "9pt"
           },
           },
+          "overflow": "min-height",
           "fields": [
           "fields": [
             "@timestamp",
             "@timestamp",
             "@message"
             "@message"
           ],
           ],
-          "sortable": true
+          "highlight": [],
+          "sortable": true,
+          "header": true,
+          "paging": true,
+          "spyable": true
         }
         }
       ]
       ]
     }
     }
   ],
   ],
-  "editable": true
-}
+  "editable": true,
+  "index": {
+    "interval": "day",
+    "pattern": "[logstash-]YYYY.MM.DD",
+    "default": "MISSING_INDEX"
+  }
+}

+ 1 - 1
index.html

@@ -37,7 +37,7 @@
     <div class="navbar navbar-static-top">
     <div class="navbar navbar-static-top">
       <div class="navbar-inner">
       <div class="navbar-inner">
         <div class="container-fluid">
         <div class="container-fluid">
-          <p class="navbar-text pull-right"><small><strong>Kibana 3</strong> <small>milestone 2</small></small></p>
+          <p class="navbar-text pull-right"><small><strong>Kibana 3</strong> <small>milestone pre-3</small></small></p>
           <span class="brand">{{dashboard.current.title}}</span>
           <span class="brand">{{dashboard.current.title}}</span>
           <div class="brand"><i class='icon-cog pointer' ng-show='dashboard.current.editable' bs-modal="'partials/dasheditor.html'"></i></div>
           <div class="brand"><i class='icon-cog pointer' ng-show='dashboard.current.editable' bs-modal="'partials/dasheditor.html'"></i></div>
         </div>
         </div>

+ 3 - 4
js/services.js

@@ -361,7 +361,6 @@ angular.module('kibana.services', [])
         .to(filter.to)
         .to(filter.to)
       break;
       break;
     case 'querystring':
     case 'querystring':
-      console.log(filter.query)
       return ejs.QueryFilter(ejs.QueryStringQuery(filter.query))
       return ejs.QueryFilter(ejs.QueryStringQuery(filter.query))
       break;
       break;
     case 'terms':
     case 'terms':
@@ -499,7 +498,7 @@ angular.module('kibana.services', [])
         self.dash_load(dashboard)
         self.dash_load(dashboard)
       // No? Ok, grab default.json, its all we have now
       // No? Ok, grab default.json, its all we have now
       } else {
       } else {
-        self.file_load('default')
+        self.file_load('default.json')
       } 
       } 
     }
     }
   }
   }
@@ -524,6 +523,7 @@ angular.module('kibana.services', [])
         // This is not optimal, we should be getting the entire index list here, or at least every
         // This is not optimal, we should be getting the entire index list here, or at least every
         // index that possibly matches the pattern
         // index that possibly matches the pattern
         self.indices = [self.current.index.default]
         self.indices = [self.current.index.default]
+        $rootScope.$broadcast('refresh')
       }
       }
     } else {
     } else {
       self.indices = [self.current.index.pattern]
       self.indices = [self.current.index.pattern]
@@ -700,6 +700,7 @@ angular.module('kibana.services', [])
   }
   }
 
 
   this.dash_load = function(dashboard) {
   this.dash_load = function(dashboard) {
+    timer.cancel_all();
 
 
     if(dashboard.index.interval === 'none') {
     if(dashboard.index.interval === 'none') {
       self.indices = [dashboard.index.pattern]
       self.indices = [dashboard.index.pattern]
@@ -707,8 +708,6 @@ angular.module('kibana.services', [])
 
 
     self.current = dashboard;
     self.current = dashboard;
 
 
-    timer.cancel_all();
-
     // Ok, now that we've setup the current dashboard, we can inject our services
     // Ok, now that we've setup the current dashboard, we can inject our services
     query = $injector.get('query');
     query = $injector.get('query');
     filterSrv = $injector.get('filterSrv')
     filterSrv = $injector.get('filterSrv')

+ 4 - 4
panels/fields/micropanel.html

@@ -1,8 +1,8 @@
 <a class="close" ng-click="dismiss()" href="">×</a>
 <a class="close" ng-click="dismiss()" href="">×</a>
 <h4>
 <h4>
   Micro Analysis of {{micropanel.field}} 
   Micro Analysis of {{micropanel.field}} 
-  <i class="pointer icon-search" ng-click="fieldExists(micropanel.field,'exists');dismiss();"></i>
-  <i class="pointer icon-ban-circle" ng-click="fieldExists(micropanel.field,'missing');dismiss();"></i>
+  <i class="pointer icon-search" ng-click="fieldExists(micropanel.field,'must');dismiss();"></i>
+  <i class="pointer icon-ban-circle" ng-click="fieldExists(micropanel.field,'mustNot');dismiss();"></i>
   <br><small>{{micropanel.count}} events in the table set</small>
   <br><small>{{micropanel.count}} events in the table set</small>
 </h4>
 </h4>
 <table style="width:480px" class='table table-bordered table-striped table-condensed'>
 <table style="width:480px" class='table table-bordered table-striped table-condensed'>
@@ -15,8 +15,8 @@
     <tr ng-repeat='field in micropanel.values'>
     <tr ng-repeat='field in micropanel.values'>
       <td>{{{true: "__blank__",false:field[0]}[field[0] == ""]}}</td>
       <td>{{{true: "__blank__",false:field[0]}[field[0] == ""]}}</td>
       <td>
       <td>
-        <i class="pointer icon-search" ng-click="build_search(micropanel.field,field[0]);dismiss();"></i>
-        <i class="pointer icon-ban-circle" ng-click="build_search(micropanel.field,field[0],true);dismiss();"></i>
+        <i class="pointer icon-search" ng-click="build_search(micropanel.field,field[0],'must');dismiss();"></i>
+        <i class="pointer icon-ban-circle" ng-click="build_search(micropanel.field,field[0],'mustNot');dismiss();"></i>
       </td>
       </td>
       <td>{{field[1]}}</td>
       <td>{{field[1]}}</td>
     </tr>
     </tr>

+ 6 - 5
panels/fields/module.js

@@ -79,14 +79,15 @@ angular.module('kibana.fields', [])
     eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active)
     eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active)
   }
   }
 
 
-  $scope.build_search = function(field,value,negate) {
-    var query = (negate ? '-':'+')+field+":\""+value+"\""
-    filterSrv.set({type:'querystring',query:query})
+  $scope.build_search = function(field,value,mandate) {
+    var query = field+":"+angular.toJson(value)
+    
+    filterSrv.set({type:'querystring',query:query,mandate:mandate})
     dashboard.refresh();
     dashboard.refresh();
   }
   }
 
 
-  $scope.fieldExists = function(field,mode) {
-    filterSrv.set({type:mode,field:field})
+  $scope.fieldExists = function(field,mandate) {
+    filterSrv.set({type:'exists',field:field,mandate:mandate})
     dashboard.refresh();
     dashboard.refresh();
   }
   }
 
 

+ 7 - 0
panels/filtering/editor.html

@@ -0,0 +1,7 @@
+<div>
+  <div class="row-fluid">    
+    <div class="span12">
+      No options here
+    </div>
+  </div>
+</div>

+ 15 - 0
panels/filtering/meta.html

@@ -0,0 +1,15 @@
+<div>
+  <style>
+    .input-query-alias {
+      margin-bottom: 5px !important;
+    }
+  </style>
+  <a class="close" ng-click="render();dismiss();" href="">×</a>
+  <h6>Query Alias</h6>
+  <form>
+    <input class="input-medium input-query-alias" type="text" ng-model="queries.list[id].alias" placeholder='Alias...' />
+    <div>
+      <i ng-repeat="color in queries.colors" class="pointer" ng-class="{'icon-circle-blank':queries.list[id].color == color,'icon-circle':queries.list[id].color != color}" style="color:{{color}}" ng-click="queries.list[id].color = color;render();"> </i>
+    </div>
+  </form>
+</div>

+ 36 - 0
panels/filtering/module.html

@@ -0,0 +1,36 @@
+<kibana-panel ng-controller='filtering' ng-init="init()">
+  <style>
+    .filter-panel-filter {
+      display:inline-block;
+      margin-left: 10px;
+      width: 200px;
+      padding: 5px;
+      border: #555 1px solid;
+      margin: 0px 5px 5px 0px;
+    }
+    .filter-must {
+      border-bottom: #7EB26D 3px solid;
+    }
+    .filter-mustNot {
+      border-bottom: #E24D42 3px solid;
+    }
+    .filter-should {
+      border-bottom: #EF843C 3px solid;
+    }
+    .filter-remove {
+      float:right;
+      margin-bottom: 0px !important;
+    }
+
+  </style>
+
+  <div ng-repeat="id in filterSrv.ids" class="small filter-panel-filter">
+    <div class="filter-{{filterSrv.list[id].mandate}}">
+      {{filterSrv.list[id].type}} ({{filterSrv.list[id].mandate}}) 
+      <i class="filter-remove pointer icon-remove" ng-click="remove(id)"></i>
+    </div>
+    <ul class="unstyled">
+      <li ng-repeat="(key,value) in stripped(filterSrv.list[id])"><strong>{{key}}</strong> : {{value}}</li>
+    </ul>
+  </div>
+</kibana-panel>

+ 42 - 0
panels/filtering/module.js

@@ -0,0 +1,42 @@
+/*
+
+  ## filtering
+
+  An experimental for interacting with the filter service
+
+  ### Parameters
+
+*/
+
+angular.module('kibana.filtering', [])
+.controller('filtering', function($scope, filterSrv, $rootScope, dashboard) {
+
+  // Set and populate defaults
+  var _d = {
+    status  : "Experimental"
+  }
+  _.defaults($scope.panel,_d);
+
+  $scope.init = function() {
+    $scope.filterSrv = filterSrv
+  }
+
+  $scope.remove = function(id) {
+    filterSrv.remove(id);
+    dashboard.refresh();
+  }
+
+  $scope.refresh = function(query) {
+    $rootScope.$broadcast('refresh')
+  }
+
+  $scope.render = function(query) {
+    $rootScope.$broadcast('render')
+  }
+
+  $scope.stripped = function(filter) {
+    var filter = _.omit(filter,'type','id','alias','mandate')
+    return filter
+  }
+
+});

+ 7 - 8
panels/histogram/module.js

@@ -32,12 +32,6 @@
   * x-axis :: Show x-axis labels and grid lines
   * x-axis :: Show x-axis labels and grid lines
   * y-axis :: Show y-axis labels and grid lines
   * y-axis :: Show y-axis labels and grid lines
   * interactive :: Allow drag to select time range
   * interactive :: Allow drag to select time range
-  ### Group Events
-  #### Receives
-  * time :: An object containing the time range to use and the index(es) to query
-  * query :: An Array of queries, even if its only one
-  #### Sends
-  * get_time :: On panel initialization get time range to query
 
 
 */
 */
 
 
@@ -80,6 +74,8 @@ angular.module('kibana.histogram', [])
       $scope.get_data();
       $scope.get_data();
     })
     })
 
 
+    $scope.get_data()
+
   }
   }
 
 
   $scope.get_data = function(segment,query_id) {
   $scope.get_data = function(segment,query_id) {
@@ -157,7 +153,10 @@ angular.module('kibana.histogram', [])
 
 
           // Null values at each end of the time range ensure we see entire range
           // Null values at each end of the time range ensure we see entire range
           if(_.isUndefined($scope.data[i]) || _segment == 0) {
           if(_.isUndefined($scope.data[i]) || _segment == 0) {
-            var data = [[_range.from.getTime(), null],[_range.to.getTime(), null]];
+            var data = []
+            if(filterSrv.idsByType('time').length > 0) {
+              data = [[_range.from.getTime(), null],[_range.to.getTime(), null]];
+            }
             var hits = 0;
             var hits = 0;
           } else {
           } else {
             var data = $scope.data[i].data
             var data = $scope.data[i].data
@@ -236,7 +235,7 @@ angular.module('kibana.histogram', [])
     $scope.modal = {
     $scope.modal = {
       title: "Inspector",
       title: "Inspector",
       body : "<h5>Last Elasticsearch Query</h5><pre>"+
       body : "<h5>Last Elasticsearch Query</h5><pre>"+
-          'curl -XGET '+config.elasticsearch+'/'+$scope.index+"/_search?pretty -d'\n"+
+          'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+
           angular.toJson(JSON.parse(request.toString()),true)+
           angular.toJson(JSON.parse(request.toString()),true)+
         "'</pre>", 
         "'</pre>", 
     } 
     } 

+ 1 - 1
panels/query/module.html

@@ -45,7 +45,7 @@
       <span class="end-query">
       <span class="end-query">
         <i class="icon-search pointer" ng-click="refresh()" ng-show="$last"></i>
         <i class="icon-search pointer" ng-click="refresh()" ng-show="$last"></i>
         <i class="icon-plus pointer" ng-click="queries.set({})" ng-show="$last"></i>
         <i class="icon-plus pointer" ng-click="queries.set({})" ng-show="$last"></i>
-      </span
+      </span>
     </form>
     </form>
   </div>
   </div>
 </kibana-panel>
 </kibana-panel>

+ 3 - 4
panels/table/module.js

@@ -55,8 +55,7 @@ angular.module('kibana.table', [])
 
 
     $scope.set_listeners($scope.panel.group)
     $scope.set_listeners($scope.panel.group)
 
 
-    // Now that we're all setup, request the time from our group
-    eventBus.broadcast($scope.$id,$scope.panel.group,"get_time")
+    $scope.get_data();
   }
   }
 
 
   $scope.set_listeners = function(group) {
   $scope.set_listeners = function(group) {
@@ -108,8 +107,8 @@ angular.module('kibana.table', [])
   }
   }
 
 
   $scope.build_search = function(field,value,negate) {
   $scope.build_search = function(field,value,negate) {
-    var query = (negate ? '-':'+')+field+":\""+value+"\""
-    filterSrv.set({type:'querystring',query:query})
+    var query = field+":"+angular.toJson(value)
+    filterSrv.set({type:'querystring',query:query,mandate:(negate ? 'mustNot':'must')})
     $scope.panel.offset = 0;
     $scope.panel.offset = 0;
     dashboard.refresh();
     dashboard.refresh();
   }
   }