当前位置:网站首页>Interpretation of the source code of all logging systems in XXL job (line by line source code interpretation)
Interpretation of the source code of all logging systems in XXL job (line by line source code interpretation)
2022-07-25 22:18:00 【It's hard not to write code all day】
Catalog
1 Look for log related files
xxl-job in , Where will logs be used , That is, in each implementation process , Will log , Executing an error on the server will save the log , And we open the page , When checking the log , Will call the interface , View log information from the background
- The first is the relevant code file that records the log

We are using xxl-job When logging, you only need to use... During task execution XxlJobHelper.log() that will do , Methods and log4j/slf4j It's as simple as .
You write code , Want to log , Then write directly
XxlJobHelper.log("hello world");
Behind the above code will Format the log content first , That is to format the messy log information better , Or become an entity class , After that , The formatted log information Save as a file
- client Interface to view logs in real time
We open the project of task scheduling center , To view the log of a task in real time , Click log information , Will call the interface
The front end calls this method Call to view
logDetailCat()


When the execution status is incomplete ,xxl-job The log console will call the interface repeatedly until the task is completed .
2 Save the log related code file
In the core source code , It involves these documents

We are in our own project , Log , It uses
XxlJobHelper.log(“hello world”);
So start with this method , The file of this method is

Go in and find this method , There are two methods of the same name , One is our ordinary log recorder , One is to log exceptions , Is in the catch In which the log is recorded

Let's first look at logging exceptions , It's usually in catch Log inside
/** * append exception stack * Add exception stack * @param e */
public static boolean log(Throwable e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
// Change exception to character string
String appendLog = stringWriter.toString();
// Get and call this log Methodical All information about class methods
StackTraceElement callInfo = new Throwable().getStackTrace()[1];
// Last call Another way to save
return logDetail(callInfo, appendLog);
}
And then look at Record general information Log information
/** * append log with pattern * Append log with mode * @param appendLogPattern like "aaa {} bbb {} ccc" * @param appendLogArguments like "111, true" String[] str2={"rrrr","yyyyy"}; */
public static boolean log(String appendLogPattern, Object ... appendLogArguments) {
// Use slf4j The parser formats the log contents
FormattingTuple ft = MessageFormatter.arrayFormat(appendLogPattern, appendLogArguments);
String appendLog = ft.getMessage(); // aaa rrrr bbb yyyyy ccc
/*appendLog = appendLogPattern; if (appendLogArguments!=null && appendLogArguments.length>0) { appendLog = MessageFormat.format(appendLogPattern, appendLogArguments); }*/
// Get stack frame information
// This is the method to get the call stack frame , Indexes 0 For the current stack frame ,
// 1 Call stack frame for , And so on , What you get here is the index 1,
// In other words, the stack frame information of calling the method is obtained ,
// Can pass StackTraceElement Get the calling class name , Method name , Lines and so on
StackTraceElement callInfo = new Throwable().getStackTrace()[1];
// Record journal
return logDetail(callInfo, appendLog);
}
The above two log() The end calls
logDetail(callInfo, appendLog)
Parameters callInfo Is all the information of the caller ,appendLog Is the specific log information
/** * append log * Additional journal * @param callInfo Which method calls this log Method , Just put all the information of which method Save to StackTraceElement in * @param appendLog The log we want to record */
private static boolean logDetail(StackTraceElement callInfo, String appendLog) {
// Get the current context object
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return false;
}
/*// "yyyy-MM-dd HH:mm:ss [ClassName]-[MethodName]-[LineNumber]-[ThreadName] log"; StackTraceElement[] stackTraceElements = new Throwable().getStackTrace(); StackTraceElement callInfo = stackTraceElements[1];*/
// Splice and format log information
// It's splicing Which method records which journal
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(DateUtil.formatDateTime(new Date())).append(" ")
.append("["+ callInfo.getClassName() + "#" + callInfo.getMethodName() +"]").append("-")
.append("["+ callInfo.getLineNumber() +"]").append("-")
.append("["+ Thread.currentThread().getName() +"]").append(" ")
.append(appendLog!=null?appendLog:"");
// The log information of the last splicing It contains Which method records which log
String formatAppendLog = stringBuffer.toString();
// appendlog // Get log file path
String logFileName = xxlJobContext.getJobLogFileName();
if (logFileName!=null && logFileName.trim().length()>0) {
// Write the log to the local file in the form of stream
// According to the log file path , Write the spliced things in
XxlJobFileAppender.appendLog(logFileName, formatAppendLog);
return true;
} else {
logger.info(">>>>>>>>>>> {}", formatAppendLog);
return false;
}
}
The above code means ; After formatting the incoming log information , call XxlJobFileAppender.appendLog(logFileName, formatAppendLog);
Preservation
I went to this file 
/** * append log * Add log content * @param logFileName Log path * @param appendLog Log contents */
public static void appendLog(String logFileName, String appendLog) {
// log file
if (logFileName==null || logFileName.trim().length()==0) {
return;
}
File logFile = new File(logFileName);
if (!logFile.exists()) {
try {
logFile.createNewFile();
} catch (IOException e) {
logger.error(e.getMessage(), e);
return;
}
}
// log
if (appendLog == null) {
appendLog = "";
}
appendLog += "\r\n";
// append file content
FileOutputStream fos = null;
try {
fos = new FileOutputStream(logFile, true);
fos.write(appendLog.getBytes("utf-8"));
fos.flush();
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
}
The above code is Save it in a specific file 了
3 The server calls the log information in real time

/** * When we open the task log in the background , The server will pull logs from the client * @author xuxueli 2015-12-19 16:13:16 * The server Address * Trigger time * Mission id * Read from line number * * When the execution status is incomplete ,xxl-job The log console will call the interface repeatedly until the task is completed . */
@RequestMapping("/logDetailCat")
@ResponseBody
public ReturnT<LogResult> logDetailCat(String executorAddress, long triggerTime, long logId, int fromLineNum){
try {
// according to Address Create a remote call object
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(executorAddress);
// Read Log information
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(triggerTime, logId, fromLineNum));
// is end Judge whether the log is over
if (logResult.getContent()!=null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
// Log id Get log information from the database
XxlJobLog jobLog = xxlJobLogDao.load(logId);
// If Execution status Greater than 0
if (jobLog.getHandleCode() > 0) {
// Set up result by TRUE
logResult.getContent().setEnd(true);
}
}
return logResult;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
}
}
边栏推荐
- El expression improves JSP
- [Fantan] how to design a test platform?
- Redis memory elimination mechanism?
- After 2 years of functional testing, I feel like I can't do anything. Where should I go in 2022?
- Playwright tutorial (II) suitable for Xiaobai
- Fill the whole square with the float property
- Wechat official account application development (I)
- arcgis开发常用源码
- 编译和反编译
- The technical aspects of ByteDance are all over, but the result is still brushed. Ask HR why...
猜你喜欢

H5幸运刮刮乐抽奖 免公众号+直运营

Playwright tutorial (I) suitable for Xiaobai

关于接口测试你想知道的都在这儿了

【汇编语言01】基础知识

【GO基础02】第一个程序

Wechat applet application development competition works comprehensive development record - Jinlu cultural tourism (cloud development - Overview)

TFrecord写入与读取
![[assembly language 01] basic knowledge](/img/df/d586288b8f41211141bc4e2bca20cf.png)
[assembly language 01] basic knowledge

Guiding principles of information security construction

Selenium basic use and use selenium to capture the recruitment information of a website (continuously updating)
随机推荐
什么是分区分桶?
How to call the size of two numbers with a function--- Xiao Tang
What is partition and barrel division?
How is it most convenient to open an account for stock speculation? Is it safe for online account managers to open an account
Redisv6.0为何引入多线程?
Selenium basic use and use selenium to capture the recruitment information of a website (continuously updating)
Div drag effect
6-18 vulnerability exploitation - backdoor connection
测试工作不受重视,你换位思考了吗?
Whether the five distribution methods will produce internal fragments and external fragments
What is class loading? Class loading process?
Minor GC 和 Full GC 有什么不同呢?
Don't know mock test yet? An article to familiarize you with mock
How many bytes does Boolean occupy?
MapGIS格式转ArcGIS方法
力矩电机控制基本原理
Recursive case -c
[fan Tan] those stories that seem to be thinking of the company but are actually very selfish (I: building wheels)
C language: random generated number + bubble sort
[fan Tan] in detail: lower control, upward management, upward drawing cake.