From 8bfab2c733401526a56b19cc01b1e7df11b7c267 Mon Sep 17 00:00:00 2001 From: Ke Mao Date: Wed, 1 Mar 2017 19:14:38 -0800 Subject: [PATCH] Improve command-line experience for capturing mobile JS heap Reviewed By: cwdick Differential Revision: D4612319 fbshipit-source-id: 607a09286abdd83368996ffc553b3ce984b62f34 --- .../react/devsupport/DevServerHelper.java | 8 ++--- .../devsupport/DevSupportManagerImpl.java | 10 +++---- .../react/devsupport/JSCHeapUpload.java | 29 +++++++++++++++---- .../middleware/heapCaptureMiddleware.js | 12 +++++--- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 69f35566b..3f2b33943 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -87,7 +87,7 @@ public class DevServerHelper { public interface PackagerCommandListener { void onPackagerReloadCommand(); - void onCaptureHeapCommand(); + void onCaptureHeapCommand(@Nullable final JSPackagerClient.Responder responder); void onPokeSamplingProfilerCommand(@Nullable final JSPackagerClient.Responder responder); } @@ -129,10 +129,10 @@ public class DevServerHelper { commandListener.onPackagerReloadCommand(); } }); - handlers.put("captureHeap", new JSPackagerClient.NotificationOnlyHandler() { + handlers.put("captureHeap", new JSPackagerClient.RequestOnlyHandler() { @Override - public void onNotification(@Nullable Object params) { - commandListener.onCaptureHeapCommand(); + public void onRequest(@Nullable Object params, JSPackagerClient.Responder responder) { + commandListener.onCaptureHeapCommand(responder); } }); handlers.put("pokeSamplingProfiler", new JSPackagerClient.RequestOnlyHandler() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java index 4f7ad2e50..aa731bcb9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java @@ -424,7 +424,7 @@ public class DevSupportManagerImpl implements new DevOptionHandler() { @Override public void onOptionSelected() { - handleCaptureHeap(); + handleCaptureHeap(null); } }); options.put( @@ -682,11 +682,11 @@ public class DevSupportManagerImpl implements } @Override - public void onCaptureHeapCommand() { + public void onCaptureHeapCommand(@Nullable final JSPackagerClient.Responder responder) { UiThreadUtil.runOnUiThread(new Runnable() { @Override public void run() { - handleCaptureHeap(); + handleCaptureHeap(responder); } }); } @@ -701,14 +701,14 @@ public class DevSupportManagerImpl implements }); } - private void handleCaptureHeap() { + private void handleCaptureHeap(@Nullable final JSPackagerClient.Responder responder) { if (mCurrentContext == null) { return; } JSCHeapCapture heapCapture = mCurrentContext.getNativeModule(JSCHeapCapture.class); heapCapture.captureHeap( mApplicationContext.getCacheDir().getPath(), - JSCHeapUpload.captureCallback(mDevServerHelper.getHeapCaptureUploadUrl())); + JSCHeapUpload.captureCallback(mDevServerHelper.getHeapCaptureUploadUrl(), responder)); } private void handlePokeSamplingProfiler(@Nullable final JSPackagerClient.Responder responder) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSCHeapUpload.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSCHeapUpload.java index f48d0dae8..f678a6d66 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSCHeapUpload.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSCHeapUpload.java @@ -9,10 +9,14 @@ package com.facebook.react.devsupport; +import javax.annotation.Nullable; + import android.util.Log; import java.io.File; import java.io.IOException; -import java.util.List; +import java.util.concurrent.TimeUnit; +import com.facebook.react.packagerconnection.JSPackagerClient; + import okhttp3.Call; import okhttp3.Callback; import okhttp3.MediaType; @@ -25,11 +29,17 @@ import okhttp3.Response; * Created by cwdick on 7/22/16. */ public class JSCHeapUpload { - public static JSCHeapCapture.CaptureCallback captureCallback(final String uploadUrl) { + public static JSCHeapCapture.CaptureCallback captureCallback( + final String uploadUrl, + @Nullable final JSPackagerClient.Responder responder) { return new JSCHeapCapture.CaptureCallback() { @Override public void onSuccess(File capture) { - OkHttpClient httpClient = new OkHttpClient.Builder().build(); + OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); + httpClientBuilder.connectTimeout(1, TimeUnit.MINUTES) + .writeTimeout(5, TimeUnit.MINUTES) + .readTimeout(5, TimeUnit.MINUTES); + OkHttpClient httpClient = httpClientBuilder.build(); RequestBody body = RequestBody.create(MediaType.parse("application/json"), capture); Request request = new Request.Builder() .url(uploadUrl) @@ -39,21 +49,28 @@ public class JSCHeapUpload { call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { - Log.e("JSCHeapCapture", "Upload of heap capture failed: " + e.toString()); + String message = "Upload of heap capture failed: " + e.toString(); + Log.e("JSCHeapCapture", message); + responder.error(message); } @Override public void onResponse(Call call, Response response) throws IOException { if (!response.isSuccessful()) { - Log.e("JSCHeapCapture", "Upload of heap capture failed with code: " + Integer.toString(response.code())); + String message = "Upload of heap capture failed with code " + Integer.toString(response.code()) + ": " + response.body().string(); + Log.e("JSCHeapCapture", message); + responder.error(message); } + responder.respond(response.body().string()); } }); } @Override public void onFailure(JSCHeapCapture.CaptureException e) { - Log.e("JSCHeapCapture", "Heap capture failed: " + e.toString()); + String message = "Heap capture failed: " + e.toString(); + Log.e("JSCHeapCapture", message); + responder.error(message); } }; } diff --git a/local-cli/server/middleware/heapCaptureMiddleware.js b/local-cli/server/middleware/heapCaptureMiddleware.js index 94e5125d6..7f73e5420 100644 --- a/local-cli/server/middleware/heapCaptureMiddleware.js +++ b/local-cli/server/middleware/heapCaptureMiddleware.js @@ -11,8 +11,8 @@ const spawn = require('child_process').spawn; const fs = require('fs'); -const path = require('path'); const http = require('http'); +const path = require('path'); const urlLib = require('url'); const SourceMapConsumer = require('source-map').SourceMapConsumer; @@ -132,7 +132,6 @@ module.exports = function(req, res, next) { console.error('Error when symbolicating: ' + err); }, (capture) => { - res.end(); const preload = path.join(__dirname, 'heapCapture/preLoadedCapture.js'); fs.writeFileSync(preload, 'var preLoadedCapture = '); fs.appendFileSync(preload, JSON.stringify(capture)); @@ -157,9 +156,14 @@ module.exports = function(req, res, next) { }); inliner.on('exit', (code, signal) => { if (code === 0) { - console.log('Heap capture written to: ' + captureHtml); + var response = captureHtml; + console.log('Heap capture written to: ' + response); + res.end(response); } else { - console.error('Error processing heap capture, inliner returned code: ' + code); + var response = 'Error processing heap capture, inliner returned code: ' + code; + console.error(response); + res.statusCode = 500; + res.end(response); } }); }