日志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.IXxlJobLogDao;
|
||||
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.rpc.netcom.NetComClientProxy;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -92,43 +93,42 @@ public class JobLogController {
|
|||
maps.put("data", list); // 分页列表
|
||||
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")
|
||||
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";
|
||||
}
|
||||
|
||||
|
||||
@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")
|
||||
@ResponseBody
|
||||
public ReturnT<String> logKill(int id){
|
||||
|
|
|
@ -1,7 +1,95 @@
|
|||
<body style="color:white;background-color:black;" >
|
||||
<pre>
|
||||
<br>
|
||||
<#if result.code == 200>${result.content}
|
||||
<#else>${result.msg}</#if>
|
||||
</pre>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>任务调度中心</title>
|
||||
<#import "/common/common.macro.ftl" as netCommon>
|
||||
<@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>
|
||||
</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;
|
||||
|
||||
import com.xxl.job.core.biz.model.LogResult;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
|
@ -25,9 +26,10 @@ public interface ExecutorBiz {
|
|||
* log
|
||||
* @param logDateTim
|
||||
* @param logId
|
||||
* @param fromLineNum
|
||||
* @return
|
||||
*/
|
||||
public ReturnT<String> log(long logDateTim, int logId);
|
||||
public ReturnT<LogResult> log(long logDateTim, int logId, int fromLineNum);
|
||||
|
||||
/**
|
||||
* run
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.xxl.job.core.biz.impl;
|
||||
|
||||
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.TriggerParam;
|
||||
import com.xxl.job.core.executor.XxlJobExecutor;
|
||||
|
@ -42,12 +43,12 @@ public class ExecutorBizImpl implements ExecutorBiz {
|
|||
}
|
||||
|
||||
@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
|
||||
String logFileName = XxlJobFileAppender.makeLogFileName(new Date(logDateTim), logId);
|
||||
|
||||
String logConteng = XxlJobFileAppender.readLog(logFileName);
|
||||
return new ReturnT<String>(ReturnT.SUCCESS_CODE, logConteng);
|
||||
LogResult logResult = XxlJobFileAppender.readLog(logFileName, fromLineNum);
|
||||
return new ReturnT<LogResult>(logResult);
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
import com.xxl.job.core.biz.model.LogResult;
|
||||
import org.apache.log4j.AppenderSkeleton;
|
||||
import org.apache.log4j.Layout;
|
||||
import org.apache.log4j.spi.LoggingEvent;
|
||||
|
@ -117,8 +118,9 @@ public class XxlJobFileAppender extends AppenderSkeleton {
|
|||
* @param logFileName
|
||||
* @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) {
|
||||
return null;
|
||||
}
|
||||
|
@ -127,11 +129,49 @@ public class XxlJobFileAppender extends AppenderSkeleton {
|
|||
if (!logFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String logData = readLines(logFile);
|
||||
return logData;
|
||||
|
||||
// read file
|
||||
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
|
||||
* @param logFile
|
||||
|
@ -162,52 +202,5 @@ public class XxlJobFileAppender extends AppenderSkeleton {
|
|||
}
|
||||
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