소스 검색

feat(templating): lots of progress on template variable context specific formats, #2918, all elasticsearch / lucene use cases seem to work now

Torkel Ödegaard 9 년 전
부모
커밋
f3ad71d751

+ 2 - 2
.jshintrc

@@ -4,7 +4,7 @@
   "bitwise":false,
   "curly": true,
   "eqnull": true,
-  "globalstrict": true,
+  "strict": true,
   "devel": true,
   "eqeqeq": true,
   "forin": false,
@@ -12,7 +12,7 @@
   "supernew": true,
   "expr": true,
   "indent": 2,
-  "latedef": true,
+  "latedef": false,
   "newcap": true,
   "noarg": true,
   "noempty": true,

+ 2 - 2
package.json

@@ -24,7 +24,7 @@
     "grunt-contrib-copy": "~0.8.2",
     "grunt-contrib-cssmin": "~0.14.0",
     "grunt-contrib-htmlmin": "~0.6.0",
-    "grunt-contrib-jshint": "~0.11.3",
+    "grunt-contrib-jshint": "~1.0.0",
     "grunt-contrib-less": "~0.7.0",
     "grunt-contrib-uglify": "~0.11.0",
     "grunt-contrib-watch": "^0.6.1",
@@ -39,7 +39,7 @@
     "grunt-tslint": "^3.0.2",
     "grunt-typescript": "^0.8.0",
     "grunt-usemin": "3.0.0",
-    "jshint-stylish": "~0.1.5",
+    "jshint-stylish": "~2.1.0",
     "karma": "~0.13.15",
     "karma-chrome-launcher": "~0.2.2",
     "karma-coverage": "0.5.3",

+ 29 - 21
public/app/features/templating/templateSrv.js

@@ -31,31 +31,37 @@ function (angular, _) {
        }, this);
     };
 
-    this.regexEscape = function(value) {
+    function regexEscape(value) {
       return value.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
-    };
+    }
+
+    function luceneEscape(value) {
+      return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, "\\$1");
+    }
 
     this.formatValue = function(value, format) {
-      if (_.isString(value)) {
-        return value;
-      } else {
-        switch(format) {
-          case "regex": {
-            var escapedValues = _.map(value, this.regexEscape);
-            return '(' + escapedValues.join('|') + ')';
-          }
-          case "lucene": {
-            var quotedValues = _.map(value, function(val) {
-              return '\\\"' + val + '\\\"';
-            });
-            return '(' + quotedValues.join(' OR ') + ')';
-          }
-          case "pipe": {
-            return value.join('|');
+      switch(format) {
+        case "regex": {
+          var escapedValues = _.map(value, regexEscape);
+          return '(' + escapedValues.join('|') + ')';
+        }
+        case "lucene": {
+          if (typeof value === 'string') {
+            return luceneEscape(value);
           }
-          default:  {
-            return '{' + value.join(',') + '}';
+          var quotedValues = _.map(value, function(val) {
+            return '\"' + luceneEscape(val) + '\"';
+          });
+          return '(' + quotedValues.join(' OR ') + ')';
+        }
+        case "pipe": {
+          return value.join('|');
+        }
+        default:  {
+          if (typeof value === 'string') {
+            return value;
           }
+          return '{' + value.join(',') + '}';
         }
       }
     };
@@ -114,7 +120,9 @@ function (angular, _) {
           return self.formatValue(systemValue);
         }
 
-        return self.formatValue(value, format);
+        var res = self.formatValue(value, format);
+        console.log('replace: ' + value, res);
+        return res;
       });
     };
 

+ 9 - 6
public/app/plugins/datasource/elasticsearch/datasource.js

@@ -47,15 +47,15 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
     };
 
     this._get = function(url) {
-      return this._request('GET', this.indexPattern.getIndexForToday() + url)
-      .then(function(results) {
+      return this._request('GET', this.indexPattern.getIndexForToday() + url).then(function(results) {
+        results.data.$$config = results.config;
         return results.data;
       });
     };
 
     this._post = function(url, data) {
-      return this._request('POST', url, data)
-      .then(function(results) {
+      return this._request('POST', url, data).then(function(results) {
+        results.data.$$config = results.config;
         return results.data;
       });
     };
@@ -170,7 +170,10 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
 
         var queryObj = this.queryBuilder.build(target);
         var esQuery = angular.toJson(queryObj);
-        var luceneQuery = angular.toJson(target.query || '*');
+        var luceneQuery = target.query || '*';
+        luceneQuery = templateSrv.replace(luceneQuery, options.scopedVars, 'lucene');
+        luceneQuery = angular.toJson(luceneQuery);
+
         // remove inner quotes
         luceneQuery = luceneQuery.substr(1, luceneQuery.length - 2);
         esQuery = esQuery.replace("$lucene_query", luceneQuery);
@@ -190,7 +193,7 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
       payload = payload.replace(/\$interval/g, options.interval);
       payload = payload.replace(/\$timeFrom/g, options.range.from.valueOf());
       payload = payload.replace(/\$timeTo/g, options.range.to.valueOf());
-      payload = templateSrv.replace(payload, options.scopedVars, 'lucene');
+      payload = templateSrv.replace(payload, options.scopedVars);
 
       return this._post('_msearch', payload).then(function(res) {
         return new ElasticResponse(sentTargets, res).getTimeSeries();

+ 17 - 1
public/app/plugins/datasource/elasticsearch/elastic_response.js

@@ -284,13 +284,29 @@ function (_, queryDef) {
     }
   };
 
+  ElasticResponse.prototype.getErrorFromElasticResponse = function(response, err) {
+    var result = {};
+    result.data = JSON.stringify(err, null, 4);
+    if (err.root_cause && err.root_cause.length > 0 && err.root_cause[0].reason) {
+      result.message = err.root_cause[0].reason;
+    } else {
+      result.message = err.reason || 'Unkown elatic error response';
+    }
+
+    if (response.$$config) {
+      result.config = response.$$config;
+    }
+
+    return result;
+  };
+
   ElasticResponse.prototype.getTimeSeries = function() {
     var seriesList = [];
 
     for (var i = 0; i < this.response.responses.length; i++) {
       var response = this.response.responses[i];
       if (response.error) {
-        throw { message: response.error };
+        throw this.getErrorFromElasticResponse(this.response, response.error);
       }
 
       if (response.hits && response.hits.hits.length > 0) {

+ 2 - 2
public/test/.jshintrc

@@ -3,7 +3,7 @@
   "bitwise":false,
   "curly": true,
   "eqnull": true,
-  "globalstrict": true,
+  "strict": true,
   "devel": true,
   "eqeqeq": true,
   "forin": false,
@@ -11,7 +11,7 @@
   "supernew": true,
   "expr": true,
   "indent": 2,
-  "latedef": true,
+  "latedef": false,
   "newcap": true,
   "noarg": true,
   "noempty": true,

+ 14 - 1
public/test/specs/templateSrv-specs.js

@@ -45,7 +45,7 @@ define([
       });
     });
 
-    describe.only('replace can pass multi / all format', function() {
+    describe('replace can pass multi / all format', function() {
       beforeEach(function() {
         _templateSrv.init([{name: 'test', current: {value: ['value1', 'value2'] }}]);
       });
@@ -59,6 +59,19 @@ define([
         var target = _templateSrv.replace('this=$test', {}, 'pipe');
         expect(target).to.be('this=value1|value2');
       });
+
+      it('should replace $test with piped value', function() {
+        var target = _templateSrv.replace('this=$test', {}, 'pipe');
+        expect(target).to.be('this=value1|value2');
+      });
+    });
+
+    describe.only('lucene format', function() {
+      it('should properly escape $test with lucene escape sequences', function() {
+        _templateSrv.init([{name: 'test', current: {value: 'value/4' }}]);
+        var target = _templateSrv.replace('this:$test', {}, 'lucene');
+        expect(target).to.be("this:value\\\/4");
+      });
     });
 
     describe('render variable to string values', function() {