Make MessageQueue to emit "SPY" events in a way that can be extensible

Summary:
This PR adds a capability for MessageQueue to emit "SPY" events in a way that can be extensible, to later allow for a tooling ecosystem to grow, one example is the existing [Snoopy](https://github.com/jondot/rn-snoopy) tool that is, for now, forced to work with monkeypatches, and after this PR will be able to use a "formal" way to trace queue events.

After this change, we can wire a "spy" into a queue that will expose the events in different and interesting ways, see below (done with Snoopy):
  <img src="https://github.com/jondot/rn-snoopy/blob/master/media/snoopy.gif?raw=true" alt="Aggregating and Charting Events with Bar" width="400px"/>
  <img src="https://github.com/jondot/rn-snoopy/blob/master/media/snoopy-filter.gif?raw=true" alt="Aggregating and Charting Events with Bar" width="400px"/>

This removes the hardcoded `SPY_MODE` flag and instead uses a function that can be injected from outside world.

```javascript
MessageQueue.spy((info)=>console.log("event!", info)
```

It also creates
Closes https://github.com/facebook/react-native/pull/9160

Differential Revision: D3669053

Pulled By: javache

fbshipit-source-id: 3e4462aa77fc8514d2ea4f15430f7bec57b583a4
This commit is contained in:
Dotan Nahum 2016-08-04 08:38:49 -07:00 committed by Facebook Github Bot 7
parent 4983a58d6c
commit 77e48f1782
1 changed files with 29 additions and 9 deletions

View File

@ -26,9 +26,10 @@ const METHOD_IDS = 1;
const PARAMS = 2;
const MIN_TIME_BETWEEN_FLUSHES_MS = 5;
const TRACE_TAG_REACT_APPS = 1 << 17;
const TO_NATIVE = 1;
const TO_JS = 0;
const SPY_MODE = false;
const TRACE_TAG_REACT_APPS = 1 << 17;
const MethodTypes = keyMirror({
remote: null,
@ -90,6 +91,21 @@ class MessageQueue {
/**
* Public APIs
*/
static spy(spyOrToggle){
if (spyOrToggle === true){
MessageQueue.prototype.__spy = (info)=>{
console.log(`${info.type == TO_JS ? 'N->JS' : 'JS->N'} : ` +
`${info.module ? (info.module+'.') : ''}${info.method}` +
`(${JSON.stringify(info.args)})`);
}
} else if (spyOrToggle === false) {
MessageQueue.prototype.__spy = null;
} else {
MessageQueue.prototype.__spy = spyOrToggle;
}
}
callFunctionReturnFlushedQueue(module, method, args) {
guard(() => {
this.__callFunction(module, method, args);
@ -182,9 +198,13 @@ class MessageQueue {
this._lastFlush = now;
}
Systrace.counterEvent('pending_js_to_native_queue', this._queue[0].length);
if (__DEV__ && SPY_MODE && isFinite(module)) {
console.log('JS->N : ' + this._remoteModuleTable[module] + '.' +
this._remoteMethodTable[module][method] + '(' + JSON.stringify(params) + ')');
if (__DEV__ && this.__spy && isFinite(module)) {
this.__spy(
{ type: TO_NATIVE,
module: this._remoteModuleTable[module],
method: this._remoteMethodTable[module][method],
args: params }
);
}
}
@ -192,8 +212,8 @@ class MessageQueue {
this._lastFlush = new Date().getTime();
this._eventLoopStartTime = this._lastFlush;
Systrace.beginEvent(`${module}.${method}()`);
if (__DEV__ && SPY_MODE) {
console.log('N->JS : ' + module + '.' + method + '(' + JSON.stringify(args) + ')');
if (__DEV__ && this.__spy) {
this.__spy({ type: TO_JS, module, method, args});
}
const moduleMethods = this._callableModules[module];
invariant(
@ -232,8 +252,8 @@ class MessageQueue {
);
}
const profileName = debug ? '<callback for ' + module + '.' + method + '>' : cbID;
if (callback && SPY_MODE && __DEV__) {
console.log('N->JS : ' + profileName + '(' + JSON.stringify(args) + ')');
if (callback && this.__spy && __DEV__) {
this.__spy({ type: TO_JS, module:null, method:profileName, args });
}
Systrace.beginEvent(
`MessageQueue.invokeCallback(${profileName}, ${stringifySafe(args)})`);