diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index 564b94c4d33..151b5a2798d 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -1,6 +1,6 @@ import { of, throwError } from 'rxjs'; import { take } from 'rxjs/operators'; -import { AnnotationQueryRequest, CoreApp, DataFrame, dateTime, FieldCache, TimeRange, TimeSeries } from '@grafana/data'; +import { AnnotationQueryRequest, CoreApp, DataFrame, dateTime, FieldCache, TimeSeries } from '@grafana/data'; import { BackendSrvRequest, FetchResponse } from '@grafana/runtime'; import LokiDatasource from './datasource'; @@ -117,6 +117,23 @@ describe('LokiDatasource', () => { expect(req.end).toBeDefined(); expect(adjustIntervalSpy).toHaveBeenCalledWith(2000, expect.anything()); }); + + it('should set the minimal step to 1ms', () => { + const target = { expr: '{job="grafana"}', refId: 'B' }; + const raw = { from: 'now', to: 'now-1h' }; + const range = { from: dateTime('2020-10-14T00:00:00'), to: dateTime('2020-10-14T00:00:01'), raw: raw }; + const options = { + range, + intervalMs: 0.0005, + }; + + const req = ds.createRangeQuery(target, options as any, 1000); + expect(req.start).toBeDefined(); + expect(req.end).toBeDefined(); + expect(adjustIntervalSpy).toHaveBeenCalledWith(0.0005, expect.anything()); + // Step is in seconds (1 ms === 0.001 s) + expect(req.step).toEqual(0.001); + }); }); describe('when doing logs queries with limits', () => { @@ -426,24 +443,6 @@ describe('LokiDatasource', () => { }); }); - describe('when creating a range query', () => { - // Loki v1 API has an issue with float step parameters, can be removed when API is fixed - it('should produce an integer step parameter', () => { - const ds = createLokiDSForTests(); - const query: LokiQuery = { expr: 'foo', refId: 'bar' }; - const range: TimeRange = { - from: dateTime(0), - to: dateTime(1e9 + 1), - raw: { from: '0', to: '1000000001' }, - }; - - // Odd timerange/interval combination that would lead to a float step - const options = { range, intervalMs: 2000 }; - - expect(Number.isInteger(ds.createRangeQuery(query, options as any, 1000).step!)).toBeTruthy(); - }); - }); - describe('when calling annotationQuery', () => { const getTestContext = (response: any) => { const query = makeAnnotationQueryRequest(); diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index a638ec4a157..7586a4cff39 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -171,9 +171,10 @@ export class LokiDatasource extends DataSourceApi { const startNs = this.getTime(options.range.from, false); const endNs = this.getTime(options.range.to, true); const rangeMs = Math.ceil((endNs - startNs) / 1e6); - const step = Math.ceil( - this.adjustInterval((options as DataQueryRequest).intervalMs || 1000, rangeMs) / 1000 - ); + const adjustedInterval = + this.adjustInterval((options as DataQueryRequest).intervalMs || 1000, rangeMs) / 1000; + // We want to ceil to 3 decimal places + const step = Math.ceil(adjustedInterval * 1000) / 1000; const alignedTimes = { start: startNs - (startNs % 1e9), end: endNs + (1e9 - (endNs % 1e9)), @@ -543,7 +544,8 @@ export class LokiDatasource extends DataSourceApi { if (interval !== 0 && range / interval > 11000) { interval = Math.ceil(range / 11000); } - return Math.max(interval, 1000); + // The min interval is set to 1ms + return Math.max(interval, 1); } }