JAVA-日志工具类

规范日志打印,统一日志模板。

/**
 * @description 日志类型枚举类
 */
@Getter
public enum LogEnum {
    //全局请求日志
    GLOBAL,
    // 系统报错日志
    SYS_ERR,
    // 用户信息
    SYS_USER
    ;

    /**
     * 判断日志类型不能为空
     *
     * @param  logType 日志类型
     * @return boolean 返回类型
     */
    public static boolean isLogType(LogEnum logType) {

        return logType != null;
    }
}

level

public final class Level implements Serializable {
    private static final long serialVersionUID = -814092767334282137L;
    public static final int OFF_INT = Integer.MAX_VALUE;
    public static final int ERROR_INT = 40000;
    public static final int WARN_INT = 30000;
    public static final int INFO_INT = 20000;
    public static final int DEBUG_INT = 10000;
    public static final int TRACE_INT = 5000;
    public static final int ALL_INT = Integer.MIN_VALUE;
    public static final Integer OFF_INTEGER = Integer.MAX_VALUE;
    public static final Integer ERROR_INTEGER = 40000;
    public static final Integer WARN_INTEGER = 30000;
    public static final Integer INFO_INTEGER = 20000;
    public static final Integer DEBUG_INTEGER = 10000;
    public static final Integer TRACE_INTEGER = 5000;
    public static final Integer ALL_INTEGER = Integer.MIN_VALUE;
    public static final Level OFF = new Level(Integer.MAX_VALUE, "OFF");
    public static final Level ERROR = new Level(40000, "ERROR");
    public static final Level WARN = new Level(30000, "WARN");
    public static final Level INFO = new Level(20000, "INFO");
    public static final Level DEBUG = new Level(10000, "DEBUG");
    public static final Level TRACE = new Level(5000, "TRACE");
    public static final Level ALL = new Level(Integer.MIN_VALUE, "ALL");
    public final int levelInt;
    public final String levelStr;

    private Level(int levelInt, String levelStr) {
        this.levelInt = levelInt;
        this.levelStr = levelStr;
    }

    public String toString() {
        return this.levelStr;
    }

    public int toInt() {
        return this.levelInt;
    }

    public Integer toInteger() {
        switch (this.levelInt) {
            case Integer.MIN_VALUE:
                return ALL_INTEGER;
            case 5000:
                return TRACE_INTEGER;
            case 10000:
                return DEBUG_INTEGER;
            case 20000:
                return INFO_INTEGER;
            case 30000:
                return WARN_INTEGER;
            case 40000:
                return ERROR_INTEGER;
            case Integer.MAX_VALUE:
                return OFF_INTEGER;
            default:
                throw new IllegalStateException("Level " + this.levelStr + ", " + this.levelInt + " is unknown.");
        }
    }

    public boolean isGreaterOrEqual(Level r) {
        return this.levelInt >= r.levelInt;
    }

    public static Level toLevel(String sArg) {
        return toLevel(sArg, DEBUG);
    }

    public static Level valueOf(String sArg) {
        return toLevel(sArg, DEBUG);
    }

    public static Level toLevel(int val) {
        return toLevel(val, DEBUG);
    }

    public static Level toLevel(int val, Level defaultLevel) {
        switch (val) {
            case Integer.MIN_VALUE:
                return ALL;
            case 5000:
                return TRACE;
            case 10000:
                return DEBUG;
            case 20000:
                return INFO;
            case 30000:
                return WARN;
            case 40000:
                return ERROR;
            case Integer.MAX_VALUE:
                return OFF;
            default:
                return defaultLevel;
        }
    }

    public static Level toLevel(String sArg, Level defaultLevel) {
        if (sArg == null) {
            return defaultLevel;
        } else if (sArg.equalsIgnoreCase("ALL")) {
            return ALL;
        } else if (sArg.equalsIgnoreCase("TRACE")) {
            return TRACE;
        } else if (sArg.equalsIgnoreCase("DEBUG")) {
            return DEBUG;
        } else if (sArg.equalsIgnoreCase("INFO")) {
            return INFO;
        } else if (sArg.equalsIgnoreCase("WARN")) {
            return WARN;
        } else if (sArg.equalsIgnoreCase("ERROR")) {
            return ERROR;
        } else {
            return sArg.equalsIgnoreCase("OFF") ? OFF : defaultLevel;
        }
    }

    private Object readResolve() {
        return toLevel(this.levelInt);
    }

    public static Level fromLocationAwareLoggerInteger(int levelInt) {
        Level level;
        switch (levelInt) {
            case 0:
                level = TRACE;
                break;
            case 10:
                level = DEBUG;
                break;
            case 20:
                level = INFO;
                break;
            case 30:
                level = WARN;
                break;
            case 40:
                level = ERROR;
                break;
            default:
                throw new IllegalArgumentException(levelInt + " not a valid level value");
        }

        return level;
    }

    public static int toLocationAwareLoggerInteger(Level level) {
        if (level == null) {
            throw new IllegalArgumentException("null level parameter is not admitted");
        } else {
            switch (level.toInt()) {
                case 5000:
                    return 0;
                case 10000:
                    return 10;
                case 20000:
                    return 20;
                case 30000:
                    return 30;
                case 40000:
                    return 40;
                default:
                    throw new IllegalArgumentException(level + " not a valid level value");
            }
        }
    }
}

LogInfo
@Data
@Accessors(chain = true)
public class LogInfo implements Serializable {

    private static final long serialVersionUID = 5250395474667395607L;

    @JSONField(ordinal = MagicNumConstant.ONE)
    private String traceId;

    @JSONField(ordinal = MagicNumConstant.TWO)
    private String type;

    @JSONField(ordinal = MagicNumConstant.THREE)
    private String level;

    @JSONField(ordinal = MagicNumConstant.FOUR)
    private String location;

    @JSONField(ordinal = MagicNumConstant.SIX)
    private Object info;

    public void setInfo(Object info) {
        this.info = info;
    }

    @Override
    public String toString() {
        String result="";
        if(StringUtils.isNotEmpty(type)){
            result+="[" + type  +"]";
        }
        if(StringUtils.isNotEmpty(location)){
            result+="[" + location  +"]";
        }
        if(info!=null && StringUtils.isNotEmpty(info.toString())){
            result+="[" + info.toString()  +"]";
        }
        return result;
    }
}
LogUtil
@Slf4j
public class LogUtil {

    private static final String TRACE_TYPE = "TRACE_TYPE";

    public static final String SCHEDULE_LEVEL = "SCHEDULE";

    public static final String K8S_CALLBACK_LEVEL = "K8S_CALLBACK";

    private static final String GLOBAL_REQUEST_LEVEL = "GLOBAL";

    private static final String TRACE_LEVEL = "TRACE";

    private static final String DEBUG_LEVEL = "DEBUG";

    private static final String INFO_LEVEL = "INFO";

    private static final String WARN_LEVEL = "WARN";

    private static final String ERROR_LEVEL = "ERROR";


    public static void startScheduleTrace() {
        MDC.put(TRACE_TYPE, SCHEDULE_LEVEL);
    }

    public static void cleanTrace() {
        MDC.clear();
    }

    /**
     * info级别的日志
     *
     * @param logType 日志类型
     * @param object  打印的日志参数
     */

    public static void info(LogEnum logType, Object... object) {

        logHandle(logType, Level.INFO, object);
    }

    /**
     * debug级别的日志
     *
     * @param logType 日志类型
     * @param object  打印的日志参数
     */
    public static void debug(LogEnum logType, Object... object) {
        logHandle(logType, Level.DEBUG, object);
    }

    /**
     * error级别的日志
     *
     * @param logType 日志类型
     * @param object  打印的日志参数
     */
    public static void error(LogEnum logType, Object... object) {
        errorObjectHandle(object);
        logHandle(logType, Level.ERROR, object);
    }

    /**
     * warn级别的日志
     *
     * @param logType 日志类型
     * @param object  打印的日志参数
     */
    public static void warn(LogEnum logType, Object... object) {
        logHandle(logType, Level.WARN, object);
    }

    /**
     * trace级别的日志
     *
     * @param logType 日志类型
     * @param object  打印的日志参数
     */
    public static void trace(LogEnum logType, Object... object) {
        logHandle(logType, Level.TRACE, object);
    }

    /**
     * 日志处理
     *
     * @param logType 日志类型
     * @param level   日志级别
     * @param object  打印的日志参数
     */
    private static void logHandle(LogEnum logType, Level level, Object[] object) {

        LogInfo logInfo = generateLogInfo(logType, level, object);

        switch (logInfo.getLevel()) {
            case TRACE_LEVEL:
                log.trace(MarkerFactory.getMarker(TRACE_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            case DEBUG_LEVEL:
                log.debug(MarkerFactory.getMarker(DEBUG_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            case GLOBAL_REQUEST_LEVEL:
                logInfo.setLevel(null);
                logInfo.setType(null);
                logInfo.setLocation(null);
                log.info(MarkerFactory.getMarker(GLOBAL_REQUEST_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            case SCHEDULE_LEVEL:
                log.info(MarkerFactory.getMarker(SCHEDULE_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            case K8S_CALLBACK_LEVEL:
                log.info(MarkerFactory.getMarker(K8S_CALLBACK_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            case INFO_LEVEL:
                log.info(MarkerFactory.getMarker(INFO_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            case WARN_LEVEL:
                log.warn(MarkerFactory.getMarker(WARN_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            case ERROR_LEVEL:
                log.error(MarkerFactory.getMarker(ERROR_LEVEL), logJsonStringLengthLimit(logInfo));
                break;
            default:
        }

    }


    /**
     * 日志信息组装的内部方法
     *
     * @param logType 日志类型
     * @param level   日志级别
     * @param object  打印的日志参数
     * @return LogInfo
     */
    private static LogInfo generateLogInfo(LogEnum logType, Level level, Object[] object) {


        LogInfo logInfo = new LogInfo();
        // 日志类型检测
        if (!LogEnum.isLogType(logType)) {
            level = Level.ERROR;
            object = new Object[MagicNumConstant.ONE];
            object[MagicNumConstant.ZERO] = "日志类型【".concat(LogEnum.SYS_ERR.name()).concat("】不正确!");
            logType = LogEnum.SYS_ERR;
        }

        // 获取trace_id
        if (StringUtils.isEmpty(MDC.get(StringConstant.LOG_TRACE_ID))) {
            MDC.put(StringConstant.LOG_TRACE_ID, UUID.randomUUID().toString());
        }
        // 设置logInfo的level,type,traceId属性
        logInfo.setLevel(level.levelStr)
                .setType(logType.toString())
                .setTraceId(MDC.get(StringConstant.LOG_TRACE_ID));


        //自定义日志级别
        //LogEnum、 MDC中的 TRACE_TYPE 做日志分流标识
        if (Level.INFO.toInt() == level.toInt()) {
            if (LogEnum.GLOBAL.equals(logType)) {
                //info全局请求
                logInfo.setLevel(GLOBAL_REQUEST_LEVEL);
            } else if (LogEnum.K8S.equals(logType)) {
                logInfo.setLevel(K8S_CALLBACK_LEVEL);
            } else {
                //schedule定时等 链路记录
                String traceType = MDC.get(TRACE_TYPE);
                if (StringUtils.isNotBlank(traceType)) {
                    logInfo.setLevel(traceType);
                }
            }
        }

        // 设置logInfo的堆栈信息
        setLogStackInfo(logInfo);
        // 设置logInfo的info信息
        setLogInfo(logInfo, object);
        // 截取logInfo的长度并转换成json字符串
        return logInfo;
    }

    /**
     * 设置loginfo的堆栈信息
     *
     * @param logInfo 日志对象
     */
    private static void setLogStackInfo(LogInfo logInfo) {
        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
        if (elements.length >= MagicNumConstant.SIX) {
            StackTraceElement element = elements[MagicNumConstant.FIVE];
            logInfo.setLocation(String.format("%s#%s:%s", element.getClassName(), element.getMethodName(), element.getLineNumber()));
        }
    }

    /**
     * 限制log日志的长度并转换成json
     *
     * @param logInfo 日志对象
     * @return String
     */
    private static String logJsonStringLengthLimit(LogInfo logInfo) {
        try {
            if(logInfo==null){
                return "";
            }
            String jsonString = logInfo.toString();
            if (StringUtils.isBlank(jsonString)) {
                return "";
            }
            if (jsonString.length() > MagicNumConstant.TEN_THOUSAND) {
                String trunk = logInfo.getInfo().toString().substring(MagicNumConstant.ZERO, MagicNumConstant.NINE_THOUSAND);
                logInfo.setInfo(trunk);
                jsonString = JSON.toJSONString(logInfo);
            }
            return jsonString;

        } catch (Exception e) {
            logInfo.setLevel(Level.ERROR.levelStr).setType(LogEnum.SYS_ERR.toString())
                    .setInfo("cannot serialize exception: " + ExceptionUtils.getStackTrace(e));
            return logInfo.toString();
        }
    }

    /**
     * 设置日志对象的info信息
     *
     * @param logInfo 日志对象
     * @param object  打印的日志参数
     */
    private static void setLogInfo(LogInfo logInfo, Object[] object) {

        if (object.length > MagicNumConstant.ONE) {
            logInfo.setInfo(MessageFormatter.arrayFormat(object[MagicNumConstant.ZERO].toString(),
                    Arrays.copyOfRange(object, MagicNumConstant.ONE, object.length)).getMessage());

        } else if (object.length == MagicNumConstant.ONE && object[MagicNumConstant.ZERO] instanceof Exception) {
            logInfo.setInfo((ExceptionUtils.getStackTrace((Exception) object[MagicNumConstant.ZERO])));
            log.error((ExceptionUtils.getStackTrace((Exception) object[MagicNumConstant.ZERO])));
        } else if (object.length == MagicNumConstant.ONE) {
            logInfo.setInfo(object[MagicNumConstant.ZERO] == null ? "" : object[MagicNumConstant.ZERO]);
        } else {
            logInfo.setInfo("");
        }

    }

    /**
     * 处理Exception的情况
     *
     * @param object 打印的日志参数
     */
    private static void errorObjectHandle(Object[] object) {

        if (object.length == MagicNumConstant.TWO && object[MagicNumConstant.ONE] instanceof Exception) {
            log.error(String.valueOf(object[MagicNumConstant.ZERO]), (Exception) object[MagicNumConstant.ONE]);
            object[MagicNumConstant.ONE] = ExceptionUtils.getStackTrace((Exception) object[MagicNumConstant.ONE]);

        } else if (object.length >= MagicNumConstant.THREE) {
            log.error(String.valueOf(object[MagicNumConstant.ZERO]),
                    Arrays.copyOfRange(object, MagicNumConstant.ONE, object.length));
            for (int i = 0; i < object.length; i++) {
                if (object[i] instanceof Exception) {
                    object[i] = ExceptionUtils.getStackTrace((Exception) object[i]);
                }

            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/caryeko/article/details/141321107