zalmoxisus / redux-devtools-extension

Redux DevTools extension.
MIT License
13.5k stars 1.01k forks source link

Replay App #191

Closed ccorcos closed 8 years ago

ccorcos commented 8 years ago

So now that we've figured out how to import an array of actions and play them back, I now want to be able to take several action arrays and build a static "replay" application. Basically, we should be able to select a scene from a list, and then scrub through them with a slider (very useful for legal review of loan applications here at Affirm.com ;)

I've already built a little prototype:

image

But ideally I could reuse some code from this devtool and contribute back. I'm just not sure how. I don't want to have to install the redux dev tools in order to scrub around. I'd like everything to be packages up together. Any thoughts on how I can do this?

Recap:

import devtool from 'devtool'

store = createStore(
  reducer,
  devtool({mode: 'replay', scenes: {'name of scene': ['list', 'of', 'actions']}),
  applyMiddleware(...middlewares),
)
zalmoxisus commented 8 years ago

Looks interesting. I'm working on something like this as well. Moreover, I'm planning not only to show scenes (logs / reports), but also to have more details about them (to help collaborative debugging). A dropdown/selection list fro quick jumping to the scene wold be also useful.

Basically, you could import remotedev-app (which is just a React component you can render where you need) or just some parts of it as we do for the extension (if you need only slider, then this would help). Or just include it in an iframe.

If you feel like using remodev-server wouldn't be a solution for you use case though we want it as flexible as possible), then probably you just want a custom monitor for redux-devtools.

About "all actions should be blocked", a lockChanges action for the instrumentation is planned.

ccorcos commented 8 years ago

Whoa, you really took off with this :) I'm more than happy to help if you need any!

Here are some specifics of my situation that I think would be a good idea to consider to make this tool as generic as possible.

1) we're using elasticsearch for our analytics so we can use kibana dashboards and stuff like that. one nuance is that elasticsearch is sql-backed so we cant have nested objects. so I have to effectively flatten/serialize the actions when I send them to elastic search. so when I load them back into replay, I'll have to unflatten/deserialize the actions.

2) grabbing information from elasticsearch is going to involve authentication somehow through the application.

3) when we get an error on rollbar, there will be a unique session id associated with that user. we can use this id to query the actions from elasticsearch. the reason we arent sending all the actions to rollbar is so we can perform additional analytics on the data.

4) with every action we send to elasticsearch, we also have an app version so we'll want to be able to git checkout that release tag. this would work if we're using electron and require the developer to install git and point to the repo.

zalmoxisus commented 8 years ago

1) we're using elasticsearch for our analytics

Though js-data-elasticsearch is just planned, it's rather easy to implement a custom adapter for js-data.

so we can use kibana dashboards and stuff like that

We want our dashboard, which will allow to filter reports and to show related reports. So, if you got a similar one, will know how it was solved before.

one nuance is that elasticsearch is sql-backed so we cant have nested objects. so I have to effectively flatten/serialize the actions when I send them to elastic search. so when I load them back into replay, I'll have to unflatten/deserialize the actions.

Even though in our architecture we can save them as json, we also serialize the actions, so it will knot affect the server performance. Along with the serialized actions we'll also send the last action type ("failed action"). Additionally we can send the commited (initial) state (also serialized), so we can limit the maximum number of actions, and send only the last N actions (otherwise, hundreds of actions will just freeze the app). There's also a problem with multiple stores in one app to be solves, but I guess it's not your case.

2) grabbing information from elasticsearch is going to involve authentication somehow through the application.

Since our plan is not to communicate with elasticsearch directly from the app, the idea is that you'll just indicate a token along with the host and port to access remotedev-server, then on the server part you make the authentication with the db.

3) when we get an error on rollbar, there will be a unique session id associated with that user. we can use this id to query the actions from elasticsearch. the reason we arent sending all the actions to rollbar is so we can perform additional analytics on the data.

Sounds great. The filtering by user id is planned.

4) with every action we send to elasticsearch, we also have an app version so we'll want to be able to git checkout that release tag. this would work if we're using electron and require the developer to install git and point to the repo.

Also sounds like a great feature we want to have.

Actually, if you intend to send data to elasticsearch directly, you don't need to host remotedev-server. You can just start it together with your development server, so it will communicate with elasticsearch to get stored data.

The reason we want to host remotedev-server (instead of having a serveless architecture) is that we want not only the reports, but also to control the user's application remotely (in case he allowed that by clicking a support button). So you wold be able to solve bugs right from the user's side, which is rather useful for bugs that can be replicated only on user's browser (I mean also the configuration) / device. I spoke about this on React Europe.

ccorcos commented 8 years ago

We want our dashboard, which will allow to filter reports and to show related reports. So, if you got a similar one, will know how it was solved before.

So Kibana and Elasticsearch are for doing user analytics, creating dashboards about app usage, and analyzing A/B tests. That's not within the scope of this project. But I did want to point out that if you send Redux actions only on errors, you're missing out on a plethora of very rich usage information. I'm sending all Redux actions to our analytics/tracking stack -- I'm flattening the actions so I can query them in SQL if I want to make a Kibana dashboard or run some aggregate queries, and then I plan to be able to unflatten them and run them through the devtool.

Actually being able to control the other persons computer another really cool idea actually. Nice talk too! That's not exactly what I'm looking to build right now but I bet you could sell that software to Intercom!

I looks like there is definitely overlap though. Here's what I'm still trying to figure out:

1) How can we set up an app with the devtools built in (without the chrome extension)?

Looks like you already know how to do this but I havent figured it out. I'm trying to figure out how this store "enhancer" is able to control actions, states, and also render to the UI. I'm poking around here but couldn't find where you instantiate the Provider. Is there a simple example of how an "enhancer" works?

2) How to import a session and go directly into replay mode (blocking all actions)?

Looking at the code for importing state, I can't find where any of this goes through a reducer to actually update the devtool state. I get lost right here with all this lifted store stuff. But it seems like we just need to flip a few booleans to hide some views and display just the views we want.

3) How to build a scene selection view within the devtool to select from various scenes to replay?

I'm planning on having some JSON hardcoded into the app that gets configured with the replay tool. The key will be the name of the scene, and the value is just an array of actions. I want to have a list / dropdown / some way of selecting these scenes, importing the state, and given a slider to run through. This is oging to be very useful for compliance-type stuff.

I'd really appreciate any direction you have here. The more you tell me about your way of doing this, the more cohesive this tool will be with everything your building :)

zalmoxisus commented 8 years ago

But I did want to point out that if you send Redux actions only on errors, you're missing out on a plethora of very rich usage information.

Definitely. Except sendOnError, there's sendOn option, where you can list actions for which you want to send the logs. If you want to send all actions, then using websockets would be much more effective, so you just set realtime option to true. You can even specify an action for which to start logging (for example it could be a button, by which users will allow it) via startOn option. Though you probably can still use your middleware for production (for end-users), and this one for development (for "replay app").

That's not exactly what I'm looking to build right now but I bet you could sell that software to Intercom!

I will keep everything OSS, and even will allow debugging via our remote servers for a moderate use.

1) How can we set up an app with the devtools built in (without the chrome extension)?

Via Remote Redux DevTools for instrumenting the store, and remotedev-app for monitoring.

Well, it's not exactly for your case to have the monitoring decoupled from your app (and to communicate with it via sockets). But it could offer more opportunities, for example using it for the mobile app or having one instance in production and another one in development. If you feel like it's out of your scope, then you probably want just to have a custom monitor for vanilla Redux DevTools.

2) How to import a session and go directly into replay mode (blocking all actions)?

This feature is only proposed yet. The current idea is that new actions will be logged but not dispatched till you exit from the loop mode (unlock). We could just dismiss them, not sure which approach is better.

3) How to build a scene selection view within the devtool to select from various scenes to replay?

I think we need something like this:

import DevTools from `remotedev-app`;

// ...
<DevTools monitors={['slider']} logs={yourJson} />

Will look into this in few days, have to finish something else right now.

zalmoxisus commented 8 years ago

Hey @ccorcos,

It takes more time than I've expected, as have to refactor the whole app. See https://github.com/zalmoxisus/remotedev-app/pull/16.

The good news is that it will be possible to use it without remotedev-server, just by using your reducers which will interpret the remotedev-app actions. I'll add an example with using only the slider monitor (as you wanted) when it will be ready.

BTW, I've released a lib to send reports from production, you can use to have more control of the data you send.

ccorcos commented 8 years ago

nice looks good!

any suggestions on how to figure out how "enhancers" work? Whats the simplest example?

zalmoxisus commented 8 years ago

The simplest example is applyMiddleware, which is also an enhancer. However, keep in mind that the store enhancer's API will be different in Redux 4.0.

I guess for your use case using a middleware is enough. If you want more control (like sanitizing, blacklisting actions...), you can use redux-remotedev. Just set every to true and add the code for elasticsearch in sender option. I tend to make it as generic as possible.

ccorcos commented 8 years ago

oh interesting. not actually all that complicated.

zalmoxisus commented 8 years ago

Hey @ccorcos,

I've published a Slider Monitor with the ability to import reports with a simple example of integration. It's highly customizable. I'm open for any improvements. An integration with elasticsearch would be more than welcome. Feel free to file any issues there.

Here's how it works in the extension (but you can include that component directly in your admin page):

koumdjxlux 1

ccorcos commented 8 years ago

@zalmoxisus this is amazing! I'll keep you posted on this. I think it might be easier for us to just download the data into a static build like you've done with the example -- that way we can pass the builds around...

cyberhck commented 7 years ago

Hey guys, is there any way to extend this and replay my custom actions? I've got all the actions from a bug report, now I want to paste the entire array and it should be able to play it. Is that possible?

zalmoxisus commented 7 years ago

@cyberhck, yes, you can import an array of actions. The format should be like:

{
  "payload": "[{\"type\": \"action1\"}, {\"type\": \"action2\"}]"
}

Also you can do it with your client script:

store.liftedStore.dispatch({ type: 'IMPORT_STATE', nextLiftedState: [{ type: 'action1' }, { type: 'action2' }] })