日志清理功能

This commit is contained in:
xueli.xue 2017-05-08 16:18:07 +08:00
parent 882d7a43e9
commit 00cd63c4ad
17 changed files with 205 additions and 13 deletions

View File

@ -813,15 +813,15 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
- 3、执行器server启动、销毁和注册逻辑调整
- 4、JettyServer关闭逻辑优化修复执行器无法正常关闭导致端口占用和频繁打印c3p0日志的问题
- 5、JobHandler中开启子线程时支持子线程输出执行日志并通过Rolling查看。
- 6、任务日志清理功能
#### TODO LIST
- 1、任务并行触发处理规则单机串行队列默认、单机并行、串行忽略、单机覆盖
- 2、任务权限管理
- 3、调度失败重试机制
- 4、执行器与数据库解耦只需配置调度中心集群地址即可与当前通过JDBC注册自动发现方式相冲突待考虑
- 5、任务日志定期清理功能支持设置日志上限
- 6、任务分片一个任务被拆分成N个独立的任务单元然后由分布式部署的执行器分别执行某一个或几个分片单元
- 7、任务分片路由分片采用一致性Hash算法计算出尽量稳定的分片顺序即使注册机器存在波动也不会引起分批分片顺序大的波动
- 5、任务分片一个任务被拆分成N个独立的任务单元然后由分布式部署的执行器分别执行某一个或几个分片单元
- 6、任务分片路由分片采用一致性Hash算法计算出尽量稳定的分片顺序即使注册机器存在波动也不会引起分批分片顺序大的波动
## 七、其他

View File

@ -167,4 +167,37 @@ public class JobLogController {
return new ReturnT<String>(500, runResult.getMsg());
}
}
@RequestMapping("/clearLog")
@ResponseBody
public ReturnT<String> clearLog(int jobGroup, int jobId, int type){
Date clearBeforeTime = null;
int clearBeforeNum = 0;
if (type == 1) {
clearBeforeTime = DateUtils.addMonths(new Date(), -1); // 清理一个月之前日志数据
} else if (type == 2) {
clearBeforeTime = DateUtils.addMonths(new Date(), -3); // 清理三个月之前日志数据
} else if (type == 3) {
clearBeforeTime = DateUtils.addMonths(new Date(), -6); // 清理六个月之前日志数据
} else if (type == 4) {
clearBeforeTime = DateUtils.addYears(new Date(), -1); // 清理一年之前日志数据
} else if (type == 5) {
clearBeforeNum = 1000; // 清理一千条以前日志数据
} else if (type == 6) {
clearBeforeNum = 10000; // 清理一万条以前日志数据
} else if (type == 7) {
clearBeforeNum = 30000; // 清理三万条以前日志数据
} else if (type == 8) {
clearBeforeNum = 100000; // 清理十万条以前日志数据
} else if (type == 9) {
clearBeforeNum = 0; // 清理所用日志数据
} else {
return new ReturnT<String>(ReturnT.FAIL_CODE, "清理类型参数异常");
}
xxlJobLogDao.clearLog(jobGroup, jobId, clearBeforeTime, clearBeforeNum);
return ReturnT.SUCCESS;
}
}

View File

@ -29,4 +29,6 @@ public interface IXxlJobLogDao {
public List<Map<String, Object>> triggerCountByDay(Date from, Date to, int handleCode);
public int clearLog(int jobGroup, int jobId, Date clearBeforeTime, int clearBeforeNum);
}

View File

@ -92,4 +92,14 @@ public class XxlJobLogDaoImpl implements IXxlJobLogDao {
return sqlSessionTemplate.selectList("XxlJobLogMapper.triggerCountByDay", params);
}
@Override
public int clearLog(int jobGroup, int jobId, Date clearBeforeTime, int clearBeforeNum) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("jobGroup", jobGroup);
params.put("jobId", jobId);
params.put("clearBeforeTime", clearBeforeTime);
params.put("clearBeforeNum", clearBeforeNum);
return sqlSessionTemplate.delete("XxlJobLogMapper.clearLog", params);
}
}

View File

@ -148,4 +148,36 @@
GROUP BY triggerDay;
</select>
<delete id="clearLog" parameterType="java.util.Map" >
delete from XXL_JOB_QRTZ_TRIGGER_LOG
<trim prefix="WHERE" prefixOverrides="AND | OR" >
<if test="jobGroup gt 0">
AND job_group = #{jobGroup}
</if>
<if test="jobId gt 0">
AND job_id = #{jobId}
</if>
<if test="clearBeforeTime != null">
AND trigger_time <![CDATA[ <= ]]> #{clearBeforeTime}
</if>
<if test="clearBeforeNum gt 0">
AND id NOT in(
SELECT id FROM(
SELECT id FROM XXL_JOB_QRTZ_TRIGGER_LOG AS t
<trim prefix="WHERE" prefixOverrides="AND | OR" >
<if test="jobGroup gt 0">
AND t.job_group = #{jobGroup}
</if>
<if test="jobId gt 0">
AND t.job_id = #{jobId}
</if>
</trim>
ORDER BY t.trigger_time desc
LIMIT 0, #{clearBeforeNum}
) t1
)
</if>
</trim>
</delete>
</mapper>

View File

@ -45,6 +45,9 @@
<#-- jquery cookie -->
<script src="${request.contextPath}/static/plugins/jquery/jquery.cookie.js"></script>
<#-- layer -->
<script src="${request.contextPath}/static/plugins/layer/layer.js"></script>
<#-- common -->
<script src="${request.contextPath}/static/js/xxl.alert.1.js"></script>
<script src="${request.contextPath}/static/js/common.1.js"></script>

View File

@ -36,7 +36,7 @@
<div class="input-group">
<span class="input-group-addon">执行器</span>
<select class="form-control" id="jobGroup" paramVal="<#if jobInfo?exists>${jobInfo.jobGroup}</#if>" >
<option value="0" >请选择</option>
<option value="0" >全部</option>
<#list JobGroupList as group>
<option value="${group.id}" >${group.title}</option>
</#list>
@ -47,7 +47,7 @@
<div class="input-group">
<span class="input-group-addon">任务</span>
<select class="form-control" id="jobId" paramVal="<#if jobInfo?exists>${jobInfo.id}</#if>" >
<option value="0" >请选择</option>
<option value="0" >全部</option>
</select>
</div>
</div>
@ -60,9 +60,12 @@
</div>
</div>
<div class="col-xs-1">
<button class="btn btn-block btn-info" id="searchBtn">搜索</button>
</div>
<div class="col-xs-2">
<button class="btn btn-block btn-info" id="searchBtn">搜索</button>
<div class="col-xs-1">
<button class="btn btn-block btn-nomal" id="clearLog">清理</button>
</div>
</div>
@ -102,6 +105,61 @@
<@netCommon.commonFooter />
</div>
<!-- 日志清理.模态框 -->
<div class="modal fade" id="clearLogModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" >日志清理</h4>
</div>
<div class="modal-body">
<form class="form-horizontal form" role="form" >
<div class="form-group">
<label class="col-sm-3 control-label"">执行器</label>
<div class="col-sm-9">
<input type="text" class="form-control jobGroupText" readonly >
<input type="hidden" name="jobGroup" >
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"">任务</label>
<div class="col-sm-9">
<input type="text" class="form-control jobIdText" readonly >
<input type="hidden" name="jobId" >
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"">清理类型</label>
<div class="col-sm-9">
<select class="form-control" name="type" >
<option value="1" >清理一个月之前日志数据</option>
<option value="2" >清理三个月之前日志数据</option>
<option value="3" >清理六个月之前日志数据</option>
<option value="4" >清理一年之前日志数据</option>
<option value="5" >清理一千条以前日志数据</option>
<option value="6" >清理一万条以前日志数据</option>
<option value="7" >清理三万条以前日志数据</option>
<option value="8" >清理十万条以前日志数据</option>
<option value="9" >清理所用日志数据</option>
</select>
</div>
</div>
<hr>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="button" class="btn btn-primary ok" >保存</button>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<@netCommon.commonScript />
<!-- DataTables -->
<script src="${request.contextPath}/static/adminlte/plugins/datatables/jquery.dataTables.min.js"></script>

View File

@ -11,7 +11,7 @@ $(function() {
dataType : "json",
success : function(data){
if (data.code == 200) {
$("#jobId").html('<option value="0" >请选择</option>');
$("#jobId").html('<option value="0" >全部</option>');
$.each(data.content, function (n, value) {
$("#jobId").append('<option value="' + value.id + '" >' + value.jobDesc + '</option>');
});
@ -153,7 +153,7 @@ $(function() {
if (row.triggerCode == 200){
var temp = '<a href="javascript:;" class="logDetail" _id="'+ row.id +'">执行日志</a>';
if(row.handleCode == 0){
temp += '<br><a href="javascript:;" class="logKill" _id="'+ row.id +'">终止任务</a>';
temp += '<br><a href="javascript:;" class="logKill" _id="'+ row.id +'" style="color: red;" >终止任务</a>';
}
return temp;
}
@ -229,6 +229,9 @@ $(function() {
*/
});
/**
* 终止任务
*/
$('#joblog_list').on('click', '.logKill', function(){
var _id = $(this).attr('_id');
ComConfirm.show("确认主动终止任务?", function(){
@ -249,4 +252,49 @@ $(function() {
});
});
/**
* 清理任务Log
*/
$('#clearLog').on('click', function(){
var jobGroup = $('#jobGroup').val();
var jobId = $('#jobId').val();
var jobGroupText = $("#jobGroup").find("option:selected").text();
var jobIdText = $("#jobId").find("option:selected").text();
$('#clearLogModal input[name=jobGroup]').val(jobGroup);
$('#clearLogModal input[name=jobId]').val(jobId);
$('#clearLogModal .jobGroupText').val(jobGroupText);
$('#clearLogModal .jobIdText').val(jobIdText);
$('#clearLogModal').modal('show');
});
$("#clearLogModal .ok").on('click', function(){
$.post(base_url + "/joblog/clearLog", $("#clearLogModal .form").serialize(), function(data, status) {
if (data.code == "200") {
$('#clearLogModal').modal('hide');
layer.open({
title: '系统提示',
content: '日志清理成功',
icon: '1',
end: function(layero, index){
logTable.fnDraw();
}
});
} else {
layer.open({
title: '系统提示',
content: (data.msg || "日志清理失败"),
icon: '2'
});
}
});
});
$("#clearLogModal").on('hide.bs.modal', function () {
$("#clearLogModal .form")[0].reset();
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
/*! layer mobile-v2.0.0 Web弹层组件 MIT License http://layer.layui.com/mobile By 贤心 */
;!function(e){"use strict";var t=document,n="querySelectorAll",i="getElementsByClassName",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var r=0,o=["layui-m-layer"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement("div");e.id=s.id=o[0]+r,s.setAttribute("class",o[0]+" "+o[0]+(n.type||0)),s.setAttribute("index",r);var l=function(){var e="object"==typeof n.title;return n.title?'<h3 style="'+(e?n.title[1]:"")+'">'+(e?n.title[0]:n.title)+"</h3>":""}(),c=function(){"string"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e='<span yes type="1">'+n.btn[0]+"</span>",2===t&&(e='<span no type="0">'+n.btn[1]+"</span>"+e),'<div class="layui-m-layerbtn">'+e+"</div>"):""}();if(n.fixed||(n.top=n.hasOwnProperty("top")?n.top:100,n.style=n.style||"",n.style+=" top:"+(t.body.scrollTop+n.top)+"px"),2===n.type&&(n.content='<i></i><i class="layui-m-layerload"></i><i></i><p>'+(n.content||"")+"</p>"),n.skin&&(n.anim="up"),"msg"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?"<div "+("string"==typeof n.shade?'style="'+n.shade+'"':"")+' class="layui-m-layershade"></div>':"")+'<div class="layui-m-layermain" '+(n.fixed?"":'style="position:static;"')+'><div class="layui-m-layersection"><div class="layui-m-layerchild '+(n.skin?"layui-m-layer-"+n.skin+" ":"")+(n.className?n.className:"")+" "+(n.anim?"layui-m-anim-"+n.anim:"")+'" '+(n.style?'style="'+n.style+'"':"")+">"+l+'<div class="layui-m-layercont">'+n.content+"</div>"+c+"</div></div></div>",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute("index"))}document.body.appendChild(s);var u=e.elem=a("#"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i]("layui-m-layerbtn")[0].children,r=s.length,o=0;o<r;o++)l.touch(s[o],a);if(e.shade&&e.shadeClose){var c=t[i]("layui-m-layershade")[0];l.touch(c,function(){layer.close(n.index,e.end)})}e.end&&(l.end[n.index]=e.end)},e.layer={v:"2.0",index:r,open:function(e){var t=new c(e||{});return t.index},close:function(e){var n=a("#"+o[0]+e)[0];n&&(n.innerHTML="",t.body.removeChild(n),clearTimeout(l.timer[e]),delete l.timer[e],"function"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[i](o[0]),n=0,a=e.length;n<a;n++)layer.close(0|e[0].getAttribute("index"))}},"function"==typeof define?define(function(){return layer}):function(){var e=document.scripts,n=e[e.length-1],i=n.src,a=i.substring(0,i.lastIndexOf("/")+1);n.getAttribute("merge")||document.head.appendChild(function(){var e=t.createElement("link");return e.href=a+"need/layer.css?2.0",e.type="text/css",e.rel="styleSheet",e.id="layermcss",e}())}()}(window);

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB