update 22
This commit is contained in:
@@ -7,10 +7,16 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import research.loghunter.dto.ErrorLogDto;
|
||||
import research.loghunter.dto.FileTreeDto;
|
||||
import research.loghunter.entity.ErrorLog;
|
||||
import research.loghunter.entity.Server;
|
||||
import research.loghunter.repository.ErrorLogRepository;
|
||||
import research.loghunter.repository.ScannedFileRepository;
|
||||
import research.loghunter.repository.ServerRepository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@@ -18,11 +24,14 @@ import java.time.LocalDateTime;
|
||||
public class ErrorLogService {
|
||||
|
||||
private final ErrorLogRepository errorLogRepository;
|
||||
private final ScannedFileRepository scannedFileRepository;
|
||||
private final ServerRepository serverRepository;
|
||||
|
||||
public Page<ErrorLogDto> search(
|
||||
Long serverId,
|
||||
Long patternId,
|
||||
String severity,
|
||||
String filePath,
|
||||
LocalDateTime startDate,
|
||||
LocalDateTime endDate,
|
||||
String keyword,
|
||||
@@ -31,7 +40,7 @@ public class ErrorLogService {
|
||||
) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
Page<ErrorLog> errorLogs = errorLogRepository.searchErrors(
|
||||
serverId, patternId, severity, startDate, endDate, keyword, pageable);
|
||||
serverId, patternId, severity, filePath, startDate, endDate, keyword, pageable);
|
||||
|
||||
return errorLogs.map(this::toDto);
|
||||
}
|
||||
@@ -48,6 +57,125 @@ public class ErrorLogService {
|
||||
.orElseThrow(() -> new RuntimeException("ErrorLog not found: " + id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 트리 구조 데이터 조회
|
||||
*/
|
||||
public List<FileTreeDto.ServerNode> getFileTree() {
|
||||
// 파일별 에러 통계 조회
|
||||
List<Object[]> stats = errorLogRepository.getFileErrorStats();
|
||||
|
||||
// 서버별로 그룹핑
|
||||
Map<Long, List<Object[]>> serverGroups = new LinkedHashMap<>();
|
||||
for (Object[] stat : stats) {
|
||||
Long serverId = ((Number) stat[0]).longValue();
|
||||
serverGroups.computeIfAbsent(serverId, k -> new ArrayList<>()).add(stat);
|
||||
}
|
||||
|
||||
List<FileTreeDto.ServerNode> result = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<Long, List<Object[]>> entry : serverGroups.entrySet()) {
|
||||
Long serverId = entry.getKey();
|
||||
List<Object[]> serverStats = entry.getValue();
|
||||
|
||||
String serverName = (String) serverStats.get(0)[1];
|
||||
|
||||
// 경로별로 그룹핑
|
||||
Map<String, List<FileTreeDto.FileNode>> pathGroups = new LinkedHashMap<>();
|
||||
int serverTotalErrors = 0;
|
||||
|
||||
for (Object[] stat : serverStats) {
|
||||
String filePath = (String) stat[2];
|
||||
int errorCount = ((Number) stat[3]).intValue();
|
||||
int criticalCount = ((Number) stat[4]).intValue();
|
||||
int errorLevelCount = ((Number) stat[5]).intValue();
|
||||
int warnCount = ((Number) stat[6]).intValue();
|
||||
|
||||
// 경로와 파일명 분리
|
||||
int lastSlash = filePath.lastIndexOf('/');
|
||||
String path = lastSlash > 0 ? filePath.substring(0, lastSlash) : "/";
|
||||
String fileName = lastSlash > 0 ? filePath.substring(lastSlash + 1) : filePath;
|
||||
|
||||
FileTreeDto.FileNode fileNode = FileTreeDto.FileNode.builder()
|
||||
.filePath(filePath)
|
||||
.fileName(fileName)
|
||||
.errorCount(errorCount)
|
||||
.criticalCount(criticalCount)
|
||||
.errorLevelCount(errorLevelCount)
|
||||
.warnCount(warnCount)
|
||||
.build();
|
||||
|
||||
pathGroups.computeIfAbsent(path, k -> new ArrayList<>()).add(fileNode);
|
||||
serverTotalErrors += errorCount;
|
||||
}
|
||||
|
||||
// PathNode 생성
|
||||
List<FileTreeDto.PathNode> pathNodes = new ArrayList<>();
|
||||
for (Map.Entry<String, List<FileTreeDto.FileNode>> pathEntry : pathGroups.entrySet()) {
|
||||
List<FileTreeDto.FileNode> files = pathEntry.getValue();
|
||||
int pathTotalErrors = files.stream().mapToInt(FileTreeDto.FileNode::getErrorCount).sum();
|
||||
|
||||
pathNodes.add(FileTreeDto.PathNode.builder()
|
||||
.path(pathEntry.getKey())
|
||||
.totalErrorCount(pathTotalErrors)
|
||||
.files(files)
|
||||
.build());
|
||||
}
|
||||
|
||||
result.add(FileTreeDto.ServerNode.builder()
|
||||
.serverId(serverId)
|
||||
.serverName(serverName)
|
||||
.totalErrorCount(serverTotalErrors)
|
||||
.paths(pathNodes)
|
||||
.build());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버별 파일 목록 조회
|
||||
*/
|
||||
public List<String> getFilesByServer(Long serverId) {
|
||||
if (serverId == null) {
|
||||
return errorLogRepository.findDistinctFilePaths();
|
||||
}
|
||||
return errorLogRepository.findDistinctFilePathsByServerId(serverId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 선택한 ID들의 에러 삭제
|
||||
*/
|
||||
@Transactional
|
||||
public int deleteByIds(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return errorLogRepository.deleteByIdIn(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 삭제 (에러로그 + 스캔기록)
|
||||
*/
|
||||
@Transactional
|
||||
public Map<String, Object> deleteFileAndErrors(Long serverId, String filePath) {
|
||||
int deletedErrors = errorLogRepository.deleteByServerIdAndFilePath(serverId, filePath);
|
||||
int deletedFiles = scannedFileRepository.deleteByServerIdAndFilePath(serverId, filePath);
|
||||
|
||||
return Map.of(
|
||||
"success", true,
|
||||
"deletedErrors", deletedErrors,
|
||||
"deletedScannedFiles", deletedFiles
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버+파일 기준 에러 삭제
|
||||
*/
|
||||
@Transactional
|
||||
public int deleteByServerAndFile(Long serverId, String filePath) {
|
||||
return errorLogRepository.deleteByServerIdAndFilePath(serverId, filePath);
|
||||
}
|
||||
|
||||
private ErrorLogDto toDto(ErrorLog errorLog) {
|
||||
return ErrorLogDto.builder()
|
||||
.id(errorLog.getId())
|
||||
|
||||
Reference in New Issue
Block a user