日志rollback展示

master
xueli.xue 8 years ago
parent 049091c4a8
commit ae26cb0c5d
  1. BIN
      doc/images/qq群-一个xxl同学进了58.png
  2. 52
      xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobLogController.java
  3. 100
      xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/logdetail.ftl
  4. 78
      xxl-job-admin/src/main/webapp/static/js/logdetail.index.1.js
  5. 4
      xxl-job-core/src/main/java/com/xxl/job/core/biz/ExecutorBiz.java
  6. 7
      xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java
  7. 47
      xxl-job-core/src/main/java/com/xxl/job/core/biz/model/LogResult.java
  8. 79
      xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java

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;
@ -93,42 +94,41 @@ public class JobLogController {
return maps;
}
@RequestMapping("/logDetail")
@ResponseBody
public ReturnT<String> logDetail(int id){
@RequestMapping("/logDetailPage")
public String logDetailPage(int id, Model model){
// base check
XxlJobLog log = xxlJobLogDao.load(id);
if (log == null) {
return new ReturnT<String>(500, "查看执行日志失败: 参数异常");
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, "查看执行日志失败: 任务发起调度失败,无法查看执行日志");
}
if (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {
return new ReturnT<String>(500, "查看执行日志失败: 任务发起调度失败,无法查看执行日志");
model.addAttribute("executorAddress", jobLog.getExecutorAddress());
model.addAttribute("triggerTime", jobLog.getTriggerTime().getTime());
model.addAttribute("logId", jobLog.getId());
}
// trigger id, trigger time
ExecutorBiz executorBiz = null;
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) new NetComClientProxy(ExecutorBiz.class, log.getExecutorAddress()).getObject();
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<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());
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
}
}
@RequestMapping("/logDetailPage")
public String logDetailPage(int id, Model model){
ReturnT<String> data = logDetail(id);
model.addAttribute("result", data);
return "joblog/logdetail";
}
@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;
}
@ -128,26 +130,19 @@ public class XxlJobFileAppender extends AppenderSkeleton {
return null;
}
String logData = readLines(logFile);
return logData;
}
/**
* read log data
* @param logFile
* @return log line content
*/
public static String readLines(File logFile){
BufferedReader reader = null;
// read file
StringBuffer logContentBuffer = new StringBuffer();
int toLineNum = 0;
LineNumberReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(logFile), "utf-8"));
if (reader != null) {
StringBuilder sb = new StringBuilder();
reader = new LineNumberReader(new FileReader(logFile));
String line = null;
while ((line = reader.readLine())!=null) {
sb.append(line).append("\n");
toLineNum++;
if (reader.getLineNumber() >= fromLineNum) {
logContentBuffer.append(line).append("\n");
}
return sb.toString();
}
} catch (IOException e) {
e.printStackTrace();
@ -160,34 +155,40 @@ public class XxlJobFileAppender extends AppenderSkeleton {
}
}
}
return null;
// 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 data from line num
* read log data
* @param logFile
* @param fromLineNum
* @return log content
* @throws Exception
* @return log line content
*/
public static String readLinesFrom(File logFile, int fromLineNum) {
LineNumberReader reader = null;
public static String readLines(File logFile){
BufferedReader reader = null;
try {
reader = new LineNumberReader(new FileReader(logFile));
// sBuffer
StringBuffer sBuffer = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(new FileInputStream(logFile), "utf-8"));
if (reader != null) {
StringBuilder sb = new StringBuilder();
String line = null;
int maxLineNum = 0;
while ((line = reader.readLine()) != null) {
maxLineNum++;
if (reader.getLineNumber() >= fromLineNum) {
sBuffer.append(line).append("\n");
sb.append(line).append("\n");
}
return sb.toString();
}
System.out.println("maxLineNum : " + maxLineNum);
return sBuffer.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
@ -199,15 +200,7 @@ public class XxlJobFileAppender extends AppenderSkeleton {
}
}
}
return null;
/*
// it will return the number of characters actually skipped
reader.skip(Long.MAX_VALUE);
int maxLineNum = reader.getLineNumber();
maxLineNum++; // 最大行号
*/
}
}

Loading…
Cancel
Save