重构Rolling日志读写逻辑,解决边界条件下异常情况,优化读写性能;

3.3.0-release
xuxueli 10 months ago
parent 790cc86348
commit 39165fd82f

@ -1,17 +1,22 @@
package com.xxl.job.core.log; package com.xxl.job.core.log;
import com.xxl.job.core.openapi.model.LogResult; import com.xxl.job.core.openapi.model.LogResult;
import com.xxl.tool.core.DateTool;
import com.xxl.tool.core.StringTool; import com.xxl.tool.core.StringTool;
import com.xxl.tool.io.FileTool;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.*; import java.io.File;
import java.nio.charset.StandardCharsets; import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
/** /**
* store trigger log in each log-file * store trigger log in each log-file
*
* @author xuxueli 2016-3-12 19:25:12 * @author xuxueli 2016-3-12 19:25:12
*/ */
public class XxlJobFileAppender { public class XxlJobFileAppender {
@ -31,23 +36,19 @@ public class XxlJobFileAppender {
private static String logBasePath = "/data/applogs/xxl-job/jobhandler"; private static String logBasePath = "/data/applogs/xxl-job/jobhandler";
private static String glueSrcPath = logBasePath.concat(File.separator).concat("gluesource"); private static String glueSrcPath = logBasePath.concat(File.separator).concat("gluesource");
private static String callbackLogPath = logBasePath.concat(File.separator).concat("callbacklogs"); private static String callbackLogPath = logBasePath.concat(File.separator).concat("callbacklogs");
public static void initLogPath(String logPath){ public static void initLogPath(String logPath) throws IOException {
// init // init
if (StringTool.isNotBlank(logPath)) { if (StringTool.isNotBlank(logPath)) {
logBasePath = logPath.trim(); logBasePath = logPath.trim();
} }
// mk base dir // mk base dir
File logPathDir = new File(logBasePath); File logPathDir = new File(logBasePath);
if (!logPathDir.exists()) { FileTool.createDirectories(logPathDir);
logPathDir.mkdirs();
}
logBasePath = logPathDir.getPath(); logBasePath = logPathDir.getPath();
// mk glue dir // mk glue dir
File glueBaseDir = new File(logPathDir, "gluesource"); File glueBaseDir = new File(logPathDir, "gluesource");
if (!glueBaseDir.exists()) { FileTool.createDirectories(glueBaseDir);
glueBaseDir.mkdirs();
}
glueSrcPath = glueBaseDir.getPath(); glueSrcPath = glueBaseDir.getPath();
} }
public static String getLogPath() { public static String getLogPath() {
@ -63,25 +64,24 @@ public class XxlJobFileAppender {
/** /**
* log filename, like "logPath/yyyy-MM-dd/9999.log" * log filename, like "logPath/yyyy-MM-dd/9999.log"
* *
* @param triggerDate * @param logId log id
* @param logId * @return log file name
* @return
*/ */
public static String makeLogFileName(Date triggerDate, long logId) { public static String makeLogFileName(Date triggerDate, long logId) {
// filePath/yyyy-MM-dd // "filePath/yyyy-MM-dd"
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // avoid concurrent problem, can not be static File logFilePath = new File(getLogPath(), DateTool.formatDate(triggerDate));
File logFilePath = new File(getLogPath(), sdf.format(triggerDate)); try {
if (!logFilePath.exists()) { FileTool.createDirectories(logFilePath);
logFilePath.mkdir(); } catch (IOException e) {
throw new RuntimeException("XxlJobFileAppender makeLogFileName error, logFilePath:"+ logFilePath.getPath(), e);
} }
// filePath/yyyy-MM-dd/9999.log // filePath/yyyy-MM-dd/9999.log
String logFileName = logFilePath.getPath() return logFilePath.getPath()
.concat(File.separator) .concat(File.separator)
.concat(String.valueOf(logId)) .concat(String.valueOf(logId))
.concat(".log"); .concat(".log");
return logFileName;
} }
/** /**
@ -92,34 +92,17 @@ public class XxlJobFileAppender {
*/ */
public static void appendLog(String logFileName, String appendLog) { public static void appendLog(String logFileName, String appendLog) {
// log file // valid
if (logFileName==null || logFileName.trim().isEmpty()) { if (StringTool.isBlank(logFileName) || appendLog == null) {
return; return;
} }
File logFile = new File(logFileName);
if (!logFile.exists()) { // append log
try { try {
logFile.createNewFile(); FileTool.writeLines(logFileName, List.of(appendLog), true);
} catch (IOException e) { } catch (IOException e) {
logger.error(e.getMessage(), e); throw new RuntimeException("XxlJobFileAppender appendLog error, logFileName:"+ logFileName, e);
return;
}
}
// log
if (appendLog == null) {
appendLog = "";
} }
appendLog += "\r\n";
// append file content
try (FileOutputStream fos = new FileOutputStream(logFile, true)) {
fos.write(appendLog.getBytes(StandardCharsets.UTF_8));
fos.flush();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} }
/** /**
@ -129,53 +112,52 @@ public class XxlJobFileAppender {
* @param fromLineNum from line num * @param fromLineNum from line num
* @return log content * @return log content
*/ */
public static LogResult readLog(String logFileName, int fromLineNum){ public static LogResult readLog(String logFileName, final int fromLineNum){
// valid log file // valid
if (logFileName==null || logFileName.trim().isEmpty()) { if (StringTool.isBlank(logFileName)) {
return new LogResult(fromLineNum, 0, "readLog fail, logFile not found", true); return new LogResult(fromLineNum, 0, "readLog fail, logFile not found", true);
} }
File logFile = new File(logFileName); if (!FileTool.exists(logFileName)) {
if (!logFile.exists()) {
return new LogResult(fromLineNum, 0, "readLog fail, logFile not exists", true); return new LogResult(fromLineNum, 0, "readLog fail, logFile not exists", true);
} }
// read file // read data
StringBuilder logContentBuilder = new StringBuilder(); StringBuilder logContentBuilder = new StringBuilder();
LineNumberReader reader = null; // num: [from, to], start as 1
int toLineNum = 0; AtomicInteger toLineNum = new AtomicInteger(0);
AtomicInteger currentLineNum = new AtomicInteger(0);
/*int readLineCount = 0;*/ /*int readLineCount = 0;*/
// do read
try { try {
reader = new LineNumberReader(new InputStreamReader(new FileInputStream(logFile), StandardCharsets.UTF_8)); FileTool.readLines(logFileName, new Consumer<String>() {
String line = null; @Override
while ((line = reader.readLine())!=null) { public void accept(String line) {
// skip before lineNum // refresh line num
toLineNum = reader.getLineNumber(); // [from, to], start as 1 currentLineNum.incrementAndGet();
if (toLineNum < fromLineNum) {
continue; // valid
if (currentLineNum.get() < fromLineNum) {
return;
} }
// append log
logContentBuilder.append(line).append("\n");
// Limit return less than 1000 rows per query request // todo // Limit return less than 1000 rows per query request // todo
/*if(++readLineCount >= 5) { /*if(++readLineCount >= 1000) {
break; break;
}*/ }*/
// collect line data
toLineNum.set(currentLineNum.get());
logContentBuilder.append(line).append(System.lineSeparator()); // [from, to], start as 1
} }
});
} catch (IOException e) { } catch (IOException e) {
logger.error(e.getMessage(), e); logger.error("XxlJobFileAppender readLog error, logFileName:{}, fromLineNum:{}", logFileName, fromLineNum, e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
} }
// result // result
return new LogResult(fromLineNum, toLineNum, logContentBuilder.toString(), false); return new LogResult(fromLineNum, toLineNum.get(), logContentBuilder.toString(), false);
} }
} }

Loading…
Cancel
Save