result_transformer.test.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import { ResultTransformer } from '../result_transformer';
  2. describe('Prometheus Result Transformer', () => {
  3. const ctx: any = {};
  4. beforeEach(() => {
  5. ctx.templateSrv = {
  6. replace: str => str,
  7. };
  8. ctx.resultTransformer = new ResultTransformer(ctx.templateSrv);
  9. });
  10. describe('When nothing is returned', () => {
  11. test('should return empty series', () => {
  12. const response = {
  13. status: 'success',
  14. data: {
  15. resultType: '',
  16. result: null,
  17. },
  18. };
  19. const series = ctx.resultTransformer.transform({ data: response }, {});
  20. expect(series).toEqual([]);
  21. });
  22. test('should return empty table', () => {
  23. const response = {
  24. status: 'success',
  25. data: {
  26. resultType: '',
  27. result: null,
  28. },
  29. };
  30. const table = ctx.resultTransformer.transform({ data: response }, { format: 'table' });
  31. expect(table).toMatchObject([{ type: 'table', rows: [] }]);
  32. });
  33. });
  34. describe('When resultFormat is table', () => {
  35. const response = {
  36. status: 'success',
  37. data: {
  38. resultType: 'matrix',
  39. result: [
  40. {
  41. metric: { __name__: 'test', job: 'testjob' },
  42. values: [[1443454528, '3846']],
  43. },
  44. {
  45. metric: {
  46. __name__: 'test',
  47. instance: 'localhost:8080',
  48. job: 'otherjob',
  49. },
  50. values: [[1443454529, '3847']],
  51. },
  52. ],
  53. },
  54. };
  55. it('should return table model', () => {
  56. const table = ctx.resultTransformer.transformMetricDataToTable(response.data.result);
  57. expect(table.type).toBe('table');
  58. expect(table.rows).toEqual([
  59. [1443454528000, 'test', '', 'testjob', 3846],
  60. [1443454529000, 'test', 'localhost:8080', 'otherjob', 3847],
  61. ]);
  62. expect(table.columns).toMatchObject([
  63. { text: 'Time', type: 'time' },
  64. { text: '__name__', filterable: true },
  65. { text: 'instance', filterable: true },
  66. { text: 'job' },
  67. { text: 'Value' },
  68. ]);
  69. expect(table.columns[4].filterable).toBeUndefined();
  70. });
  71. it('should column title include refId if response count is more than 2', () => {
  72. const table = ctx.resultTransformer.transformMetricDataToTable(response.data.result, 2, 'B');
  73. expect(table.type).toBe('table');
  74. expect(table.columns).toMatchObject([
  75. { text: 'Time', type: 'time' },
  76. { text: '__name__' },
  77. { text: 'instance' },
  78. { text: 'job' },
  79. { text: 'Value #B' },
  80. ]);
  81. });
  82. });
  83. describe('When resultFormat is table and instant = true', () => {
  84. const response = {
  85. status: 'success',
  86. data: {
  87. resultType: 'vector',
  88. result: [
  89. {
  90. metric: { __name__: 'test', job: 'testjob' },
  91. value: [1443454528, '3846'],
  92. },
  93. ],
  94. },
  95. };
  96. it('should return table model', () => {
  97. const table = ctx.resultTransformer.transformMetricDataToTable(response.data.result);
  98. expect(table.type).toBe('table');
  99. expect(table.rows).toEqual([[1443454528000, 'test', 'testjob', 3846]]);
  100. expect(table.columns).toMatchObject([
  101. { text: 'Time', type: 'time' },
  102. { text: '__name__' },
  103. { text: 'job' },
  104. { text: 'Value' },
  105. ]);
  106. });
  107. });
  108. describe('When resultFormat is heatmap', () => {
  109. const response = {
  110. status: 'success',
  111. data: {
  112. resultType: 'matrix',
  113. result: [
  114. {
  115. metric: { __name__: 'test', job: 'testjob', le: '1' },
  116. values: [[1445000010, '10'], [1445000020, '10'], [1445000030, '0']],
  117. },
  118. {
  119. metric: { __name__: 'test', job: 'testjob', le: '2' },
  120. values: [[1445000010, '20'], [1445000020, '10'], [1445000030, '30']],
  121. },
  122. {
  123. metric: { __name__: 'test', job: 'testjob', le: '3' },
  124. values: [[1445000010, '30'], [1445000020, '10'], [1445000030, '40']],
  125. },
  126. ],
  127. },
  128. };
  129. it('should convert cumulative histogram to regular', () => {
  130. const options = {
  131. format: 'heatmap',
  132. start: 1445000010,
  133. end: 1445000030,
  134. legendFormat: '{{le}}',
  135. };
  136. const result = ctx.resultTransformer.transform({ data: response }, options);
  137. expect(result).toEqual([
  138. { target: '1', datapoints: [[10, 1445000010000], [10, 1445000020000], [0, 1445000030000]] },
  139. { target: '2', datapoints: [[10, 1445000010000], [0, 1445000020000], [30, 1445000030000]] },
  140. { target: '3', datapoints: [[10, 1445000010000], [0, 1445000020000], [10, 1445000030000]] },
  141. ]);
  142. });
  143. it('should handle missing datapoints', () => {
  144. const seriesList = [
  145. { datapoints: [[1, 1000], [2, 2000]] },
  146. { datapoints: [[2, 1000], [5, 2000], [1, 3000]] },
  147. { datapoints: [[3, 1000], [7, 2000]] },
  148. ];
  149. const expected = [
  150. { datapoints: [[1, 1000], [2, 2000]] },
  151. { datapoints: [[1, 1000], [3, 2000], [1, 3000]] },
  152. { datapoints: [[1, 1000], [2, 2000]] },
  153. ];
  154. const result = ctx.resultTransformer.transformToHistogramOverTime(seriesList);
  155. expect(result).toEqual(expected);
  156. });
  157. it('should throw error when data in wrong format', () => {
  158. const seriesList = [{ rows: [] }, { datapoints: [] }];
  159. expect(() => {
  160. ctx.resultTransformer.transformToHistogramOverTime(seriesList);
  161. }).toThrow();
  162. });
  163. it('should throw error when prometheus returned non-timeseries', () => {
  164. // should be { metric: {}, values: [] } for timeseries
  165. const metricData = { metric: {}, value: [] };
  166. expect(() => {
  167. ctx.resultTransformer.transformMetricData(metricData, { step: 1 }, 1000, 2000);
  168. }).toThrow();
  169. });
  170. });
  171. describe('When resultFormat is time series', () => {
  172. it('should transform matrix into timeseries', () => {
  173. const response = {
  174. status: 'success',
  175. data: {
  176. resultType: 'matrix',
  177. result: [
  178. {
  179. metric: { __name__: 'test', job: 'testjob' },
  180. values: [[0, '10'], [1, '10'], [2, '0']],
  181. },
  182. ],
  183. },
  184. };
  185. const options = {
  186. format: 'timeseries',
  187. start: 0,
  188. end: 2,
  189. };
  190. const result = ctx.resultTransformer.transform({ data: response }, options);
  191. expect(result).toEqual([{ target: 'test{job="testjob"}', datapoints: [[10, 0], [10, 1000], [0, 2000]] }]);
  192. });
  193. it('should fill timeseries with null values', () => {
  194. const response = {
  195. status: 'success',
  196. data: {
  197. resultType: 'matrix',
  198. result: [
  199. {
  200. metric: { __name__: 'test', job: 'testjob' },
  201. values: [[1, '10'], [2, '0']],
  202. },
  203. ],
  204. },
  205. };
  206. const options = {
  207. format: 'timeseries',
  208. step: 1,
  209. start: 0,
  210. end: 2,
  211. };
  212. const result = ctx.resultTransformer.transform({ data: response }, options);
  213. expect(result).toEqual([{ target: 'test{job="testjob"}', datapoints: [[null, 0], [10, 1000], [0, 2000]] }]);
  214. });
  215. it('should align null values with step', () => {
  216. const response = {
  217. status: 'success',
  218. data: {
  219. resultType: 'matrix',
  220. result: [
  221. {
  222. metric: { __name__: 'test', job: 'testjob' },
  223. values: [[4, '10'], [8, '10']],
  224. },
  225. ],
  226. },
  227. };
  228. const options = {
  229. format: 'timeseries',
  230. step: 2,
  231. start: 0,
  232. end: 8,
  233. };
  234. const result = ctx.resultTransformer.transform({ data: response }, options);
  235. expect(result).toEqual([
  236. { target: 'test{job="testjob"}', datapoints: [[null, 0], [null, 2000], [10, 4000], [null, 6000], [10, 8000]] },
  237. ]);
  238. });
  239. });
  240. });