metric_find_query.test.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import moment from 'moment';
  2. import { PrometheusDatasource } from '../datasource';
  3. import PrometheusMetricFindQuery from '../metric_find_query';
  4. import q from 'q';
  5. describe('PrometheusMetricFindQuery', () => {
  6. const instanceSettings = {
  7. url: 'proxied',
  8. directUrl: 'direct',
  9. user: 'test',
  10. password: 'mupp',
  11. jsonData: { httpMethod: 'GET' },
  12. };
  13. const raw = {
  14. from: moment.utc('2018-04-25 10:00'),
  15. to: moment.utc('2018-04-25 11:00'),
  16. };
  17. const ctx: any = {
  18. backendSrvMock: {
  19. datasourceRequest: jest.fn(() => Promise.resolve({})),
  20. },
  21. templateSrvMock: {
  22. replace: a => a,
  23. },
  24. timeSrvMock: {
  25. timeRange: () => ({
  26. from: raw.from,
  27. to: raw.to,
  28. raw: raw,
  29. }),
  30. },
  31. };
  32. ctx.setupMetricFindQuery = (data: any) => {
  33. ctx.backendSrvMock.datasourceRequest.mockReturnValue(Promise.resolve({ status: 'success', data: data.response }));
  34. return new PrometheusMetricFindQuery(ctx.ds, data.query, ctx.timeSrvMock);
  35. };
  36. beforeEach(() => {
  37. ctx.backendSrvMock.datasourceRequest.mockReset();
  38. ctx.ds = new PrometheusDatasource(instanceSettings, q, ctx.backendSrvMock, ctx.templateSrvMock, ctx.timeSrvMock);
  39. });
  40. describe('When performing metricFindQuery', () => {
  41. it('label_values(resource) should generate label search query', async () => {
  42. const query = ctx.setupMetricFindQuery({
  43. query: 'label_values(resource)',
  44. response: {
  45. data: ['value1', 'value2', 'value3'],
  46. },
  47. });
  48. const results = await query.process();
  49. expect(results).toHaveLength(3);
  50. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledTimes(1);
  51. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledWith({
  52. method: 'GET',
  53. url: 'proxied/api/v1/label/resource/values',
  54. silent: true,
  55. });
  56. });
  57. it('label_values(metric, resource) should generate series query with correct time', async () => {
  58. const query = ctx.setupMetricFindQuery({
  59. query: 'label_values(metric, resource)',
  60. response: {
  61. data: [
  62. { __name__: 'metric', resource: 'value1' },
  63. { __name__: 'metric', resource: 'value2' },
  64. { __name__: 'metric', resource: 'value3' },
  65. ],
  66. },
  67. });
  68. const results = await query.process();
  69. expect(results).toHaveLength(3);
  70. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledTimes(1);
  71. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledWith({
  72. method: 'GET',
  73. url: `proxied/api/v1/series?match[]=metric&start=${raw.from.unix()}&end=${raw.to.unix()}`,
  74. silent: true,
  75. });
  76. });
  77. it('label_values(metric{label1="foo", label2="bar", label3="baz"}, resource) should generate series query with correct time', async () => {
  78. const query = ctx.setupMetricFindQuery({
  79. query: 'label_values(metric{label1="foo", label2="bar", label3="baz"}, resource)',
  80. response: {
  81. data: [
  82. { __name__: 'metric', resource: 'value1' },
  83. { __name__: 'metric', resource: 'value2' },
  84. { __name__: 'metric', resource: 'value3' },
  85. ],
  86. },
  87. });
  88. const results = await query.process();
  89. expect(results).toHaveLength(3);
  90. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledTimes(1);
  91. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledWith({
  92. method: 'GET',
  93. url: `proxied/api/v1/series?match[]=${encodeURIComponent(
  94. 'metric{label1="foo", label2="bar", label3="baz"}'
  95. )}&start=${raw.from.unix()}&end=${raw.to.unix()}`,
  96. silent: true,
  97. });
  98. });
  99. it('label_values(metric, resource) result should not contain empty string', async () => {
  100. const query = ctx.setupMetricFindQuery({
  101. query: 'label_values(metric, resource)',
  102. response: {
  103. data: [
  104. { __name__: 'metric', resource: 'value1' },
  105. { __name__: 'metric', resource: 'value2' },
  106. { __name__: 'metric', resource: '' },
  107. ],
  108. },
  109. });
  110. const results = await query.process();
  111. expect(results).toHaveLength(2);
  112. expect(results[0].text).toBe('value1');
  113. expect(results[1].text).toBe('value2');
  114. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledTimes(1);
  115. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledWith({
  116. method: 'GET',
  117. url: `proxied/api/v1/series?match[]=metric&start=${raw.from.unix()}&end=${raw.to.unix()}`,
  118. silent: true,
  119. });
  120. });
  121. it('metrics(metric.*) should generate metric name query', async () => {
  122. const query = ctx.setupMetricFindQuery({
  123. query: 'metrics(metric.*)',
  124. response: {
  125. data: ['metric1', 'metric2', 'metric3', 'nomatch'],
  126. },
  127. });
  128. const results = await query.process();
  129. expect(results).toHaveLength(3);
  130. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledTimes(1);
  131. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledWith({
  132. method: 'GET',
  133. url: 'proxied/api/v1/label/__name__/values',
  134. silent: true,
  135. });
  136. });
  137. it('query_result(metric) should generate metric name query', async () => {
  138. const query = ctx.setupMetricFindQuery({
  139. query: 'query_result(metric)',
  140. response: {
  141. data: {
  142. resultType: 'vector',
  143. result: [
  144. {
  145. metric: { __name__: 'metric', job: 'testjob' },
  146. value: [1443454528.0, '3846'],
  147. },
  148. ],
  149. },
  150. },
  151. });
  152. const results = await query.process();
  153. expect(results).toHaveLength(1);
  154. expect(results[0].text).toBe('metric{job="testjob"} 3846 1443454528000');
  155. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledTimes(1);
  156. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledWith({
  157. method: 'GET',
  158. url: `proxied/api/v1/query?query=metric&time=${raw.to.unix()}`,
  159. requestId: undefined,
  160. });
  161. });
  162. it('up{job="job1"} should fallback using generate series query', async () => {
  163. const query = ctx.setupMetricFindQuery({
  164. query: 'up{job="job1"}',
  165. response: {
  166. data: [
  167. { __name__: 'up', instance: '127.0.0.1:1234', job: 'job1' },
  168. { __name__: 'up', instance: '127.0.0.1:5678', job: 'job1' },
  169. { __name__: 'up', instance: '127.0.0.1:9102', job: 'job1' },
  170. ],
  171. },
  172. });
  173. const results = await query.process();
  174. expect(results).toHaveLength(3);
  175. expect(results[0].text).toBe('up{instance="127.0.0.1:1234",job="job1"}');
  176. expect(results[1].text).toBe('up{instance="127.0.0.1:5678",job="job1"}');
  177. expect(results[2].text).toBe('up{instance="127.0.0.1:9102",job="job1"}');
  178. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledTimes(1);
  179. expect(ctx.backendSrvMock.datasourceRequest).toHaveBeenCalledWith({
  180. method: 'GET',
  181. url: `proxied/api/v1/series?match[]=${encodeURIComponent(
  182. 'up{job="job1"}'
  183. )}&start=${raw.from.unix()}&end=${raw.to.unix()}`,
  184. silent: true,
  185. });
  186. });
  187. });
  188. });