mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-22 01:26:48 +03:00
Add docs for remote monitoring
This commit is contained in:
parent
22dcd97b9b
commit
6de0b367fd
|
@ -16,6 +16,7 @@ It can be used as a browser extension (for [Chrome](https://chrome.google.com/we
|
|||
- [Manual Integration as a React Component](./docs/Walkthrough.md#manual-integration)
|
||||
- [Extension Options (Arguments)](https://github.com/zalmoxisus/redux-devtools-extension/tree/master/docs/API/Arguments.md)
|
||||
- [Extension Methods (Advanced API)](https://github.com/zalmoxisus/redux-devtools-extension/tree/master/docs/API/Methods.md)
|
||||
- [Remote monitoring](./docs/Integrations/Remote.md)
|
||||
- [Troubleshooting](https://github.com/zalmoxisus/redux-devtools-extension/tree/master/docs/Troubleshooting.md)
|
||||
- [Recipes](https://github.com/zalmoxisus/redux-devtools-extension/tree/master/docs/Recipes.md)
|
||||
- [FAQ](https://github.com/zalmoxisus/redux-devtools-extension/tree/master/docs/FAQ.md)
|
||||
|
|
157
docs/Integrations/Remote.md
Normal file
157
docs/Integrations/Remote.md
Normal file
|
@ -0,0 +1,157 @@
|
|||
## Remote monitoring
|
||||
|
||||
By installing [`redux-devtools-cli`](https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-cli#usage), starting the server server and launching the Redux DevTools app (`redux-devtools --open`), you can connect any remote application, even not javascript. There are some integrations for javascript like [remote-redux-devtools](https://github.com/zalmoxisus/remote-redux-devtools) and [remotedev](https://github.com/zalmoxisus/remotedev), but the plan is to deprecate them and support it out of the box from the extension without a websocket server. It is more useful for non-js apps.
|
||||
|
||||
### WebSocket Clients
|
||||
|
||||
We're using [SocketCluster](http://socketcluster.io/) for realtime communication, which provides a fast and scalable webSocket layer and a minimal pub/sub system. You need to include one of [its clients](https://github.com/SocketCluster/client-drivers) in your app to communicate with RemotedevServer. Currently there are clients for [JavaScript (NodeJS)](https://github.com/SocketCluster/socketcluster-client), [Java](https://github.com/sacOO7/socketcluster-client-java), [Python](https://github.com/sacOO7/socketcluster-client-python), [C](https://github.com/sacOO7/socketcluster-client-C), [Objective-C](https://github.com/abpopov/SocketCluster-ios-client) and [.NET/C#](https://github.com/sacOO7/SocketclusterClientDotNet).
|
||||
|
||||
By default, the websocket server is running on `ws://localhost:8000/socketcluster/`.
|
||||
|
||||
### Messaging lifecycle
|
||||
|
||||
#### 1. Connecting to the WebSocket server
|
||||
|
||||
The client driver provides a way to connect to the server via websockets (see the docs for the selected client).
|
||||
|
||||
##### JavaScript
|
||||
```js
|
||||
var socket = socketCluster.connect({
|
||||
hostname: 'localhost',
|
||||
port: 8000
|
||||
});
|
||||
```
|
||||
|
||||
##### Python
|
||||
```py
|
||||
socket = Socketcluster.socket("ws://localhost:8000/socketcluster/")
|
||||
socket.connect()
|
||||
```
|
||||
|
||||
> Note that JavaScript client composes the url from `hostname` and `port`, adding `/socketcluster/` path automatically. For other clients, you should specify that path. For example, for `ObjectiveC` it would be `self.client.initWithHost("localhost/socketcluster/", onPort: 8000, securely: false)`.
|
||||
|
||||
#### 2. Disconnecting and reconnecting
|
||||
|
||||
SocketCluster client handles reconnecting for you, but you still might want to know when the connection is established, or when it failed to connect.
|
||||
|
||||
##### JavaScript
|
||||
```js
|
||||
socket.on('connect', status => {
|
||||
// Here will come the next step
|
||||
});
|
||||
socket.on('disconnect', code => {
|
||||
console.warn('Socket disconnected with code', code);
|
||||
});
|
||||
socket.on('error', error => {
|
||||
console.warn('Socket error', error);
|
||||
});
|
||||
```
|
||||
|
||||
##### Python
|
||||
```py
|
||||
def onconnect(socket):
|
||||
// Here will call the next step
|
||||
|
||||
def ondisconnect(socket):
|
||||
logging.info("on disconnect got called")
|
||||
|
||||
def onConnectError(socket, error):
|
||||
logging.info("On connect error got called")
|
||||
|
||||
socket.setBasicListener(onconnect, ondisconnect, onConnectError)
|
||||
```
|
||||
|
||||
#### 3. Authorizing and subscribing to the channel of events
|
||||
|
||||
We're not providing an authorizing mechanism yet. All you have to do is to emit a `login` event, and you'll get a `channelName` you should subscribe for, and watch for messages and events. Make sure to pass the `master` event, otherwise it should be a monitor, not a client app.
|
||||
|
||||
##### JavaScript
|
||||
```js
|
||||
socket.emit('login', 'master', (error, channelName) => {
|
||||
if (error) { console.log(error); return; }
|
||||
channel = socket.subscribe(channelName);
|
||||
channel.watch(handleMessages);
|
||||
socket.on(channelName, handleMessages);
|
||||
});
|
||||
|
||||
function handleMessages(message) {
|
||||
// 5. Listening for monitor events
|
||||
}
|
||||
```
|
||||
|
||||
##### Python
|
||||
```py
|
||||
socket.emitack("login", "master", login)
|
||||
|
||||
def login(key, error, channelName):
|
||||
socket.subscribe(channelName)
|
||||
socket.onchannel(channelName, handleMessages)
|
||||
socket.on(channelName, handleMessages)
|
||||
|
||||
def handleMessages(key, message):
|
||||
// 5. Listening for monitor events
|
||||
```
|
||||
|
||||
You could just emit the `login` event, and omit subscribing (and point `5` bellow) if you want only to log data, not to interact with te app.
|
||||
|
||||
#### 4. Sending the action and state to the monitor
|
||||
|
||||
To send your data to the monitor use `log` or `log-noid` channel. The latter will add the socket id to the message from the server side (useful when the message was sent before the connection was established).
|
||||
|
||||
The message object includes the following:
|
||||
- `type` - usually should be `ACTION`. If you want to indicate that we're starting a new log (clear all actions emitted before and add `@@INIT`), use `INIT`. In case you have a lifted state similar to one provided by [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument), use `STATE`.
|
||||
- `action` - the action object. It is recommended to lift it in another object, and add `timestamp` to show when the action was fired off: `{ timestamp: Date.now(), action: { type: 'SOME_ACTION' } }`.
|
||||
- `payload` - usually the state or lifted state object.
|
||||
- `name` - name of the instance to be shown in the instances selector. If not provided, it will be equal to `instanceId`.
|
||||
- `instanceId` - an id to identify the instance. If not provided, it will be the same as `id`. However, it is useful when having several instances (or stores) in the same connection. Also if the user will specify a constant value, it would allow to persist the state on app reload.
|
||||
- `id` - socket connection id, which should be either `socket.id` or should not provided and use `log-noid` channel.
|
||||
|
||||
##### JavaScript
|
||||
```js
|
||||
const message = {
|
||||
type: 'ACTION',
|
||||
action: { action, timestamp: Date.now() },
|
||||
payload: state,
|
||||
id: socket.id,
|
||||
instanceId: window.btoa(location.href),
|
||||
name: document.title
|
||||
};
|
||||
socket.emit(socket.id ? 'log' : 'log-noid', message);
|
||||
```
|
||||
|
||||
##### Python
|
||||
```py
|
||||
class Message:
|
||||
def __init__(self, action, state):
|
||||
self.type = "ACTION"
|
||||
self.action = action
|
||||
self.payload = state
|
||||
id: socket.id
|
||||
socket.emit(socket.id if "log" else "log-noid", Message(action, state));
|
||||
```
|
||||
|
||||
#### 5. Listening for monitor events
|
||||
|
||||
When a monitor action is emitted, you'll get an event on the subscribed function. The argument object includes a `type` key, which can be:
|
||||
- `DISPATCH` - a monitor action dispatched on Redux DevTools monitor, like `{ type: 'DISPATCH', payload: { type: 'JUMP_TO_STATE', 'index': 2 }`. See [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument/blob/master/src/instrument.js) for details. Additionally to that API, you'll get also a stringified `state` object when needed. So, for example, for time travelling (`JUMP_TO_STATE`) you can just parse and set the state (see the example). Usually implementing this type of actions would be enough.
|
||||
- `ACTION` - the user requested to dispatch an action remotely like `{ type: 'ACTION', action: '{ type: \'INCREMENT_COUNTER\' }' }`. The `action` can be either a stringified javascript object which should be evalled or a function which arguments should be evalled like [here](https://github.com/zalmoxisus/remotedev-utils/blob/master/src/index.js#L62-L70).
|
||||
- `START` - a monitor was opened. You could handle this event in order not to do extra tasks when the app is not monitored.
|
||||
- `STOP` - a monitor was closed. You can take this as no need to send data to the monitor. I there are several monitors and one was closed, all others will send `START` event to acknowledge that we still have to send data.
|
||||
|
||||
See [`mobx-remotedev`](https://github.com/zalmoxisus/mobx-remotedev/blob/master/src/monitorActions.js) for an example of implementation without [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument/blob/master/src/instrument.js).
|
||||
|
||||
##### JavaScript
|
||||
```js
|
||||
function handleMessages(message) {
|
||||
if (message.type === 'DISPATCH' && message.payload.type === 'JUMP_TO_STATE') {
|
||||
store.setState(JSON.parse(message.state));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### Python
|
||||
```py
|
||||
def handleMessages(key, message):
|
||||
if message.type === "DISPATCH" and message.payload.type === "JUMP_TO_STATE":
|
||||
store.setState(json.loads(message.state));
|
||||
```
|
|
@ -155,7 +155,7 @@ Redux DevTools server is database agnostic using `knex` schema. By default every
|
|||
```
|
||||
|
||||
### Advanced
|
||||
- [Writing your integration for a native application](https://github.com/zalmoxisus/remotedev-server/blob/master/docs/API/Realtime.md)
|
||||
- [Writing your integration for a native application](https://github.com/reduxjs/redux-devtools/blob/master/docs/Integrations/Remote.md)
|
||||
|
||||
### License
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user