Commit b4736558 by kay delaney Committed by David

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
parent ab3df985
......@@ -178,6 +178,7 @@ export interface UpdateDatasourceInstancePayload {
exploreId: ExploreId;
datasourceInstance: DataSourceApi;
version?: string;
mode?: ExploreMode;
}
export interface ToggleLogLevelPayload {
......
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';
jest.mock('app/features/plugins/datasource_srv', () => ({
getDatasourceSrv: () => ({
getExternal: jest.fn().mockReturnValue([]),
get: jest.fn().mockReturnValue({
testDatasource: jest.fn(),
init: jest.fn(),
}),
}),
}));
import * as DatasourceSrv from 'app/features/plugins/datasource_srv';
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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment