datasource.test.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. import '../datasource';
  2. import CloudWatchDatasource from '../datasource';
  3. import { dateMath } from '@grafana/data';
  4. import { TemplateSrv } from 'app/features/templating/template_srv';
  5. import { CustomVariable } from 'app/features/templating/all';
  6. import _ from 'lodash';
  7. import { CloudWatchQuery } from '../types';
  8. import { DataSourceInstanceSettings } from '@grafana/ui';
  9. import { BackendSrv } from 'app/core/services/backend_srv';
  10. import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
  11. describe('CloudWatchDatasource', () => {
  12. const instanceSettings = {
  13. jsonData: { defaultRegion: 'us-east-1' },
  14. } as DataSourceInstanceSettings;
  15. const templateSrv = new TemplateSrv();
  16. const timeSrv = {
  17. time: { from: 'now-1h', to: 'now' },
  18. timeRange: () => {
  19. return {
  20. from: dateMath.parse(timeSrv.time.from, false),
  21. to: dateMath.parse(timeSrv.time.to, true),
  22. };
  23. },
  24. } as TimeSrv;
  25. const backendSrv = {} as BackendSrv;
  26. const ctx = {
  27. backendSrv,
  28. templateSrv,
  29. } as any;
  30. beforeEach(() => {
  31. ctx.ds = new CloudWatchDatasource(instanceSettings, {} as any, backendSrv, templateSrv, timeSrv);
  32. });
  33. describe('When performing CloudWatch query', () => {
  34. let requestParams: { queries: CloudWatchQuery[] };
  35. const query = {
  36. range: { from: 'now-1h', to: 'now' },
  37. rangeRaw: { from: 1483228800, to: 1483232400 },
  38. targets: [
  39. {
  40. refId: 'A',
  41. region: 'us-east-1',
  42. namespace: 'AWS/EC2',
  43. metricName: 'CPUUtilization',
  44. dimensions: {
  45. InstanceId: 'i-12345678',
  46. },
  47. statistics: ['Average'],
  48. period: '300',
  49. },
  50. ],
  51. };
  52. const response: any = {
  53. timings: [null],
  54. results: {
  55. A: {
  56. error: '',
  57. refId: 'A',
  58. meta: {},
  59. series: [
  60. {
  61. name: 'CPUUtilization_Average',
  62. points: [[1, 1483228800000], [2, 1483229100000], [5, 1483229700000]],
  63. tags: {
  64. InstanceId: 'i-12345678',
  65. },
  66. },
  67. ],
  68. },
  69. },
  70. };
  71. beforeEach(() => {
  72. ctx.backendSrv.datasourceRequest = jest.fn(params => {
  73. requestParams = params.data;
  74. return Promise.resolve({ data: response });
  75. });
  76. });
  77. it('should generate the correct query', done => {
  78. ctx.ds.query(query).then(() => {
  79. const params = requestParams.queries[0];
  80. expect(params.namespace).toBe(query.targets[0].namespace);
  81. expect(params.metricName).toBe(query.targets[0].metricName);
  82. expect(params.dimensions['InstanceId']).toBe('i-12345678');
  83. expect(params.statistics).toEqual(query.targets[0].statistics);
  84. expect(params.period).toBe(query.targets[0].period);
  85. done();
  86. });
  87. });
  88. it('should generate the correct query with interval variable', done => {
  89. templateSrv.init([
  90. new CustomVariable(
  91. {
  92. name: 'period',
  93. current: {
  94. value: '10m',
  95. },
  96. multi: false,
  97. },
  98. {} as any
  99. ),
  100. ]);
  101. const query = {
  102. range: { from: 'now-1h', to: 'now' },
  103. rangeRaw: { from: 1483228800, to: 1483232400 },
  104. targets: [
  105. {
  106. refId: 'A',
  107. region: 'us-east-1',
  108. namespace: 'AWS/EC2',
  109. metricName: 'CPUUtilization',
  110. dimensions: {
  111. InstanceId: 'i-12345678',
  112. },
  113. statistics: ['Average'],
  114. period: '[[period]]',
  115. },
  116. ],
  117. };
  118. ctx.ds.query(query).then(() => {
  119. const params = requestParams.queries[0];
  120. expect(params.period).toBe('600');
  121. done();
  122. });
  123. });
  124. it.each(['pNN.NN', 'p9', 'p99.', 'p99.999'])('should cancel query for invalid extended statistics (%s)', stat => {
  125. const query = {
  126. range: { from: 'now-1h', to: 'now' },
  127. rangeRaw: { from: 1483228800, to: 1483232400 },
  128. targets: [
  129. {
  130. refId: 'A',
  131. region: 'us-east-1',
  132. namespace: 'AWS/EC2',
  133. metricName: 'CPUUtilization',
  134. dimensions: {
  135. InstanceId: 'i-12345678',
  136. },
  137. statistics: [stat],
  138. period: '60s',
  139. },
  140. ],
  141. };
  142. expect(ctx.ds.query.bind(ctx.ds, query)).toThrow(/Invalid extended statistics/);
  143. });
  144. it('should return series list', done => {
  145. ctx.ds.query(query).then((result: any) => {
  146. expect(result.data[0].target).toBe(response.results.A.series[0].name);
  147. expect(result.data[0].datapoints[0][0]).toBe(response.results.A.series[0].points[0][0]);
  148. done();
  149. });
  150. });
  151. });
  152. describe('When query region is "default"', () => {
  153. it('should return the datasource region if empty or "default"', () => {
  154. const defaultRegion = instanceSettings.jsonData.defaultRegion;
  155. expect(ctx.ds.getActualRegion()).toBe(defaultRegion);
  156. expect(ctx.ds.getActualRegion('')).toBe(defaultRegion);
  157. expect(ctx.ds.getActualRegion('default')).toBe(defaultRegion);
  158. });
  159. it('should return the specified region if specified', () => {
  160. expect(ctx.ds.getActualRegion('some-fake-region-1')).toBe('some-fake-region-1');
  161. });
  162. let requestParams: { queries: CloudWatchQuery[] };
  163. beforeEach(() => {
  164. ctx.ds.performTimeSeriesQuery = jest.fn(request => {
  165. requestParams = request;
  166. return Promise.resolve({ data: {} });
  167. });
  168. });
  169. it('should query for the datasource region if empty or "default"', done => {
  170. const query = {
  171. range: { from: 'now-1h', to: 'now' },
  172. rangeRaw: { from: 1483228800, to: 1483232400 },
  173. targets: [
  174. {
  175. refId: 'A',
  176. region: 'default',
  177. namespace: 'AWS/EC2',
  178. metricName: 'CPUUtilization',
  179. dimensions: {
  180. InstanceId: 'i-12345678',
  181. },
  182. statistics: ['Average'],
  183. period: 300,
  184. },
  185. ],
  186. };
  187. ctx.ds.query(query).then((result: any) => {
  188. expect(requestParams.queries[0].region).toBe(instanceSettings.jsonData.defaultRegion);
  189. done();
  190. });
  191. });
  192. });
  193. describe('When performing CloudWatch query for extended statistics', () => {
  194. const query = {
  195. range: { from: 'now-1h', to: 'now' },
  196. rangeRaw: { from: 1483228800, to: 1483232400 },
  197. targets: [
  198. {
  199. refId: 'A',
  200. region: 'us-east-1',
  201. namespace: 'AWS/ApplicationELB',
  202. metricName: 'TargetResponseTime',
  203. dimensions: {
  204. LoadBalancer: 'lb',
  205. TargetGroup: 'tg',
  206. },
  207. statistics: ['p90.00'],
  208. period: 300,
  209. },
  210. ],
  211. };
  212. const response: any = {
  213. timings: [null],
  214. results: {
  215. A: {
  216. error: '',
  217. refId: 'A',
  218. meta: {},
  219. series: [
  220. {
  221. name: 'TargetResponseTime_p90.00',
  222. points: [[1, 1483228800000], [2, 1483229100000], [5, 1483229700000]],
  223. tags: {
  224. LoadBalancer: 'lb',
  225. TargetGroup: 'tg',
  226. },
  227. },
  228. ],
  229. },
  230. },
  231. };
  232. beforeEach(() => {
  233. ctx.backendSrv.datasourceRequest = jest.fn(params => {
  234. return Promise.resolve({ data: response });
  235. });
  236. });
  237. it('should return series list', done => {
  238. ctx.ds.query(query).then((result: any) => {
  239. expect(result.data[0].target).toBe(response.results.A.series[0].name);
  240. expect(result.data[0].datapoints[0][0]).toBe(response.results.A.series[0].points[0][0]);
  241. done();
  242. });
  243. });
  244. });
  245. describe('When performing CloudWatch query with template variables', () => {
  246. let requestParams: { queries: CloudWatchQuery[] };
  247. beforeEach(() => {
  248. templateSrv.init([
  249. new CustomVariable(
  250. {
  251. name: 'var1',
  252. current: {
  253. value: 'var1-foo',
  254. },
  255. multi: false,
  256. },
  257. {} as any
  258. ),
  259. new CustomVariable(
  260. {
  261. name: 'var2',
  262. current: {
  263. value: 'var2-foo',
  264. },
  265. multi: false,
  266. },
  267. {} as any
  268. ),
  269. new CustomVariable(
  270. {
  271. name: 'var3',
  272. options: [
  273. { selected: true, value: 'var3-foo' },
  274. { selected: false, value: 'var3-bar' },
  275. { selected: true, value: 'var3-baz' },
  276. ],
  277. current: {
  278. value: ['var3-foo', 'var3-baz'],
  279. },
  280. multi: true,
  281. },
  282. {} as any
  283. ),
  284. ]);
  285. ctx.backendSrv.datasourceRequest = jest.fn(params => {
  286. requestParams = params.data;
  287. return Promise.resolve({ data: {} });
  288. });
  289. });
  290. it('should generate the correct query for single template variable', done => {
  291. const query = {
  292. range: { from: 'now-1h', to: 'now' },
  293. rangeRaw: { from: 1483228800, to: 1483232400 },
  294. targets: [
  295. {
  296. refId: 'A',
  297. region: 'us-east-1',
  298. namespace: 'TestNamespace',
  299. metricName: 'TestMetricName',
  300. dimensions: {
  301. dim2: '[[var2]]',
  302. },
  303. statistics: ['Average'],
  304. period: 300,
  305. },
  306. ],
  307. };
  308. ctx.ds.query(query).then(() => {
  309. expect(requestParams.queries[0].dimensions['dim2']).toBe('var2-foo');
  310. done();
  311. });
  312. });
  313. it('should generate the correct query for multilple template variables', done => {
  314. const query = {
  315. range: { from: 'now-1h', to: 'now' },
  316. rangeRaw: { from: 1483228800, to: 1483232400 },
  317. targets: [
  318. {
  319. refId: 'A',
  320. region: 'us-east-1',
  321. namespace: 'TestNamespace',
  322. metricName: 'TestMetricName',
  323. dimensions: {
  324. dim1: '[[var1]]',
  325. dim2: '[[var2]]',
  326. dim3: '[[var3]]',
  327. },
  328. statistics: ['Average'],
  329. period: 300,
  330. },
  331. ],
  332. scopedVars: {
  333. var1: { selected: true, value: 'var1-foo' },
  334. var2: { selected: true, value: 'var2-foo' },
  335. },
  336. };
  337. ctx.ds.query(query).then(() => {
  338. expect(requestParams.queries[0].dimensions['dim1']).toBe('var1-foo');
  339. expect(requestParams.queries[0].dimensions['dim2']).toBe('var2-foo');
  340. expect(requestParams.queries[0].dimensions['dim3']).toBe('var3-foo');
  341. expect(requestParams.queries[1].dimensions['dim1']).toBe('var1-foo');
  342. expect(requestParams.queries[1].dimensions['dim2']).toBe('var2-foo');
  343. expect(requestParams.queries[1].dimensions['dim3']).toBe('var3-baz');
  344. done();
  345. });
  346. });
  347. it('should generate the correct query for multilple template variables, lack scopedVars', done => {
  348. const query = {
  349. range: { from: 'now-1h', to: 'now' },
  350. rangeRaw: { from: 1483228800, to: 1483232400 },
  351. targets: [
  352. {
  353. refId: 'A',
  354. region: 'us-east-1',
  355. namespace: 'TestNamespace',
  356. metricName: 'TestMetricName',
  357. dimensions: {
  358. dim1: '[[var1]]',
  359. dim2: '[[var2]]',
  360. dim3: '[[var3]]',
  361. },
  362. statistics: ['Average'],
  363. period: 300,
  364. },
  365. ],
  366. scopedVars: {
  367. var1: { selected: true, value: 'var1-foo' },
  368. },
  369. };
  370. ctx.ds.query(query).then(() => {
  371. expect(requestParams.queries[0].dimensions['dim1']).toBe('var1-foo');
  372. expect(requestParams.queries[0].dimensions['dim2']).toBe('var2-foo');
  373. expect(requestParams.queries[0].dimensions['dim3']).toBe('var3-foo');
  374. expect(requestParams.queries[1].dimensions['dim1']).toBe('var1-foo');
  375. expect(requestParams.queries[1].dimensions['dim2']).toBe('var2-foo');
  376. expect(requestParams.queries[1].dimensions['dim3']).toBe('var3-baz');
  377. done();
  378. });
  379. });
  380. it('should generate the correct query for multilple template variables with expression', done => {
  381. const query: any = {
  382. range: { from: 'now-1h', to: 'now' },
  383. rangeRaw: { from: 1483228800, to: 1483232400 },
  384. targets: [
  385. {
  386. refId: 'A',
  387. id: 'id1',
  388. region: 'us-east-1',
  389. namespace: 'TestNamespace',
  390. metricName: 'TestMetricName',
  391. dimensions: {
  392. dim1: '[[var1]]',
  393. dim2: '[[var2]]',
  394. dim3: '[[var3]]',
  395. },
  396. statistics: ['Average'],
  397. period: 300,
  398. expression: '',
  399. },
  400. {
  401. refId: 'B',
  402. id: 'id2',
  403. expression: 'METRICS("id1") * 2',
  404. dimensions: {
  405. // garbage data for fail test
  406. dim1: '[[var1]]',
  407. dim2: '[[var2]]',
  408. dim3: '[[var3]]',
  409. },
  410. statistics: [], // dummy
  411. },
  412. ],
  413. scopedVars: {
  414. var1: { selected: true, value: 'var1-foo' },
  415. var2: { selected: true, value: 'var2-foo' },
  416. },
  417. };
  418. ctx.ds.query(query).then(() => {
  419. expect(requestParams.queries.length).toBe(3);
  420. expect(requestParams.queries[0].id).toMatch(/^id1.*/);
  421. expect(requestParams.queries[0].dimensions['dim1']).toBe('var1-foo');
  422. expect(requestParams.queries[0].dimensions['dim2']).toBe('var2-foo');
  423. expect(requestParams.queries[0].dimensions['dim3']).toBe('var3-foo');
  424. expect(requestParams.queries[1].id).toMatch(/^id1.*/);
  425. expect(requestParams.queries[1].dimensions['dim1']).toBe('var1-foo');
  426. expect(requestParams.queries[1].dimensions['dim2']).toBe('var2-foo');
  427. expect(requestParams.queries[1].dimensions['dim3']).toBe('var3-baz');
  428. expect(requestParams.queries[2].id).toMatch(/^id2.*/);
  429. expect(requestParams.queries[2].expression).toBe('METRICS("id1") * 2');
  430. done();
  431. });
  432. });
  433. });
  434. function describeMetricFindQuery(query: any, func: any) {
  435. describe('metricFindQuery ' + query, () => {
  436. const scenario: any = {};
  437. scenario.setup = (setupCallback: any) => {
  438. beforeEach(() => {
  439. setupCallback();
  440. ctx.backendSrv.datasourceRequest = jest.fn(args => {
  441. scenario.request = args.data;
  442. return Promise.resolve({ data: scenario.requestResponse });
  443. });
  444. ctx.ds.metricFindQuery(query).then((args: any) => {
  445. scenario.result = args;
  446. });
  447. });
  448. };
  449. func(scenario);
  450. });
  451. }
  452. describeMetricFindQuery('regions()', (scenario: any) => {
  453. scenario.setup(() => {
  454. scenario.requestResponse = {
  455. results: {
  456. metricFindQuery: {
  457. tables: [{ rows: [['us-east-1', 'us-east-1']] }],
  458. },
  459. },
  460. };
  461. });
  462. it('should call __GetRegions and return result', () => {
  463. expect(scenario.result[0].text).toContain('us-east-1');
  464. expect(scenario.request.queries[0].type).toBe('metricFindQuery');
  465. expect(scenario.request.queries[0].subtype).toBe('regions');
  466. });
  467. });
  468. describeMetricFindQuery('namespaces()', (scenario: any) => {
  469. scenario.setup(() => {
  470. scenario.requestResponse = {
  471. results: {
  472. metricFindQuery: {
  473. tables: [{ rows: [['AWS/EC2', 'AWS/EC2']] }],
  474. },
  475. },
  476. };
  477. });
  478. it('should call __GetNamespaces and return result', () => {
  479. expect(scenario.result[0].text).toContain('AWS/EC2');
  480. expect(scenario.request.queries[0].type).toBe('metricFindQuery');
  481. expect(scenario.request.queries[0].subtype).toBe('namespaces');
  482. });
  483. });
  484. describeMetricFindQuery('metrics(AWS/EC2)', (scenario: any) => {
  485. scenario.setup(() => {
  486. scenario.requestResponse = {
  487. results: {
  488. metricFindQuery: {
  489. tables: [{ rows: [['CPUUtilization', 'CPUUtilization']] }],
  490. },
  491. },
  492. };
  493. });
  494. it('should call __GetMetrics and return result', () => {
  495. expect(scenario.result[0].text).toBe('CPUUtilization');
  496. expect(scenario.request.queries[0].type).toBe('metricFindQuery');
  497. expect(scenario.request.queries[0].subtype).toBe('metrics');
  498. });
  499. });
  500. describeMetricFindQuery('dimension_keys(AWS/EC2)', (scenario: any) => {
  501. scenario.setup(() => {
  502. scenario.requestResponse = {
  503. results: {
  504. metricFindQuery: {
  505. tables: [{ rows: [['InstanceId', 'InstanceId']] }],
  506. },
  507. },
  508. };
  509. });
  510. it('should call __GetDimensions and return result', () => {
  511. expect(scenario.result[0].text).toBe('InstanceId');
  512. expect(scenario.request.queries[0].type).toBe('metricFindQuery');
  513. expect(scenario.request.queries[0].subtype).toBe('dimension_keys');
  514. });
  515. });
  516. describeMetricFindQuery('dimension_values(us-east-1,AWS/EC2,CPUUtilization,InstanceId)', (scenario: any) => {
  517. scenario.setup(() => {
  518. scenario.requestResponse = {
  519. results: {
  520. metricFindQuery: {
  521. tables: [{ rows: [['i-12345678', 'i-12345678']] }],
  522. },
  523. },
  524. };
  525. });
  526. it('should call __ListMetrics and return result', () => {
  527. expect(scenario.result[0].text).toContain('i-12345678');
  528. expect(scenario.request.queries[0].type).toBe('metricFindQuery');
  529. expect(scenario.request.queries[0].subtype).toBe('dimension_values');
  530. });
  531. });
  532. describeMetricFindQuery('dimension_values(default,AWS/EC2,CPUUtilization,InstanceId)', (scenario: any) => {
  533. scenario.setup(() => {
  534. scenario.requestResponse = {
  535. results: {
  536. metricFindQuery: {
  537. tables: [{ rows: [['i-12345678', 'i-12345678']] }],
  538. },
  539. },
  540. };
  541. });
  542. it('should call __ListMetrics and return result', () => {
  543. expect(scenario.result[0].text).toContain('i-12345678');
  544. expect(scenario.request.queries[0].type).toBe('metricFindQuery');
  545. expect(scenario.request.queries[0].subtype).toBe('dimension_values');
  546. });
  547. });
  548. describeMetricFindQuery('resource_arns(default,ec2:instance,{"environment":["production"]})', (scenario: any) => {
  549. scenario.setup(() => {
  550. scenario.requestResponse = {
  551. results: {
  552. metricFindQuery: {
  553. tables: [
  554. {
  555. rows: [
  556. [
  557. 'arn:aws:ec2:us-east-1:123456789012:instance/i-12345678901234567',
  558. 'arn:aws:ec2:us-east-1:123456789012:instance/i-76543210987654321',
  559. ],
  560. ],
  561. },
  562. ],
  563. },
  564. },
  565. };
  566. });
  567. it('should call __ListMetrics and return result', () => {
  568. expect(scenario.result[0].text).toContain('arn:aws:ec2:us-east-1:123456789012:instance/i-12345678901234567');
  569. expect(scenario.request.queries[0].type).toBe('metricFindQuery');
  570. expect(scenario.request.queries[0].subtype).toBe('resource_arns');
  571. });
  572. });
  573. it('should caclculate the correct period', () => {
  574. const hourSec = 60 * 60;
  575. const daySec = hourSec * 24;
  576. const start = 1483196400 * 1000;
  577. const testData: any[] = [
  578. [
  579. { period: 60, namespace: 'AWS/EC2' },
  580. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  581. hourSec * 3,
  582. 60,
  583. ],
  584. [
  585. { period: null, namespace: 'AWS/EC2' },
  586. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  587. hourSec * 3,
  588. 300,
  589. ],
  590. [
  591. { period: 60, namespace: 'AWS/ELB' },
  592. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  593. hourSec * 3,
  594. 60,
  595. ],
  596. [
  597. { period: null, namespace: 'AWS/ELB' },
  598. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  599. hourSec * 3,
  600. 60,
  601. ],
  602. [
  603. { period: 1, namespace: 'CustomMetricsNamespace' },
  604. {
  605. range: {
  606. from: new Date(start),
  607. to: new Date(start + (1440 - 1) * 1000),
  608. },
  609. },
  610. hourSec * 3 - 1,
  611. 1,
  612. ],
  613. [
  614. { period: 1, namespace: 'CustomMetricsNamespace' },
  615. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  616. hourSec * 3 - 1,
  617. 60,
  618. ],
  619. [
  620. { period: 60, namespace: 'CustomMetricsNamespace' },
  621. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  622. hourSec * 3,
  623. 60,
  624. ],
  625. [
  626. { period: null, namespace: 'CustomMetricsNamespace' },
  627. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  628. hourSec * 3 - 1,
  629. 60,
  630. ],
  631. [
  632. { period: null, namespace: 'CustomMetricsNamespace' },
  633. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  634. hourSec * 3,
  635. 60,
  636. ],
  637. [
  638. { period: null, namespace: 'CustomMetricsNamespace' },
  639. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  640. daySec * 15,
  641. 60,
  642. ],
  643. [
  644. { period: null, namespace: 'CustomMetricsNamespace' },
  645. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  646. daySec * 63,
  647. 300,
  648. ],
  649. [
  650. { period: null, namespace: 'CustomMetricsNamespace' },
  651. { range: { from: new Date(start), to: new Date(start + 3600 * 1000) } },
  652. daySec * 455,
  653. 3600,
  654. ],
  655. ];
  656. for (const t of testData) {
  657. const target = t[0];
  658. const options = t[1];
  659. const now = new Date(options.range.from.valueOf() + t[2] * 1000);
  660. const expected = t[3];
  661. const actual = ctx.ds.getPeriod(target, options, now);
  662. expect(actual).toBe(expected);
  663. }
  664. });
  665. });