自定义日志管理
This commit is contained in:
parent
5061f4f140
commit
dd3f70c324
@ -0,0 +1,32 @@
|
|||||||
|
// LogbackConfig.java
|
||||||
|
package com.goeing.printserver.main.config;
|
||||||
|
|
||||||
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
|
import ch.qos.logback.classic.Logger;
|
||||||
|
import com.goeing.printserver.main.utils.MemoryLogAppender;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class LogbackConfig {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemoryLogAppender memoryLogAppender;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void registerAppender() {
|
||||||
|
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||||
|
|
||||||
|
// // 添加 appender 到 root logger
|
||||||
|
Logger rootLogger = context.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
||||||
|
rootLogger.addAppender(memoryLogAppender);
|
||||||
|
memoryLogAppender.start();
|
||||||
|
|
||||||
|
// 可选:也加到你的包 logger
|
||||||
|
// Logger appLogger = context.getLogger("com.goeing.printserver");
|
||||||
|
// appLogger.addAppender(memoryLogAppender);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.goeing.printserver.main.controller;
|
||||||
|
|
||||||
|
import com.goeing.printserver.main.utils.MemoryLogAppender;
|
||||||
|
import com.goeing.printserver.main.utils.MemoryLogStorage;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志控制器,提供日志相关的 API 接口
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/logs")
|
||||||
|
@Slf4j
|
||||||
|
public class LogController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemoryLogStorage memoryLogStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取系统日志
|
||||||
|
* @param limit 限制数量,默认100
|
||||||
|
* @param level 日志级别过滤,默认ALL
|
||||||
|
* @return 日志列表
|
||||||
|
*/
|
||||||
|
@GetMapping
|
||||||
|
public Map<String, Object> getLogs(
|
||||||
|
@RequestParam(defaultValue = "100") int limit,
|
||||||
|
@RequestParam(defaultValue = "ALL") String level) {
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<MemoryLogAppender.LogEntry> logs = memoryLogStorage.getLogs(limit, level);
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("logs", logs);
|
||||||
|
result.put("total", logs.size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取日志失败", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "获取日志失败: " + e.getMessage());
|
||||||
|
result.put("logs", List.of());
|
||||||
|
result.put("total", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空系统日志
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@DeleteMapping
|
||||||
|
public Map<String, Object> clearLogs() {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
memoryLogStorage.clearLogs();
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "日志已清空");
|
||||||
|
log.info("系统日志已被清空");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("清空日志失败", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "清空日志失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.goeing.printserver.main.utils;
|
||||||
|
|
||||||
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
|
import ch.qos.logback.core.AppenderBase;
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内存日志追加器,用于缓存日志到内存中
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class MemoryLogAppender extends AppenderBase<ILoggingEvent> {
|
||||||
|
@Autowired
|
||||||
|
private MemoryLogStorage memoryLogStorage; // ✅ Spring 注入,全局唯一
|
||||||
|
|
||||||
|
private static final DateTimeFormatter FORMATTER =
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
System.out.println("✅ MemoryLogAppender started with context: " + context);
|
||||||
|
super.start(); // 必须调用
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void append(ILoggingEvent event) {
|
||||||
|
if (!isStarted()) return;
|
||||||
|
|
||||||
|
LogEntry logEntry = new LogEntry(
|
||||||
|
LocalDateTime.now().format(FORMATTER),
|
||||||
|
event.getLevel().toString(),
|
||||||
|
event.getLoggerName(),
|
||||||
|
event.getFormattedMessage()
|
||||||
|
);
|
||||||
|
memoryLogStorage.addLog(logEntry); // 写入共享存储
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志条目类
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public static class LogEntry {
|
||||||
|
private final String timestamp;
|
||||||
|
private final String level;
|
||||||
|
private final String logger;
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
public LogEntry(String timestamp, String level, String logger, String message) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.level = level;
|
||||||
|
this.logger = logger;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package com.goeing.printserver.main.utils;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MemoryLogStorage {
|
||||||
|
|
||||||
|
private final Queue<MemoryLogAppender.LogEntry> logs = new ConcurrentLinkedQueue<>();
|
||||||
|
private static final int MAX_LOGS = 2000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加日志条目,并控制最大数量
|
||||||
|
*/
|
||||||
|
public void addLog(MemoryLogAppender.LogEntry logEntry) {
|
||||||
|
logs.offer(logEntry);
|
||||||
|
// 保持最多 MAX_LOGS 条
|
||||||
|
while (logs.size() > MAX_LOGS) {
|
||||||
|
logs.poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志列表(支持过滤和分页)
|
||||||
|
*/
|
||||||
|
public List<MemoryLogAppender.LogEntry> getLogs(int limit, String level) {
|
||||||
|
List<MemoryLogAppender.LogEntry> result = new ArrayList<>();
|
||||||
|
for (MemoryLogAppender.LogEntry log : logs) {
|
||||||
|
if (level == null || "ALL".equals(level) || level.equals(log.getLevel())) {
|
||||||
|
result.add(log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 最新的在前
|
||||||
|
result.sort((a, b) -> b.getTimestamp().compareTo(a.getTimestamp()));
|
||||||
|
// 限制数量
|
||||||
|
if (limit > 0 && result.size() > limit) {
|
||||||
|
return result.subList(0, limit);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空所有日志
|
||||||
|
*/
|
||||||
|
public void clearLogs() {
|
||||||
|
logs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日志数量(用于监控)
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return logs.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user