fix(log): store navigation path to get correct logging path (#32795)

(cherry picked from commit 4a70065e5f)
This commit is contained in:
JUST.in DO IT
2025-03-25 10:18:55 -07:00
committed by Michael S. Molina
parent 7ed236170d
commit e593bc0a2e
2 changed files with 93 additions and 71 deletions

View File

@@ -20,7 +20,10 @@ import sinon from 'sinon';
import { SupersetClient } from '@superset-ui/core'; import { SupersetClient } from '@superset-ui/core';
import logger from 'src/middleware/loggerMiddleware'; import logger from 'src/middleware/loggerMiddleware';
import { LOG_EVENT } from 'src/logger/actions'; import { LOG_EVENT } from 'src/logger/actions';
import { LOG_ACTIONS_LOAD_CHART } from 'src/logger/LogUtils'; import {
LOG_ACTIONS_LOAD_CHART,
LOG_ACTIONS_SPA_NAVIGATION,
} from 'src/logger/LogUtils';
describe('logger middleware', () => { describe('logger middleware', () => {
const dashboardId = 123; const dashboardId = 123;
@@ -40,7 +43,6 @@ describe('logger middleware', () => {
eventData: { eventData: {
key: 'value', key: 'value',
start_offset: 100, start_offset: 100,
path: `/dashboard/${dashboardId}/`,
}, },
}, },
}; };
@@ -82,11 +84,19 @@ describe('logger middleware', () => {
}); });
it('should include ts, start_offset, event_name, impression_id, source, and source_id in every event', () => { it('should include ts, start_offset, event_name, impression_id, source, and source_id in every event', () => {
logger(mockStore)(next)(action); const fetchLog = logger(mockStore)(next);
fetchLog({
type: LOG_EVENT,
payload: {
eventName: LOG_ACTIONS_SPA_NAVIGATION,
eventData: { path: `/dashboard/${dashboardId}/` },
},
});
timeSandbox.clock.tick(2000); timeSandbox.clock.tick(2000);
fetchLog(action);
expect(SupersetClient.post.callCount).toBe(1); timeSandbox.clock.tick(2000);
const { events } = SupersetClient.post.getCall(0).args[0].postPayload; expect(SupersetClient.post.callCount).toBe(2);
const { events } = SupersetClient.post.getCall(1).args[0].postPayload;
const mockEventdata = action.payload.eventData; const mockEventdata = action.payload.eventData;
const mockEventname = action.payload.eventName; const mockEventname = action.payload.eventName;
expect(events[0]).toMatchObject({ expect(events[0]).toMatchObject({

View File

@@ -23,7 +23,10 @@ import { SupersetClient } from '@superset-ui/core';
import { safeStringify } from '../utils/safeStringify'; import { safeStringify } from '../utils/safeStringify';
import { LOG_EVENT } from '../logger/actions'; import { LOG_EVENT } from '../logger/actions';
import { LOG_EVENT_TYPE_TIMING } from '../logger/LogUtils'; import {
LOG_EVENT_TYPE_TIMING,
LOG_ACTIONS_SPA_NAVIGATION,
} from '../logger/LogUtils';
import DebouncedMessageQueue from '../utils/DebouncedMessageQueue'; import DebouncedMessageQueue from '../utils/DebouncedMessageQueue';
const LOG_ENDPOINT = '/superset/log/?explode=events'; const LOG_ENDPOINT = '/superset/log/?explode=events';
@@ -67,78 +70,87 @@ const logMessageQueue = new DebouncedMessageQueue({
delayThreshold: 1000, delayThreshold: 1000,
}); });
let lastEventId = 0; let lastEventId = 0;
const loggerMiddleware = store => next => action => { const loggerMiddleware = store => next => {
if (action.type !== LOG_EVENT) { let navPath;
return next(action); return action => {
} if (action.type !== LOG_EVENT) {
return next(action);
}
const { dashboardInfo, explore, impressionId, dashboardLayout, sqlLab } = const { dashboardInfo, explore, impressionId, dashboardLayout, sqlLab } =
store.getState(); store.getState();
let logMetadata = { let logMetadata = {
impression_id: impressionId, impression_id: impressionId,
version: 'v2', version: 'v2',
};
const { eventName } = action.payload;
let { eventData = {} } = action.payload;
const path = eventData.path || window?.location?.href;
if (dashboardInfo?.id && path?.includes('/dashboard/')) {
logMetadata = {
source: 'dashboard',
source_id: dashboardInfo.id,
dashboard_id: dashboardInfo.id,
...logMetadata,
}; };
} else if (explore?.slice) { const { eventName } = action.payload;
logMetadata = { let { eventData = {} } = action.payload;
source: 'explore',
source_id: explore.slice ? explore.slice.slice_id : 0, if (eventName === LOG_ACTIONS_SPA_NAVIGATION) {
...(explore.slice.slice_id && { slice_id: explore.slice.slice_id }), navPath = eventData.path;
...logMetadata, }
}; const path = navPath || window?.location?.href;
} else if (path?.includes('/sqllab/')) {
const editor = sqlLab.queryEditors.find( if (dashboardInfo?.id && path?.includes('/dashboard/')) {
({ id }) => id === sqlLab.tabHistory.slice(-1)[0], logMetadata = {
); source: 'dashboard',
logMetadata = { source_id: dashboardInfo.id,
source: 'sqlLab', dashboard_id: dashboardInfo.id,
source_id: editor?.id, ...logMetadata,
db_id: editor?.dbId, };
schema: editor?.schema, } else if (explore?.slice) {
}; logMetadata = {
} source: 'explore',
source_id: explore.slice ? explore.slice.slice_id : 0,
...(explore.slice.slice_id && { slice_id: explore.slice.slice_id }),
...logMetadata,
};
} else if (path?.includes('/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,
};
}
eventData = {
...logMetadata,
ts: new Date().getTime(),
event_name: eventName,
...eventData,
};
if (LOG_EVENT_TYPE_TIMING.has(eventName)) {
eventData = { eventData = {
...logMetadata,
ts: new Date().getTime(),
event_name: eventName,
...eventData, ...eventData,
event_type: 'timing',
trigger_event: lastEventId,
}; };
} else { if (LOG_EVENT_TYPE_TIMING.has(eventName)) {
lastEventId = nanoid(); eventData = {
eventData = { ...eventData,
...eventData, event_type: 'timing',
event_type: 'user', trigger_event: lastEventId,
event_id: lastEventId, };
visibility: document.visibilityState, } else {
}; lastEventId = nanoid();
} eventData = {
...eventData,
event_type: 'user',
event_id: lastEventId,
visibility: document.visibilityState,
};
}
if (eventData.target_id && dashboardLayout?.present?.[eventData.target_id]) { if (
const { meta } = dashboardLayout.present[eventData.target_id]; eventData.target_id &&
// chart name or tab/header text dashboardLayout?.present?.[eventData.target_id]
eventData.target_name = meta.chartId ? meta.sliceName : meta.text; ) {
} const { meta } = dashboardLayout.present[eventData.target_id];
// chart name or tab/header text
eventData.target_name = meta.chartId ? meta.sliceName : meta.text;
}
logMessageQueue.append(eventData); logMessageQueue.append(eventData);
return eventData; return eventData;
};
}; };
export default loggerMiddleware; export default loggerMiddleware;