Init crash reports

This commit is contained in:
Sergey Karmanov 2020-11-02 16:30:14 +03:00
parent b59c4bdc2b
commit 384b2047ac
7 changed files with 189 additions and 4 deletions

View File

@ -20,6 +20,9 @@ package ru.windcorp.progressia.client;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import ru.windcorp.progressia.ProgressiaLauncher;
import ru.windcorp.progressia.common.util.crash.CrashReportGenerator;
import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer;
import ru.windcorp.progressia.common.util.crash.providers.OSContextProvider;
public class ProgressiaClientMain {
@ -28,6 +31,15 @@ public class ProgressiaClientMain {
public static void main(String[] args) {
logger.info("App started!");
CrashReportGenerator.registerProvider(new OSContextProvider());
CrashReportGenerator.registerAnalyzer(new OutOfMemoryAnalyzer());
try {
long[] ssdss = new long[1 << 30];
} catch (Throwable t)
{
CrashReportGenerator.makeCrashReport(t, "");
}
ProgressiaLauncher.launch(args, new ClientProxy());
}

View File

@ -0,0 +1,5 @@
package ru.windcorp.progressia.common.util.crash;
public interface Analyzer {
String getPrompt(Throwable throwable, String messageFormat, Object... args);
}

View File

@ -0,0 +1,8 @@
package ru.windcorp.progressia.common.util.crash;
import java.util.Map;
public interface ContextProvider {
Map<String, String> provideContext();
}

View File

@ -0,0 +1,134 @@
package ru.windcorp.progressia.common.util.crash;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
public class CrashReportGenerator {
private CrashReportGenerator() {
}
final static File latestLogFile = new File("crash-reports/latest.log");
private static Collection<ContextProvider> providers = new ArrayList<ContextProvider>();
private static Collection<Map<String, String>> providerResponse = new ArrayList<Map<String, String>>();
private static Collection<Analyzer> analyzers = new ArrayList<Analyzer>();
private static Collection<String> analyzerResponse = new ArrayList<String>();
private static final Logger logger = LogManager.getLogger("crash");
static public void makeCrashReport(Throwable throwable, String messageFormat, Object... args) {
StringBuilder output = new StringBuilder();
for (ContextProvider currentProvider : providers) {
if (currentProvider != null) {
providerResponse.add(currentProvider.provideContext());
}
}
if (throwable != null) {
for (Analyzer currentAnalyzer : analyzers) {
if (currentAnalyzer != null) {
analyzerResponse.add(currentAnalyzer.getPrompt(throwable, messageFormat, args));
}
}
}
for (Map<String, String> currentProviderResponse : providerResponse) {
if (currentProviderResponse != null && !currentProviderResponse.isEmpty()) {
addSeparator(output);
for (Map.Entry<String, String> entry : currentProviderResponse.entrySet()) {
output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
}
}
}
for (String currentPrompt : analyzerResponse) {
if (currentPrompt != null && !currentPrompt.isEmpty()) {
addSeparator(output);
output.append(currentPrompt).append("\n");
}
}
// Formatting to a human-readable string
StringWriter sink = new StringWriter();
if (throwable != null) {
try {
throwable.printStackTrace(new PrintWriter(sink));
} catch (Exception e) {
// PLAK
}
} else {
sink.append("Null");
}
logger.info("\n" + output.toString());
logger.fatal("Stacktrace: \n" + sink.toString());
addSeparator(output);
output.append("Stacktrace: \n");
output.append(sink.toString()).append("\n");
try {
System.err.println(output.toString());
} catch (Exception e) {
// PLAK
}
createFileForCrashReport(output);
createFileForLatestCrashReport(output);
System.exit(0);
}
public static void createFileForCrashReport(StringBuilder sb) {
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
File logFile = new File("crash-reports/" + "crash-" + dateFormat.format(date) + ".log");
try (FileOutputStream fos = new FileOutputStream(logFile)) {
byte[] buffer = sb.toString().getBytes();
fos.write(buffer, 0, buffer.length);
} catch (IOException ex) {
// Crash Report not created
}
}
public static void createFileForLatestCrashReport(StringBuilder sb) {
try (FileOutputStream fos = new FileOutputStream(latestLogFile)) {
byte[] buffer = sb.toString().getBytes();
fos.write(buffer, 0, buffer.length);
} catch (IOException ex) {
// Crash Report not created
}
}
public static void registerProvider(ContextProvider provider) {
providers.add(provider);
}
public static void registerAnalyzer(Analyzer analyzer) {
analyzers.add(analyzer);
}
private static void addSeparator(StringBuilder sb) {
sb.append("-------------------------------------------------").append("\n");
}
}

View File

@ -0,0 +1,12 @@
package ru.windcorp.progressia.common.util.crash.analyzers;
import ru.windcorp.progressia.common.util.crash.Analyzer;
public class OutOfMemoryAnalyzer implements Analyzer {
@Override
public String getPrompt(Throwable throwable, String messageFormat, Object... args) {
if (throwable instanceof OutOfMemoryError)
return "Try add memory for the JVM";
return null;
}
}

View File

@ -0,0 +1,18 @@
package ru.windcorp.progressia.common.util.crash.providers;
import ru.windcorp.progressia.common.util.crash.ContextProvider;
import java.util.HashMap;
import java.util.Map;
public class OSContextProvider implements ContextProvider {
@Override
public Map<String, String> provideContext() {
Map<String, String> theThings = new HashMap<>();
theThings.put("Name OS", System.getProperty("os.name"));
theThings.put("Version OS", System.getProperty("os.version"));
theThings.put("Architecture OS", System.getProperty("os.arch"));
return theThings;
}
}

View File

@ -13,18 +13,14 @@
<RollingFile name="FileLog" fileName="${APP_LOG_ROOT}/game.log"
filePattern="${APP_LOG_ROOT}/game-%d{yyyy-MM-dd}-%i.log">
<LevelRangeFilter minLevel="FATAL" maxLevel="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="18MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="FileLog" />
<AppenderRef ref="Console" />