package com.vci.ubcs.log.service.impl; import com.vci.ubcs.log.vo.LocalLogVO; import com.vci.ubcs.log.service.ILogLocalService; import com.vci.ubcs.log.entity.LocalLog; import com.vci.ubcs.resource.utils.FileUtil; import com.vci.ubcs.resource.utils.ZipUtil; import com.vci.ubcs.starter.exception.VciBaseException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.springblade.core.log.exception.ServiceException; import com.vci.ubcs.omd.cache.EnumCache; import com.vci.ubcs.omd.enums.EnumEnum; import com.vci.ubcs.resource.bo.FileObjectBO; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.Func; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.*; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.rmi.ServerException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * 本地系统日志 * @author ludc * @date 2023/10/31 15:39 */ @Service @Slf4j public class LogLocalServiceImpl implements ILogLocalService{ /** * 各个服务存放的的父路径 */ @Value("${local-log.parent-path:/data1/ubcs/ubcs-server}") private String PARENTPATH; /** * 日志文件的具体位置 */ @Value("${local-log.log-path:/target/log}") private String LOGPATH; /** * 当前操作系统,是否为windows系统 */ private Boolean isWindows = true; { String os = System.getProperty("os.name").toLowerCase(); //默认就配置为windows的,如果不是当前系统不是windows就需要对其转换为linux的文件路径格式 if (!os.contains("win")) { this.PARENTPATH = this.PARENTPATH.substring(this.PARENTPATH.lastIndexOf(":") + 1).replace("\\", "/"); this.LOGPATH = this.LOGPATH.replace("\\", "/"); this.isWindows = false; } } /** * 压缩文件的工具类 */ @Resource private ZipUtil zipUtil; /** * 获取本地日志列表 * @param logParentPath * @return */ //@Override public List getSystemLogList(String logParentPath) { List localLogs = new ArrayList<>(); // 不为空说明是加载当前这个服务路径下的日志文件 if(Func.isNotEmpty(logParentPath)){ File file = new File(logParentPath); if (file.isDirectory()) { File[] files = file.listFiles(); Arrays.stream(files).forEach(item->{ // 组建日志文件对象 LocalLog localLog = new LocalLog(); localLog.setLogName(item.getName()); localLog.setLogType(getLogType(item.getName())); localLog.setCreateTime(getLastModifiedOrCreatTime(false,logParentPath)); localLog.setLastModifier(getLastModifiedOrCreatTime(true,logParentPath)); localLog.setLogPath(logParentPath); String serviceId = getServiceId(logParentPath); localLog.setServiceId(serviceId); localLog.setServiceName(getServiceName(serviceId)); localLog.setHasChildren(false); localLogs.add(localLog); }); } }else { File fileDir = new File(PARENTPATH); File[] childDir = fileDir.listFiles(); Arrays.stream(childDir).forEach(dir->{ if(dir.getName().contains("ubcs_")){ String fullPath = dir.getPath() + LOGPATH; File file = new File(fullPath); LocalLog localLog = new LocalLog(); localLog.setLastModifier(getLastModifiedOrCreatTime(true,fullPath)); localLog.setCreateTime(getLastModifiedOrCreatTime(false,fullPath)); localLog.setLogPath(fullPath); String serviceId = getServiceId(file.getPath()); localLog.setServiceId(serviceId); String serviceName = getServiceName(serviceId); localLog.setServiceName(serviceName); localLog.setLogType(serviceName+"日志父目录"); localLog.setLogName(serviceName+"日志父目录"); localLog.setHasChildren(true); localLogs.add(localLog); } }); } return localLogs; } /** * 获取文件最后修改或者创建时间 * @param isModifier * @return */ private String getLastModifiedOrCreatTime(boolean isModifier,String pathStr) { Path path = FileSystems.getDefault().getPath(pathStr); String date = ""; try { BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 是获取最后修改时间 if(isModifier){ date = dateFormat.format(new Date(attr.lastModifiedTime().toMillis())); }else { date = dateFormat.format(new Date(attr.creationTime().toMillis())); } } catch (IOException e) { throw new ServiceException("Error reading file date attributes: " + e.getMessage()); } return date; } /** * 获取日志类型 * @param fileName * @return */ private String getLogType(String fileName){ //判断日志的的类型 if (fileName.contains("error")) { return "Error"; } else if (fileName.contains("info")) { return "Info"; } else if (fileName.contains("warning")) { return "Warning"; } else { return "Unknown"; } } /** * 获取服务ID * @param servciePath * @return */ private String getServiceId(String servciePath){ // 根据当前操作系统来决定是通过什么字符来截取 String[] parts = servciePath.split(this.isWindows ? "\\\\":"/"); String extractedString = ""; if(parts.length > 3){ extractedString = parts[parts.length - 3]; } return extractedString; } /** * 获取服务名称 * @param serViceId * @return */ private String getServiceName(String serViceId){ return EnumCache.getValue(EnumEnum.SERCIVE_NAME_ROLE, serViceId); } /** * 截取路径中的日志文件名称 * @param logFullPath * @return */ private String getLogFileName(String logFullPath){ // 根据当前操作系统来决定是通过什么字符来截取 String[] parts = logFullPath.split(this.isWindows ? "\\\\":"/"); String logFileName = ""; if(parts.length > 3){ logFileName = parts[parts.length - 1]; } return logFileName; } /** * 下载日志文件 * @param localLogVO 下载日志对象 * @return * @throws ServerException */ @Override public FileObjectBO downloadLogByServiceNameAndFileName(LocalLogVO localLogVO) throws ServerException { if(Func.isEmpty(localLogVO) || Func.isEmpty(localLogVO.getLogPath())){ throw new ServerException("未获取到该日志路径!"); } FileObjectBO fileObjectBO = new FileObjectBO(); String logFullPaths = localLogVO.getLogFullPaths(); // 判断是否是父目录 if(!localLogVO.getHasChildren()){ //只下载一个日志文件 File file = new File(logFullPaths); if(!file.isFile() || !file.exists()){ throw new ServerException("本地日志文件路径"+ logFullPaths +"中未找到日志"); } try { fileObjectBO.setName(file.getName()); fileObjectBO.setInputStream(new FileInputStream(file)); fileObjectBO.setFileLocalPath(logFullPaths); fileObjectBO.setFileExtension(".log"); }catch (Throwable e){ throw new VciBaseException("获取文件的流有问题",new String[]{logFullPaths},e); } }else{ // 是父目录,所以需要获取到下面的所有子目录 // 有多个,需要使用zip进行压缩 String tempFolder = FileUtil.getDefaultTempFolder(); File[] file1 = new File(logFullPaths).listFiles(); if(file1.length > 0){ Arrays.stream(file1).forEach(item->{ String fileName = tempFolder + File.separator + System.currentTimeMillis() + ".log"; File file = new File(fileName); try { if(!file.exists()) { file.createNewFile(); } }catch (Throwable e){ throw new VciBaseException("创建文件出错,{0}",new String[]{fileName}); } File logFile = new File(item.getPath()); if(!logFile.exists() || !logFile.isFile()){ throw new VciBaseException("本地日志文件路径"+item.getPath()+"中未找到日志"); } try(OutputStream os = new FileOutputStream(file); InputStream ins = new FileInputStream(logFile); ){ IOUtils.copy(ins,os); }catch (Throwable e){ throw new VciBaseException("下载文件到临时文件夹里出错,{0}",new String[]{fileName}); } }); String zipName = new File(tempFolder).getPath() + File.separator + getLogFileName(logFullPaths) + "等"+file1.length + "个文件.zip"; zipUtil.folderToZipFile(tempFolder,zipName); fileObjectBO.setFileLocalPath(zipName); fileObjectBO.setFileExtension(".log"); if(log.isDebugEnabled()){ log.debug("下载文件的信息,",zipName); } } } return fileObjectBO; } /** * 删除日志文件 * @param localLogVO 文件全路径集合 * @throws ServerException */ @Override public R deleteLogFile(LocalLogVO localLogVO) throws ServerException { List resMsgs = new ArrayList<>(); // 判断是否是日志顶层目录 if(localLogVO.getHasChildren()){ // 是顶层目录,需要循环去删除包含的所有日志文件 File parentFile = new File(localLogVO.getLogFullPaths()); if(parentFile.isDirectory()){ Arrays.stream(parentFile.listFiles()).forEach(logFile->{ if (logFile.exists()) { //删除失败的直接记录下文件名 if (!logFile.delete()) { resMsgs.add(getLogFileName(logFile.getPath())); } } }); } }else { // 单个删除 File file = new File(localLogVO.getLogFullPaths()); if (file.exists()) { //删除失败的直接记录下文件名 if (!file.delete()) { resMsgs.add(getLogFileName(localLogVO.getLogFullPaths())); } } } return resMsgs.size()==0 ? R.success("删除成功!"):R.fail("以下日志文件:"+resMsgs.stream().collect(Collectors.joining(","))+"删除失败!"); } }