PublicDashboards: Data discrepancy fix. Use real datasource plugin when it is a public dashboard. (#73708)

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Ezequiel Victorero <ezequiel.victorero@grafana.com>
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
Juan Cabanas
2023-08-30 09:38:13 -03:00
committed by GitHub
parent 5038137662
commit 969ef5282c
12 changed files with 285 additions and 362 deletions

View File

@@ -11,12 +11,15 @@ import {
createDataFrame,
} from '@grafana/data';
import { config } from '../config';
import {
DataSourceWithBackend,
isExpressionReference,
standardStreamOptionsProvider,
toStreamingDataResponse,
} from './DataSourceWithBackend';
import { publicDashboardQueryHandler } from './publicDashboardQueryHandler';
class MyDataSource extends DataSourceWithBackend<DataQuery, DataSourceJsonData> {
constructor(instanceSettings: DataSourceInstanceSettings<DataSourceJsonData>) {
@@ -44,6 +47,7 @@ jest.mock('../services', () => ({
};
},
}));
jest.mock('./publicDashboardQueryHandler');
describe('DataSourceWithBackend', () => {
test('check the executed queries', () => {
@@ -313,6 +317,43 @@ describe('DataSourceWithBackend', () => {
expect(isExpressionReference(undefined)).toBeFalsy();
});
});
describe('public dashboard scope', () => {
test("check public dashboard handler is not executed when it's not public dashboard scope", () => {
const { ds } = createMockDatasource();
const request = {
maxDataPoints: 10,
intervalMs: 5000,
targets: [{ refId: 'A' }, { refId: 'B', datasource: { type: 'sample' } }],
dashboardUID: 'dashA',
panelId: 123,
queryGroupId: 'abc',
} as DataQueryRequest;
ds.query(request);
expect(publicDashboardQueryHandler).not.toHaveBeenCalledWith(request);
});
test("check public dashboard handler is executed when it's public dashboard scope", () => {
config.publicDashboardAccessToken = 'abc123';
const { ds } = createMockDatasource();
const request = {
maxDataPoints: 10,
intervalMs: 5000,
targets: [{ refId: 'A' }, { refId: 'B', datasource: { type: 'sample' } }],
dashboardUID: 'dashA',
panelId: 123,
queryGroupId: 'abc',
} as DataQueryRequest;
ds.query(request);
expect(publicDashboardQueryHandler).toHaveBeenCalledWith(request);
});
});
});
function createMockDatasource() {

View File

@@ -29,6 +29,7 @@ import {
StreamingFrameOptions,
} from '../services';
import { publicDashboardQueryHandler } from './publicDashboardQueryHandler';
import { BackendDataSourceResponse, toDataQueryResponse } from './queryResponse';
/**
@@ -123,6 +124,10 @@ class DataSourceWithBackend<
* Ideally final -- any other implementation may not work as expected
*/
query(request: DataQueryRequest<TQuery>): Observable<DataQueryResponse> {
if (config.publicDashboardAccessToken) {
return publicDashboardQueryHandler(request);
}
const { intervalMs, maxDataPoints, queryCachingTTL, range, requestId, hideFromInspector = false } = request;
let targets = request.targets;

View File

@@ -0,0 +1,50 @@
import { catchError, Observable, of, switchMap } from 'rxjs';
import { DataQuery, DataQueryRequest, DataQueryResponse } from '@grafana/data';
import { config } from '../config';
import { getBackendSrv } from '../services/backendSrv';
import { BackendDataSourceResponse, toDataQueryResponse } from './queryResponse';
export function publicDashboardQueryHandler(request: DataQueryRequest<DataQuery>): Observable<DataQueryResponse> {
const {
intervalMs,
maxDataPoints,
requestId,
panelId,
queryCachingTTL,
range: { from: fromRange, to: toRange },
} = request;
// Return early if no queries exist
if (!request.targets.length) {
return of({ data: [] });
}
const body = {
intervalMs,
maxDataPoints,
queryCachingTTL,
timeRange: {
from: fromRange.valueOf().toString(),
to: toRange.valueOf().toString(),
timezone: request.timezone,
},
};
return getBackendSrv()
.fetch<BackendDataSourceResponse>({
url: `/api/public/dashboards/${config.publicDashboardAccessToken!}/panels/${panelId}/query`,
method: 'POST',
data: body,
requestId,
})
.pipe(
switchMap((raw) => {
return of(toDataQueryResponse(raw, request.targets));
}),
catchError((err) => {
return of(toDataQueryResponse(err));
})
);
}