com.eg.agent.android.crashes.CrashReporter Maven / Gradle / Ivy
package com.eg.agent.android.crashes;
/*import com.newrelic.agent.android.AgentConfiguration;
import com.newrelic.agent.android.harvest.crash.Crash;
import com.newrelic.agent.android.logging.AgentLog;
import com.newrelic.agent.android.logging.AgentLogManager;
import com.newrelic.agent.android.metric.Metric;
import com.newrelic.agent.android.metric.MetricNames;
import com.newrelic.agent.android.stats.StatsEngine;
import com.newrelic.agent.android.stats.TicToc;
import com.newrelic.agent.android.util.NamedThreadFactory;*/
import com.eg.agent.android.AgentConfiguration;
import com.eg.agent.android.harvest.crash.Crash;
import com.eg.agent.android.logging.AgentLog;
import com.eg.agent.android.logging.AgentLogManager;
import com.eg.agent.android.metric.Metric;
import com.eg.agent.android.metric.MetricNames;
import com.eg.agent.android.stats.StatsEngine;
import com.eg.agent.android.stats.TicToc;
import com.eg.agent.android.util.NamedThreadFactory;
import org.apache.http.HttpStatus;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
public class CrashReporter {
private static final String CRASH_COLLECTOR_PATH = "/mobile_crash";
private static final int CRASH_COLLECTOR_TIMEOUT = 5000;
private static AgentConfiguration agentConfiguration;
private static ExecutorService executor;
protected static final AtomicBoolean initialized = new AtomicBoolean(false);
protected static CrashReporter instance = new CrashReporter();
private CrashStore crashStore;
protected boolean isEnabled = false;
private final AgentLog log = AgentLogManager.getAgentLog();
private Thread.UncaughtExceptionHandler previousExceptionHandler;
private boolean reportCrashes = true;
static class C03461 implements Runnable {
C03461() {
}
public void run() {
if (CrashReporter.instance.hasReachableNetworkConnection()) {
CrashReporter.instance.reportSavedCrashes();
CrashReporter.instance.reportSupportabilityMetrics();
return;
}
CrashReporter.instance.log.warning("Unable to upload cached crash to New Relic - no network");
}
}
private class CrashSender implements Runnable {
private final Crash crash;
CrashSender(Crash crash) {
this.crash = crash;
}
public void run() {
try {
HttpURLConnection connection = (HttpURLConnection) new URL((CrashReporter.agentConfiguration.useSsl() ? "https://" : "http://") + CrashReporter.agentConfiguration.getCrashCollectorHost() + CrashReporter.CRASH_COLLECTOR_PATH).openConnection();
TicToc timer = new TicToc();
timer.tic();
connection.setDoOutput(true);
connection.setChunkedStreamingMode(0);
connection.setRequestProperty("Content-Type", "application/json");
connection.setConnectTimeout(CrashReporter.CRASH_COLLECTOR_TIMEOUT);
connection.setReadTimeout(CrashReporter.CRASH_COLLECTOR_TIMEOUT);
try {
this.crash.incrementUploadCount();
CrashReporter.this.crashStore.store(this.crash);
OutputStream out = new BufferedOutputStream(connection.getOutputStream());
out.write(this.crash.toJsonString().getBytes());
out.close();
switch (connection.getResponseCode()) {
case 200:
CrashReporter.this.crashStore.delete(this.crash);
StatsEngine.get().sampleTimeMs(MetricNames.SUPPORTABILITY_CRASH_UPLOAD_TIME, timer.peek());
CrashReporter.this.log.info("Crash " + this.crash.getUuid().toString() + " successfully submitted.");
break;
case HttpStatus.SC_INTERNAL_SERVER_ERROR /*500*/:
CrashReporter.this.crashStore.delete(this.crash);
StatsEngine.get().inc(MetricNames.SUPPORTABILITY_CRASH_REMOVED_REJECTED);
CrashReporter.this.recordFailedUpload("The crash was rejected and will be deleted - Response code " + connection.getResponseCode());
break;
default:
CrashReporter.this.recordFailedUpload("Something went wrong while submitting a crash (will try again later) - Response code " + connection.getResponseCode());
break;
}
} catch (Exception e) {
CrashReporter.this.recordFailedUpload("Crash upload failed: " + e);
CrashReporter.this.log.debug("Crash collection took " + timer.toc() + "ms");
} finally {
connection.disconnect();
}
CrashReporter.this.log.debug("Crash collection took " + timer.toc() + "ms");
} catch (Exception e2) {
CrashReporter.this.recordFailedUpload("Unable to report crash to New Relic, will try again later. " + e2);
}
}
}
public class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private final AtomicBoolean handledException = new AtomicBoolean(false);
public void uncaughtException(Thread r11, Throwable r12) {
/* JADX: method processing error */
/*
Error: java.util.NoSuchElementException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1431)
at java.util.HashMap$KeyIterator.next(HashMap.java:1453)
at jadx.core.dex.visitors.blocksmaker.BlockFinallyExtract.applyRemove(BlockFinallyExtract.java:535)
at jadx.core.dex.visitors.blocksmaker.BlockFinallyExtract.extractFinally(BlockFinallyExtract.java:175)
at jadx.core.dex.visitors.blocksmaker.BlockFinallyExtract.processExceptionHandler(BlockFinallyExtract.java:79)
at jadx.core.dex.visitors.blocksmaker.BlockFinallyExtract.visit(BlockFinallyExtract.java:51)
at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:31)
at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:17)
at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:14)
at jadx.core.ProcessClass.process(ProcessClass.java:37)
at jadx.core.ProcessClass.processDependencies(ProcessClass.java:59)
at jadx.core.ProcessClass.process(ProcessClass.java:42)
at jadx.api.JadxDecompiler.processClass(JadxDecompiler.java:306)
at jadx.api.JavaClass.decompile(JavaClass.java:62)
at jadx.api.JadxDecompiler$1.run(JadxDecompiler.java:199)
*/
/*
r10 = this;
r9 = 1;
r8 = 0;
r6 = com.newrelic.agent.android.Agent.getUnityInstrumentationFlag();
r7 = "YES";
r6 = r6.equals(r7);
if (r6 != 0) goto L_0x0020;
L_0x000e:
r6 = r10.handledException;
r6 = r6.compareAndSet(r8, r9);
if (r6 != 0) goto L_0x0020;
L_0x0016:
r6 = com.newrelic.agent.android.stats.StatsEngine.get();
r7 = "Supportability/AgentHealth/Recursion/UncaughtExceptionHandler";
r6.inc(r7);
L_0x001f:
return;
L_0x0020:
r6 = com.newrelic.agent.android.crashes.CrashReporter.instance; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.isEnabled; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
if (r6 == 0) goto L_0x002e; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x0026:
r6 = com.newrelic.agent.android.FeatureFlag.CrashReporting; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.FeatureFlag.featureEnabled(r6); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
if (r6 != 0) goto L_0x0051; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x002e:
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.log; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = "A crash has been detected but crash reporting is disabled!"; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.debug(r7); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r10.chainExceptionHandler(r11, r12); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.this;
r6.storeSupportabilityMetrics();
r6 = com.newrelic.agent.android.Agent.getUnityInstrumentationFlag();
r7 = "YES";
r6 = r6.equals(r7);
if (r6 != 0) goto L_0x001f;
L_0x004d:
r10.chainExceptionHandler(r11, r12);
goto L_0x001f;
L_0x0051:
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.log; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = new java.lang.StringBuilder; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7.(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = "A crash has been detected in "; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.append(r8); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = r11.getStackTrace(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r9 = 0; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = r8[r9]; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = r8.getClassName(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.append(r8); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = " and will be reported ASAP."; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.append(r8); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.toString(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.debug(r7); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r6.log; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = new java.lang.StringBuilder; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = "Analytics data is currently "; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = r6.append(r8); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.agentConfiguration; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.getEnableAnalyticsEvents(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
if (r6 == 0) goto L_0x0127; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x0099:
r6 = "enabled "; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x009b:
r6 = r8.append(r6); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.toString(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7.debug(r6); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r0 = com.newrelic.agent.android.analytics.AnalyticsControllerImpl.getInstance(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = 1; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r0.setEnabled(r6); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r4 = com.newrelic.agent.android.harvest.Harvest.getMillisSinceStart(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = 0; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = (r4 > r6 ? 1 : (r4 == r6 ? 0 : -1)); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
if (r6 == 0) goto L_0x00c2; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x00b8:
r6 = "sessionDuration"; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = (float) r4; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = 1148846080; // 0x447a0000 float:1000.0 double:5.676053805E-315; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7 / r8; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = 0; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r0.setAttribute(r6, r7, r8); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x00c2:
r1 = new com.newrelic.agent.android.harvest.crash.Crash; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r0.getSessionAttributes(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r0.getEventManager(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.getQueuedEvents(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = com.newrelic.agent.android.crashes.CrashReporter.agentConfiguration; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = r8.getEnableAnalyticsEvents(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r1.(r12, r6, r7, r8); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.crashStore; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.store(r1); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.reportCrash(r1); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.Agent.getUnityInstrumentationFlag(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = "YES"; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.equals(r7); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
if (r6 != 0) goto L_0x0111; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x00f5:
r6 = com.newrelic.agent.android.crashes.CrashReporter.executor; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.shutdown(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.executor; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = 10000; // 0x2710 float:1.4013E-41 double:4.9407E-320; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = java.util.concurrent.TimeUnit.MILLISECONDS; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = r6.awaitTermination(r8, r7); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
if (r6 != 0) goto L_0x0111; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x010a:
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = "Crash upload thread(s) timed-out before completion"; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.recordFailedUpload(r7); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x0111:
r6 = com.newrelic.agent.android.crashes.CrashReporter.this;
r6.storeSupportabilityMetrics();
r6 = com.newrelic.agent.android.Agent.getUnityInstrumentationFlag();
r7 = "YES";
r6 = r6.equals(r7);
if (r6 != 0) goto L_0x001f;
L_0x0122:
r10.chainExceptionHandler(r11, r12);
goto L_0x001f;
L_0x0127:
r6 = "disabled"; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
goto L_0x009b; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
L_0x012b:
r2 = move-exception; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = new java.lang.StringBuilder; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7.(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r8 = "Exception caught while sending crash: "; Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.append(r8); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.append(r2); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r7 = r7.toString(); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
r6.recordFailedUpload(r7); Catch:{ Exception -> 0x012b, Throwable -> 0x0145 }
goto L_0x0111;
L_0x0145:
r3 = move-exception;
r6 = com.newrelic.agent.android.crashes.CrashReporter.this; Catch:{ all -> 0x0174 }
r7 = new java.lang.StringBuilder; Catch:{ all -> 0x0174 }
r7.(); Catch:{ all -> 0x0174 }
r8 = "Error encountered while preparing crash for New Relic! "; Catch:{ all -> 0x0174 }
r7 = r7.append(r8); Catch:{ all -> 0x0174 }
r7 = r7.append(r3); Catch:{ all -> 0x0174 }
r7 = r7.toString(); Catch:{ all -> 0x0174 }
r6.recordFailedUpload(r7); Catch:{ all -> 0x0174 }
r6 = com.newrelic.agent.android.crashes.CrashReporter.this;
r6.storeSupportabilityMetrics();
r6 = com.newrelic.agent.android.Agent.getUnityInstrumentationFlag();
r7 = "YES";
r6 = r6.equals(r7);
if (r6 != 0) goto L_0x001f;
L_0x016f:
r10.chainExceptionHandler(r11, r12);
goto L_0x001f;
L_0x0174:
r6 = move-exception;
r7 = com.newrelic.agent.android.crashes.CrashReporter.this;
r7.storeSupportabilityMetrics();
r7 = com.newrelic.agent.android.Agent.getUnityInstrumentationFlag();
r8 = "YES";
r7 = r7.equals(r8);
if (r7 != 0) goto L_0x0189;
L_0x0186:
r10.chainExceptionHandler(r11, r12);
L_0x0189:
throw r6;
*/
throw new UnsupportedOperationException("Method not decompiled: com.newrelic.agent.android.crashes.CrashReporter.UncaughtExceptionHandler.uncaughtException(java.lang.Thread, java.lang.Throwable):void");
}
private void chainExceptionHandler(Thread thread, Throwable throwable) {
if (CrashReporter.this.previousExceptionHandler != null) {
CrashReporter.this.log.debug("Chaining crash reporting duties to " + CrashReporter.this.previousExceptionHandler.getClass().getSimpleName());
CrashReporter.this.previousExceptionHandler.uncaughtException(thread, throwable);
}
}
}
public static void initialize(AgentConfiguration _agentConfiguration) {
if (initialized.compareAndSet(false, true)) {
executor = Executors.newCachedThreadPool(new NamedThreadFactory("CrashUploader"));
agentConfiguration = _agentConfiguration;
instance.isEnabled = agentConfiguration.getReportCrashes();
instance.crashStore = agentConfiguration.getCrashStore();
executor.submit(new C03461());
if (instance.isEnabled) {
instance.installCrashHandler();
}
}
}
public static AgentConfiguration getAgentConfiguration() {
return agentConfiguration;
}
public UncaughtExceptionHandler getHandler() {
return new UncaughtExceptionHandler();
}
public static UncaughtExceptionHandler getInstanceHandler() {
return instance.getHandler();
}
public static void setReportCrashes(boolean reportCrashes) {
instance.reportCrashes = reportCrashes;
}
public static int getStoredCrashCount() {
return instance.crashStore.count();
}
public static List fetchAllCrashes() {
return instance.crashStore.fetchAll();
}
public static void clear() {
instance.crashStore.clear();
}
private void installCrashHandler() {
Thread.UncaughtExceptionHandler currentExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
if (currentExceptionHandler == null) {
this.log.debug("Installing New Relic crash handler.");
} else if (currentExceptionHandler instanceof UncaughtExceptionHandler) {
this.log.debug("New Relic crash handler already installed.");
return;
} else {
this.previousExceptionHandler = currentExceptionHandler;
this.log.debug("Installing New Relic crash handler and chaining " + this.previousExceptionHandler.getClass().getName());
}
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
}
protected void reportSavedCrashes() {
for (Crash crash : this.crashStore.fetchAll()) {
if (crash.isStale()) {
this.crashStore.delete(crash);
this.log.info("Crash [" + crash.getUuid().toString() + "] has become stale, and has been removed");
StatsEngine.get().inc(MetricNames.SUPPORTABILITY_CRASH_REMOVED_STALE);
} else {
reportCrash(crash);
}
}
}
protected Future> reportCrash(Crash crash) {
if (!this.reportCrashes) {
return null;
}
return executor.submit(new CrashSender(crash));
}
protected void recordFailedUpload(String errorMsg) {
this.log.error(errorMsg);
StatsEngine.get().inc(MetricNames.SUPPORTABILITY_CRASH_FAILED_UPLOAD);
}
protected void storeSupportabilityMetrics() {
ConcurrentHashMap statsMap = StatsEngine.get().getStatsMap();
}
protected void reportSupportabilityMetrics() {
}
private boolean requestWasSuccessful(HttpURLConnection connection) throws IOException {
switch (connection.getResponseCode()) {
case 200:
return true;
default:
this.log.error("[crashsender] Server returned " + Integer.valueOf(connection.getResponseCode()).toString());
return false;
}
}
private boolean hasReachableNetworkConnection() {
try {
return InetAddress.getByName(agentConfiguration.getCrashCollectorHost()).isReachable(CRASH_COLLECTOR_TIMEOUT);
} catch (IOException e) {
return false;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy