{"id":14958046,"url":"https://github.com/logrocket/redux-logger","last_synced_at":"2025-05-13T15:12:15.304Z","repository":{"id":36264167,"uuid":"40568608","full_name":"LogRocket/redux-logger","owner":"LogRocket","description":"Logger for Redux","archived":false,"fork":false,"pushed_at":"2020-08-20T16:46:14.000Z","size":416,"stargazers_count":5755,"open_issues_count":59,"forks_count":318,"subscribers_count":60,"default_branch":"master","last_synced_at":"2025-05-07T07:49:05.892Z","etag":null,"topics":["angular","react","redux","redux-logger","redux-middleware"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LogRocket.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-11T22:38:12.000Z","updated_at":"2025-05-01T12:16:48.000Z","dependencies_parsed_at":"2022-07-29T21:09:49.537Z","dependency_job_id":null,"html_url":"https://github.com/LogRocket/redux-logger","commit_stats":null,"previous_names":["theaqua/redux-logger","fcomb/redux-logger","evgenyrodionov/redux-logger"],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LogRocket%2Fredux-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LogRocket%2Fredux-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LogRocket%2Fredux-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LogRocket%2Fredux-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LogRocket","download_url":"https://codeload.github.com/LogRocket/redux-logger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253969264,"owners_count":21992263,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","react","redux","redux-logger","redux-middleware"],"created_at":"2024-09-24T13:16:04.680Z","updated_at":"2025-05-13T15:12:10.292Z","avatar_url":"https://github.com/LogRocket.png","language":"JavaScript","readme":"# Logger for Redux\n[![npm](https://img.shields.io/npm/v/redux-logger.svg?maxAge=2592000?style=plastic)](https://www.npmjs.com/package/redux-logger)\n[![npm](https://img.shields.io/npm/dm/redux-logger.svg?maxAge=2592000?style=plastic)](https://www.npmjs.com/package/redux-logger)\n[![Build Status](https://circleci.com/gh/LogRocket/redux-logger/tree/master.svg?style=svg)](https://circleci.com/gh/LogRocket/redux-logger/tree/master)\n\n![redux-logger](http://i.imgur.com/CgAuHlE.png)\n\nNow maintained by [LogRocket](https://logrocket.com?cid=github_redux)!\n\n[![](https://i.imgur.com/Yp5mUx2.png)](https://logrocket.com?cid=github_redux)\n\n\u003e LogRocket is a production Redux logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay Redux actions + state, network requests, console logs, and see a video of what the user saw.\n\nFor more informatiom about the future of redux-logger, check out the [discussion here](https://github.com/LogRocket/redux-logger/issues/314).\n\n## Table of contents\n* [Install](#install)\n* [Usage](#usage)\n* [Options](#options)\n* [Recipes](#recipes)\n  * [Log only in development](#log-only-in-development)\n  * [Log everything except actions with certain type](#log-everything-except-actions-with-certain-type)\n  * [Collapse actions with certain type](#collapse-actions-with-certain-type)\n  * [Transform Immutable (without `combineReducers`)](#transform-immutable-without-combinereducers)\n  * [Transform Immutable (with `combineReducers`)](#transform-immutable-with-combinereducers)\n  * [Log batched actions](#log-batched-actions)\n* [To Do](#to-do)\n* [Known issues](#known-issues) (with `react-native` only at this moment)\n* [License](#license)\n\n## Install\n`npm i --save redux-logger`\n\nTypescript types are also available, via [DefinitelyTyped](https://www.npmjs.com/package/@types/redux-logger):\n\n`npm i @types/redux-logger`\n\n## Usage\n```javascript\nimport { applyMiddleware, createStore } from 'redux';\n\n// Logger with default options\nimport logger from 'redux-logger'\nconst store = createStore(\n  reducer,\n  applyMiddleware(logger)\n)\n\n// Note passing middleware as the third argument requires redux@\u003e=3.1.0\n```\n\nOr you can create your own logger with custom [options](https://github.com/LogRocket/redux-logger#options):\n```javascript\nimport { applyMiddleware, createStore } from 'redux';\nimport { createLogger } from 'redux-logger'\n\nconst logger = createLogger({\n  // ...options\n});\n\nconst store = createStore(\n  reducer,\n  applyMiddleware(logger)\n);\n```\n\nNote: logger **must be** the last middleware in chain, otherwise it will log thunk and promise, not actual actions ([#20](https://github.com/LogRocket/redux-logger/issues/20)).\n\n## Options\n```javascript\n{\n  predicate, // if specified this function will be called before each action is processed with this middleware.\n  collapsed, // takes a Boolean or optionally a Function that receives `getState` function for accessing current store state and `action` object as parameters. Returns `true` if the log group should be collapsed, `false` otherwise.\n  duration = false: Boolean, // print the duration of each action?\n  timestamp = true: Boolean, // print the timestamp with each action?\n\n  level = 'log': 'log' | 'console' | 'warn' | 'error' | 'info', // console's level\n  colors: ColorsObject, // colors for title, prev state, action and next state: https://github.com/LogRocket/redux-logger/blob/master/src/defaults.js#L12-L18\n  titleFormatter, // Format the title used when logging actions.\n\n  stateTransformer, // Transform state before print. Eg. convert Immutable object to plain JSON.\n  actionTransformer, // Transform action before print. Eg. convert Immutable object to plain JSON.\n  errorTransformer, // Transform error before print. Eg. convert Immutable object to plain JSON.\n\n  logger = console: LoggerObject, // implementation of the `console` API.\n  logErrors = true: Boolean, // should the logger catch, log, and re-throw errors?\n\n  diff = false: Boolean, // (alpha) show diff between states?\n  diffPredicate // (alpha) filter function for showing states diff, similar to `predicate`\n}\n```\n\n### Options description\n\n#### __level (String | Function | Object)__\nLevel of `console`. `warn`, `error`, `info` or [else](https://developer.mozilla.org/en/docs/Web/API/console).\n\nIt can be a function `(action: Object) =\u003e level: String`.\n\nIt can be an object with level string for: `prevState`, `action`, `nextState`, `error`\n\nIt can be an object with getter functions: `prevState`, `action`, `nextState`, `error`. Useful if you want to print\nmessage based on specific state or action. Set any of them to `false` if you want to hide it.\n\n* `prevState(prevState: Object) =\u003e level: String`\n* `action(action: Object) =\u003e level: String`\n* `nextState(nextState: Object) =\u003e level: String`\n* `error(error: Any, prevState: Object) =\u003e level: String`\n\n*Default: `log`*\n\n#### __duration (Boolean)__\nPrint duration of each action?\n\n*Default: `false`*\n\n#### __timestamp (Boolean)__\nPrint timestamp with each action?\n\n*Default: `true`*\n\n#### __colors (Object)__\nObject with color getter functions: `title`, `prevState`, `action`, `nextState`, `error`. Useful if you want to paint\nmessage based on specific state or action. Set any of them to `false` if you want to show plain message without colors.\n\n* `title(action: Object) =\u003e color: String`\n* `prevState(prevState: Object) =\u003e color: String`\n* `action(action: Object) =\u003e color: String`\n* `nextState(nextState: Object) =\u003e color: String`\n* `error(error: Any, prevState: Object) =\u003e color: String`\n\n#### __logger (Object)__\nImplementation of the `console` API. Useful if you are using a custom, wrapped version of `console`.\n\n*Default: `console`*\n\n#### __logErrors (Boolean)__\nShould the logger catch, log, and re-throw errors? This makes it clear which action triggered the error but makes \"break\non error\" in dev tools harder to use, as it breaks on re-throw rather than the original throw location.\n\n*Default: `true`*\n\n#### __collapsed = (getState: Function, action: Object, logEntry: Object) =\u003e Boolean__\nTakes a boolean or optionally a function that receives `getState` function for accessing current store state and `action` object as parameters. Returns `true` if the log group should be collapsed, `false` otherwise.\n\n*Default: `false`*\n\n#### __predicate = (getState: Function, action: Object) =\u003e Boolean__\nIf specified this function will be called before each action is processed with this middleware.\nReceives `getState` function for  accessing current store state and `action` object as parameters. Returns `true` if action should be logged, `false` otherwise.\n\n*Default: `null` (always log)*\n\n#### __stateTransformer = (state: Object) =\u003e state__\nTransform state before print. Eg. convert Immutable object to plain JSON.\n\n*Default: identity function*\n\n#### __actionTransformer = (action: Object) =\u003e action__\nTransform action before print. Eg. convert Immutable object to plain JSON.\n\n*Default: identity function*\n\n#### __errorTransformer = (error: Any) =\u003e error__\nTransform error before print.\n\n*Default: identity function*\n\n#### __titleFormatter = (action: Object, time: String?, took: Number?) =\u003e title__\nFormat the title used for each action.\n\n*Default: prints something like `action @ ${time} ${action.type} (in ${took.toFixed(2)} ms)`*\n\n#### __diff (Boolean)__\nShow states diff.\n\n*Default: `false`*\n\n#### __diffPredicate = (getState: Function, action: Object) =\u003e Boolean__\nFilter states diff for certain cases.\n\n*Default: `undefined`*\n\n## Recipes\n### Log only in development\n```javascript\nconst middlewares = [];\n\nif (process.env.NODE_ENV === `development`) {\n  const { logger } = require(`redux-logger`);\n\n  middlewares.push(logger);\n}\n\nconst store = compose(applyMiddleware(...middlewares))(createStore)(reducer);\n```\n\n### Log everything except actions with certain type\n```javascript\ncreateLogger({\n  predicate: (getState, action) =\u003e action.type !== AUTH_REMOVE_TOKEN\n});\n```\n\n### Collapse actions with certain type\n```javascript\ncreateLogger({\n  collapsed: (getState, action) =\u003e action.type === FORM_CHANGE\n});\n```\n\n### Collapse actions that don't have errors\n```javascript\ncreateLogger({\n  collapsed: (getState, action, logEntry) =\u003e !logEntry.error\n});\n```\n\n### Transform Immutable (without `combineReducers`)\n```javascript\nimport { Iterable } from 'immutable';\n\nconst stateTransformer = (state) =\u003e {\n  if (Iterable.isIterable(state)) return state.toJS();\n  else return state;\n};\n\nconst logger = createLogger({\n  stateTransformer,\n});\n```\n\n### Transform Immutable (with `combineReducers`)\n```javascript\nconst logger = createLogger({\n  stateTransformer: (state) =\u003e {\n    let newState = {};\n\n    for (var i of Object.keys(state)) {\n      if (Immutable.Iterable.isIterable(state[i])) {\n        newState[i] = state[i].toJS();\n      } else {\n        newState[i] = state[i];\n      }\n    };\n\n    return newState;\n  }\n});\n```\n\n### Log batched actions\nThanks to [@smashercosmo](https://github.com/smashercosmo)\n```javascript\nimport { createLogger } from 'redux-logger';\n\nconst actionTransformer = action =\u003e {\n  if (action.type === 'BATCHING_REDUCER.BATCH') {\n    action.payload.type = action.payload.map(next =\u003e next.type).join(' =\u003e ');\n    return action.payload;\n  }\n\n  return action;\n};\n\nconst level = 'info';\n\nconst logger = {};\n\nfor (const method in console) {\n  if (typeof console[method] === 'function') {\n    logger[method] = console[method].bind(console);\n  }\n}\n\nlogger[level] = function levelFn(...args) {\n  const lastArg = args.pop();\n\n  if (Array.isArray(lastArg)) {\n    return lastArg.forEach(item =\u003e {\n      console[level].apply(console, [...args, item]);\n    });\n  }\n\n  console[level].apply(console, arguments);\n};\n\nexport default createLogger({\n  level,\n  actionTransformer,\n  logger\n});\n```\n\n## To Do\n- [x] Update eslint config to [airbnb's](https://www.npmjs.com/package/eslint-config-airbnb)\n- [ ] Clean up code, because it's very messy, to be honest\n- [ ] Write tests\n- [ ] Node.js support\n- [ ] React-native support\n\nFeel free to create PR for any of those tasks!\n\n## Known issues\n* Performance issues in react-native ([#32](https://github.com/LogRocket/redux-logger/issues/32))\n\n## License\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flogrocket%2Fredux-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flogrocket%2Fredux-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flogrocket%2Fredux-logger/lists"}