This is an automated email from the ASF dual-hosted git repository.
justinpark pushed a commit to branch 4.1-airbnb
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/4.1-airbnb by this push:
new 0d564a1ba5 fix(log): store navigation path to get correct logging path
(#32795)
0d564a1ba5 is described below
commit 0d564a1ba5c707d687086accd89dcfdbb12f2149
Author: JUST.in DO IT <[email protected]>
AuthorDate: Tue Mar 25 10:18:55 2025 -0700
fix(log): store navigation path to get correct logging path (#32795)
(cherry picked from commit 4a70065e5f6840fbcd657f50045c825a7b1d58d6)
(cherry picked from commit fd44f705283e0f8de86ea2fc481066ccd45a2362)
---
superset-frontend/src/middleware/logger.test.js | 33 +++--
.../src/middleware/loggerMiddleware.js | 140 +++++++++++----------
2 files changed, 99 insertions(+), 74 deletions(-)
diff --git a/superset-frontend/src/middleware/logger.test.js
b/superset-frontend/src/middleware/logger.test.js
index 5d51649e00..342ca44b17 100644
--- a/superset-frontend/src/middleware/logger.test.js
+++ b/superset-frontend/src/middleware/logger.test.js
@@ -20,7 +20,10 @@ import sinon from 'sinon';
import { SupersetClient } from '@superset-ui/core';
import logger from 'src/middleware/loggerMiddleware';
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', () => {
const dashboardId = 123;
@@ -40,11 +43,14 @@ describe('logger middleware', () => {
eventData: {
key: 'value',
start_offset: 100,
- path: `/dashboard/${dashboardId}/`,
},
},
};
+ const timeSandbox = sinon.createSandbox({
+ useFakeTimers: true,
+ });
+
let postStub;
beforeEach(() => {
postStub = sinon.stub(SupersetClient, 'post');
@@ -52,6 +58,7 @@ describe('logger middleware', () => {
afterEach(() => {
next.resetHistory();
postStub.restore();
+ timeSandbox.clock.reset();
});
it('should listen to LOG_EVENT action type', () => {
@@ -66,11 +73,10 @@ describe('logger middleware', () => {
});
it('should POST an event to /superset/log/ when called', () => {
- const clock = sinon.useFakeTimers();
logger(mockStore)(next)(action);
expect(next.callCount).toBe(0);
- clock.tick(2000);
+ timeSandbox.clock.tick(2000);
expect(SupersetClient.post.callCount).toBe(1);
expect(SupersetClient.post.getCall(0).args[0].endpoint).toMatch(
'/superset/log/',
@@ -78,12 +84,19 @@ describe('logger middleware', () => {
});
it('should include ts, start_offset, event_name, impression_id, source, and
source_id in every event', () => {
- const clock = sinon.useFakeTimers();
- logger(mockStore)(next)(action);
- clock.tick(2000);
-
- expect(SupersetClient.post.callCount).toBe(1);
- const { events } = SupersetClient.post.getCall(0).args[0].postPayload;
+ const fetchLog = logger(mockStore)(next);
+ fetchLog({
+ type: LOG_EVENT,
+ payload: {
+ eventName: LOG_ACTIONS_SPA_NAVIGATION,
+ eventData: { path: `/dashboard/${dashboardId}/` },
+ },
+ });
+ timeSandbox.clock.tick(2000);
+ fetchLog(action);
+ timeSandbox.clock.tick(2000);
+ expect(SupersetClient.post.callCount).toBe(2);
+ const { events } = SupersetClient.post.getCall(1).args[0].postPayload;
const mockEventdata = action.payload.eventData;
const mockEventname = action.payload.eventName;
expect(events[0]).toMatchObject({
diff --git a/superset-frontend/src/middleware/loggerMiddleware.js
b/superset-frontend/src/middleware/loggerMiddleware.js
index a3eb629571..c008d027b3 100644
--- a/superset-frontend/src/middleware/loggerMiddleware.js
+++ b/superset-frontend/src/middleware/loggerMiddleware.js
@@ -23,7 +23,10 @@ import { SupersetClient } from '@superset-ui/core';
import { safeStringify } from '../utils/safeStringify';
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';
const LOG_ENDPOINT = '/superset/log/?explode=events';
@@ -67,78 +70,87 @@ const logMessageQueue = new DebouncedMessageQueue({
delayThreshold: 1000,
});
let lastEventId = 0;
-const loggerMiddleware = store => next => action => {
- if (action.type !== LOG_EVENT) {
- return next(action);
- }
+const loggerMiddleware = store => next => {
+ let navPath;
+ return action => {
+ if (action.type !== LOG_EVENT) {
+ return next(action);
+ }
- const { dashboardInfo, explore, impressionId, dashboardLayout, sqlLab } =
- store.getState();
- let logMetadata = {
- impression_id: impressionId,
- version: 'v2',
- };
- const { eventName } = action.payload;
- let { eventData = {} } = action.payload;
+ const { dashboardInfo, explore, impressionId, dashboardLayout, sqlLab } =
+ store.getState();
+ let logMetadata = {
+ impression_id: impressionId,
+ version: 'v2',
+ };
+ const { eventName } = action.payload;
+ let { eventData = {} } = action.payload;
- const path = eventData.path || window?.location?.href;
+ if (eventName === LOG_ACTIONS_SPA_NAVIGATION) {
+ navPath = eventData.path;
+ }
+ const path = navPath || 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) {
- 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,
- };
- }
+ if (dashboardInfo?.id && path?.includes('/dashboard/')) {
+ logMetadata = {
+ source: 'dashboard',
+ source_id: dashboardInfo.id,
+ dashboard_id: dashboardInfo.id,
+ ...logMetadata,
+ };
+ } 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,
- event_type: 'timing',
- trigger_event: lastEventId,
- };
- } else {
- lastEventId = nanoid();
eventData = {
+ ...logMetadata,
+ ts: new Date().getTime(),
+ event_name: eventName,
...eventData,
- event_type: 'user',
- event_id: lastEventId,
- visibility: document.visibilityState,
};
- }
+ if (LOG_EVENT_TYPE_TIMING.has(eventName)) {
+ eventData = {
+ ...eventData,
+ event_type: 'timing',
+ trigger_event: lastEventId,
+ };
+ } else {
+ lastEventId = nanoid();
+ eventData = {
+ ...eventData,
+ event_type: 'user',
+ event_id: lastEventId,
+ visibility: document.visibilityState,
+ };
+ }
- if (eventData.target_id && dashboardLayout?.present?.[eventData.target_id]) {
- const { meta } = dashboardLayout.present[eventData.target_id];
- // chart name or tab/header text
- eventData.target_name = meta.chartId ? meta.sliceName : meta.text;
- }
+ if (
+ eventData.target_id &&
+ dashboardLayout?.present?.[eventData.target_id]
+ ) {
+ 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);
- return eventData;
+ logMessageQueue.append(eventData);
+ return eventData;
+ };
};
export default loggerMiddleware;