| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- package com.example.client.util;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.PrintStream;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- /**
- * Lightweight local logging for a standalone Java desktop client.
- * Change APP_NAME and package before use.
- */
- public final class AppLog {
- private static final String APP_NAME = "client";
- private static final Object LOCK = new Object();
- private static final SimpleDateFormat TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
- private static PrintStream out;
- private static volatile String exitReason;
- private static volatile String uncaughtThread;
- private static volatile Throwable uncaughtException;
- private AppLog() { }
- public static void init() {
- synchronized (LOCK) {
- if (out != null) return;
- try {
- File code = new File(AppLog.class.getProtectionDomain().getCodeSource().getLocation().toURI());
- File base = code.isFile() ? code.getParentFile() : new File(System.getProperty("user.dir"));
- File dir = new File(base, "logs");
- if (!dir.exists() && !dir.mkdirs()) return;
- String day = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
- out = new PrintStream(new FileOutputStream(new File(dir, APP_NAME + "-" + day + ".log"), true), true, "UTF-8");
- Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
- public void uncaughtException(Thread thread, Throwable exception) {
- exitReason = "UNCAUGHT_EXCEPTION";
- uncaughtThread = thread.getName();
- uncaughtException = exception;
- }
- });
- Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
- public void run() {
- if ("USER_CLOSE".equals(exitReason)) {
- log("INFO", "Client exited, reason=user-close", null);
- } else if ("UNCAUGHT_EXCEPTION".equals(exitReason)) {
- log("ERROR", "Client exited, reason=uncaught-exception, thread=" + clean(uncaughtThread), uncaughtException);
- }
- }
- }, APP_NAME + "-log-shutdown"));
- } catch (Exception ignored) {
- // Logging is best-effort and must not stop client startup.
- }
- }
- }
- public static void login(String userId, String method, boolean success) {
- log(success ? "INFO" : "WARN", "Login " + (success ? "succeeded" : "failed")
- + ", method=" + clean(method) + ", user=" + clean(userId), null);
- }
- public static void scan(String type, String code) {
- log("INFO", "Scan, type=" + clean(type) + ", code=" + clean(code), null);
- }
- public static void work(String action, String code, boolean success) {
- log(success ? "INFO" : "WARN", "Operation " + (success ? "succeeded" : "failed")
- + ", action=" + clean(action) + ", code=" + clean(code), null);
- }
- public static void markUserClose() {
- exitReason = "USER_CLOSE";
- }
- private static String clean(String value) {
- return value == null ? "" : value.replace('\r', ' ').replace('\n', ' ');
- }
- private static void log(String level, String message, Throwable exception) {
- synchronized (LOCK) {
- if (out == null) return;
- out.println("[" + TIME.format(new Date()) + "][" + level + "]["
- + Thread.currentThread().getName() + "] " + message);
- if (exception != null) exception.printStackTrace(out);
- out.flush();
- }
- }
- }
|