mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Datasource/Loki: Loki now goes to Logs mode when importing prom queries (#20890)
* Datasource/Loki: Loki now goes to Logs mode when importing prom queries Closes #20831 * Fixes behavior and adds tests * Update public/app/features/explore/state/actions.test.ts
This commit is contained in:
parent
ab3df98523
commit
b4736558ac
@ -178,6 +178,7 @@ export interface UpdateDatasourceInstancePayload {
|
||||
exploreId: ExploreId;
|
||||
datasourceInstance: DataSourceApi;
|
||||
version?: string;
|
||||
mode?: ExploreMode;
|
||||
}
|
||||
|
||||
export interface ToggleLogLevelPayload {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { loadDatasource, navigateToExplore, refreshExplore } from './actions';
|
||||
import { changeDatasource, loadDatasource, navigateToExplore, refreshExplore } from './actions';
|
||||
import * as Actions from './actions';
|
||||
import { ExploreId, ExploreMode, ExploreUpdateState, ExploreUrlState } from 'app/types';
|
||||
import { thunkTester } from 'test/core/thunk/thunkTester';
|
||||
import {
|
||||
@ -8,6 +9,7 @@ import {
|
||||
loadDatasourceReadyAction,
|
||||
setQueriesAction,
|
||||
updateUIStateAction,
|
||||
updateDatasourceInstanceAction,
|
||||
} from './actionTypes';
|
||||
import { Emitter } from 'app/core/core';
|
||||
import { ActionOf } from 'app/core/redux/actionCreatorFactory';
|
||||
@ -16,16 +18,24 @@ import { DataQuery, DefaultTimeZone, LogsDedupStrategy, RawTimeRange, toUtc } fr
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { updateLocation } from '../../../core/actions';
|
||||
import { MockDataSourceApi } from '../../../../test/mocks/datasource_srv';
|
||||
import * as DatasourceSrv from 'app/features/plugins/datasource_srv';
|
||||
|
||||
jest.mock('app/features/plugins/datasource_srv', () => ({
|
||||
getDatasourceSrv: () => ({
|
||||
getExternal: jest.fn().mockReturnValue([]),
|
||||
get: jest.fn().mockReturnValue({
|
||||
testDatasource: jest.fn(),
|
||||
init: jest.fn(),
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
jest.mock('app/features/plugins/datasource_srv');
|
||||
const getDatasourceSrvMock = (DatasourceSrv.getDatasourceSrv as any) as jest.Mock<DatasourceSrv.DatasourceSrv>;
|
||||
|
||||
beforeEach(() => {
|
||||
getDatasourceSrvMock.mockClear();
|
||||
getDatasourceSrvMock.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
getExternal: jest.fn().mockReturnValue([]),
|
||||
get: jest.fn().mockReturnValue({
|
||||
testDatasource: jest.fn(),
|
||||
init: jest.fn(),
|
||||
}),
|
||||
} as any)
|
||||
);
|
||||
});
|
||||
|
||||
jest.mock('../../dashboard/services/TimeSrv', () => ({
|
||||
getTimeSrv: jest.fn().mockReturnValue({
|
||||
@ -163,6 +173,62 @@ describe('refreshExplore', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('changing datasource', () => {
|
||||
it('should switch to logs mode when changing from prometheus to loki', async () => {
|
||||
const lokiMock = {
|
||||
testDatasource: () => Promise.resolve({ status: 'success' }),
|
||||
name: 'Loki',
|
||||
init: jest.fn(),
|
||||
meta: { id: 'some id', name: 'Loki' },
|
||||
};
|
||||
|
||||
getDatasourceSrvMock.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
getExternal: jest.fn().mockReturnValue([]),
|
||||
get: jest.fn().mockReturnValue(lokiMock),
|
||||
} as any)
|
||||
);
|
||||
|
||||
const exploreId = ExploreId.left;
|
||||
const name = 'Prometheus';
|
||||
const mockPromDatasourceInstance = {
|
||||
testDatasource: () => Promise.resolve({ status: 'success' }),
|
||||
name,
|
||||
init: jest.fn(),
|
||||
meta: { id: 'some id', name },
|
||||
};
|
||||
|
||||
const initialState = {
|
||||
explore: {
|
||||
[exploreId]: {
|
||||
requestedDatasourceName: 'Loki',
|
||||
datasourceInstance: mockPromDatasourceInstance,
|
||||
},
|
||||
},
|
||||
user: {
|
||||
orgId: 1,
|
||||
},
|
||||
};
|
||||
|
||||
jest.spyOn(Actions, 'importQueries').mockImplementationOnce(() => jest.fn);
|
||||
jest.spyOn(Actions, 'loadDatasource').mockImplementationOnce(() => jest.fn);
|
||||
jest.spyOn(Actions, 'runQueries').mockImplementationOnce(() => jest.fn);
|
||||
const dispatchedActions = await thunkTester(initialState)
|
||||
.givenThunk(changeDatasource)
|
||||
.whenThunkIsDispatched(exploreId, name);
|
||||
|
||||
expect(dispatchedActions).toEqual([
|
||||
updateDatasourceInstanceAction({
|
||||
exploreId,
|
||||
datasourceInstance: lokiMock as any,
|
||||
version: undefined,
|
||||
mode: ExploreMode.Logs,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loading datasource', () => {
|
||||
describe('when loadDatasource thunk is dispatched', () => {
|
||||
describe('and all goes fine', () => {
|
||||
|
@ -124,11 +124,16 @@ export function changeDatasource(exploreId: ExploreId, datasource: string): Thun
|
||||
const orgId = getState().user.orgId;
|
||||
const datasourceVersion = newDataSourceInstance.getVersion && (await newDataSourceInstance.getVersion());
|
||||
|
||||
// HACK: Switch to logs mode if coming from Prometheus to Loki
|
||||
const prometheusToLoki =
|
||||
currentDataSourceInstance?.meta?.name === 'Prometheus' && newDataSourceInstance?.meta?.name === 'Loki';
|
||||
|
||||
dispatch(
|
||||
updateDatasourceInstanceAction({
|
||||
exploreId,
|
||||
datasourceInstance: newDataSourceInstance,
|
||||
version: datasourceVersion,
|
||||
mode: prometheusToLoki ? ExploreMode.Logs : undefined,
|
||||
})
|
||||
);
|
||||
|
||||
@ -316,12 +321,12 @@ export const loadDatasourceReady = (
|
||||
* @param sourceDataSource
|
||||
* @param targetDataSource
|
||||
*/
|
||||
export function importQueries(
|
||||
export const importQueries = (
|
||||
exploreId: ExploreId,
|
||||
queries: DataQuery[],
|
||||
sourceDataSource: DataSourceApi,
|
||||
targetDataSource: DataSourceApi
|
||||
): ThunkResult<void> {
|
||||
): ThunkResult<void> => {
|
||||
return async dispatch => {
|
||||
if (!sourceDataSource) {
|
||||
// explore not initialized
|
||||
@ -346,12 +351,12 @@ export function importQueries(
|
||||
|
||||
dispatch(queriesImportedAction({ exploreId, queries: nextQueries }));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Main action to asynchronously load a datasource. Dispatches lots of smaller actions for feedback.
|
||||
*/
|
||||
export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi, orgId: number): ThunkResult<void> {
|
||||
export const loadDatasource = (exploreId: ExploreId, instance: DataSourceApi, orgId: number): ThunkResult<void> => {
|
||||
return async (dispatch, getState) => {
|
||||
const datasourceName = instance.name;
|
||||
|
||||
@ -373,7 +378,7 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi, or
|
||||
|
||||
dispatch(loadDatasourceReady(exploreId, instance, orgId));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Action to modify a query given a datasource-specific modifier action.
|
||||
@ -399,7 +404,7 @@ export function modifyQueries(
|
||||
/**
|
||||
* Main action to run queries and dispatches sub-actions based on which result viewers are active
|
||||
*/
|
||||
export function runQueries(exploreId: ExploreId): ThunkResult<void> {
|
||||
export const runQueries = (exploreId: ExploreId): ThunkResult<void> => {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(updateTime({ exploreId }));
|
||||
|
||||
@ -484,7 +489,7 @@ export function runQueries(exploreId: ExploreId): ThunkResult<void> {
|
||||
|
||||
dispatch(queryStoreSubscriptionAction({ exploreId, querySubscription: newQuerySub }));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const toRawTimeRange = (range: TimeRange): RawTimeRange => {
|
||||
let from = range.raw.from;
|
||||
|
@ -269,7 +269,7 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
|
||||
.addMapper({
|
||||
filter: updateDatasourceInstanceAction,
|
||||
mapper: (state, action): ExploreItemState => {
|
||||
const { datasourceInstance, version } = action.payload;
|
||||
const { datasourceInstance, version, mode } = action.payload;
|
||||
|
||||
// Custom components
|
||||
stopQueryState(state.querySubscription);
|
||||
@ -291,7 +291,7 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
|
||||
}
|
||||
|
||||
const updatedDatasourceInstance = Object.assign(datasourceInstance, { meta: newMetadata });
|
||||
const [supportedModes, mode] = getModesForDatasource(updatedDatasourceInstance, state.mode);
|
||||
const [supportedModes, newMode] = getModesForDatasource(updatedDatasourceInstance, state.mode);
|
||||
|
||||
return {
|
||||
...state,
|
||||
@ -304,7 +304,7 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
|
||||
loading: false,
|
||||
queryKeys: [],
|
||||
supportedModes,
|
||||
mode,
|
||||
mode: mode ?? newMode,
|
||||
originPanelId: state.urlState && state.urlState.originPanelId,
|
||||
};
|
||||
},
|
||||
|
@ -190,9 +190,9 @@ export class DatasourceSrv implements DataSourceService {
|
||||
}
|
||||
}
|
||||
|
||||
export function getDatasourceSrv(): DatasourceSrv {
|
||||
export const getDatasourceSrv = (): DatasourceSrv => {
|
||||
return getDataSourceService() as DatasourceSrv;
|
||||
}
|
||||
};
|
||||
|
||||
coreModule.service('datasourceSrv', DatasourceSrv);
|
||||
export default DatasourceSrv;
|
||||
|
Loading…
Reference in New Issue
Block a user