datasource_specs.ts 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. import _ from 'lodash';
  2. import { describe, beforeEach, it, expect, angularMocks } from 'test/lib/common';
  3. import moment from 'moment';
  4. import angular from 'angular';
  5. import helpers from 'test/specs/helpers';
  6. import { ElasticDatasource } from '../datasource';
  7. describe('ElasticDatasource', function() {
  8. var ctx = new helpers.ServiceTestContext();
  9. beforeEach(angularMocks.module('grafana.core'));
  10. beforeEach(angularMocks.module('grafana.services'));
  11. beforeEach(ctx.providePhase(['templateSrv', 'backendSrv', 'timeSrv']));
  12. beforeEach(
  13. angularMocks.inject(function($q, $rootScope, $httpBackend, $injector) {
  14. ctx.$q = $q;
  15. ctx.$httpBackend = $httpBackend;
  16. ctx.$rootScope = $rootScope;
  17. ctx.$injector = $injector;
  18. $httpBackend.when('GET', /\.html$/).respond('');
  19. })
  20. );
  21. function createDatasource(instanceSettings) {
  22. instanceSettings.jsonData = instanceSettings.jsonData || {};
  23. ctx.ds = ctx.$injector.instantiate(ElasticDatasource, {
  24. instanceSettings: instanceSettings,
  25. });
  26. }
  27. describe('When testing datasource with index pattern', function() {
  28. beforeEach(function() {
  29. createDatasource({
  30. url: 'http://es.com',
  31. index: '[asd-]YYYY.MM.DD',
  32. jsonData: { interval: 'Daily', esVersion: '2' },
  33. });
  34. });
  35. it('should translate index pattern to current day', function() {
  36. var requestOptions;
  37. ctx.backendSrv.datasourceRequest = function(options) {
  38. requestOptions = options;
  39. return ctx.$q.when({ data: {} });
  40. };
  41. ctx.ds.testDatasource();
  42. ctx.$rootScope.$apply();
  43. var today = moment.utc().format('YYYY.MM.DD');
  44. expect(requestOptions.url).to.be('http://es.com/asd-' + today + '/_mapping');
  45. });
  46. });
  47. describe('When issuing metric query with interval pattern', function() {
  48. var requestOptions, parts, header;
  49. beforeEach(function() {
  50. createDatasource({
  51. url: 'http://es.com',
  52. index: '[asd-]YYYY.MM.DD',
  53. jsonData: { interval: 'Daily', esVersion: '2' },
  54. });
  55. ctx.backendSrv.datasourceRequest = function(options) {
  56. requestOptions = options;
  57. return ctx.$q.when({ data: { responses: [] } });
  58. };
  59. ctx.ds.query({
  60. range: {
  61. from: moment.utc([2015, 4, 30, 10]),
  62. to: moment.utc([2015, 5, 1, 10]),
  63. },
  64. targets: [
  65. {
  66. bucketAggs: [],
  67. metrics: [{ type: 'raw_document' }],
  68. query: 'escape\\:test',
  69. },
  70. ],
  71. });
  72. ctx.$rootScope.$apply();
  73. parts = requestOptions.data.split('\n');
  74. header = angular.fromJson(parts[0]);
  75. });
  76. it('should translate index pattern to current day', function() {
  77. expect(header.index).to.eql(['asd-2015.05.30', 'asd-2015.05.31', 'asd-2015.06.01']);
  78. });
  79. it('should json escape lucene query', function() {
  80. var body = angular.fromJson(parts[1]);
  81. expect(body.query.bool.filter[1].query_string.query).to.be('escape\\:test');
  82. });
  83. });
  84. describe('When issuing document query', function() {
  85. var requestOptions, parts, header;
  86. beforeEach(function() {
  87. createDatasource({
  88. url: 'http://es.com',
  89. index: 'test',
  90. jsonData: { esVersion: '2' },
  91. });
  92. ctx.backendSrv.datasourceRequest = function(options) {
  93. requestOptions = options;
  94. return ctx.$q.when({ data: { responses: [] } });
  95. };
  96. ctx.ds.query({
  97. range: {
  98. from: moment([2015, 4, 30, 10]),
  99. to: moment([2015, 5, 1, 10]),
  100. },
  101. targets: [
  102. {
  103. bucketAggs: [],
  104. metrics: [{ type: 'raw_document' }],
  105. query: 'test',
  106. },
  107. ],
  108. });
  109. ctx.$rootScope.$apply();
  110. parts = requestOptions.data.split('\n');
  111. header = angular.fromJson(parts[0]);
  112. });
  113. it('should set search type to query_then_fetch', function() {
  114. expect(header.search_type).to.eql('query_then_fetch');
  115. });
  116. it('should set size', function() {
  117. var body = angular.fromJson(parts[1]);
  118. expect(body.size).to.be(500);
  119. });
  120. });
  121. describe('When getting fields', function() {
  122. beforeEach(function() {
  123. createDatasource({ url: 'http://es.com', index: 'metricbeat' });
  124. ctx.backendSrv.datasourceRequest = function(options) {
  125. return ctx.$q.when({
  126. data: {
  127. metricbeat: {
  128. mappings: {
  129. metricsets: {
  130. _all: {},
  131. properties: {
  132. '@timestamp': { type: 'date' },
  133. beat: {
  134. properties: {
  135. name: {
  136. fields: { raw: { type: 'keyword' } },
  137. type: 'string',
  138. },
  139. hostname: { type: 'string' },
  140. },
  141. },
  142. system: {
  143. properties: {
  144. cpu: {
  145. properties: {
  146. system: { type: 'float' },
  147. user: { type: 'float' },
  148. },
  149. },
  150. process: {
  151. properties: {
  152. cpu: {
  153. properties: {
  154. total: { type: 'float' },
  155. },
  156. },
  157. name: { type: 'string' },
  158. },
  159. },
  160. },
  161. },
  162. },
  163. },
  164. },
  165. },
  166. },
  167. });
  168. };
  169. });
  170. it('should return nested fields', function() {
  171. ctx.ds
  172. .getFields({
  173. find: 'fields',
  174. query: '*',
  175. })
  176. .then(fieldObjects => {
  177. var fields = _.map(fieldObjects, 'text');
  178. expect(fields).to.eql([
  179. '@timestamp',
  180. 'beat.name.raw',
  181. 'beat.name',
  182. 'beat.hostname',
  183. 'system.cpu.system',
  184. 'system.cpu.user',
  185. 'system.process.cpu.total',
  186. 'system.process.name',
  187. ]);
  188. });
  189. ctx.$rootScope.$apply();
  190. });
  191. it('should return fields related to query type', function() {
  192. ctx.ds
  193. .getFields({
  194. find: 'fields',
  195. query: '*',
  196. type: 'number',
  197. })
  198. .then(fieldObjects => {
  199. var fields = _.map(fieldObjects, 'text');
  200. expect(fields).to.eql(['system.cpu.system', 'system.cpu.user', 'system.process.cpu.total']);
  201. });
  202. ctx.ds
  203. .getFields({
  204. find: 'fields',
  205. query: '*',
  206. type: 'date',
  207. })
  208. .then(fieldObjects => {
  209. var fields = _.map(fieldObjects, 'text');
  210. expect(fields).to.eql(['@timestamp']);
  211. });
  212. ctx.$rootScope.$apply();
  213. });
  214. });
  215. describe('When issuing aggregation query on es5.x', function() {
  216. var requestOptions, parts, header;
  217. beforeEach(function() {
  218. createDatasource({
  219. url: 'http://es.com',
  220. index: 'test',
  221. jsonData: { esVersion: '5' },
  222. });
  223. ctx.backendSrv.datasourceRequest = function(options) {
  224. requestOptions = options;
  225. return ctx.$q.when({ data: { responses: [] } });
  226. };
  227. ctx.ds.query({
  228. range: {
  229. from: moment([2015, 4, 30, 10]),
  230. to: moment([2015, 5, 1, 10]),
  231. },
  232. targets: [
  233. {
  234. bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '2' }],
  235. metrics: [{ type: 'count' }],
  236. query: 'test',
  237. },
  238. ],
  239. });
  240. ctx.$rootScope.$apply();
  241. parts = requestOptions.data.split('\n');
  242. header = angular.fromJson(parts[0]);
  243. });
  244. it('should not set search type to count', function() {
  245. expect(header.search_type).to.not.eql('count');
  246. });
  247. it('should set size to 0', function() {
  248. var body = angular.fromJson(parts[1]);
  249. expect(body.size).to.be(0);
  250. });
  251. });
  252. describe('When issuing metricFind query on es5.x', function() {
  253. var requestOptions, parts, header, body, results;
  254. beforeEach(function() {
  255. createDatasource({
  256. url: 'http://es.com',
  257. index: 'test',
  258. jsonData: { esVersion: '5' },
  259. });
  260. ctx.backendSrv.datasourceRequest = function(options) {
  261. requestOptions = options;
  262. return ctx.$q.when({
  263. data: {
  264. responses: [
  265. {
  266. aggregations: {
  267. '1': {
  268. buckets: [
  269. { doc_count: 1, key: 'test' },
  270. {
  271. doc_count: 2,
  272. key: 'test2',
  273. key_as_string: 'test2_as_string',
  274. },
  275. ],
  276. },
  277. },
  278. },
  279. ],
  280. },
  281. });
  282. };
  283. ctx.ds.metricFindQuery('{"find": "terms", "field": "test"}').then(res => {
  284. results = res;
  285. });
  286. ctx.$rootScope.$apply();
  287. parts = requestOptions.data.split('\n');
  288. header = angular.fromJson(parts[0]);
  289. body = angular.fromJson(parts[1]);
  290. });
  291. it('should get results', function() {
  292. expect(results.length).to.eql(2);
  293. });
  294. it('should use key or key_as_string', function() {
  295. expect(results[0].text).to.eql('test');
  296. expect(results[1].text).to.eql('test2_as_string');
  297. });
  298. it('should not set search type to count', function() {
  299. expect(header.search_type).to.not.eql('count');
  300. });
  301. it('should set size to 0', function() {
  302. expect(body.size).to.be(0);
  303. });
  304. it('should not set terms aggregation size to 0', function() {
  305. expect(body['aggs']['1']['terms'].size).to.not.be(0);
  306. });
  307. });
  308. });