Browse Source

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

Rashid Khan 12 years ago
parent
commit
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.
 // 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
 
+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 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.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",
           "fields": [],
+          "localTime": true,
+          "timeField": "@timestamp",
           "highlight": [],
           "sortable": true,
           "header": true,

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

@@ -1,48 +1,49 @@
   <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'>
         <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 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)">
         <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>
-  <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>

+ 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'">
           <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-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 ng-if="event.kibana.details">
             <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.
        */
       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
        * spyable:: Set to false to disable the inspect icon
        */
@@ -258,7 +266,8 @@ function (angular, app, _, kbn, moment) {
         _segment,
         request,
         boolQuery,
-        results;
+        queries,
+        sort;
 
       $scope.panel.error =  false;
 
@@ -267,6 +276,12 @@ function (angular, app, _, kbn, moment) {
         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;
 
       _segment = _.isUndefined(segment) ? 0 : segment;
@@ -275,7 +290,8 @@ function (angular, app, _, kbn, moment) {
       request = $scope.ejs.Request().indices(dashboard.indices[_segment]);
 
       $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();
       _.each(queries,function(q) {
@@ -294,14 +310,12 @@ function (angular, app, _, kbn, moment) {
           .postTags('@end-highlight@')
         )
         .size($scope.panel.size*$scope.panel.pages)
-        .sort($scope.panel.sort[0],$scope.panel.sort[1]);
+        .sort(sort);
 
       $scope.populate_modal(request);
 
-      results = request.doSearch();
-
       // Populate scope when we have results
-      results.then(function(results) {
+      request.doSearch().then(function(results) {
         $scope.panelMeta.loading = false;
 
         if(_segment === 0) {
@@ -470,19 +484,9 @@ function (angular, app, _, kbn, moment) {
   });
 
   // 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");
     };
   });