From 3277ea83ea2f805eeefd445fd8c61ef2a7e6a364 Mon Sep 17 00:00:00 2001 From: "JUST.in DO IT" Date: Mon, 20 Mar 2023 10:08:27 -0700 Subject: [PATCH] feat(sqllab): log error_detail on fetch failed (#23377) --- .../src/SqlLab/actions/sqlLab.js | 22 ++++++++++++++ .../src/SqlLab/actions/sqlLab.test.js | 29 +++++++++++++++---- superset-frontend/src/logger/LogUtils.ts | 3 ++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index c27485879b8cd..da0bc2dc5b085 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -32,6 +32,8 @@ import { } from 'src/components/MessageToasts/actions'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import COMMON_ERR_MESSAGES from 'src/utils/errorMessages'; +import { LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY } from 'src/logger/LogUtils'; +import { logEvent } from 'src/logger/actions'; import { newQueryTabName } from '../utils/newQueryTabName'; export const RESET_STATE = 'RESET_STATE'; @@ -269,6 +271,26 @@ export function queryFailed(query, msg, link, errors) { }) : Promise.resolve(); + const eventData = { + has_err: true, + start_offset: query.startDttm, + ts: new Date().getTime(), + }; + errors?.forEach(({ error_type: errorType, extra }) => { + const messages = extra?.issue_codes.map(({ message }) => message) || [ + errorType, + ]; + messages.forEach(message => { + dispatch( + logEvent(LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY, { + ...eventData, + error_type: errorType, + error_details: message, + }), + ); + }); + }); + return ( sync .catch(() => diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.test.js b/superset-frontend/src/SqlLab/actions/sqlLab.test.js index 63711550b2485..3aedf3b255609 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.test.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.test.js @@ -24,6 +24,7 @@ import thunk from 'redux-thunk'; import shortid from 'shortid'; import * as featureFlags from 'src/featureFlags'; import * as actions from 'src/SqlLab/actions/sqlLab'; +import { LOG_EVENT } from 'src/logger/actions'; import { defaultQueryEditor, query, @@ -240,22 +241,38 @@ describe('async actions', () => { }); }); - it('calls queryFailed on fetch error', () => { - expect.assertions(1); + it('calls queryFailed on fetch error and logs the error details', () => { + expect.assertions(3); fetchMock.post( runQueryEndpoint, - { throws: { message: 'error text' } }, + { + throws: { + message: 'error text', + timeout: true, + statusText: 'timeout', + }, + }, { overwriteRoutes: true }, ); const store = mockStore({}); - const expectedActionTypes = [actions.START_QUERY, actions.QUERY_FAILED]; + const expectedActionTypes = [ + actions.START_QUERY, + LOG_EVENT, + LOG_EVENT, + actions.QUERY_FAILED, + ]; const { dispatch } = store; const request = actions.runQuery(query); return request(dispatch, () => initialState).then(() => { - expect(store.getActions().map(a => a.type)).toEqual( - expectedActionTypes, + const actions = store.getActions(); + expect(actions.map(a => a.type)).toEqual(expectedActionTypes); + expect(actions[1].payload.eventData.error_details).toContain( + 'Issue 1000', + ); + expect(actions[2].payload.eventData.error_details).toContain( + 'Issue 1001', ); }); }); diff --git a/superset-frontend/src/logger/LogUtils.ts b/superset-frontend/src/logger/LogUtils.ts index 5c4c05e4f09bc..1e67400520eae 100644 --- a/superset-frontend/src/logger/LogUtils.ts +++ b/superset-frontend/src/logger/LogUtils.ts @@ -52,12 +52,15 @@ export const LOG_ACTIONS_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'; +export const LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY = + 'sqllab_fetch_failed_query'; // Log event types -------------------------------------------------------------- export const LOG_EVENT_TYPE_TIMING = new Set([ LOG_ACTIONS_LOAD_CHART, LOG_ACTIONS_RENDER_CHART, LOG_ACTIONS_HIDE_BROWSER_TAB, + LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY, ]); export const LOG_EVENT_TYPE_USER = new Set([ LOG_ACTIONS_MOUNT_DASHBOARD,