Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Commit

Permalink
feat(sqllab): Add event logger (apache#23040)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinpark authored Feb 13, 2023
1 parent 49aa9b4 commit 4980621
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 14 deletions.
3 changes: 2 additions & 1 deletion superset-frontend/src/SqlLab/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
} from 'src/featureFlags';
import setupExtensions from 'src/setup/setupExtensions';
import getBootstrapData from 'src/utils/getBootstrapData';
import logger from 'src/middleware/loggerMiddleware';
import getInitialState from './reducers/getInitialState';
import rootReducer from './reducers/index';
import { initEnhancer } from '../reduxUtils';
Expand Down Expand Up @@ -116,7 +117,7 @@ const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(thunkMiddleware),
applyMiddleware(thunkMiddleware, logger),
initEnhancer(
!isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE),
sqlLabPersistStateConfig,
Expand Down
49 changes: 40 additions & 9 deletions superset-frontend/src/SqlLab/components/App/App.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,61 @@
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', () => () => (
<div data-test="mock-tabbed-sql-editors" />
));
jest.mock('src/SqlLab/components/QueryAutoRefresh', () => () => (
<div data-test="mock-query-auto-refresh" />
));

describe('SqlLab App', () => {
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
const store = mockStore(sqlLabReducer(undefined, {}), {});
let wrapper;

beforeEach(() => {
wrapper = shallow(<App store={store} />).dive();
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});

it('is valid', () => {
expect(React.isValidElement(<App />)).toBe(true);
});

it('should render', () => {
const inner = wrapper.dive();
expect(inner.find('.SqlLab')).toHaveLength(1);
expect(inner.find(TabbedSqlEditors)).toHaveLength(1);
const { getByTestId } = render(<App />, { 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(<App />, {
useRedux: true,
store: storeExceedLocalStorage,
});
rerender(<App updated />);
expect(storeExceedLocalStorage.getActions()).toContainEqual(
expect.objectContaining({
type: LOG_EVENT,
}),
);
});
});
17 changes: 14 additions & 3 deletions superset-frontend/src/SqlLab/components/App/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -125,6 +127,7 @@ class App extends React.PureComponent {
) {
this.showLocalStorageUsageWarning(
this.props.localStorageUsageInKilobytes,
this.props.queries?.lenghth || 0,
);
}
}
Expand All @@ -140,7 +143,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." +
Expand All @@ -154,6 +157,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() {
Expand All @@ -162,7 +173,7 @@ class App extends React.PureComponent {
return window.location.replace('/superset/sqllab/history/');
}
return (
<SqlLabStyles className="App SqlLab">
<SqlLabStyles data-test="SqlLabApp" className="App SqlLab">
<QueryAutoRefresh
queries={queries}
refreshQueries={actions?.refreshQueries}
Expand Down Expand Up @@ -193,7 +204,7 @@ function mapStateToProps(state) {

function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
actions: bindActionCreators({ ...Actions, logEvent }, dispatch),
};
}

Expand Down
2 changes: 2 additions & 0 deletions superset-frontend/src/logger/LogUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export const LOG_ACTIONS_CONFIRM_OVERWRITE_DASHBOARD_METADATA =
export const LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_IMAGE =
'dashboard_download_as_image';
export const LOG_ACTIONS_CHART_DOWNLOAD_AS_IMAGE = 'chart_download_as_image';
export const LOG_ACTIONS_SQLLAB_WARN_LOCAL_STORAGE_USAGE =
'sqllab_warn_local_storage_usage';

// Log event types --------------------------------------------------------------
export const LOG_EVENT_TYPE_TIMING = new Set([
Expand Down
12 changes: 11 additions & 1 deletion superset-frontend/src/middleware/loggerMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const loggerMiddleware = store => next => action => {
return next(action);
}

const { dashboardInfo, explore, impressionId, dashboardLayout } =
const { dashboardInfo, explore, impressionId, dashboardLayout, sqlLab } =
store.getState();
let logMetadata = {
impression_id: impressionId,
Expand All @@ -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;
Expand Down

0 comments on commit 4980621

Please sign in to comment.