metric_find_query.test.ts 8.1 KB

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