fix(ccdi-project): remove local upload log files

This commit is contained in:
wkc
2026-03-10 10:25:23 +08:00
parent 924605ac3a
commit 1241ba0bd6
4 changed files with 37 additions and 166 deletions

View File

@@ -1,110 +0,0 @@
package com.ruoyi.ccdi.project.log;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* File upload batch log appender.
*/
@Slf4j
public class FileUploadLogAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
private static final ThreadLocal<FileAppender<ILoggingEvent>> currentAppender = new ThreadLocal<>();
private PatternLayout layout;
@Override
public void start() {
LoggerContext loggerContext = resolveLoggerContext();
setContext(loggerContext);
this.layout = new PatternLayout();
this.layout.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n");
this.layout.setContext(loggerContext);
this.layout.start();
super.start();
log.info("【文件上传日志】FileUploadLogAppender已启动");
}
@Override
protected void append(ILoggingEvent event) {
FileAppender<ILoggingEvent> appender = currentAppender.get();
if (appender != null) {
appender.doAppend(event);
}
}
/**
* Create a dedicated batch log file.
*
* @param uploadPath upload root path from ruoyi.profile
* @param projectId project id
* @param batchId batch id
*/
public static void createBatchLogFile(String uploadPath, Long projectId, String batchId) {
try {
LoggerContext loggerContext = resolveLoggerContext();
String timestamp = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date());
String logDirPath = uploadPath + File.separator + "logs" + File.separator
+ "file-upload" + File.separator + projectId;
File logDir = new File(logDirPath);
if (!logDir.exists() && !logDir.mkdirs()) {
throw new IllegalStateException("无法创建批次日志目录: " + logDirPath);
}
String logFilePath = logDirPath + File.separator + timestamp + ".log";
FileAppender<ILoggingEvent> appender = new FileAppender<>();
appender.setContext(loggerContext);
appender.setFile(logFilePath);
PatternLayout layout = new PatternLayout();
layout.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n");
layout.setContext(loggerContext);
layout.start();
appender.setLayout(layout);
appender.setAppend(true);
appender.start();
currentAppender.set(appender);
log.info("【文件上传日志】创建批次日志文件成功: path={}, batchId={}", logFilePath, batchId);
} catch (Exception e) {
log.error("【文件上传日志】创建批次日志文件失败: projectId={}, batchId={}", projectId, batchId, e);
}
}
/**
* Close the current batch log file.
*/
public static void closeBatchLogFile() {
FileAppender<ILoggingEvent> appender = currentAppender.get();
if (appender != null) {
appender.stop();
currentAppender.remove();
log.info("【文件上传日志】关闭批次日志文件");
}
}
private static LoggerContext resolveLoggerContext() {
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
if (loggerFactory instanceof LoggerContext loggerContext) {
return loggerContext;
}
throw new IllegalStateException("SLF4J logger factory is not a Logback LoggerContext");
}
}

View File

@@ -7,7 +7,6 @@ import com.ruoyi.ccdi.project.domain.dto.CcdiFileUploadQueryDTO;
import com.ruoyi.ccdi.project.domain.entity.CcdiBankStatement;
import com.ruoyi.ccdi.project.domain.entity.CcdiFileUploadRecord;
import com.ruoyi.ccdi.project.domain.vo.CcdiFileUploadStatisticsVO;
import com.ruoyi.ccdi.project.log.FileUploadLogAppender;
import com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper;
import com.ruoyi.ccdi.project.mapper.CcdiFileUploadRecordMapper;
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
@@ -269,10 +268,6 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
String batchId) {
log.info("【文件上传】调度线程启动: projectId={}, batchId={}", projectId, batchId);
// 创建批次日志文件
FileUploadLogAppender.createBatchLogFile(uploadPath, projectId, batchId);
try {
// 循环提交任务
for (int i = 0; i < tempFilePaths.size(); i++) {
// Critical Fix #6: 检查线程中断状态
@@ -319,10 +314,6 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
}
log.info("【文件上传】调度线程完成: projectId={}, batchId={}", projectId, batchId);
} finally {
// 关闭批次日志文件
FileUploadLogAppender.closeBatchLogFile();
}
}
/**

View File

@@ -1,44 +0,0 @@
package com.ruoyi.ccdi.project.log;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.lang.reflect.Field;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
class FileUploadLogAppenderTest {
@TempDir
Path tempDir;
@AfterEach
void tearDown() {
FileUploadLogAppender.closeBatchLogFile();
}
@Test
void createBatchLogFile_shouldInitializeAppenderWithLoggerContext() throws Exception {
FileUploadLogAppender.createBatchLogFile(tempDir.toString(), 32L, "batch-1");
FileAppender<ILoggingEvent> appender = currentAppender();
assertNotNull(appender);
assertNotNull(appender.getContext());
assertTrue(appender.isStarted());
}
@SuppressWarnings("unchecked")
private FileAppender<ILoggingEvent> currentAppender() throws Exception {
Field field = FileUploadLogAppender.class.getDeclaredField("currentAppender");
field.setAccessible(true);
ThreadLocal<FileAppender<ILoggingEvent>> threadLocal =
(ThreadLocal<FileAppender<ILoggingEvent>>) field.get(null);
return threadLocal.get();
}
}

View File

@@ -18,10 +18,13 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -56,9 +59,25 @@ class CcdiFileUploadServiceImplTest {
@Mock
private CcdiBankStatementMapper bankStatementMapper;
@Mock
private Executor fileUploadExecutor;
@TempDir
Path tempDir;
@Test
void submitTasksAsync_shouldNotCreateLocalBatchLogFiles() throws Exception {
setField("uploadPath", tempDir.toString());
Path tempFile = createTempFile();
CcdiFileUploadRecord record = buildRecord();
invokeSubmitTasksAsync(List.of(tempFile.toString()), List.of(record), "batch-1");
Path batchLogDir = tempDir.resolve("logs").resolve("file-upload").resolve(String.valueOf(PROJECT_ID));
assertFalse(Files.exists(batchLogDir));
}
@Test
void processFileAsync_shouldKeepParsingUntilBankStatementsSaved() throws IOException {
List<String> events = new ArrayList<>();
@@ -279,6 +298,21 @@ class CcdiFileUploadServiceImplTest {
return response;
}
private void invokeSubmitTasksAsync(List<String> tempFilePaths,
List<CcdiFileUploadRecord> records,
String batchId) throws Exception {
Method method = CcdiFileUploadServiceImpl.class.getDeclaredMethod("submitTasksAsync",
Long.class, Integer.class, List.class, List.class, String.class);
method.setAccessible(true);
method.invoke(service, PROJECT_ID, LSFX_PROJECT_ID, tempFilePaths, records, batchId);
}
private void setField(String fieldName, Object value) throws Exception {
Field field = CcdiFileUploadServiceImpl.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(service, value);
}
private int findEventIndex(List<String> events, String suffix) {
for (int i = 0; i < events.size(); i++) {
if (events.get(i).endsWith(suffix)) {