ayush-sharaf opened a new issue, #42564: URL: https://github.com/apache/superset/issues/42564
### Bug description `change_dashboard_filter` is dispatched for native dashboard filters with an empty payload, so the log records *that* filters changed but never *what* they were changed to. https://github.com/apache/superset/blob/master/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx#L432 ```js const handleApply = useCallback(() => { dispatch(logEvent(LOG_ACTIONS_CHANGE_DASHBOARD_FILTER, {})); ``` `dataMaskSelected` — the filter state being applied — is in scope on the very next lines and is discarded. The cross-filter path does carry context by comparison, though only column names: https://github.com/apache/superset/blob/master/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.tsx#L297 ```js boundActionCreators.logEvent(LOG_ACTIONS_CHANGE_DASHBOARD_FILTER, { id: chart?.id, columns: vals !== null ? [col] : [], }); ``` A resulting row from a real session looks like this — every field is either envelope or session context, nothing about the filter: ```json {"impression_id": "6K_whEgrMNwJ2mlbS1LfA", "version": "v2", "ts": 1784877876239, "event_name": "change_dashboard_filter", "event_type": "user", "event_id": "qtmRj8G_fYdzeH54kRncH", "visibility": "visible"} ``` Relatedly, `select_dashboard_tab` carries `{target_id, index, target_name}`, so there is also no way to know which filters were active when a user viewed a given tab. ### Why it cannot be reconstructed downstream Two workarounds that look plausible but don't hold: **Resolve the filter state from a permalink.** Not available for embedded dashboards — the data mask is only published when a real user id is present: https://github.com/apache/superset/blob/master/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx#L409 ```js // embedded users can't persist filter combinations if (user?.userId) { publishDataMask(history, dashboardId, updateKey, dataMaskApplied, tabId); } ``` so embedded referrers carry no `native_filters_key` and there is nothing to look up. **Read the filters back out of `ChartDataRestApi.data`.** The native filter contribution is merged into the same `form_data.filters` array as the chart's own saved adhoc filters, with nothing marking which is which. A real payload: ```json "filters": [ {"col": "status", "op": "==", "val": "done"}, {"col": "user_id", "op": "IS NOT NULL"}, {"col": "task_created_date", "op": "TEMPORAL_RANGE", "val": "No filter"} ] ``` Only the third entry comes from the dashboard filter bar; the first two are saved on the chart. Separating them requires diffing against each chart's stored `params`, and charts served from cache emit no request at all, so the reconstruction is both approximate and incomplete. ### How to reproduce 1. Open a dashboard with a native filter. 2. Select a filter value and click **Apply**. 3. Inspect the `logs` table (or the `/superset/log/` request payload) for the `change_dashboard_filter` event. 4. The event is present, but contains no reference to the filter or the selected value. ### Expected results The event carries the applied filter state — at minimum the filter name and the selected value(s) — so downstream consumers can tell what was filtered. ### Actual results The payload is `{}` plus the standard envelope. ### Possible approaches **A. Enrich at the dispatch site (smallest change).** Pass a compact projection of `dataMaskSelected` in `handleApply`, e.g. `[{ id, name, value }]` per active filter. Authoritative, since it is exactly the state being applied, and local to one call site. **B. Enrich in `loggerMiddleware` for an allowlist of events.** The middleware already reads the store but does not pull the filter slices: https://github.com/apache/superset/blob/master/superset-frontend/src/middleware/loggerMiddleware.ts#L158 ```js const { dashboardInfo, explore, impressionId, dashboardLayout, sqlLab } = store.getState(); ``` `dataMask` and `nativeFilters` are in the same store. Filter names are at `nativeFilters.filters[id].name` and selected values at `dataMask[id].filterState.value`, so a compact `applied_filters` array can be attached generically. This also covers the second half of the problem: it would give `select_dashboard_tab` (and other user events) the filter context in effect at the time. This should be gated to a small allowlist rather than applied to every event — `load_chart` fires per chart per render and would balloon. A and B are complementary: A gives an explicit "filters were changed to X" event, B gives "this view happened under filters X". **C. Reconstruct server-side.** Ruled out for the reasons above; noting it so it isn't re-proposed. ### Considerations Filter values are user data and can be sensitive depending on the deployment (names, identifiers, free text). It may be worth making the value capture configurable, or defaulting to filter names plus a set/unset flag and recording values only when explicitly enabled. ### Environment - superset: `master` (line references above are against master; also reproduces on 6.0.1) - browser: any ### Additional context Observed while building an audit trail over the log table for embedded dashboards. Related: #42562 (Drill to Detail emitted no log event). Happy to open a PR for A, B, or both — would appreciate a maintainer's preference on the shape of the payload and on whether value capture should be configurable before I do. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
