metric_find_query.test.ts 8.1 KB

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