package cn.qaiu.parser.customjs; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 演练场日志收集器 * 收集JavaScript执行过程中的日志信息 * 注意:为避免Nashorn对Java重载方法的选择问题,所有日志方法都使用Object参数 * * @author QAIU */ public class JsPlaygroundLogger { private static final Logger log = LoggerFactory.getLogger(JsPlaygroundLogger.class); // 使用线程安全的列表 private static final int MAX_LOG_SIZE = 1000; private final List logs = Collections.synchronizedList(new ArrayList<>()); /** * 日志条目 */ public static class LogEntry { private final String level; private final String message; private final long timestamp; private final String source; // "JS" 或 "JAVA" public LogEntry(String level, String message, String source) { this.level = level; this.message = message; this.timestamp = System.currentTimeMillis(); this.source = source; } public String getLevel() { return level; } public String getMessage() { return message; } public long getTimestamp() { return timestamp; } public String getSource() { return source; } } /** * 将任意对象转为字符串 */ private String toString(Object obj) { if (obj == null) { return "null"; } return obj.toString(); } /** * 添加日志条目,超过最大容量时移除最早的条目 */ private void addLog(LogEntry entry) { synchronized (logs) { if (logs.size() >= MAX_LOG_SIZE) { logs.remove(0); } logs.add(entry); } } /** * 记录日志(内部方法) * @param level 日志级别 * @param message 日志消息 * @param source 日志来源:"JS" 或 "JAVA" */ private void log(String level, Object message, String source) { String msg = toString(message); addLog(new LogEntry(level, msg, source)); log.debug("[{}PlaygroundLogger] {}: {}", source, level, msg); } /** * 调试日志(供JavaScript调用) * 使用Object参数避免Nashorn重载选择问题 */ public void debug(Object message) { log("DEBUG", message, "JS"); } /** * 信息日志(供JavaScript调用) * 使用Object参数避免Nashorn重载选择问题 */ public void info(Object message) { log("INFO", message, "JS"); } /** * 警告日志(供JavaScript调用) * 使用Object参数避免Nashorn重载选择问题 */ public void warn(Object message) { log("WARN", message, "JS"); } /** * 错误日志(供JavaScript调用) * 使用Object参数避免Nashorn重载选择问题 */ public void error(Object message) { log("ERROR", message, "JS"); } /** * 错误日志(带异常,供JavaScript调用) */ public void error(Object message, Throwable throwable) { String msg = toString(message); if (throwable != null) { msg = msg + ": " + throwable.getMessage(); } addLog(new LogEntry("ERROR", msg, "JS")); log.debug("[JSPlaygroundLogger] ERROR: {}", msg); } // ===== 以下是供Java层调用的内部方法 ===== /** * 调试日志(供Java层调用) */ public void debugJava(String message) { log("DEBUG", message, "JAVA"); } /** * 信息日志(供Java层调用) */ public void infoJava(String message) { log("INFO", message, "JAVA"); } /** * 警告日志(供Java层调用) */ public void warnJava(String message) { log("WARN", message, "JAVA"); } /** * 错误日志(供Java层调用) */ public void errorJava(String message) { log("ERROR", message, "JAVA"); } /** * 错误日志(带异常,供Java层调用) */ public void errorJava(String message, Throwable throwable) { String msg = message; if (throwable != null) { msg = msg + ": " + throwable.getMessage(); } addLog(new LogEntry("ERROR", msg, "JAVA")); log.debug("[JAVAPlaygroundLogger] ERROR: {}", msg); } /** * 获取所有日志 */ public List getLogs() { synchronized (logs) { return new ArrayList<>(logs); } } /** * 获取日志数量 */ public int size() { return logs.size(); } /** * 清空日志 */ public void clear() { logs.clear(); } }