Adding Soft Error Logging to FallbackJSBundleLoader
Reviewed By: michalgr Differential Revision: D4405355 fbshipit-source-id: 7730a1afd74ace7fdad91b22f9254e83d16d1050
This commit is contained in:
parent
c3892fa871
commit
87c6bcb65d
|
@ -32,4 +32,3 @@ android_library(
|
|||
'PUBLIC',
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ import java.util.List;
|
|||
import java.util.ListIterator;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
|
||||
/**
|
||||
* FallbackJSBundleLoader
|
||||
*
|
||||
|
@ -24,6 +26,7 @@ import java.util.Stack;
|
|||
public final class FallbackJSBundleLoader extends JSBundleLoader {
|
||||
|
||||
/* package */ static final String RECOVERABLE = "facebook::react::Recoverable";
|
||||
/* package */ static final String TAG = "FallbackJSBundleLoader";
|
||||
|
||||
// Loaders to delegate to, with the preferred one at the top.
|
||||
private Stack<JSBundleLoader> mLoaders;
|
||||
|
@ -60,7 +63,7 @@ public final class FallbackJSBundleLoader extends JSBundleLoader {
|
|||
|
||||
mLoaders.pop();
|
||||
mRecoveredErrors.add(e);
|
||||
// TODO (t14839302): Report a soft error for each swallowed exception.
|
||||
FLog.wtf(TAG, "Falling back from recoverable error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
android_library(
|
||||
name = 'logging',
|
||||
srcs = glob(['**/*.java']),
|
||||
|
||||
exported_deps = [
|
||||
react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'),
|
||||
],
|
||||
|
||||
deps = [
|
||||
react_native_dep('third-party/java/jsr-305:jsr-305'),
|
||||
],
|
||||
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.common.logging;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class FakeLoggingDelegate implements LoggingDelegate {
|
||||
|
||||
public static final class LogLine {
|
||||
public final int priority;
|
||||
public final String tag;
|
||||
public final String msg;
|
||||
public final @Nullable Throwable tr;
|
||||
|
||||
private LogLine(
|
||||
int priority,
|
||||
String tag,
|
||||
String msg,
|
||||
@Nullable Throwable tr) {
|
||||
|
||||
this.priority = priority;
|
||||
this.tag = tag;
|
||||
this.msg = msg;
|
||||
this.tr = tr;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int ASSERT = FLog.ASSERT;
|
||||
public static final int DEBUG = FLog.DEBUG;
|
||||
public static final int ERROR = FLog.ERROR;
|
||||
public static final int INFO = FLog.INFO;
|
||||
public static final int VERBOSE = FLog.VERBOSE;
|
||||
public static final int WARN = FLog.WARN;
|
||||
|
||||
/**
|
||||
* There is no log level for Terrible Failures (we emit them at the Error
|
||||
* Log-level), but to test that WTF errors are being logged, we are making up
|
||||
* a new log level here, guaranteed to be larger than any of the other log
|
||||
* levels.
|
||||
*/
|
||||
public static final int WTF =
|
||||
1 + Collections.max(Arrays.asList(ASSERT, DEBUG, ERROR, INFO, VERBOSE, WARN));
|
||||
|
||||
private int mMinLogLevel = FLog.VERBOSE;
|
||||
private final ArrayList<LogLine> mLogs = new ArrayList<>();
|
||||
|
||||
/** Test Harness */
|
||||
|
||||
private static boolean matchLogQuery(
|
||||
int priority,
|
||||
String tag,
|
||||
@Nullable String throwMsg,
|
||||
LogLine line) {
|
||||
return priority == line.priority
|
||||
&& tag.equals(line.tag)
|
||||
&& (throwMsg == null || throwMsg.equals(line.tr.getMessage()));
|
||||
}
|
||||
|
||||
public boolean logContains(int priority, String tag, String throwMsg) {
|
||||
for (FakeLoggingDelegate.LogLine line : mLogs) {
|
||||
if (matchLogQuery(priority, tag, throwMsg, line)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** LoggingDelegate API */
|
||||
|
||||
public int getMinimumLoggingLevel() {
|
||||
return mMinLogLevel;
|
||||
}
|
||||
|
||||
public void setMinimumLoggingLevel(int level) {
|
||||
mMinLogLevel = level;
|
||||
}
|
||||
|
||||
public boolean isLoggable(int level) {
|
||||
return level >= mMinLogLevel;
|
||||
}
|
||||
|
||||
private void logImpl(int priority, String tag, String msg, Throwable tr) {
|
||||
if (isLoggable(priority)) {
|
||||
mLogs.add(new LogLine(priority, tag, msg, tr));
|
||||
}
|
||||
}
|
||||
|
||||
public void log(int priority, String tag, String msg) {
|
||||
logImpl(priority, tag, msg, null);
|
||||
}
|
||||
|
||||
public void d(String tag, String msg, Throwable tr) {
|
||||
logImpl(DEBUG, tag, msg, tr);
|
||||
}
|
||||
|
||||
public void d(String tag, String msg) {
|
||||
logImpl(DEBUG, tag, msg, null);
|
||||
}
|
||||
|
||||
public void e(String tag, String msg, Throwable tr) {
|
||||
logImpl(ERROR, tag, msg, tr);
|
||||
}
|
||||
|
||||
public void e(String tag, String msg) {
|
||||
logImpl(ERROR, tag, msg, null);
|
||||
}
|
||||
|
||||
public void i(String tag, String msg, Throwable tr) {
|
||||
logImpl(INFO, tag, msg, tr);
|
||||
}
|
||||
|
||||
public void i(String tag, String msg) {
|
||||
logImpl(INFO, tag, msg, null);
|
||||
}
|
||||
|
||||
public void v(String tag, String msg, Throwable tr) {
|
||||
logImpl(VERBOSE, tag, msg, tr);
|
||||
}
|
||||
|
||||
public void v(String tag, String msg) {
|
||||
logImpl(VERBOSE, tag, msg, null);
|
||||
}
|
||||
|
||||
public void w(String tag, String msg, Throwable tr) {
|
||||
logImpl(WARN, tag, msg, tr);
|
||||
}
|
||||
|
||||
public void w(String tag, String msg) {
|
||||
logImpl(WARN, tag, msg, null);
|
||||
}
|
||||
|
||||
public void wtf(String tag, String msg, Throwable tr) {
|
||||
logImpl(WTF, tag, msg, tr);
|
||||
}
|
||||
|
||||
public void wtf(String tag, String msg) {
|
||||
logImpl(WTF, tag, msg, null);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ rn_robolectric_test(
|
|||
react_native_dep('third-party/java/mockito:mockito'),
|
||||
react_native_dep('third-party/java/robolectric3/robolectric:robolectric'),
|
||||
react_native_target('java/com/facebook/react/cxxbridge:bridge'),
|
||||
react_native_tests_target('java/com/facebook/common/logging:logging'),
|
||||
],
|
||||
visibility = [
|
||||
'PUBLIC'
|
||||
|
|
|
@ -15,6 +15,10 @@ import java.util.Arrays;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.common.logging.FakeLoggingDelegate;
|
||||
import com.facebook.common.logging.LoggingDelegate;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.fest.assertions.api.Assertions.fail;
|
||||
|
||||
|
@ -34,6 +38,14 @@ public class FallbackJSBundleLoaderTest {
|
|||
UNRECOVERABLE = prefix.replace(first, (char) (first + 1));
|
||||
}
|
||||
|
||||
private FakeLoggingDelegate mLoggingDelegate;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mLoggingDelegate = new FakeLoggingDelegate();
|
||||
FLog.setLoggingDelegate(mLoggingDelegate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void firstLoaderSucceeds() {
|
||||
JSBundleLoader delegates[] = new JSBundleLoader[] {
|
||||
|
@ -48,6 +60,12 @@ public class FallbackJSBundleLoaderTest {
|
|||
|
||||
verify(delegates[0], times(1)).loadScript(null);
|
||||
verify(delegates[1], never()).loadScript(null);
|
||||
|
||||
assertThat(mLoggingDelegate.logContains(
|
||||
FakeLoggingDelegate.WTF,
|
||||
FallbackJSBundleLoader.TAG,
|
||||
null))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -66,6 +84,12 @@ public class FallbackJSBundleLoaderTest {
|
|||
verify(delegates[0], times(1)).loadScript(null);
|
||||
verify(delegates[1], times(1)).loadScript(null);
|
||||
verify(delegates[2], never()).loadScript(null);
|
||||
|
||||
assertThat(mLoggingDelegate.logContains(
|
||||
FakeLoggingDelegate.WTF,
|
||||
FallbackJSBundleLoader.TAG,
|
||||
recoverableMsg("error1")))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -98,6 +122,18 @@ public class FallbackJSBundleLoaderTest {
|
|||
|
||||
verify(delegates[0], times(1)).loadScript(null);
|
||||
verify(delegates[1], times(1)).loadScript(null);
|
||||
|
||||
assertThat(mLoggingDelegate.logContains(
|
||||
FakeLoggingDelegate.WTF,
|
||||
FallbackJSBundleLoader.TAG,
|
||||
recoverableMsg("error1")))
|
||||
.isTrue();
|
||||
|
||||
assertThat(mLoggingDelegate.logContains(
|
||||
FakeLoggingDelegate.WTF,
|
||||
FallbackJSBundleLoader.TAG,
|
||||
recoverableMsg("error2")))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -119,6 +155,12 @@ public class FallbackJSBundleLoaderTest {
|
|||
|
||||
verify(delegates[0], times(1)).loadScript(null);
|
||||
verify(delegates[1], never()).loadScript(null);
|
||||
|
||||
assertThat(mLoggingDelegate.logContains(
|
||||
FakeLoggingDelegate.WTF,
|
||||
FallbackJSBundleLoader.TAG,
|
||||
null))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
private static JSBundleLoader successfulLoader(String url) {
|
||||
|
|
Loading…
Reference in New Issue