日志rollback展示
This commit is contained in:
parent
049091c4a8
commit
ae26cb0c5d
Binary file not shown.
After Width: | Height: | Size: 438 KiB |
|
@ -7,6 +7,7 @@ import com.xxl.job.admin.dao.IXxlJobGroupDao;
|
||||||
import com.xxl.job.admin.dao.IXxlJobInfoDao;
|
import com.xxl.job.admin.dao.IXxlJobInfoDao;
|
||||||
import com.xxl.job.admin.dao.IXxlJobLogDao;
|
import com.xxl.job.admin.dao.IXxlJobLogDao;
|
||||||
import com.xxl.job.core.biz.ExecutorBiz;
|
import com.xxl.job.core.biz.ExecutorBiz;
|
||||||
|
import com.xxl.job.core.biz.model.LogResult;
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
import com.xxl.job.core.biz.model.ReturnT;
|
||||||
import com.xxl.job.core.rpc.netcom.NetComClientProxy;
|
import com.xxl.job.core.rpc.netcom.NetComClientProxy;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
@ -92,43 +93,42 @@ public class JobLogController {
|
||||||
maps.put("data", list); // 分页列表
|
maps.put("data", list); // 分页列表
|
||||||
return maps;
|
return maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping("/logDetail")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> logDetail(int id){
|
|
||||||
// base check
|
|
||||||
XxlJobLog log = xxlJobLogDao.load(id);
|
|
||||||
if (log == null) {
|
|
||||||
return new ReturnT<String>(500, "查看执行日志失败: 参数异常");
|
|
||||||
}
|
|
||||||
if (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {
|
|
||||||
return new ReturnT<String>(500, "查看执行日志失败: 任务发起调度失败,无法查看执行日志");
|
|
||||||
}
|
|
||||||
|
|
||||||
// trigger id, trigger time
|
|
||||||
ExecutorBiz executorBiz = null;
|
|
||||||
try {
|
|
||||||
executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, log.getExecutorAddress()).getObject();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return new ReturnT<String>(500, e.getMessage());
|
|
||||||
}
|
|
||||||
ReturnT<String> logResult = executorBiz.log(log.getTriggerTime().getTime(), id);
|
|
||||||
|
|
||||||
if (ReturnT.SUCCESS_CODE == logResult.getCode()) {
|
|
||||||
return new ReturnT<String>(logResult.getMsg());
|
|
||||||
} else {
|
|
||||||
return new ReturnT<String>(500, "查看执行日志失败: " + logResult.getMsg());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/logDetailPage")
|
@RequestMapping("/logDetailPage")
|
||||||
public String logDetailPage(int id, Model model){
|
public String logDetailPage(int id, Model model){
|
||||||
ReturnT<String> data = logDetail(id);
|
|
||||||
model.addAttribute("result", data);
|
// base check
|
||||||
|
ReturnT<String> logStatue = ReturnT.SUCCESS;
|
||||||
|
XxlJobLog jobLog = xxlJobLogDao.load(id);
|
||||||
|
if (jobLog == null) {
|
||||||
|
logStatue = new ReturnT<String>(ReturnT.FAIL_CODE, "查看执行日志失败: 日志ID非法");
|
||||||
|
} else {
|
||||||
|
if (ReturnT.SUCCESS_CODE != jobLog.getTriggerCode()) {
|
||||||
|
logStatue = new ReturnT<String>(ReturnT.FAIL_CODE, "查看执行日志失败: 任务发起调度失败,无法查看执行日志");
|
||||||
|
}
|
||||||
|
|
||||||
|
model.addAttribute("executorAddress", jobLog.getExecutorAddress());
|
||||||
|
model.addAttribute("triggerTime", jobLog.getTriggerTime().getTime());
|
||||||
|
model.addAttribute("logId", jobLog.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
model.addAttribute("logStatue", logStatue);
|
||||||
return "joblog/logdetail";
|
return "joblog/logdetail";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/logDetailCat")
|
||||||
|
@ResponseBody
|
||||||
|
public ReturnT<LogResult> logDetailCat(String executorAddress, long triggerTime, int logId, int fromLineNum){
|
||||||
|
try {
|
||||||
|
ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, executorAddress).getObject();
|
||||||
|
ReturnT<LogResult> logResult = executorBiz.log(triggerTime, logId, fromLineNum);
|
||||||
|
return logResult;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@RequestMapping("/logKill")
|
@RequestMapping("/logKill")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public ReturnT<String> logKill(int id){
|
public ReturnT<String> logKill(int id){
|
||||||
|
|
|
@ -1,7 +1,95 @@
|
||||||
<body style="color:white;background-color:black;" >
|
<!DOCTYPE html>
|
||||||
<pre>
|
<html>
|
||||||
<br>
|
<head>
|
||||||
<#if result.code == 200>${result.content}
|
<title>任务调度中心</title>
|
||||||
<#else>${result.msg}</#if>
|
<#import "/common/common.macro.ftl" as netCommon>
|
||||||
</pre>
|
<@netCommon.commonStyle />
|
||||||
|
<style type="text/css">
|
||||||
|
.logConsolePre {
|
||||||
|
font-size:12px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/*bottom: 0;
|
||||||
|
top: 0px;*/
|
||||||
|
position: absolute;
|
||||||
|
/*color:white;background-color:black*/
|
||||||
|
}
|
||||||
|
.logConsoleRunning {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="skin-blue fixed layout-top-nav">
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<header class="main-header">
|
||||||
|
<nav class="navbar navbar-static-top">
|
||||||
|
<div class="container">
|
||||||
|
<#-- icon -->
|
||||||
|
<div class="navbar-header">
|
||||||
|
<a href="../../index2.html" class="navbar-brand"><b>日志</b>Console</a>
|
||||||
|
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
|
||||||
|
<i class="fa fa-bars"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#-- left nav -->
|
||||||
|
<div class="collapse navbar-collapse pull-left" id="navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<#--<li class="active" ><a href="javascript:;">任务:<span class="sr-only">(current)</span></a></li>-->
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#-- right nav -->
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:window.location.reload();" >
|
||||||
|
<i class="fa fa-fw fa-refresh" ></i>
|
||||||
|
刷新
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="content-wrapper" >
|
||||||
|
<pre class="logConsolePre"><div id="logConsole"></div><li class="fa fa-refresh fa-spin logConsoleRunning" ></li></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<@netCommon.commonScript />
|
||||||
|
<script>
|
||||||
|
|
||||||
|
// 参数
|
||||||
|
var running = true; // 允许运行
|
||||||
|
var executorAddress;
|
||||||
|
var triggerTime;
|
||||||
|
var logId;
|
||||||
|
|
||||||
|
// init
|
||||||
|
<#if logStatue.code == 200>
|
||||||
|
running = true;
|
||||||
|
$('.logConsoleRunning').show();
|
||||||
|
|
||||||
|
executorAddress = '${executorAddress}';
|
||||||
|
triggerTime = '${triggerTime}';
|
||||||
|
logId = '${logId}';
|
||||||
|
<#else>
|
||||||
|
running = false;
|
||||||
|
$('.logConsoleRunning').hide();
|
||||||
|
|
||||||
|
$('.logConsole').append('${logStatue.msg}');
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script src="${request.contextPath}/static/js/logdetail.index.1.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,78 @@
|
||||||
|
$(function() {
|
||||||
|
|
||||||
|
// valid
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载日志
|
||||||
|
var fromLineNum = 0;
|
||||||
|
var pullFailCount = 0;
|
||||||
|
function pullLog() {
|
||||||
|
|
||||||
|
// pullFailCount, max=20
|
||||||
|
if (pullFailCount >= 20) {
|
||||||
|
console.log("pullLog fail-count limit");
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// valid
|
||||||
|
if (!running) {
|
||||||
|
$('.logConsoleRunning').hide();
|
||||||
|
logRun = window.clearInterval(logRun)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load
|
||||||
|
console.log("pullLog, fromLineNum:" + fromLineNum);
|
||||||
|
$.ajax({
|
||||||
|
type : 'POST',
|
||||||
|
async: false, // async, avoid js invoke pagelist before jobId data init
|
||||||
|
url : base_url + '/joblog/logDetailCat',
|
||||||
|
data : {
|
||||||
|
"executorAddress":executorAddress,
|
||||||
|
"triggerTime":triggerTime,
|
||||||
|
"logId":logId,
|
||||||
|
"fromLineNum":fromLineNum
|
||||||
|
},
|
||||||
|
dataType : "json",
|
||||||
|
success : function(data){
|
||||||
|
pullFailCount++;
|
||||||
|
if (data.code == 200) {
|
||||||
|
if (!data.content) {
|
||||||
|
console.log('pullLog fail');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fromLineNum != data.content.fromLineNum) {
|
||||||
|
console.log('pullLog fromLineNum not match');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fromLineNum == (data.content.toLineNum + 1) ) {
|
||||||
|
console.log('pullLog already line-end');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append
|
||||||
|
fromLineNum = data.content.toLineNum + 1;
|
||||||
|
$('#logConsole').append(data.content.logContent);
|
||||||
|
pullFailCount = 0;
|
||||||
|
|
||||||
|
// valid end
|
||||||
|
if (data.content.end) {
|
||||||
|
running = false;
|
||||||
|
console.log("pullLog already file-end");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ComAlertTec.show(data.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 周期运行
|
||||||
|
pullLog();
|
||||||
|
var logRun = setInterval(function () {
|
||||||
|
pullLog()
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
});
|
|
@ -1,5 +1,6 @@
|
||||||
package com.xxl.job.core.biz;
|
package com.xxl.job.core.biz;
|
||||||
|
|
||||||
|
import com.xxl.job.core.biz.model.LogResult;
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
import com.xxl.job.core.biz.model.ReturnT;
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
import com.xxl.job.core.biz.model.TriggerParam;
|
||||||
|
|
||||||
|
@ -25,9 +26,10 @@ public interface ExecutorBiz {
|
||||||
* log
|
* log
|
||||||
* @param logDateTim
|
* @param logDateTim
|
||||||
* @param logId
|
* @param logId
|
||||||
|
* @param fromLineNum
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public ReturnT<String> log(long logDateTim, int logId);
|
public ReturnT<LogResult> log(long logDateTim, int logId, int fromLineNum);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* run
|
* run
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.xxl.job.core.biz.impl;
|
package com.xxl.job.core.biz.impl;
|
||||||
|
|
||||||
import com.xxl.job.core.biz.ExecutorBiz;
|
import com.xxl.job.core.biz.ExecutorBiz;
|
||||||
|
import com.xxl.job.core.biz.model.LogResult;
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
import com.xxl.job.core.biz.model.ReturnT;
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
import com.xxl.job.core.biz.model.TriggerParam;
|
||||||
import com.xxl.job.core.executor.XxlJobExecutor;
|
import com.xxl.job.core.executor.XxlJobExecutor;
|
||||||
|
@ -42,12 +43,12 @@ public class ExecutorBizImpl implements ExecutorBiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReturnT<String> log(long logDateTim, int logId) {
|
public ReturnT<LogResult> log(long logDateTim, int logId, int fromLineNum) {
|
||||||
// log filename: yyyy-MM-dd/9999.log
|
// log filename: yyyy-MM-dd/9999.log
|
||||||
String logFileName = XxlJobFileAppender.makeLogFileName(new Date(logDateTim), logId);
|
String logFileName = XxlJobFileAppender.makeLogFileName(new Date(logDateTim), logId);
|
||||||
|
|
||||||
String logConteng = XxlJobFileAppender.readLog(logFileName);
|
LogResult logResult = XxlJobFileAppender.readLog(logFileName, fromLineNum);
|
||||||
return new ReturnT<String>(ReturnT.SUCCESS_CODE, logConteng);
|
return new ReturnT<LogResult>(logResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.xxl.job.core.biz.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by xuxueli on 17/3/23.
|
||||||
|
*/
|
||||||
|
public class LogResult implements Serializable {
|
||||||
|
private static final long serialVersionUID = 42L;
|
||||||
|
|
||||||
|
private int fromLineNum;
|
||||||
|
private int toLineNum;
|
||||||
|
private String logContent;
|
||||||
|
private boolean isEnd;
|
||||||
|
|
||||||
|
public int getFromLineNum() {
|
||||||
|
return fromLineNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFromLineNum(int fromLineNum) {
|
||||||
|
this.fromLineNum = fromLineNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getToLineNum() {
|
||||||
|
return toLineNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToLineNum(int toLineNum) {
|
||||||
|
this.toLineNum = toLineNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogContent() {
|
||||||
|
return logContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogContent(String logContent) {
|
||||||
|
this.logContent = logContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnd() {
|
||||||
|
return isEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnd(boolean end) {
|
||||||
|
isEnd = end;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.xxl.job.core.log;
|
package com.xxl.job.core.log;
|
||||||
|
|
||||||
|
import com.xxl.job.core.biz.model.LogResult;
|
||||||
import org.apache.log4j.AppenderSkeleton;
|
import org.apache.log4j.AppenderSkeleton;
|
||||||
import org.apache.log4j.Layout;
|
import org.apache.log4j.Layout;
|
||||||
import org.apache.log4j.spi.LoggingEvent;
|
import org.apache.log4j.spi.LoggingEvent;
|
||||||
|
@ -117,8 +118,9 @@ public class XxlJobFileAppender extends AppenderSkeleton {
|
||||||
* @param logFileName
|
* @param logFileName
|
||||||
* @return log content
|
* @return log content
|
||||||
*/
|
*/
|
||||||
public static String readLog(String logFileName ){
|
public static LogResult readLog(String logFileName, int fromLineNum){
|
||||||
|
|
||||||
|
// valid log file
|
||||||
if (logFileName==null || logFileName.trim().length()==0) {
|
if (logFileName==null || logFileName.trim().length()==0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -127,11 +129,49 @@ public class XxlJobFileAppender extends AppenderSkeleton {
|
||||||
if (!logFile.exists()) {
|
if (!logFile.exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String logData = readLines(logFile);
|
// read file
|
||||||
return logData;
|
StringBuffer logContentBuffer = new StringBuffer();
|
||||||
|
int toLineNum = 0;
|
||||||
|
LineNumberReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new LineNumberReader(new FileReader(logFile));
|
||||||
|
String line = null;
|
||||||
|
|
||||||
|
while ((line = reader.readLine())!=null) {
|
||||||
|
toLineNum++;
|
||||||
|
if (reader.getLineNumber() >= fromLineNum) {
|
||||||
|
logContentBuffer.append(line).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (reader != null) {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// result
|
||||||
|
LogResult logResult = new LogResult();
|
||||||
|
logResult.setFromLineNum(fromLineNum);
|
||||||
|
logResult.setToLineNum(toLineNum);
|
||||||
|
logResult.setLogContent(logContentBuffer.toString());
|
||||||
|
logResult.setEnd(false);
|
||||||
|
return logResult;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// it will return the number of characters actually skipped
|
||||||
|
reader.skip(Long.MAX_VALUE);
|
||||||
|
int maxLineNum = reader.getLineNumber();
|
||||||
|
maxLineNum++; // 最大行号
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read log data
|
* read log data
|
||||||
* @param logFile
|
* @param logFile
|
||||||
|
@ -162,52 +202,5 @@ public class XxlJobFileAppender extends AppenderSkeleton {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* read data from line num
|
|
||||||
* @param logFile
|
|
||||||
* @param fromLineNum
|
|
||||||
* @return log content
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static String readLinesFrom(File logFile, int fromLineNum) {
|
|
||||||
LineNumberReader reader = null;
|
|
||||||
try {
|
|
||||||
reader = new LineNumberReader(new FileReader(logFile));
|
|
||||||
|
|
||||||
// sBuffer
|
|
||||||
StringBuffer sBuffer = new StringBuffer();
|
|
||||||
String line = null;
|
|
||||||
int maxLineNum = 0;
|
|
||||||
while ((line = reader.readLine())!=null) {
|
|
||||||
maxLineNum++;
|
|
||||||
if (reader.getLineNumber() >= fromLineNum) {
|
|
||||||
sBuffer.append(line).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println("maxLineNum : " + maxLineNum);
|
|
||||||
return sBuffer.toString();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (reader != null) {
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
|
|
||||||
/*
|
|
||||||
// it will return the number of characters actually skipped
|
|
||||||
reader.skip(Long.MAX_VALUE);
|
|
||||||
int maxLineNum = reader.getLineNumber();
|
|
||||||
maxLineNum++; // 最大行号
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue