xueli.xue 8 роки тому
батько
коміт
ae26cb0c5d

BIN
doc/images/qq群-一个xxl同学进了58.png


+ 30 - 30
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobLogController.java

@@ -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){
+
+	@RequestMapping("/logDetailPage")
+	public String logDetailPage(int id, Model model){
+
 		// 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, "查看执行日志失败: 任务发起调度失败,无法查看执行日志");
+		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());
 		}
-		
-		// 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){

+ 94 - 6
xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/logdetail.ftl

@@ -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>

+ 78 - 0
xxl-job-admin/src/main/webapp/static/js/logdetail.index.1.js

@@ -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);
+
+});

+ 3 - 1
xxl-job-core/src/main/java/com/xxl/job/core/biz/ExecutorBiz.java

@@ -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

+ 4 - 3
xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java

@@ -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

+ 47 - 0
xxl-job-core/src/main/java/com/xxl/job/core/biz/model/LogResult.java

@@ -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;
+    }
+}

+ 46 - 53
xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java

@@ -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,27 +129,20 @@ public class XxlJobFileAppender extends AppenderSkeleton {
 		if (!logFile.exists()) {
 			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();
-				String line = null;
-				while ((line = reader.readLine()) != null) {
-					sb.append(line).append("\n");
+			reader = new LineNumberReader(new FileReader(logFile));
+			String line = null;
+
+			while ((line = reader.readLine())!=null) {
+				toLineNum++;
+				if (reader.getLineNumber() >= fromLineNum) {
+					logContentBuffer.append(line).append("\n");
 				}
-				return sb.toString();
 			}
 		} catch (IOException e) {
 			e.printStackTrace();
@@ -159,35 +154,41 @@ public class XxlJobFileAppender extends AppenderSkeleton {
 					e.printStackTrace();
 				}
 			}
-		} 
-		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();
-	    	String line = null;
-	    	int maxLineNum = 0;
-	    	while ((line = reader.readLine())!=null) {
-	    		maxLineNum++;
-	    		if (reader.getLineNumber() >= fromLineNum) {
-	    			sBuffer.append(line).append("\n");
+			reader = new BufferedReader(new InputStreamReader(new FileInputStream(logFile), "utf-8"));
+			if (reader != null) {
+				StringBuilder sb = new StringBuilder();
+				String line = null;
+				while ((line = reader.readLine()) != null) {
+					sb.append(line).append("\n");
 				}
+				return sb.toString();
 			}
-	    	
-	    	System.out.println("maxLineNum : " + maxLineNum);
-	    	return sBuffer.toString();
 		} catch (IOException e) {
 			e.printStackTrace();
 		} finally {
@@ -198,16 +199,8 @@ public class XxlJobFileAppender extends AppenderSkeleton {
 					e.printStackTrace();
 				}
 			}
-		}
-		
+		} 
 		return null;
-		
-        /*
-        // it will return the number of characters actually skipped
-        reader.skip(Long.MAX_VALUE);	
-        int maxLineNum = reader.getLineNumber();  
-        maxLineNum++;	// 最大行号
-        */
-    }
-	
+	}
+
 }