Bläddra i källkod

option to adjust table time field to browser's local timezone. Set as default on logstash dashboard

Rashid Khan 12 år sedan
förälder
incheckning
6696e13073

+ 8 - 2
docs/kibana/panels/table.asciidoc

@@ -52,12 +52,18 @@ columns in the table, would trim each column at 20 character. The entirety of th
 still available in the expanded view of the event.
 still available in the expanded view of the event.
 // src/app/panels/table/module.js:105
 // src/app/panels/table/module.js:105
 
 
-spyable:: Set to false to disable the inspect icon
+localTime:: Set to true to adjust the timeField to the browser's local time
 // src/app/panels/table/module.js:112
 // src/app/panels/table/module.js:112
 
 
+timeField:: If localTime is set to true, this field will be adjusted to the browsers local time
+// src/app/panels/table/module.js:116
+
+spyable:: Set to false to disable the inspect icon
+// src/app/panels/table/module.js:120
+
 ==== Queries
 ==== Queries
 queries object:: This object describes the queries to use on this panel.
 queries object:: This object describes the queries to use on this panel.
 queries.mode::: Of the queries available, which to use. Options: +all, pinned, unpinned, selected+
 queries.mode::: Of the queries available, which to use. Options: +all, pinned, unpinned, selected+
 queries.ids::: In +selected+ mode, which query ids are selected.
 queries.ids::: In +selected+ mode, which query ids are selected.
-// src/app/panels/table/module.js:116
+// src/app/panels/table/module.js:124
 
 

+ 2 - 0
src/app/dashboards/logstash.json

@@ -128,6 +128,8 @@
           },
           },
           "overflow": "min-height",
           "overflow": "min-height",
           "fields": [],
           "fields": [],
+          "localTime": true,
+          "timeField": "@timestamp",
           "highlight": [],
           "highlight": [],
           "sortable": true,
           "sortable": true,
           "header": true,
           "header": true,

+ 39 - 38
src/app/panels/table/editor.html

@@ -1,48 +1,49 @@
   <div class="row-fluid">
   <div class="row-fluid">
-    <div class="span4">
-      <form class="input-append">
-        <h6>Add Column</h6>
+    <div class="section span6">
+      <h5>Columns</h5>
+      <form class="input-append editor-option">
         <input bs-typeahead="fields.list" type="text" class="input-small" ng-model='newfield'>
         <input bs-typeahead="fields.list" type="text" class="input-small" ng-model='newfield'>
         <button class="btn" ng-click="toggle_field(newfield);newfield=''"><i class="icon-plus"></i></button>
         <button class="btn" ng-click="toggle_field(newfield);newfield=''"><i class="icon-plus"></i></button>
-      </form>
+      </form><br>
+      <span style="margin-left:3px" ng-repeat="field in $parent.panel.fields" class="label">{{field}} <i class="pointer icon-remove-sign" ng-click="toggle_field(field)"></i></span>
     </div>
     </div>
-    <div class="span8">
-      <h6>Columns <small>Click to remove</small></h6>
-      <span style="margin-left:3px" ng-click="toggle_field(field)" ng-repeat="field in $parent.panel.fields" class="label pointer remove">{{field}} </span>
-    </div>
-  </div>
-  <div class="row-fluid">
-    <div class="span4">
-      <form class="input-append">
-        <h6>Add field</h6>
+    <div class="section span6">
+      <h5>Hightlighted Fields</h5>
+      <form class="input-append editor-option">
         <input bs-typeahead="fields.list" type="text" class="input-small" ng-model='newhighlight' ng-change="set_refresh(true)">
         <input bs-typeahead="fields.list" type="text" class="input-small" ng-model='newhighlight' ng-change="set_refresh(true)">
         <button class="btn" ng-click="toggle_highlight(newhighlight);newhighlight=''"><i class="icon-plus"></i></button>
         <button class="btn" ng-click="toggle_highlight(newhighlight);newhighlight=''"><i class="icon-plus"></i></button>
-      </form>
-    </div>
-    <div class="span8">
-      <h6>Highlighted fields <small>Click to remove</small></h6>
-      <span style="margin-left:3px" ng-click="toggle_highlight(field);set_refresh(true)" ng-repeat="field in $parent.panel.highlight" class="label remove pointer">{{field}} </span>
+      </form><br>
+      <span style="margin-left:3px" ng-repeat="field in $parent.panel.highlight" class="label">{{field}} <i class="pointer icon-remove-sign" ng-click="toggle_highlight(field);set_refresh(true)" ></i></span>
     </div>
     </div>
   </div>
   </div>
-  <h5>Options</h5>
-  <div class="row-fluid">
-    <div class="span1">
-      <h6>Header</h6><input type="checkbox" ng-model="panel.header" ng-checked="panel.header">
-    </div>
-    <div class="span1">
-      <h6>Sorting</h6><input type="checkbox" ng-model="panel.sortable" ng-checked="panel.sortable">
-    </div>
-    <div class="span3" style="white-space:nowrap" ng-show='panel.sortable'>
-      <h6>Sort</h6>
-      <input ng-show="all_fields.length<=0 || !all_fields"style="width:85%" ng-model="panel.sort[0]" type="text"></input>
-      <select ng-show="all_fields.length>0"style="width:85%" ng-model="panel.sort[0]" ng-options="f for f in all_fields"></select>
-      <i ng-click="set_sort(panel.sort[0])" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
-    </div>
-    <div class="span2"><h6>Font Size</h6>
-      <select class="input-small" ng-model="panel.style['font-size']" ng-options="f for f in ['7pt','8pt','9pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select></span>
-    </div>
-    <div class="span2">
-      <h6>Trim Factor <tip>Trim fields to this long divided by # of rows. Requires data refresh.</tip></h6>
-      <input type="number" class="input-small" ng-model="panel.trimFactor" ng-change="set_refresh(true)">
+
+  <div class="editor-row">
+    <div class="section">
+      <h5>Options</h5>
+      <div class="editor-option">
+        <h6>Header</h6><input type="checkbox" ng-model="panel.header" ng-checked="panel.header">
+      </div>
+      <div class="editor-option">
+        <h6>Sorting</h6><input type="checkbox" ng-model="panel.sortable" ng-checked="panel.sortable">
+      </div>
+      <div class="editor-option" style="white-space:nowrap" ng-show='panel.sortable'>
+        <h6>Sort</h6>
+        <input class="input-small" bs-typeahead="fields.list" ng-model="panel.sort[0]" type="text"></input>
+        <i ng-click="set_sort(panel.sort[0])" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
+      </div>
+      <div class="editor-option"><h6>Font Size</h6>
+        <select class="input-small" ng-model="panel.style['font-size']" ng-options="f for f in ['7pt','8pt','9pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select></span>
+      </div>
+      <div class="editor-option">
+        <h6>Trim Factor <tip>Trim fields to this long divided by # of rows. Requires data refresh.</tip></h6>
+        <input type="number" class="input-small" ng-model="panel.trimFactor" ng-change="set_refresh(true)">
+      </div>
+      <div class="editor-option">
+        <h6>Local Time <tip>Adjust time field to browser's local time</tip></h6><input type="checkbox" ng-change="set_refresh(true)" ng-model="panel.localTime" ng-checked="panel.localTime">
+      </div>
+      <div class="editor-option" ng-show="panel.localTime">
+        <h6>Time Field</h6>
+        <input type="text" class="input-small" ng-model="panel.timeField" ng-change="set_refresh(true)" bs-typeahead="fields.list">
+      </div>
     </div>
     </div>
   </div>
   </div>

+ 4 - 1
src/app/panels/table/module.html

@@ -69,7 +69,10 @@
         <tbody bindonce ng-repeat="event in data| slice:panel.offset:panel.offset+panel.size" ng-class-odd="'odd'">
         <tbody bindonce ng-repeat="event in data| slice:panel.offset:panel.offset+panel.size" ng-class-odd="'odd'">
           <tr ng-click="toggle_details(event)" class="pointer">
           <tr ng-click="toggle_details(event)" class="pointer">
             <td ng-if="panel.fields.length<1" bo-text="event._source|stringify|tableTruncate:panel.trimFactor:1"></td>
             <td ng-if="panel.fields.length<1" bo-text="event._source|stringify|tableTruncate:panel.trimFactor:1"></td>
-            <td ng-show="panel.fields.length>0" ng-repeat="field in panel.fields" bo-html="(event.kibana.highlight[field]||event.kibana._source[field]) |tableHighlight | tableTruncate:panel.trimFactor:panel.fields.length"></td>
+            <td ng-show="panel.fields.length>0" ng-repeat="field in panel.fields">
+              <span ng-if="!panel.localTime || panel.timeField != field" bo-html="(event.kibana.highlight[field]||event.kibana._source[field]) |tableHighlight | tableTruncate:panel.trimFactor:panel.fields.length"></span>
+              <span ng-if="panel.localTime && panel.timeField == field" bo-html="event.sort[1]|tableLocalTime:event"></span>
+            </td>
           </tr>
           </tr>
           <tr ng-if="event.kibana.details">
           <tr ng-if="event.kibana.details">
             <td colspan={{panel.fields.length}} ng-switch="event.kibana.view">
             <td colspan={{panel.fields.length}} ng-switch="event.kibana.view">

+ 23 - 19
src/app/panels/table/module.js

@@ -109,6 +109,14 @@ function (angular, app, _, kbn, moment) {
        * still available in the expanded view of the event.
        * still available in the expanded view of the event.
        */
        */
       trimFactor: 300,
       trimFactor: 300,
+      /** @scratch /panels/table/5
+       * localTime:: Set to true to adjust the timeField to the browser's local time
+       */
+      localTime: false,
+      /** @scratch /panels/table/5
+       * timeField:: If localTime is set to true, this field will be adjusted to the browsers local time
+       */
+      timeField: '@timestamp',
       /** @scratch /panels/table/5
       /** @scratch /panels/table/5
        * spyable:: Set to false to disable the inspect icon
        * spyable:: Set to false to disable the inspect icon
        */
        */
@@ -258,7 +266,8 @@ function (angular, app, _, kbn, moment) {
         _segment,
         _segment,
         request,
         request,
         boolQuery,
         boolQuery,
-        results;
+        queries,
+        sort;
 
 
       $scope.panel.error =  false;
       $scope.panel.error =  false;
 
 
@@ -267,6 +276,12 @@ function (angular, app, _, kbn, moment) {
         return;
         return;
       }
       }
 
 
+      sort = [$scope.ejs.Sort($scope.panel.sort[0]).order($scope.panel.sort[1])];
+      if($scope.panel.localTime) {
+        sort.push($scope.ejs.Sort($scope.panel.timeField).order($scope.panel.sort[1]));
+      }
+
+
       $scope.panelMeta.loading = true;
       $scope.panelMeta.loading = true;
 
 
       _segment = _.isUndefined(segment) ? 0 : segment;
       _segment = _.isUndefined(segment) ? 0 : segment;
@@ -275,7 +290,8 @@ function (angular, app, _, kbn, moment) {
       request = $scope.ejs.Request().indices(dashboard.indices[_segment]);
       request = $scope.ejs.Request().indices(dashboard.indices[_segment]);
 
 
       $scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
       $scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
-      var queries = querySrv.getQueryObjs($scope.panel.queries.ids);
+
+      queries = querySrv.getQueryObjs($scope.panel.queries.ids);
 
 
       boolQuery = $scope.ejs.BoolQuery();
       boolQuery = $scope.ejs.BoolQuery();
       _.each(queries,function(q) {
       _.each(queries,function(q) {
@@ -294,14 +310,12 @@ function (angular, app, _, kbn, moment) {
           .postTags('@end-highlight@')
           .postTags('@end-highlight@')
         )
         )
         .size($scope.panel.size*$scope.panel.pages)
         .size($scope.panel.size*$scope.panel.pages)
-        .sort($scope.panel.sort[0],$scope.panel.sort[1]);
+        .sort(sort);
 
 
       $scope.populate_modal(request);
       $scope.populate_modal(request);
 
 
-      results = request.doSearch();
-
       // Populate scope when we have results
       // Populate scope when we have results
-      results.then(function(results) {
+      request.doSearch().then(function(results) {
         $scope.panelMeta.loading = false;
         $scope.panelMeta.loading = false;
 
 
         if(_segment === 0) {
         if(_segment === 0) {
@@ -470,19 +484,9 @@ function (angular, app, _, kbn, moment) {
   });
   });
 
 
   // WIP
   // WIP
-  module.filter('tableFieldFormat', function(fields){
-    return function(text,field,event,scope) {
-      var type;
-      if(
-        !_.isUndefined(fields.mapping[event._index]) &&
-        !_.isUndefined(fields.mapping[event._index][event._type])
-      ) {
-        type = fields.mapping[event._index][event._type][field]['type'];
-        if(type === 'date' && scope.panel.normTimes) {
-          return moment(text).format('YYYY-MM-DD HH:mm:ss');
-        }
-      }
-      return text;
+  module.filter('tableLocalTime', function(){
+    return function(text,event) {
+      return moment(event.sort[1]).format("YYYY-MM-DDTHH:mm:ss.SSSZ");
     };
     };
   });
   });