feat(countly): initial

This commit is contained in:
huanghongxun 2021-10-27 00:21:32 +08:00
parent 026239903d
commit 08054f3026
3 changed files with 198 additions and 26 deletions

View File

@ -0,0 +1,87 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.countly;
import org.jackhuang.hmcl.util.io.HttpRequest;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import static org.jackhuang.hmcl.util.Pair.pair;
public class Countly {
private String deviceId;
private String endpoint;
private String serverURL;
public void sendMetric(String metrics) throws IOException {
HttpRequest.GET(serverURL + endpoint,
pair("begin_session", "1"),
pair("session_id", "1"),
pair("metrics", metrics),
pair("device_id", deviceId),
pair("timestamp", Long.toString(System.currentTimeMillis())),
pair("tz", Integer.toString(TimeZone.getDefault().getOffset(new Date().getTime()) / 60000)),
pair("hour", Integer.toString(currentHour())),
pair("dow", Integer.toString(currentDayOfWeek())),
pair("app_key", APP_KEY),
pair("sdk_name", "java-native"),
pair("sdk_version", "20.11.1"))
.getString();
}
private static int getTimezoneOffset() {
return TimeZone.getDefault().getOffset(new Date().getTime()) / 60000;
}
private static String getLocale() {
final Locale locale = Locale.getDefault();
return locale.getLanguage() + "_" + locale.getCountry();
}
private static int currentHour() {
return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
}
private int currentDayOfWeek() {
int day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
switch (day) {
case Calendar.SUNDAY:
return 0;
case Calendar.MONDAY:
return 1;
case Calendar.TUESDAY:
return 2;
case Calendar.WEDNESDAY:
return 3;
case Calendar.THURSDAY:
return 4;
case Calendar.FRIDAY:
return 5;
case Calendar.SATURDAY:
return 6;
}
return 0;
}
private static final String APP_KEY = "";
}

View File

@ -0,0 +1,104 @@
package org.jackhuang.hmcl.countly;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.util.CrashReporter;
import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.platform.Architecture;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import static org.jackhuang.hmcl.util.Lang.mapOf;
import static org.jackhuang.hmcl.util.Pair.pair;
public class CrashReport {
private final Thread thread;
private final Throwable throwable;
private final String stackTrace;
private boolean nonFatal;
public CrashReport(Thread thread, Throwable throwable) {
this.thread = thread;
this.throwable = throwable;
stackTrace = StringUtils.getStackTrace(throwable);
nonFatal = false;
}
public CrashReport setNonFatal() {
nonFatal = true;
return this;
}
public boolean shouldBeReport() {
if (!stackTrace.contains("org.jackhuang"))
return false;
return true;
}
public Map<String, Object> getMetrics(long runningTime) {
return mapOf(
pair("_run", runningTime),
pair("_app_version", Metadata.VERSION),
pair("_os", OperatingSystem.SYSTEM_NAME),
pair("_os_version", OperatingSystem.SYSTEM_VERSION),
pair("_disk_current", getDiskAvailable()),
pair("_disk_total", getDiskTotal()),
pair("_ram_current", getMemoryAvailable()),
pair("_ram_total", Runtime.getRuntime().maxMemory() / BYTES_IN_MB),
pair("_error", stackTrace),
pair("_logs", Logging.getLogs()),
pair("_name", throwable.getLocalizedMessage()),
pair("_nonfatal", nonFatal)
);
}
public String getDisplayText() {
return "---- Hello Minecraft! Crash Report ----\n" +
" Version: " + Metadata.VERSION + "\n" +
" Time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\n" +
" Thread: " + thread + "\n" +
"\n Content: \n " +
stackTrace + "\n\n" +
"-- System Details --\n" +
" Operating System: " + OperatingSystem.SYSTEM_NAME + ' ' + OperatingSystem.SYSTEM_VERSION + "\n" +
" System Architecture: " + Architecture.SYSTEM_ARCH_NAME + "\n" +
" Java Architecture: " + Architecture.CURRENT_ARCH_NAME + "\n" +
" Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor") + "\n" +
" Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor") + "\n" +
" JVM Max Memory: " + Runtime.getRuntime().maxMemory() + "\n" +
" JVM Total Memory: " + Runtime.getRuntime().totalMemory() + "\n" +
" JVM Free Memory: " + Runtime.getRuntime().freeMemory() + "\n";
}
private static final Long BYTES_IN_MB = 1024L * 1024;
private static long getMemoryAvailable() {
Long total = Runtime.getRuntime().totalMemory();
Long availMem = Runtime.getRuntime().freeMemory();
return (total - availMem) / BYTES_IN_MB;
}
private static long getDiskAvailable() {
long total = 0, free = 0;
for (File f : File.listRoots()) {
total += f.getTotalSpace();
free += f.getUsableSpace();
}
return (total - free) / BYTES_IN_MB;
}
private static long getDiskTotal() {
long total = 0;
for (File f : File.listRoots()) {
total += f.getTotalSpace();
}
return total / BYTES_IN_MB;
}
}

View File

@ -21,6 +21,7 @@ import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.countly.CrashReport;
import org.jackhuang.hmcl.ui.CrashWindow;
import org.jackhuang.hmcl.upgrade.IntegrityChecker;
import org.jackhuang.hmcl.upgrade.UpdateChecker;
@ -65,8 +66,6 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
pair("com.sun.javafx.css.StyleManager.findMatchingStyles", i18n("launcher.update_java")),
pair("NoSuchAlgorithmException", "Has your operating system been installed completely or is a ghost system?")
};
static final Set<String> CAUGHT_EXCEPTIONS = newSetFromMap(new ConcurrentHashMap<>());
}
private boolean checkThrowable(Throwable e) {
@ -101,29 +100,11 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
LOG.log(Level.SEVERE, "Uncaught exception in thread " + t.getName(), e);
try {
String stackTrace = StringUtils.getStackTrace(e);
if (!stackTrace.contains("org.jackhuang"))
CrashReport report = new CrashReport(t, e);
if (!report.shouldBeReport())
return;
if (Hole.CAUGHT_EXCEPTIONS.contains(stackTrace))
return;
Hole.CAUGHT_EXCEPTIONS.add(stackTrace);
String text = "---- Hello Minecraft! Crash Report ----\n" +
" Version: " + Metadata.VERSION + "\n" +
" Time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\n" +
" Thread: " + t + "\n" +
"\n Content: \n " +
stackTrace + "\n\n" +
"-- System Details --\n" +
" Operating System: " + OperatingSystem.SYSTEM_NAME + ' ' + OperatingSystem.SYSTEM_VERSION + "\n" +
" System Architecture: " + Architecture.SYSTEM_ARCH_NAME + "\n" +
" Java Architecture: " + Architecture.CURRENT_ARCH_NAME + "\n" +
" Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor") + "\n" +
" Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor") + "\n" +
" JVM Max Memory: " + Runtime.getRuntime().maxMemory() + "\n" +
" JVM Total Memory: " + Runtime.getRuntime().totalMemory() + "\n" +
" JVM Free Memory: " + Runtime.getRuntime().freeMemory() + "\n";
String text = report.getDisplayText();
LOG.log(Level.SEVERE, text);
Platform.runLater(() -> {
@ -132,7 +113,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
new CrashWindow(text).show();
}
if (!UpdateChecker.isOutdated() && IntegrityChecker.isSelfVerified()) {
reportToServer(text);
reportToServer(report);
}
}
});
@ -141,10 +122,10 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
}
}
private void reportToServer(final String text) {
private void reportToServer(CrashReport crashReport) {
Thread t = new Thread(() -> {
HashMap<String, String> map = new HashMap<>();
map.put("crash_report", text);
map.put("crash_report", crashReport.getDisplayText());
map.put("version", Metadata.VERSION);
map.put("log", Logging.getLogs());
try {