From 8e9181e7d1e9920c25558ad847cabdc1c84c15d7 Mon Sep 17 00:00:00 2001 From: Andrej Ocenas Date: Fri, 16 Oct 2020 17:24:23 +0200 Subject: [PATCH] Loki: Run instant query only when doing metric query (#28325) * Run instant query only when doing metric query * Update public/app/plugins/datasource/loki/datasource.ts Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> --- .../datasource/loki/datasource.test.ts | 100 ++++++++---------- .../app/plugins/datasource/loki/datasource.ts | 4 +- 2 files changed, 50 insertions(+), 54 deletions(-) diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index 0d6a2af25e9..acca7bd7bff 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -36,33 +36,33 @@ const timeSrvStub = { }), }; +const testResponse: FetchResponse = { + data: { + data: { + resultType: LokiResultType.Stream, + result: [ + { + stream: {}, + values: [['1573646419522934000', 'hello']], + }, + ], + }, + status: 'success', + }, + ok: true, + headers: ({} as unknown) as Headers, + redirected: false, + status: 200, + statusText: 'Success', + type: 'default', + url: '', + config: ({} as unknown) as BackendSrvRequest, +}; + describe('LokiDatasource', () => { let fetchStream: Subject; const fetchMock = jest.spyOn(backendSrv, 'fetch'); - const testResponse: FetchResponse = { - data: { - data: { - resultType: LokiResultType.Stream, - result: [ - { - stream: {}, - values: [['1573646419522934000', 'hello']], - }, - ], - }, - status: 'success', - }, - ok: true, - headers: ({} as unknown) as Headers, - redirected: false, - status: 200, - statusText: 'Success', - type: 'default', - url: '', - config: ({} as unknown) as BackendSrvRequest, - }; - beforeEach(() => { jest.clearAllMocks(); fetchStream = new Subject(); @@ -178,48 +178,42 @@ describe('LokiDatasource', () => { }); describe('when querying', () => { - it('should run range and instant query in Explore', done => { + function setup(expr: string, app: CoreApp) { const ds = createLokiDSForTests(); const options = getQueryOptions({ - targets: [{ expr: '{job="grafana"}', refId: 'B' }], - app: CoreApp.Explore, + targets: [{ expr, refId: 'B' }], + app, }); - ds.runInstantQuery = jest.fn(() => of({ data: [] })); ds.runRangeQuery = jest.fn(() => of({ data: [] })); + return { ds, options }; + } - observableTester().subscribeAndExpectOnComplete({ - observable: ds.query(options), - expect: () => { - expect(ds.runInstantQuery).toBeCalled(); - expect(ds.runRangeQuery).toBeCalled(); - }, - done, - }); + it('should run range and instant query in Explore if running metric query', async () => { + const { ds, options } = setup('rate({job="grafana"}[10m])', CoreApp.Explore); + await ds.query(options).toPromise(); + expect(ds.runInstantQuery).toBeCalled(); + expect(ds.runRangeQuery).toBeCalled(); }); - it('should run only range query in Dashboard', done => { - const ds = createLokiDSForTests(); - const options = getQueryOptions({ - targets: [{ expr: '{job="grafana"}', refId: 'B' }], - }); - - ds.runInstantQuery = jest.fn(() => of({ data: [] })); - ds.runRangeQuery = jest.fn(() => of({ data: [] })); - - observableTester().subscribeAndExpectOnComplete({ - observable: ds.query(options), - expect: () => { - expect(ds.runRangeQuery).toBeCalled(); - }, - done, - }); + it('should run only range query in Explore if running logs query', async () => { + const { ds, options } = setup('{job="grafana"}', CoreApp.Explore); + await ds.query(options).toPromise(); + expect(ds.runInstantQuery).not.toBeCalled(); + expect(ds.runRangeQuery).toBeCalled(); }); - it('should return series data for both queries in Explore', done => { + it('should run only range query in Dashboard', async () => { + const { ds, options } = setup('rate({job="grafana"}[10m])', CoreApp.Dashboard); + await ds.query(options).toPromise(); + expect(ds.runInstantQuery).not.toBeCalled(); + expect(ds.runRangeQuery).toBeCalled(); + }); + + it('should return series data for both queries in Explore if metrics query', done => { const ds = createLokiDSForTests(); const options = getQueryOptions({ - targets: [{ expr: '{job="grafana"} |= "foo"', refId: 'B' }], + targets: [{ expr: 'rate({job="grafana"} |= "foo" [10m])', refId: 'B' }], app: CoreApp.Explore, }); diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index d99feb36502..626a3d93b50 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -99,7 +99,9 @@ export class LokiDatasource extends DataSourceApi { })); for (const target of filteredTargets) { - if (options.app === CoreApp.Explore) { + // In explore we want to show result of metrics instant query in a table under the graph panel to mimic behaviour of prometheus. + // We don't want to do that in dashboards though as user would have to pick the correct data frame. + if (options.app === CoreApp.Explore && isMetricsQuery(target.expr)) { subQueries.push(this.runInstantQuery(target, options, filteredTargets.length)); } subQueries.push(this.runRangeQuery(target, options, filteredTargets.length));