mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-12 13:26:53 -04:00
feat(countly): initial
This commit is contained in:
parent
026239903d
commit
08054f3026
87
HMCL/src/main/java/org/jackhuang/hmcl/countly/Countly.java
Normal file
87
HMCL/src/main/java/org/jackhuang/hmcl/countly/Countly.java
Normal 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 = "";
|
||||||
|
}
|
104
HMCL/src/main/java/org/jackhuang/hmcl/countly/CrashReport.java
Normal file
104
HMCL/src/main/java/org/jackhuang/hmcl/countly/CrashReport.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,7 @@ import javafx.application.Platform;
|
|||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Alert.AlertType;
|
import javafx.scene.control.Alert.AlertType;
|
||||||
import org.jackhuang.hmcl.Metadata;
|
import org.jackhuang.hmcl.Metadata;
|
||||||
|
import org.jackhuang.hmcl.countly.CrashReport;
|
||||||
import org.jackhuang.hmcl.ui.CrashWindow;
|
import org.jackhuang.hmcl.ui.CrashWindow;
|
||||||
import org.jackhuang.hmcl.upgrade.IntegrityChecker;
|
import org.jackhuang.hmcl.upgrade.IntegrityChecker;
|
||||||
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
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("com.sun.javafx.css.StyleManager.findMatchingStyles", i18n("launcher.update_java")),
|
||||||
pair("NoSuchAlgorithmException", "Has your operating system been installed completely or is a ghost system?")
|
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) {
|
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);
|
LOG.log(Level.SEVERE, "Uncaught exception in thread " + t.getName(), e);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String stackTrace = StringUtils.getStackTrace(e);
|
CrashReport report = new CrashReport(t, e);
|
||||||
if (!stackTrace.contains("org.jackhuang"))
|
if (!report.shouldBeReport())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Hole.CAUGHT_EXCEPTIONS.contains(stackTrace))
|
String text = report.getDisplayText();
|
||||||
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";
|
|
||||||
|
|
||||||
LOG.log(Level.SEVERE, text);
|
LOG.log(Level.SEVERE, text);
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
@ -132,7 +113,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
|
|||||||
new CrashWindow(text).show();
|
new CrashWindow(text).show();
|
||||||
}
|
}
|
||||||
if (!UpdateChecker.isOutdated() && IntegrityChecker.isSelfVerified()) {
|
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(() -> {
|
Thread t = new Thread(() -> {
|
||||||
HashMap<String, String> map = new HashMap<>();
|
HashMap<String, String> map = new HashMap<>();
|
||||||
map.put("crash_report", text);
|
map.put("crash_report", crashReport.getDisplayText());
|
||||||
map.put("version", Metadata.VERSION);
|
map.put("version", Metadata.VERSION);
|
||||||
map.put("log", Logging.getLogs());
|
map.put("log", Logging.getLogs());
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user