Redux Logging in Production

Written by edelstein | Published 2017/05/16
Tech Story Tags: react | redux | redux-logging | production | understanding-problems

TLDRvia the TL;DR App

Understanding problems in web apps is hard. Between mysterious JavaScript errors, user-reported bugs, and issues caught in QA, there’s a constant struggle to get ahead of the problems affecting your users. And these are just the obvious issues — most bugs are never actually reported since users who have a bad experience just leave or suffer in silence.

To solve this problem, developers are increasingly adopting frontend logging tools, since modern state management libraries like Redux leave a rich audit trail. Logging actions and state in production makes it easy to understand bugs and user-reported issues.

In this post, I’ll show you how to set up Redux logging with LogRocket. Then, I’ll discuss techniques for making Redux apps easier to debug.

LogRocket: a DVR for web apps

LogRocket is a frontend 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 the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Setting up LogRocket

Setting up LogRocket is easy, and only requires adding a few lines of code to your app:

  1. Install with NPM: npm i --save logrocket.

  2. Create a free account at https://app.logrocket.com, and take note of your application id.

  3. Initialize LogRocket in your app:

    import LogRocket from 'logrocket';

// Initialize LogRocket with your app IDLogRocket.init(<your_application_id>);

4. Add the Redux middleware.

import { applyMiddleware, createStore } from 'redux';

const store = createStore(  reducer, // your app reducer  applyMiddleware(middlewares, LogRocket.reduxMiddleware()),);

That’s it for the basic setup- this is all you need to get started with LogRocket!

LogRocket also has plugins for alternate Flux implementations like ngrx and vuex, which you can read about here.

Replaying User Sessions

Replaying a session in LogRocket is like seeing it happen in your own browser. You can inspect Redux actions with the full action payload as well as the previous and next states.

LogRocket captures both network requests and responses and lets you dig in to specific requests and see the headers and body. The waterfall chart shows timings, making it easy to see which requests were slow, or if a potential race condition occurred.

Sometimes Redux logs alone aren’t enough to understand a bug, especially when dealing with user-reported issues. LogRocket’s video replay helps here by letting you see exactly what a user saw in your app.

Since this video is actually a reconstruction of the DOM (and not a real video) you can inspect HTML/CSS to understand visual bugs, or play at 2x speed to gain a quick understanding of what a user did in the app when handling support issues.

Integrating Redux logging into your workflow

Being able to replay user sessions and see Redux logs is helpful across the development workflow.

Fixing Bugs

LogRocket integrates with error reporting tools like Sentry and Bugsnag, letting you see Redux logs and video for every bug. This is not only helpful for fixing bugs, but also for understanding error impact, since some JavaScript errors are completely innocuous. By watching the video from when an error occurred, you can easily tell if it actually affects users, or can be ignored.

Support

All too often, users will report issues but not give enough context to figure out exactly what happened.

If you are using a chat support tool like Intercom, you can integrate LogRocket directly so that it adds a note with a recording URL whenever a user starts chatting.

If you are integrating with a more general analytics tool, you can add recording URL’s with a tracking API like this:

LogRocket.getSessionURL(function (sessionURL) {  analytics.track('LogRocket recording', sessionURL);})

Making the most of production Redux logging

Production logging is immediately useful in all Redux apps, but by architecting your app with logging in mind, you can ensure that logs are maximally useful when debugging issues.

Try to keep most state in Redux

I don’t want to get into the debate on local vs Redux state here, but when deciding whether a given piece of state should be in Redux, ask yourself if seeing that state could be helpful when debugging issues. If the answer is yes, consider putting that state in Redux so that it will be logged with crash reports and user issues.

Use data fetching libraries that leverage Redux

Libraries like apollo-client for GraphQL, and redux-query for REST both facilitate fetching data from the network via Redux. They use Redux as a persistence layer, meaning that when debugging issues, you can inspect your Redux logs to see what data these clients have fetched.

If you’d prefer a simpler approach, you can roll your own data fetching “framework” by simply dispatching explicit actions when querying and receiving data from the network.

Use Redux to handle sources of non-determinism

When accessing data from APIs like websockets, local storage, IndexedDB, or even Date(), consider dispatching Redux actions with the result, so that you can easily debug these in the future. For example, when listening on a websocket, dispatch a Redux action on every message- that way you can see the data in your Redux logs.

Leverage other console APIs

Console methods like console.time(), console.count() and console.group() let you add rich data to your logs like React component render counts, transaction timings and component lifecycle logs. If you’re interested in learning more, I wrote a post about this here.

Build and upload source maps to LogRocket

LogRocket supports source maps which you can upload via a cli. By doing this you can see symbolicated stack traces for JavaScript errors, Redux actions, console logs and network requests, which lets you see where particular actions were triggered in your code.

Conclusion

React and Redux are often lauded as tools for building maintainable applications — a significant component of which is debuggability. Logging Redux data in production gives such insight since bugs and other user-reported issues can be easily debugged by inspecting Redux state, network requests and the DOM.

Using LogRocket for Redux logging can greatly simplify fixing bugs and supporting your users. You can learn more here:

LogRocket | Logging and Session Replay for JavaScript Apps_LogRocket helps you understand problems affecting your users, so that you can get back to building great software._logrocket.com

I love writing about React, Redux, and other developer tools. If you have any thoughts or comments feel free to leave them here or chat with me on twitter @b_edelstein. Thanks for reading!


Published by HackerNoon on 2017/05/16