elastic_response.test.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. import { ElasticResponse } from '../elastic_response';
  2. describe('ElasticResponse', () => {
  3. let targets;
  4. let response;
  5. let result;
  6. describe('simple query and count', () => {
  7. beforeEach(() => {
  8. targets = [
  9. {
  10. refId: 'A',
  11. metrics: [{ type: 'count', id: '1' }],
  12. bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '2' }],
  13. },
  14. ];
  15. response = {
  16. responses: [
  17. {
  18. aggregations: {
  19. '2': {
  20. buckets: [
  21. {
  22. doc_count: 10,
  23. key: 1000,
  24. },
  25. {
  26. doc_count: 15,
  27. key: 2000,
  28. },
  29. ],
  30. },
  31. },
  32. },
  33. ],
  34. };
  35. result = new ElasticResponse(targets, response).getTimeSeries();
  36. });
  37. it('should return 1 series', () => {
  38. expect(result.data.length).toBe(1);
  39. expect(result.data[0].target).toBe('Count');
  40. expect(result.data[0].datapoints.length).toBe(2);
  41. expect(result.data[0].datapoints[0][0]).toBe(10);
  42. expect(result.data[0].datapoints[0][1]).toBe(1000);
  43. });
  44. });
  45. describe('simple query count & avg aggregation', () => {
  46. let result;
  47. beforeEach(() => {
  48. targets = [
  49. {
  50. refId: 'A',
  51. metrics: [{ type: 'count', id: '1' }, { type: 'avg', field: 'value', id: '2' }],
  52. bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '3' }],
  53. },
  54. ];
  55. response = {
  56. responses: [
  57. {
  58. aggregations: {
  59. '3': {
  60. buckets: [
  61. {
  62. '2': { value: 88 },
  63. doc_count: 10,
  64. key: 1000,
  65. },
  66. {
  67. '2': { value: 99 },
  68. doc_count: 15,
  69. key: 2000,
  70. },
  71. ],
  72. },
  73. },
  74. },
  75. ],
  76. };
  77. result = new ElasticResponse(targets, response).getTimeSeries();
  78. });
  79. it('should return 2 series', () => {
  80. expect(result.data.length).toBe(2);
  81. expect(result.data[0].datapoints.length).toBe(2);
  82. expect(result.data[0].datapoints[0][0]).toBe(10);
  83. expect(result.data[0].datapoints[0][1]).toBe(1000);
  84. expect(result.data[1].target).toBe('Average value');
  85. expect(result.data[1].datapoints[0][0]).toBe(88);
  86. expect(result.data[1].datapoints[1][0]).toBe(99);
  87. });
  88. });
  89. describe('single group by query one metric', () => {
  90. let result;
  91. beforeEach(() => {
  92. targets = [
  93. {
  94. refId: 'A',
  95. metrics: [{ type: 'count', id: '1' }],
  96. bucketAggs: [
  97. { type: 'terms', field: 'host', id: '2' },
  98. { type: 'date_histogram', field: '@timestamp', id: '3' },
  99. ],
  100. },
  101. ];
  102. response = {
  103. responses: [
  104. {
  105. aggregations: {
  106. '2': {
  107. buckets: [
  108. {
  109. '3': {
  110. buckets: [{ doc_count: 1, key: 1000 }, { doc_count: 3, key: 2000 }],
  111. },
  112. doc_count: 4,
  113. key: 'server1',
  114. },
  115. {
  116. '3': {
  117. buckets: [{ doc_count: 2, key: 1000 }, { doc_count: 8, key: 2000 }],
  118. },
  119. doc_count: 10,
  120. key: 'server2',
  121. },
  122. ],
  123. },
  124. },
  125. },
  126. ],
  127. };
  128. result = new ElasticResponse(targets, response).getTimeSeries();
  129. });
  130. it('should return 2 series', () => {
  131. expect(result.data.length).toBe(2);
  132. expect(result.data[0].datapoints.length).toBe(2);
  133. expect(result.data[0].target).toBe('server1');
  134. expect(result.data[1].target).toBe('server2');
  135. });
  136. });
  137. describe('single group by query two metrics', () => {
  138. let result;
  139. beforeEach(() => {
  140. targets = [
  141. {
  142. refId: 'A',
  143. metrics: [{ type: 'count', id: '1' }, { type: 'avg', field: '@value', id: '4' }],
  144. bucketAggs: [
  145. { type: 'terms', field: 'host', id: '2' },
  146. { type: 'date_histogram', field: '@timestamp', id: '3' },
  147. ],
  148. },
  149. ];
  150. response = {
  151. responses: [
  152. {
  153. aggregations: {
  154. '2': {
  155. buckets: [
  156. {
  157. '3': {
  158. buckets: [
  159. { '4': { value: 10 }, doc_count: 1, key: 1000 },
  160. { '4': { value: 12 }, doc_count: 3, key: 2000 },
  161. ],
  162. },
  163. doc_count: 4,
  164. key: 'server1',
  165. },
  166. {
  167. '3': {
  168. buckets: [
  169. { '4': { value: 20 }, doc_count: 1, key: 1000 },
  170. { '4': { value: 32 }, doc_count: 3, key: 2000 },
  171. ],
  172. },
  173. doc_count: 10,
  174. key: 'server2',
  175. },
  176. ],
  177. },
  178. },
  179. },
  180. ],
  181. };
  182. result = new ElasticResponse(targets, response).getTimeSeries();
  183. });
  184. it('should return 2 series', () => {
  185. expect(result.data.length).toBe(4);
  186. expect(result.data[0].datapoints.length).toBe(2);
  187. expect(result.data[0].target).toBe('server1 Count');
  188. expect(result.data[1].target).toBe('server1 Average @value');
  189. expect(result.data[2].target).toBe('server2 Count');
  190. expect(result.data[3].target).toBe('server2 Average @value');
  191. });
  192. });
  193. describe('with percentiles ', () => {
  194. let result;
  195. beforeEach(() => {
  196. targets = [
  197. {
  198. refId: 'A',
  199. metrics: [{ type: 'percentiles', settings: { percents: [75, 90] }, id: '1' }],
  200. bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '3' }],
  201. },
  202. ];
  203. response = {
  204. responses: [
  205. {
  206. aggregations: {
  207. '3': {
  208. buckets: [
  209. {
  210. '1': { values: { '75': 3.3, '90': 5.5 } },
  211. doc_count: 10,
  212. key: 1000,
  213. },
  214. {
  215. '1': { values: { '75': 2.3, '90': 4.5 } },
  216. doc_count: 15,
  217. key: 2000,
  218. },
  219. ],
  220. },
  221. },
  222. },
  223. ],
  224. };
  225. result = new ElasticResponse(targets, response).getTimeSeries();
  226. });
  227. it('should return 2 series', () => {
  228. expect(result.data.length).toBe(2);
  229. expect(result.data[0].datapoints.length).toBe(2);
  230. expect(result.data[0].target).toBe('p75');
  231. expect(result.data[1].target).toBe('p90');
  232. expect(result.data[0].datapoints[0][0]).toBe(3.3);
  233. expect(result.data[0].datapoints[0][1]).toBe(1000);
  234. expect(result.data[1].datapoints[1][0]).toBe(4.5);
  235. });
  236. });
  237. describe('with extended_stats', () => {
  238. let result;
  239. beforeEach(() => {
  240. targets = [
  241. {
  242. refId: 'A',
  243. metrics: [
  244. {
  245. type: 'extended_stats',
  246. meta: { max: true, std_deviation_bounds_upper: true },
  247. id: '1',
  248. },
  249. ],
  250. bucketAggs: [{ type: 'terms', field: 'host', id: '3' }, { type: 'date_histogram', id: '4' }],
  251. },
  252. ];
  253. response = {
  254. responses: [
  255. {
  256. aggregations: {
  257. '3': {
  258. buckets: [
  259. {
  260. key: 'server1',
  261. '4': {
  262. buckets: [
  263. {
  264. '1': {
  265. max: 10.2,
  266. min: 5.5,
  267. std_deviation_bounds: { upper: 3, lower: -2 },
  268. },
  269. doc_count: 10,
  270. key: 1000,
  271. },
  272. ],
  273. },
  274. },
  275. {
  276. key: 'server2',
  277. '4': {
  278. buckets: [
  279. {
  280. '1': {
  281. max: 10.2,
  282. min: 5.5,
  283. std_deviation_bounds: { upper: 3, lower: -2 },
  284. },
  285. doc_count: 10,
  286. key: 1000,
  287. },
  288. ],
  289. },
  290. },
  291. ],
  292. },
  293. },
  294. },
  295. ],
  296. };
  297. result = new ElasticResponse(targets, response).getTimeSeries();
  298. });
  299. it('should return 4 series', () => {
  300. expect(result.data.length).toBe(4);
  301. expect(result.data[0].datapoints.length).toBe(1);
  302. expect(result.data[0].target).toBe('server1 Max');
  303. expect(result.data[1].target).toBe('server1 Std Dev Upper');
  304. expect(result.data[0].datapoints[0][0]).toBe(10.2);
  305. expect(result.data[1].datapoints[0][0]).toBe(3);
  306. });
  307. });
  308. describe('single group by with alias pattern', () => {
  309. let result;
  310. beforeEach(() => {
  311. targets = [
  312. {
  313. refId: 'A',
  314. metrics: [{ type: 'count', id: '1' }],
  315. alias: '{{term @host}} {{metric}} and {{not_exist}} {{@host}}',
  316. bucketAggs: [
  317. { type: 'terms', field: '@host', id: '2' },
  318. { type: 'date_histogram', field: '@timestamp', id: '3' },
  319. ],
  320. },
  321. ];
  322. response = {
  323. responses: [
  324. {
  325. aggregations: {
  326. '2': {
  327. buckets: [
  328. {
  329. '3': {
  330. buckets: [{ doc_count: 1, key: 1000 }, { doc_count: 3, key: 2000 }],
  331. },
  332. doc_count: 4,
  333. key: 'server1',
  334. },
  335. {
  336. '3': {
  337. buckets: [{ doc_count: 2, key: 1000 }, { doc_count: 8, key: 2000 }],
  338. },
  339. doc_count: 10,
  340. key: 'server2',
  341. },
  342. {
  343. '3': {
  344. buckets: [{ doc_count: 2, key: 1000 }, { doc_count: 8, key: 2000 }],
  345. },
  346. doc_count: 10,
  347. key: 0,
  348. },
  349. ],
  350. },
  351. },
  352. },
  353. ],
  354. };
  355. result = new ElasticResponse(targets, response).getTimeSeries();
  356. });
  357. it('should return 2 series', () => {
  358. expect(result.data.length).toBe(3);
  359. expect(result.data[0].datapoints.length).toBe(2);
  360. expect(result.data[0].target).toBe('server1 Count and {{not_exist}} server1');
  361. expect(result.data[1].target).toBe('server2 Count and {{not_exist}} server2');
  362. expect(result.data[2].target).toBe('0 Count and {{not_exist}} 0');
  363. });
  364. });
  365. describe('histogram response', () => {
  366. let result;
  367. beforeEach(() => {
  368. targets = [
  369. {
  370. refId: 'A',
  371. metrics: [{ type: 'count', id: '1' }],
  372. bucketAggs: [{ type: 'histogram', field: 'bytes', id: '3' }],
  373. },
  374. ];
  375. response = {
  376. responses: [
  377. {
  378. aggregations: {
  379. '3': {
  380. buckets: [{ doc_count: 1, key: 1000 }, { doc_count: 3, key: 2000 }, { doc_count: 2, key: 1000 }],
  381. },
  382. },
  383. },
  384. ],
  385. };
  386. result = new ElasticResponse(targets, response).getTimeSeries();
  387. });
  388. it('should return table with byte and count', () => {
  389. expect(result.data[0].rows.length).toBe(3);
  390. expect(result.data[0].columns).toEqual([{ text: 'bytes', filterable: true }, { text: 'Count' }]);
  391. });
  392. });
  393. describe('with two filters agg', () => {
  394. let result;
  395. beforeEach(() => {
  396. targets = [
  397. {
  398. refId: 'A',
  399. metrics: [{ type: 'count', id: '1' }],
  400. bucketAggs: [
  401. {
  402. id: '2',
  403. type: 'filters',
  404. settings: {
  405. filters: [{ query: '@metric:cpu' }, { query: '@metric:logins.count' }],
  406. },
  407. },
  408. { type: 'date_histogram', field: '@timestamp', id: '3' },
  409. ],
  410. },
  411. ];
  412. response = {
  413. responses: [
  414. {
  415. aggregations: {
  416. '2': {
  417. buckets: {
  418. '@metric:cpu': {
  419. '3': {
  420. buckets: [{ doc_count: 1, key: 1000 }, { doc_count: 3, key: 2000 }],
  421. },
  422. },
  423. '@metric:logins.count': {
  424. '3': {
  425. buckets: [{ doc_count: 2, key: 1000 }, { doc_count: 8, key: 2000 }],
  426. },
  427. },
  428. },
  429. },
  430. },
  431. },
  432. ],
  433. };
  434. result = new ElasticResponse(targets, response).getTimeSeries();
  435. });
  436. it('should return 2 series', () => {
  437. expect(result.data.length).toBe(2);
  438. expect(result.data[0].datapoints.length).toBe(2);
  439. expect(result.data[0].target).toBe('@metric:cpu');
  440. expect(result.data[1].target).toBe('@metric:logins.count');
  441. });
  442. });
  443. describe('with dropfirst and last aggregation', () => {
  444. beforeEach(() => {
  445. targets = [
  446. {
  447. refId: 'A',
  448. metrics: [{ type: 'avg', id: '1' }, { type: 'count' }],
  449. bucketAggs: [
  450. {
  451. id: '2',
  452. type: 'date_histogram',
  453. field: 'host',
  454. settings: { trimEdges: 1 },
  455. },
  456. ],
  457. },
  458. ];
  459. response = {
  460. responses: [
  461. {
  462. aggregations: {
  463. '2': {
  464. buckets: [
  465. {
  466. '1': { value: 1000 },
  467. key: 1,
  468. doc_count: 369,
  469. },
  470. {
  471. '1': { value: 2000 },
  472. key: 2,
  473. doc_count: 200,
  474. },
  475. {
  476. '1': { value: 2000 },
  477. key: 3,
  478. doc_count: 200,
  479. },
  480. ],
  481. },
  482. },
  483. },
  484. ],
  485. };
  486. result = new ElasticResponse(targets, response).getTimeSeries();
  487. });
  488. it('should remove first and last value', () => {
  489. expect(result.data.length).toBe(2);
  490. expect(result.data[0].datapoints.length).toBe(1);
  491. });
  492. });
  493. describe('No group by time', () => {
  494. beforeEach(() => {
  495. targets = [
  496. {
  497. refId: 'A',
  498. metrics: [{ type: 'avg', id: '1' }, { type: 'count' }],
  499. bucketAggs: [{ id: '2', type: 'terms', field: 'host' }],
  500. },
  501. ];
  502. response = {
  503. responses: [
  504. {
  505. aggregations: {
  506. '2': {
  507. buckets: [
  508. {
  509. '1': { value: 1000 },
  510. key: 'server-1',
  511. doc_count: 369,
  512. },
  513. {
  514. '1': { value: 2000 },
  515. key: 'server-2',
  516. doc_count: 200,
  517. },
  518. ],
  519. },
  520. },
  521. },
  522. ],
  523. };
  524. result = new ElasticResponse(targets, response).getTimeSeries();
  525. });
  526. it('should return table', () => {
  527. expect(result.data.length).toBe(1);
  528. expect(result.data[0].type).toBe('table');
  529. expect(result.data[0].rows.length).toBe(2);
  530. expect(result.data[0].rows[0][0]).toBe('server-1');
  531. expect(result.data[0].rows[0][1]).toBe(1000);
  532. expect(result.data[0].rows[0][2]).toBe(369);
  533. expect(result.data[0].rows[1][0]).toBe('server-2');
  534. expect(result.data[0].rows[1][1]).toBe(2000);
  535. });
  536. });
  537. describe('Multiple metrics of same type', () => {
  538. beforeEach(() => {
  539. targets = [
  540. {
  541. refId: 'A',
  542. metrics: [{ type: 'avg', id: '1', field: 'test' }, { type: 'avg', id: '2', field: 'test2' }],
  543. bucketAggs: [{ id: '2', type: 'terms', field: 'host' }],
  544. },
  545. ];
  546. response = {
  547. responses: [
  548. {
  549. aggregations: {
  550. '2': {
  551. buckets: [
  552. {
  553. '1': { value: 1000 },
  554. '2': { value: 3000 },
  555. key: 'server-1',
  556. doc_count: 369,
  557. },
  558. ],
  559. },
  560. },
  561. },
  562. ],
  563. };
  564. result = new ElasticResponse(targets, response).getTimeSeries();
  565. });
  566. it('should include field in metric name', () => {
  567. expect(result.data[0].type).toBe('table');
  568. expect(result.data[0].rows[0][1]).toBe(1000);
  569. expect(result.data[0].rows[0][2]).toBe(3000);
  570. });
  571. });
  572. describe('Raw documents query', () => {
  573. beforeEach(() => {
  574. targets = [
  575. {
  576. refId: 'A',
  577. metrics: [{ type: 'raw_document', id: '1' }],
  578. bucketAggs: [],
  579. },
  580. ];
  581. response = {
  582. responses: [
  583. {
  584. hits: {
  585. total: 100,
  586. hits: [
  587. {
  588. _id: '1',
  589. _type: 'type',
  590. _index: 'index',
  591. _source: { sourceProp: 'asd' },
  592. fields: { fieldProp: 'field' },
  593. },
  594. {
  595. _source: { sourceProp: 'asd2' },
  596. fields: { fieldProp: 'field2' },
  597. },
  598. ],
  599. },
  600. },
  601. ],
  602. };
  603. result = new ElasticResponse(targets, response).getTimeSeries();
  604. });
  605. it('should return docs', () => {
  606. expect(result.data.length).toBe(1);
  607. expect(result.data[0].type).toBe('docs');
  608. expect(result.data[0].total).toBe(100);
  609. expect(result.data[0].datapoints.length).toBe(2);
  610. expect(result.data[0].datapoints[0].sourceProp).toBe('asd');
  611. expect(result.data[0].datapoints[0].fieldProp).toBe('field');
  612. });
  613. });
  614. });