chore(sqllab): Add logging for actions (#28876)
This commit is contained in:
parent
66bd0ce3d0
commit
05829cbda9
|
|
@ -71,6 +71,12 @@ import {
|
||||||
reRunQuery,
|
reRunQuery,
|
||||||
} from 'src/SqlLab/actions/sqlLab';
|
} from 'src/SqlLab/actions/sqlLab';
|
||||||
import { URL_PARAMS } from 'src/constants';
|
import { URL_PARAMS } from 'src/constants';
|
||||||
|
import useLogAction from 'src/logger/useLogAction';
|
||||||
|
import {
|
||||||
|
LOG_ACTIONS_SQLLAB_COPY_RESULT_TO_CLIPBOARD,
|
||||||
|
LOG_ACTIONS_SQLLAB_CREATE_CHART,
|
||||||
|
LOG_ACTIONS_SQLLAB_DOWNLOAD_CSV,
|
||||||
|
} from 'src/logger/LogUtils';
|
||||||
import Icons from 'src/components/Icons';
|
import Icons from 'src/components/Icons';
|
||||||
import ExploreCtasResultsButton from '../ExploreCtasResultsButton';
|
import ExploreCtasResultsButton from '../ExploreCtasResultsButton';
|
||||||
import ExploreResultsButton from '../ExploreResultsButton';
|
import ExploreResultsButton from '../ExploreResultsButton';
|
||||||
|
|
@ -171,6 +177,7 @@ const ResultSet = ({
|
||||||
'dbId',
|
'dbId',
|
||||||
'tab',
|
'tab',
|
||||||
'sql',
|
'sql',
|
||||||
|
'sqlEditorId',
|
||||||
'templateParams',
|
'templateParams',
|
||||||
'schema',
|
'schema',
|
||||||
'rows',
|
'rows',
|
||||||
|
|
@ -201,6 +208,7 @@ const ResultSet = ({
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const logAction = useLogAction({ queryId, sqlEditorId: query.sqlEditorId });
|
||||||
|
|
||||||
const reRunQueryIfSessionTimeoutErrorOnMount = useCallback(() => {
|
const reRunQueryIfSessionTimeoutErrorOnMount = useCallback(() => {
|
||||||
if (
|
if (
|
||||||
|
|
@ -258,7 +266,7 @@ const ResultSet = ({
|
||||||
const { results } = query;
|
const { results } = query;
|
||||||
|
|
||||||
const openInNewWindow = clickEvent.metaKey;
|
const openInNewWindow = clickEvent.metaKey;
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_CREATE_CHART, {});
|
||||||
if (results?.query_id) {
|
if (results?.query_id) {
|
||||||
const key = await postFormData(results.query_id, 'query', {
|
const key = await postFormData(results.query_id, 'query', {
|
||||||
...EXPLORE_CHART_DEFAULT,
|
...EXPLORE_CHART_DEFAULT,
|
||||||
|
|
@ -321,7 +329,11 @@ const ResultSet = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{csv && (
|
{csv && (
|
||||||
<Button buttonSize="small" href={getExportCsvUrl(query.id)}>
|
<Button
|
||||||
|
buttonSize="small"
|
||||||
|
href={getExportCsvUrl(query.id)}
|
||||||
|
onClick={() => logAction(LOG_ACTIONS_SQLLAB_DOWNLOAD_CSV, {})}
|
||||||
|
>
|
||||||
<i className="fa fa-file-text-o" /> {t('Download to CSV')}
|
<i className="fa fa-file-text-o" /> {t('Download to CSV')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
@ -335,6 +347,9 @@ const ResultSet = ({
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
hideTooltip
|
hideTooltip
|
||||||
|
onCopyEnd={() =>
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_COPY_RESULT_TO_CLIPBOARD, {})
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</ResultSetButtons>
|
</ResultSetButtons>
|
||||||
{search && (
|
{search && (
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,11 @@ import { DropdownButton } from 'src/components/DropdownButton';
|
||||||
import { detectOS } from 'src/utils/common';
|
import { detectOS } from 'src/utils/common';
|
||||||
import { QueryButtonProps } from 'src/SqlLab/types';
|
import { QueryButtonProps } from 'src/SqlLab/types';
|
||||||
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
|
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
|
||||||
|
import {
|
||||||
|
LOG_ACTIONS_SQLLAB_RUN_QUERY,
|
||||||
|
LOG_ACTIONS_SQLLAB_STOP_QUERY,
|
||||||
|
} from 'src/logger/LogUtils';
|
||||||
|
import useLogAction from 'src/logger/useLogAction';
|
||||||
|
|
||||||
export interface RunQueryActionButtonProps {
|
export interface RunQueryActionButtonProps {
|
||||||
queryEditorId: string;
|
queryEditorId: string;
|
||||||
|
|
@ -58,7 +63,13 @@ const onClick = (
|
||||||
allowAsync: boolean,
|
allowAsync: boolean,
|
||||||
runQuery: (c?: boolean) => void = () => undefined,
|
runQuery: (c?: boolean) => void = () => undefined,
|
||||||
stopQuery = () => {},
|
stopQuery = () => {},
|
||||||
|
logAction: (name: string, payload: Record<string, any>) => void,
|
||||||
): void => {
|
): void => {
|
||||||
|
const eventName = shouldShowStopButton
|
||||||
|
? LOG_ACTIONS_SQLLAB_STOP_QUERY
|
||||||
|
: LOG_ACTIONS_SQLLAB_RUN_QUERY;
|
||||||
|
|
||||||
|
logAction(eventName, { shortcut: false });
|
||||||
if (shouldShowStopButton) return stopQuery();
|
if (shouldShowStopButton) return stopQuery();
|
||||||
if (allowAsync) {
|
if (allowAsync) {
|
||||||
return runQuery(true);
|
return runQuery(true);
|
||||||
|
|
@ -90,6 +101,7 @@ const RunQueryActionButton = ({
|
||||||
stopQuery,
|
stopQuery,
|
||||||
}: RunQueryActionButtonProps) => {
|
}: RunQueryActionButtonProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const logAction = useLogAction({ queryEditorId });
|
||||||
const userOS = detectOS();
|
const userOS = detectOS();
|
||||||
|
|
||||||
const { selectedText, sql } = useQueryEditor(queryEditorId, [
|
const { selectedText, sql } = useQueryEditor(queryEditorId, [
|
||||||
|
|
@ -122,7 +134,7 @@ const RunQueryActionButton = ({
|
||||||
<ButtonComponent
|
<ButtonComponent
|
||||||
data-test="run-query-action"
|
data-test="run-query-action"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
onClick(shouldShowStopBtn, allowAsync, runQuery, stopQuery)
|
onClick(shouldShowStopBtn, allowAsync, runQuery, stopQuery, logAction)
|
||||||
}
|
}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
tooltip={
|
tooltip={
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ import {
|
||||||
import { getDatasourceAsSaveableDataset } from 'src/utils/datasourceUtils';
|
import { getDatasourceAsSaveableDataset } from 'src/utils/datasourceUtils';
|
||||||
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
|
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
|
||||||
import { QueryEditor } from 'src/SqlLab/types';
|
import { QueryEditor } from 'src/SqlLab/types';
|
||||||
|
import useLogAction from 'src/logger/useLogAction';
|
||||||
|
import {
|
||||||
|
LOG_ACTIONS_SQLLAB_CREATE_CHART,
|
||||||
|
LOG_ACTIONS_SQLLAB_SAVE_QUERY,
|
||||||
|
} from 'src/logger/LogUtils';
|
||||||
|
|
||||||
interface SaveQueryProps {
|
interface SaveQueryProps {
|
||||||
queryEditorId: string;
|
queryEditorId: string;
|
||||||
|
|
@ -92,6 +97,7 @@ const SaveQuery = ({
|
||||||
}),
|
}),
|
||||||
[queryEditor, columns],
|
[queryEditor, columns],
|
||||||
);
|
);
|
||||||
|
const logAction = useLogAction({ queryEditorId });
|
||||||
const defaultLabel = query.name || query.description || t('Undefined');
|
const defaultLabel = query.name || query.description || t('Undefined');
|
||||||
const [description, setDescription] = useState<string>(
|
const [description, setDescription] = useState<string>(
|
||||||
query.description || '',
|
query.description || '',
|
||||||
|
|
@ -106,7 +112,12 @@ const SaveQuery = ({
|
||||||
|
|
||||||
const overlayMenu = (
|
const overlayMenu = (
|
||||||
<Menu>
|
<Menu>
|
||||||
<Menu.Item onClick={() => setShowSaveDatasetModal(true)}>
|
<Menu.Item
|
||||||
|
onClick={() => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_CREATE_CHART, {});
|
||||||
|
setShowSaveDatasetModal(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
{t('Save dataset')}
|
{t('Save dataset')}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
@ -130,6 +141,7 @@ const SaveQuery = ({
|
||||||
const close = () => setShowSave(false);
|
const close = () => setShowSave(false);
|
||||||
|
|
||||||
const onSaveWrapper = () => {
|
const onSaveWrapper = () => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_SAVE_QUERY, {});
|
||||||
onSave(queryPayload(), query.id);
|
onSave(queryPayload(), query.id);
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ import withToasts from 'src/components/MessageToasts/withToasts';
|
||||||
import CopyToClipboard from 'src/components/CopyToClipboard';
|
import CopyToClipboard from 'src/components/CopyToClipboard';
|
||||||
import { storeQuery } from 'src/utils/common';
|
import { storeQuery } from 'src/utils/common';
|
||||||
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
|
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
|
||||||
|
import { LOG_ACTIONS_SQLLAB_COPY_LINK } from 'src/logger/LogUtils';
|
||||||
|
import useLogAction from 'src/logger/useLogAction';
|
||||||
|
|
||||||
interface ShareSqlLabQueryProps {
|
interface ShareSqlLabQueryProps {
|
||||||
queryEditorId: string;
|
queryEditorId: string;
|
||||||
|
|
@ -51,7 +53,7 @@ const ShareSqlLabQuery = ({
|
||||||
addDangerToast,
|
addDangerToast,
|
||||||
}: ShareSqlLabQueryProps) => {
|
}: ShareSqlLabQueryProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const logAction = useLogAction({ queryEditorId });
|
||||||
const { dbId, name, schema, autorun, sql, remoteId, templateParams } =
|
const { dbId, name, schema, autorun, sql, remoteId, templateParams } =
|
||||||
useQueryEditor(queryEditorId, [
|
useQueryEditor(queryEditorId, [
|
||||||
'dbId',
|
'dbId',
|
||||||
|
|
@ -91,6 +93,9 @@ const ShareSqlLabQuery = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const getCopyUrl = (callback: Function) => {
|
const getCopyUrl = (callback: Function) => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_COPY_LINK, {
|
||||||
|
shortcut: false,
|
||||||
|
});
|
||||||
if (isFeatureEnabled(FeatureFlag.ShareQueriesViaKvStore)) {
|
if (isFeatureEnabled(FeatureFlag.ShareQueriesViaKvStore)) {
|
||||||
return getCopyUrlForKvStore(callback);
|
return getCopyUrlForKvStore(callback);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,17 @@ import {
|
||||||
} from 'src/utils/localStorageHelpers';
|
} from 'src/utils/localStorageHelpers';
|
||||||
import { EmptyStateBig } from 'src/components/EmptyState';
|
import { EmptyStateBig } from 'src/components/EmptyState';
|
||||||
import getBootstrapData from 'src/utils/getBootstrapData';
|
import getBootstrapData from 'src/utils/getBootstrapData';
|
||||||
|
import useLogAction from 'src/logger/useLogAction';
|
||||||
|
import {
|
||||||
|
LOG_ACTIONS_SQLLAB_CREATE_TABLE_AS,
|
||||||
|
LOG_ACTIONS_SQLLAB_CREATE_VIEW_AS,
|
||||||
|
LOG_ACTIONS_SQLLAB_ESTIMATE_QUERY_COST,
|
||||||
|
LOG_ACTIONS_SQLLAB_FORMAT_SQL,
|
||||||
|
LOG_ACTIONS_SQLLAB_LOAD_TAB_STATE,
|
||||||
|
LOG_ACTIONS_SQLLAB_RUN_QUERY,
|
||||||
|
LOG_ACTIONS_SQLLAB_STOP_QUERY,
|
||||||
|
Logger,
|
||||||
|
} from 'src/logger/LogUtils';
|
||||||
import TemplateParamsEditor from '../TemplateParamsEditor';
|
import TemplateParamsEditor from '../TemplateParamsEditor';
|
||||||
import SouthPane from '../SouthPane';
|
import SouthPane from '../SouthPane';
|
||||||
import SaveQuery, { QueryPayload } from '../SaveQuery';
|
import SaveQuery, { QueryPayload } from '../SaveQuery';
|
||||||
|
|
@ -273,6 +284,7 @@ const SqlEditor: FC<Props> = ({
|
||||||
};
|
};
|
||||||
}, shallowEqual);
|
}, shallowEqual);
|
||||||
|
|
||||||
|
const logAction = useLogAction({ queryEditorId: queryEditor.id });
|
||||||
const isActive = currentQueryEditorId === queryEditor.id;
|
const isActive = currentQueryEditorId === queryEditor.id;
|
||||||
const [height, setHeight] = useState(0);
|
const [height, setHeight] = useState(0);
|
||||||
const [autorun, setAutorun] = useState(queryEditor.autorun);
|
const [autorun, setAutorun] = useState(queryEditor.autorun);
|
||||||
|
|
@ -319,9 +331,15 @@ const SqlEditor: FC<Props> = ({
|
||||||
[ctas, database, defaultQueryLimit, dispatch, queryEditor],
|
[ctas, database, defaultQueryLimit, dispatch, queryEditor],
|
||||||
);
|
);
|
||||||
|
|
||||||
const formatCurrentQuery = useCallback(() => {
|
const formatCurrentQuery = useCallback(
|
||||||
|
(useShortcut?: boolean) => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_FORMAT_SQL, {
|
||||||
|
shortcut: Boolean(useShortcut),
|
||||||
|
});
|
||||||
dispatch(formatQuery(queryEditor));
|
dispatch(formatQuery(queryEditor));
|
||||||
}, [dispatch, queryEditor]);
|
},
|
||||||
|
[dispatch, queryEditor, logAction],
|
||||||
|
);
|
||||||
|
|
||||||
const stopQuery = useCallback(() => {
|
const stopQuery = useCallback(() => {
|
||||||
if (latestQuery && ['running', 'pending'].indexOf(latestQuery.state) >= 0) {
|
if (latestQuery && ['running', 'pending'].indexOf(latestQuery.state) >= 0) {
|
||||||
|
|
@ -360,6 +378,7 @@ const SqlEditor: FC<Props> = ({
|
||||||
descr: KEY_MAP[KeyboardShortcut.CtrlR],
|
descr: KEY_MAP[KeyboardShortcut.CtrlR],
|
||||||
func: () => {
|
func: () => {
|
||||||
if (queryEditor.sql.trim() !== '') {
|
if (queryEditor.sql.trim() !== '') {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_RUN_QUERY, { shortcut: true });
|
||||||
startQuery();
|
startQuery();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -370,6 +389,7 @@ const SqlEditor: FC<Props> = ({
|
||||||
descr: KEY_MAP[KeyboardShortcut.CtrlEnter],
|
descr: KEY_MAP[KeyboardShortcut.CtrlEnter],
|
||||||
func: () => {
|
func: () => {
|
||||||
if (queryEditor.sql.trim() !== '') {
|
if (queryEditor.sql.trim() !== '') {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_RUN_QUERY, { shortcut: true });
|
||||||
startQuery();
|
startQuery();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -386,6 +406,7 @@ const SqlEditor: FC<Props> = ({
|
||||||
descr: KEY_MAP[KeyboardShortcut.CtrlT],
|
descr: KEY_MAP[KeyboardShortcut.CtrlT],
|
||||||
}),
|
}),
|
||||||
func: () => {
|
func: () => {
|
||||||
|
Logger.markTimeOrigin();
|
||||||
dispatch(addNewQueryEditor());
|
dispatch(addNewQueryEditor());
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -400,14 +421,17 @@ const SqlEditor: FC<Props> = ({
|
||||||
key: KeyboardShortcut.CtrlE,
|
key: KeyboardShortcut.CtrlE,
|
||||||
descr: KEY_MAP[KeyboardShortcut.CtrlE],
|
descr: KEY_MAP[KeyboardShortcut.CtrlE],
|
||||||
}),
|
}),
|
||||||
func: stopQuery,
|
func: () => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_STOP_QUERY, { shortcut: true });
|
||||||
|
stopQuery();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'formatQuery',
|
name: 'formatQuery',
|
||||||
key: KeyboardShortcut.CtrlShiftF,
|
key: KeyboardShortcut.CtrlShiftF,
|
||||||
descr: KEY_MAP[KeyboardShortcut.CtrlShiftF],
|
descr: KEY_MAP[KeyboardShortcut.CtrlShiftF],
|
||||||
func: () => {
|
func: () => {
|
||||||
formatCurrentQuery();
|
formatCurrentQuery(true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
@ -505,6 +529,13 @@ const SqlEditor: FC<Props> = ({
|
||||||
!queryEditor.loaded;
|
!queryEditor.loaded;
|
||||||
|
|
||||||
const loadQueryEditor = useEffectEvent(() => {
|
const loadQueryEditor = useEffectEvent(() => {
|
||||||
|
const duration = Logger.getTimestamp();
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_LOAD_TAB_STATE, {
|
||||||
|
duration,
|
||||||
|
queryEditorId: queryEditor.id,
|
||||||
|
inLocalStorage: Boolean(queryEditor.inLocalStorage),
|
||||||
|
hasLoaded: !shouldLoadQueryEditor,
|
||||||
|
});
|
||||||
if (shouldLoadQueryEditor) {
|
if (shouldLoadQueryEditor) {
|
||||||
dispatch(fetchQueryEditor(queryEditor, displayLimit));
|
dispatch(fetchQueryEditor(queryEditor, displayLimit));
|
||||||
}
|
}
|
||||||
|
|
@ -602,6 +633,7 @@ const SqlEditor: FC<Props> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const getQueryCostEstimate = () => {
|
const getQueryCostEstimate = () => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_ESTIMATE_QUERY_COST, { shortcut: false });
|
||||||
if (database) {
|
if (database) {
|
||||||
dispatch(estimateQueryCost(queryEditor));
|
dispatch(estimateQueryCost(queryEditor));
|
||||||
}
|
}
|
||||||
|
|
@ -668,7 +700,9 @@ const SqlEditor: FC<Props> = ({
|
||||||
/>
|
/>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
)}
|
)}
|
||||||
<Menu.Item onClick={formatCurrentQuery}>{t('Format SQL')}</Menu.Item>
|
<Menu.Item onClick={() => formatCurrentQuery()}>
|
||||||
|
{t('Format SQL')}
|
||||||
|
</Menu.Item>
|
||||||
{!isEmpty(scheduledQueriesConf) && (
|
{!isEmpty(scheduledQueriesConf) && (
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
<ScheduleQueryButton
|
<ScheduleQueryButton
|
||||||
|
|
@ -706,6 +740,9 @@ const SqlEditor: FC<Props> = ({
|
||||||
{allowCTAS && (
|
{allowCTAS && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_CREATE_TABLE_AS, {
|
||||||
|
shortcut: false,
|
||||||
|
});
|
||||||
setShowCreateAsModal(true);
|
setShowCreateAsModal(true);
|
||||||
setCreateAs(CtasEnum.Table);
|
setCreateAs(CtasEnum.Table);
|
||||||
}}
|
}}
|
||||||
|
|
@ -717,6 +754,9 @@ const SqlEditor: FC<Props> = ({
|
||||||
{allowCVAS && (
|
{allowCVAS && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
logAction(LOG_ACTIONS_SQLLAB_CREATE_VIEW_AS, {
|
||||||
|
shortcut: false,
|
||||||
|
});
|
||||||
setShowCreateAsModal(true);
|
setShowCreateAsModal(true);
|
||||||
setCreateAs(CtasEnum.View);
|
setCreateAs(CtasEnum.View);
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import { connect } from 'react-redux';
|
||||||
import URI from 'urijs';
|
import URI from 'urijs';
|
||||||
import type { QueryEditor, SqlLabRootState } from 'src/SqlLab/types';
|
import type { QueryEditor, SqlLabRootState } from 'src/SqlLab/types';
|
||||||
import { FeatureFlag, styled, t, isFeatureEnabled } from '@superset-ui/core';
|
import { FeatureFlag, styled, t, isFeatureEnabled } from '@superset-ui/core';
|
||||||
|
import { Logger } from 'src/logger/LogUtils';
|
||||||
import { Tooltip } from 'src/components/Tooltip';
|
import { Tooltip } from 'src/components/Tooltip';
|
||||||
import { detectOS } from 'src/utils/common';
|
import { detectOS } from 'src/utils/common';
|
||||||
import * as Actions from 'src/SqlLab/actions/sqlLab';
|
import * as Actions from 'src/SqlLab/actions/sqlLab';
|
||||||
|
|
@ -193,6 +194,7 @@ class TabbedSqlEditors extends PureComponent<TabbedSqlEditorsProps> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
|
Logger.markTimeOrigin();
|
||||||
this.newQueryEditor();
|
this.newQueryEditor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +203,14 @@ class TabbedSqlEditors extends PureComponent<TabbedSqlEditorsProps> {
|
||||||
this.props.actions.removeQueryEditor(qe);
|
this.props.actions.removeQueryEditor(qe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onTabClicked = () => {
|
||||||
|
Logger.markTimeOrigin();
|
||||||
|
const noQueryEditors = this.props.queryEditors?.length === 0;
|
||||||
|
if (noQueryEditors) {
|
||||||
|
this.newQueryEditor();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const noQueryEditors = this.props.queryEditors?.length === 0;
|
const noQueryEditors = this.props.queryEditors?.length === 0;
|
||||||
const editors = this.props.queryEditors?.map(qe => (
|
const editors = this.props.queryEditors?.map(qe => (
|
||||||
|
|
@ -261,7 +271,7 @@ class TabbedSqlEditors extends PureComponent<TabbedSqlEditorsProps> {
|
||||||
onChange={this.handleSelect}
|
onChange={this.handleSelect}
|
||||||
fullWidth={false}
|
fullWidth={false}
|
||||||
hideAdd={this.props.offline}
|
hideAdd={this.props.offline}
|
||||||
onTabClick={() => noQueryEditors && this.newQueryEditor()}
|
onTabClick={this.onTabClicked}
|
||||||
onEdit={this.handleEdit}
|
onEdit={this.handleEdit}
|
||||||
type={noQueryEditors ? 'card' : 'editable-card'}
|
type={noQueryEditors ? 'card' : 'editable-card'}
|
||||||
addIcon={
|
addIcon={
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,21 @@ export const LOG_ACTIONS_DRILL_BY_BREADCRUMB_CLICKED =
|
||||||
'drill_by_breadcrumb_clicked';
|
'drill_by_breadcrumb_clicked';
|
||||||
export const LOG_ACTIONS_SQLLAB_MONITOR_LOCAL_STORAGE_USAGE =
|
export const LOG_ACTIONS_SQLLAB_MONITOR_LOCAL_STORAGE_USAGE =
|
||||||
'sqllab_monitor_local_storage_usage';
|
'sqllab_monitor_local_storage_usage';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_CREATE_TABLE_AS = 'sqllab_create_table_as';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_CREATE_VIEW_AS = 'sqllab_create_view_as';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_RUN_QUERY = 'sqllab_run_query';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_STOP_QUERY = 'sqllab_stop_query';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_ESTIMATE_QUERY_COST =
|
||||||
|
'sqllab_estimate_query_cost';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_SAVE_QUERY = 'sqllab_save_query';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_SAVE_DATASET = 'sqllab_save_dataset';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_COPY_LINK = 'sqllab_copy_link';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_FORMAT_SQL = 'sqllab_format_sql';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_DOWNLOAD_CSV = 'sqllab_download_csv';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_COPY_RESULT_TO_CLIPBOARD =
|
||||||
|
'sqllab_copy_result_to_clipboard';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_CREATE_CHART = 'sqllab_create_chart';
|
||||||
|
export const LOG_ACTIONS_SQLLAB_LOAD_TAB_STATE = 'sqllab_load_tab_state';
|
||||||
|
|
||||||
// Log event types --------------------------------------------------------------
|
// Log event types --------------------------------------------------------------
|
||||||
export const LOG_EVENT_TYPE_TIMING = new Set([
|
export const LOG_EVENT_TYPE_TIMING = new Set([
|
||||||
|
|
@ -77,6 +92,7 @@ export const LOG_EVENT_TYPE_TIMING = new Set([
|
||||||
LOG_ACTIONS_RENDER_CHART,
|
LOG_ACTIONS_RENDER_CHART,
|
||||||
LOG_ACTIONS_HIDE_BROWSER_TAB,
|
LOG_ACTIONS_HIDE_BROWSER_TAB,
|
||||||
LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY,
|
LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY,
|
||||||
|
LOG_ACTIONS_SQLLAB_LOAD_TAB_STATE,
|
||||||
]);
|
]);
|
||||||
export const LOG_EVENT_TYPE_USER = new Set([
|
export const LOG_EVENT_TYPE_USER = new Set([
|
||||||
LOG_ACTIONS_MOUNT_DASHBOARD,
|
LOG_ACTIONS_MOUNT_DASHBOARD,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import configureStore from 'redux-mock-store';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
|
import { renderHook } from '@testing-library/react-hooks';
|
||||||
|
import { createWrapper } from 'spec/helpers/testing-library';
|
||||||
|
import useLogAction from './useLogAction';
|
||||||
|
import { LOG_ACTIONS_SQLLAB_COPY_LINK } from './LogUtils';
|
||||||
|
import { LOG_EVENT } from './actions';
|
||||||
|
|
||||||
|
const middlewares = [thunk];
|
||||||
|
const mockStore = configureStore(middlewares);
|
||||||
|
|
||||||
|
test('dispatches logEvent action with static EventData', () => {
|
||||||
|
const staticEventData = { staticEventKey: 'value1' };
|
||||||
|
const store = mockStore();
|
||||||
|
const { result } = renderHook(() => useLogAction(staticEventData), {
|
||||||
|
wrapper: createWrapper({
|
||||||
|
useRedux: true,
|
||||||
|
store,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
result.current(LOG_ACTIONS_SQLLAB_COPY_LINK, { count: 1 });
|
||||||
|
store.getActions();
|
||||||
|
expect(store.getActions()).toEqual([
|
||||||
|
{
|
||||||
|
type: LOG_EVENT,
|
||||||
|
payload: {
|
||||||
|
eventName: LOG_ACTIONS_SQLLAB_COPY_LINK,
|
||||||
|
eventData: {
|
||||||
|
payload: {
|
||||||
|
...staticEventData,
|
||||||
|
count: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { logEvent } from 'src/logger/actions';
|
||||||
|
|
||||||
|
export default function useLogAction(staticEventData: Record<string, any>) {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const logAction = useCallback<typeof logEvent>(
|
||||||
|
(type, payload) =>
|
||||||
|
dispatch(
|
||||||
|
logEvent(type, {
|
||||||
|
payload: {
|
||||||
|
...staticEventData,
|
||||||
|
...payload,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
[staticEventData, dispatch],
|
||||||
|
);
|
||||||
|
|
||||||
|
return logAction;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue