diff --git a/superset-frontend/src/SqlLab/App.jsx b/superset-frontend/src/SqlLab/App.jsx
index 812202eec20f8..623f59ec7c758 100644
--- a/superset-frontend/src/SqlLab/App.jsx
+++ b/superset-frontend/src/SqlLab/App.jsx
@@ -30,6 +30,7 @@ import {
FeatureFlag,
} from 'src/featureFlags';
import setupExtensions from 'src/setup/setupExtensions';
+import logger from 'src/middleware/loggerMiddleware';
import getInitialState from './reducers/getInitialState';
import rootReducer from './reducers/index';
import { initEnhancer } from '../reduxUtils';
@@ -116,7 +117,7 @@ const store = createStore(
rootReducer,
initialState,
compose(
- applyMiddleware(thunkMiddleware),
+ applyMiddleware(thunkMiddleware, logger),
initEnhancer(
!isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE),
sqlLabPersistStateConfig,
diff --git a/superset-frontend/src/SqlLab/components/App/App.test.jsx b/superset-frontend/src/SqlLab/components/App/App.test.jsx
index 0629de27d5d6c..c06262915637a 100644
--- a/superset-frontend/src/SqlLab/components/App/App.test.jsx
+++ b/superset-frontend/src/SqlLab/components/App/App.test.jsx
@@ -19,21 +19,29 @@
import React from 'react';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
-
-import { shallow } from 'enzyme';
+import { render } from 'spec/helpers/testing-library';
import App from 'src/SqlLab/components/App';
-import TabbedSqlEditors from 'src/SqlLab/components/TabbedSqlEditors';
import sqlLabReducer from 'src/SqlLab/reducers/index';
+import { LOCALSTORAGE_MAX_USAGE_KB } from 'src/SqlLab/constants';
+import { LOG_EVENT } from 'src/logger/actions';
+
+jest.mock('src/SqlLab/components/TabbedSqlEditors', () => () => (
+
+));
+jest.mock('src/SqlLab/components/QueryAutoRefresh', () => () => (
+
+));
describe('SqlLab App', () => {
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
const store = mockStore(sqlLabReducer(undefined, {}), {});
- let wrapper;
-
beforeEach(() => {
- wrapper = shallow().dive();
+ jest.useFakeTimers();
+ });
+ afterEach(() => {
+ jest.useRealTimers();
});
it('is valid', () => {
@@ -41,8 +49,31 @@ describe('SqlLab App', () => {
});
it('should render', () => {
- const inner = wrapper.dive();
- expect(inner.find('.SqlLab')).toHaveLength(1);
- expect(inner.find(TabbedSqlEditors)).toHaveLength(1);
+ const { getByTestId } = render(, { useRedux: true, store });
+ expect(getByTestId('SqlLabApp')).toBeInTheDocument();
+ expect(getByTestId('mock-tabbed-sql-editors')).toBeInTheDocument();
+ });
+
+ it('logs current usage warning', async () => {
+ const localStorageUsageInKilobytes = LOCALSTORAGE_MAX_USAGE_KB + 10;
+ const storeExceedLocalStorage = mockStore(
+ sqlLabReducer(
+ {
+ localStorageUsageInKilobytes,
+ },
+ {},
+ ),
+ );
+
+ const { rerender } = render(, {
+ useRedux: true,
+ store: storeExceedLocalStorage,
+ });
+ rerender();
+ expect(storeExceedLocalStorage.getActions()).toContainEqual(
+ expect.objectContaining({
+ type: LOG_EVENT,
+ }),
+ );
});
});
diff --git a/superset-frontend/src/SqlLab/components/App/index.jsx b/superset-frontend/src/SqlLab/components/App/index.jsx
index 3aae12bfb33ca..3e9c4310cb505 100644
--- a/superset-frontend/src/SqlLab/components/App/index.jsx
+++ b/superset-frontend/src/SqlLab/components/App/index.jsx
@@ -29,6 +29,8 @@ import {
LOCALSTORAGE_WARNING_MESSAGE_THROTTLE_MS,
} from 'src/SqlLab/constants';
import * as Actions from 'src/SqlLab/actions/sqlLab';
+import { logEvent } from 'src/logger/actions';
+import { LOG_ACTIONS_SQLLAB_WARN_LOCAL_STORAGE_USAGE } from 'src/logger/LogUtils';
import TabbedSqlEditors from '../TabbedSqlEditors';
import QueryAutoRefresh from '../QueryAutoRefresh';
@@ -62,6 +64,7 @@ class App extends React.PureComponent {
) {
this.showLocalStorageUsageWarning(
this.props.localStorageUsageInKilobytes,
+ this.props.queries?.lenghth || 0,
);
}
}
@@ -77,7 +80,7 @@ class App extends React.PureComponent {
this.setState({ hash: window.location.hash });
}
- showLocalStorageUsageWarning(currentUsage) {
+ showLocalStorageUsageWarning(currentUsage, queryCount) {
this.props.actions.addDangerToast(
t(
"SQL Lab uses your browser's local storage to store queries and results." +
@@ -91,6 +94,14 @@ class App extends React.PureComponent {
},
),
);
+ const eventData = {
+ current_usage: currentUsage,
+ query_count: queryCount,
+ };
+ this.props.actions.logEvent(
+ LOG_ACTIONS_SQLLAB_WARN_LOCAL_STORAGE_USAGE,
+ eventData,
+ );
}
render() {
@@ -99,7 +110,7 @@ class App extends React.PureComponent {
return window.location.replace('/superset/sqllab/history/');
}
return (
-
+
next => action => {
return next(action);
}
- const { dashboardInfo, explore, impressionId, dashboardLayout } =
+ const { dashboardInfo, explore, impressionId, dashboardLayout, sqlLab } =
store.getState();
let logMetadata = {
impression_id: impressionId,
@@ -90,6 +90,16 @@ const loggerMiddleware = store => next => action => {
source_id: explore.slice ? explore.slice.slice_id : 0,
...logMetadata,
};
+ } else if (sqlLab) {
+ const editor = sqlLab.queryEditors.find(
+ ({ id }) => id === sqlLab.tabHistory.slice(-1)[0],
+ );
+ logMetadata = {
+ source: 'sqlLab',
+ source_id: editor?.id,
+ db_id: editor?.dbId,
+ schema: editor?.schema,
+ };
}
const { eventName } = action.payload;