日志清理功能

v1.7
xueli.xue 8 years ago
parent 882d7a43e9
commit 00cd63c4ad

@ -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算法计算出尽量稳定的分片顺序即使注册机器存在波动也不会引起分批分片顺序大的波动
## 七、其他

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

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

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

@ -147,5 +147,37 @@
</if>
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>

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

@ -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>
@ -59,10 +59,13 @@
<input type="text" class="form-control" id="filterTime" readonly >
</div>
</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-info" id="searchBtn"></button>
</div>
<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>

@ -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;
}
@ -228,7 +228,10 @@ $(function() {
});
*/
});
/**
*
*/
$('#joblog_list').on('click', '.logKill', function(){
var _id = $(this).attr('_id');
ComConfirm.show("确认主动终止任务?", function(){
@ -248,5 +251,50 @@ $(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

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

Loading…
Cancel
Save