目前XXL-JOB
使用自定义XxlJobHelper
来做日志埋点,但是实际上很多内部框架的日志都未接入,此时定时任务出现错误,需要上执行器上查看日志信息,这时候无法查询到本次调度相关日志。
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
为了后续方便接入链路,使用MDC
传递logId
日志埋点工具类
/**
* 扩展XXL-JOB帮助类
* 将调度执行日志也打印到本地log文件中
*
* @see com.xxl.job.core.context.XxlJobHelper
* @author Yu
* @date 2021/4/3 23:24
*/
public class XxlJobExHelper {
public static long getJobId() {
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return -1;
}
return xxlJobContext.getJobId();
}
public static String getJobParam() {
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return null;
}
return xxlJobContext.getJobParam();
}
// ---------------------- for log ----------------------
public static String getJobLogFileName() {
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return null;
}
return xxlJobContext.getJobLogFileName();
}
public static String getLogId() {
String path = XxlJobContext.getXxlJobContext().getJobLogFileName();
if (Objects.isNull(path)) {
return "";
}
int startIdx = path.lastIndexOf("\\") + 1;
int endIdx = path.lastIndexOf(".");
if (startIdx == 0 || endIdx == -1) {
return "";
}
return path.substring(startIdx, endIdx);
}
// ---------------------- for shard ----------------------
public static int getShardIndex() {
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return -1;
}
return xxlJobContext.getShardIndex();
}
public static int getShardTotal() {
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return -1;
}
return xxlJobContext.getShardTotal();
}
// ---------------------- tool for log ----------------------
private static Logger logger = LoggerFactory.getLogger(XxlJobExHelper.class);
/**
* append log with pattern
*
* @param appendLogPattern like "aaa {} bbb {} ccc"
* @param appendLogArguments like "111, true"
*/
public static boolean log(String appendLogPattern, Object ... appendLogArguments) {
FormattingTuple ft = MessageFormatter.arrayFormat(appendLogPattern, appendLogArguments);
String appendLog = ft.getMessage();
StackTraceElement callInfo = new Throwable().getStackTrace()[1];
return logDetail(callInfo, appendLog);
}
/**
* append exception stack
*
* @param e
*/
public static boolean log(Throwable e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
String appendLog = stringWriter.toString();
StackTraceElement callInfo = new Throwable().getStackTrace()[1];
return logDetail(callInfo, appendLog);
}
/**
* append log
*
* @param callInfo
* @param appendLog
*/
private static boolean logDetail(StackTraceElement callInfo, String appendLog) {
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return false;
}
StringBuilder stringBuffer = new StringBuilder();
stringBuffer.append(DateUtil.formatDateTime(new Date()))
.append(" ")
.append("["+ callInfo.getClassName() + "#" + callInfo.getMethodName() +"]")
.append("-")
.append("["+ callInfo.getLineNumber() +"]")
.append("-")
.append("["+ Thread.currentThread().getName() +"]")
.append(" ")
.append(appendLog != null ? appendLog : "");
String formatAppendLog = stringBuffer.toString();
// appendlog
String logFileName = xxlJobContext.getJobLogFileName();
logger.info(">>>>>>>>>>> {}", formatAppendLog);
if (logFileName != null && logFileName.trim().length() > 0) {
XxlJobFileAppender.appendLog(logFileName, formatAppendLog);
return true;
} else {
return false;
}
}
// ---------------------- tool for handleResult ----------------------
/**
* handle success
*
* @return
*/
public static boolean handleSuccess(){
return handleResult(XxlJobContext.HANDLE_COCE_SUCCESS, null);
}
/**
* handle success with log msg
*
* @param handleMsg
* @return
*/
public static boolean handleSuccess(String handleMsg) {
return handleResult(XxlJobContext.HANDLE_COCE_SUCCESS, handleMsg);
}
/**
* handle fail
*
* @return
*/
public static boolean handleFail(){
return handleResult(XxlJobContext.HANDLE_COCE_FAIL, null);
}
/**
* handle fail with log msg
*
* @param handleMsg
* @return
*/
public static boolean handleFail(String handleMsg) {
return handleResult(XxlJobContext.HANDLE_COCE_FAIL, handleMsg);
}
/**
* handle timeout
*
* @return
*/
public static boolean handleTimeout(){
return handleResult(XxlJobContext.HANDLE_COCE_TIMEOUT, null);
}
/**
* handle timeout with log msg
*
* @param handleMsg
* @return
*/
public static boolean handleTimeout(String handleMsg){
return handleResult(XxlJobContext.HANDLE_COCE_TIMEOUT, handleMsg);
}
/**
* @param handleCode
*
* 200 : success
* 500 : fail
* 502 : timeout
*
* @param handleMsg
* @return
*/
public static boolean handleResult(int handleCode, String handleMsg) {
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
if (xxlJobContext == null) {
return false;
}
xxlJobContext.setHandleCode(handleCode);
if (handleMsg != null) {
xxlJobContext.setHandleMsg(handleMsg);
}
return true;
}
}
拦截器
@Aspect
@Order(-1)
public class XxlJobInterceptor {
@Around("@annotation(xxlJob)")
public Object handle(ProceedingJoinPoint point, XxlJob xxlJob) throws Throwable{
try{
MDC.put(TraceConstant.TRACE_ID_NAME, XxlJobExHelper.getLogId());
return point.proceed();
} finally{
MDC.remove(TraceConstant.TRACE_ID_NAME);
}
}
}
配置属性类
@Getter
@Setter
@ConfigurationProperties(prefix = "teddy.boot.xxl.job")
public class XxlJobProperties {
private String adminAddresses;
private String accessToken;
private Executor executor;
@Getter
@Setter
public static class Executor {
private String appname;
private String address;
private String ip;
private int port;
private String logPath;
private int logRetentionDays;
}
}
自动配置类
@Configuration
@EnableConfigurationProperties(XxlJobProperties.class)
public class XxlJobAutoConfiguration {
private static Logger log = LoggerFactory.getLogger(XxlJobAutoConfiguration.class);
@Bean
@ConditionalOnMissingBean
public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties properties) {
log.info(">>>>>>>>>>> xxl-job executor init...");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(properties.getAdminAddresses());
xxlJobSpringExecutor.setAppname(properties.getExecutor().getAppname());
xxlJobSpringExecutor.setAddress(properties.getExecutor().getAddress());
xxlJobSpringExecutor.setIp(properties.getExecutor().getIp());
xxlJobSpringExecutor.setPort(properties.getExecutor().getPort());
xxlJobSpringExecutor.setAccessToken(properties.getAccessToken());
xxlJobSpringExecutor.setLogPath(properties.getExecutor().getLogPath());
xxlJobSpringExecutor.setLogRetentionDays(properties.getExecutor().getLogRetentionDays());
return xxlJobSpringExecutor;
}
@Bean
@ConditionalOnMissingBean
public XxlJobInterceptor xxlJobInterceptor() {
return new XxlJobInterceptor();
}
}