From 5761179ad9b4d005c392258408ec6269070c33fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Mon, 3 Jun 2019 13:40:33 +0200 Subject: [PATCH] Feature: Adds redux action logging toggle from url params (#17368) With live tailing introduced in Explore we now have a lot of actions dispatching and the Redux Dev Tools doesn't cope with the amount and rate of actions and crashes. This PR turns on redux action logging when you add logActions=true in the url and turns it off if you refresh the page or add logActions=false in the url. --- public/app/core/actions/application.ts | 3 +++ public/app/core/middlewares/application.ts | 27 ++++++++++++++++++++++ public/app/core/reducers/application.ts | 17 ++++++++++++++ public/app/core/reducers/index.ts | 2 ++ public/app/store/configureStore.ts | 22 ++++++++++-------- public/app/types/application.ts | 3 +++ public/app/types/store.ts | 2 ++ 7 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 public/app/core/actions/application.ts create mode 100644 public/app/core/middlewares/application.ts create mode 100644 public/app/core/reducers/application.ts create mode 100644 public/app/types/application.ts diff --git a/public/app/core/actions/application.ts b/public/app/core/actions/application.ts new file mode 100644 index 00000000000..9bde989e8ca --- /dev/null +++ b/public/app/core/actions/application.ts @@ -0,0 +1,3 @@ +import { noPayloadActionCreatorFactory } from 'app/core/redux'; + +export const toggleLogActions = noPayloadActionCreatorFactory('TOGGLE_LOG_ACTIONS').create(); diff --git a/public/app/core/middlewares/application.ts b/public/app/core/middlewares/application.ts new file mode 100644 index 00000000000..3ca9768d626 --- /dev/null +++ b/public/app/core/middlewares/application.ts @@ -0,0 +1,27 @@ +import { Store, Dispatch } from 'redux'; +import { StoreState } from 'app/types/store'; +import { ActionOf } from '../redux/actionCreatorFactory'; +import { toggleLogActions } from '../actions/application'; + +export const toggleLogActionsMiddleware = (store: Store) => (next: Dispatch) => (action: ActionOf) => { + const isLogActionsAction = action.type === toggleLogActions.type; + if (isLogActionsAction) { + return next(action); + } + + const logActionsTrue = + window && window.location && window.location.search && window.location.search.indexOf('logActions=true') !== -1; + const logActionsFalse = + window && window.location && window.location.search && window.location.search.indexOf('logActions=false') !== -1; + const logActions = store.getState().application.logActions; + + if (logActionsTrue && !logActions) { + store.dispatch(toggleLogActions()); + } + + if (logActionsFalse && logActions) { + store.dispatch(toggleLogActions()); + } + + return next(action); +}; diff --git a/public/app/core/reducers/application.ts b/public/app/core/reducers/application.ts new file mode 100644 index 00000000000..458f4931619 --- /dev/null +++ b/public/app/core/reducers/application.ts @@ -0,0 +1,17 @@ +import { ApplicationState } from 'app/types/application'; +import { reducerFactory } from 'app/core/redux'; +import { toggleLogActions } from '../actions/application'; + +export const initialState: ApplicationState = { + logActions: false, +}; + +export const applicationReducer = reducerFactory(initialState) + .addMapper({ + filter: toggleLogActions, + mapper: (state): ApplicationState => ({ + ...state, + logActions: !state.logActions, + }), + }) + .create(); diff --git a/public/app/core/reducers/index.ts b/public/app/core/reducers/index.ts index 1c8670ed0d6..cc0c950ec4a 100644 --- a/public/app/core/reducers/index.ts +++ b/public/app/core/reducers/index.ts @@ -1,9 +1,11 @@ import { navIndexReducer as navIndex } from './navModel'; import { locationReducer as location } from './location'; import { appNotificationsReducer as appNotifications } from './appNotification'; +import { applicationReducer as application } from './application'; export default { navIndex, location, appNotifications, + application, }; diff --git a/public/app/store/configureStore.ts b/public/app/store/configureStore.ts index e561a7f5e59..2d7d3288d3b 100644 --- a/public/app/store/configureStore.ts +++ b/public/app/store/configureStore.ts @@ -1,7 +1,7 @@ import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; import thunk from 'redux-thunk'; import { combineEpics, createEpicMiddleware } from 'redux-observable'; -// import { createLogger } from 'redux-logger'; +import { createLogger } from 'redux-logger'; import sharedReducers from 'app/core/reducers'; import alertingReducers from 'app/features/alerting/state/reducers'; import teamsReducers from 'app/features/teams/state/reducers'; @@ -17,6 +17,8 @@ import organizationReducers from 'app/features/org/state/reducers'; import { setStore } from './store'; import { startSubscriptionsEpic, startSubscriptionEpic, limitMessageRateEpic } from 'app/features/explore/state/epics'; import { WebSocketSubject, webSocket } from 'rxjs/webSocket'; +import { StoreState } from 'app/types/store'; +import { toggleLogActionsMiddleware } from 'app/core/middlewares/application'; const rootReducers = { ...sharedReducers, @@ -51,15 +53,17 @@ const epicMiddleware = createEpicMiddleware({ dependencies }); export function configureStore() { const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; - const rootReducer = combineReducers(rootReducers); + const logger = createLogger({ + predicate: (getState: () => StoreState) => { + return getState().application.logActions; + }, + }); + const storeEnhancers = + process.env.NODE_ENV !== 'production' + ? applyMiddleware(toggleLogActionsMiddleware, thunk, epicMiddleware, logger) + : applyMiddleware(thunk, epicMiddleware); - if (process.env.NODE_ENV !== 'production') { - // DEV builds we had the logger middleware - setStore(createStore(rootReducer, {}, composeEnhancers(applyMiddleware(thunk, epicMiddleware)))); - } else { - setStore(createStore(rootReducer, {}, composeEnhancers(applyMiddleware(thunk, epicMiddleware)))); - } - + setStore(createStore(rootReducer, {}, composeEnhancers(storeEnhancers))); epicMiddleware.run(rootEpic); } diff --git a/public/app/types/application.ts b/public/app/types/application.ts new file mode 100644 index 00000000000..d4562d68c44 --- /dev/null +++ b/public/app/types/application.ts @@ -0,0 +1,3 @@ +export interface ApplicationState { + logActions: boolean; +} diff --git a/public/app/types/store.ts b/public/app/types/store.ts index 975cd40ae71..66a3db1a3cb 100644 --- a/public/app/types/store.ts +++ b/public/app/types/store.ts @@ -13,6 +13,7 @@ import { OrganizationState } from './organization'; import { AppNotificationsState } from './appNotifications'; import { PluginsState } from './plugins'; import { NavIndex } from '@grafana/ui'; +import { ApplicationState } from './application'; export interface StoreState { navIndex: NavIndex; @@ -29,6 +30,7 @@ export interface StoreState { appNotifications: AppNotificationsState; user: UserState; plugins: PluginsState; + application: ApplicationState; } /*