package com.elab.log.log4j;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.AppenderBase;
import com.dianping.cat.Cat;

import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * CAT集成Logback拓展
 *
 * @author Liukx
 * @create 2018-02-06 17:58
 * @email liukx@elab-plus.com
 **/
public class CatLogbackLog extends AppenderBase<ILoggingEvent> {

    private final int lineLength = 200;
    private final String type = "Logback";

    @Override
    protected void append(ILoggingEvent event) {
        boolean isTraceMode = Cat.getManager().isTraceMode();
        Level level = event.getLevel();
        if (level.isGreaterOrEqual(Level.ERROR)) {
            this.logError(event);
        } else if (!isTraceMode) {
            this.logTrace(event);
        }

    }

    /**
     * 处理异常栈
     *
     * @param exception
     * @return
     */
    private String buildExceptionStack(Throwable exception) {
        if (exception != null) {
            StringWriter writer = new StringWriter(2048);
            exception.printStackTrace(new PrintWriter(writer));
            return writer.toString();
        } else {
            return "";
        }
    }

    /**
     * 打印错误日志
     *
     * @param event
     */
    private void logError(ILoggingEvent event) {
        ThrowableProxy info = (ThrowableProxy) event.getThrowableProxy();
        if (info != null) {
            Throwable exception = info.getThrowable();
            Object message = event.getMessage();
            if (message != null) {
                Cat.logError(String.valueOf(message), exception);
            } else {
                Cat.logError(exception);
            }
        }

    }

    private void logTrace(ILoggingEvent event) {
        String name = event.getLevel().toString();
        Object message = event.getMessage();
        String data;
        if (message instanceof Throwable) {
            data = this.buildExceptionStack((Throwable) message);
        } else {
            data = event.getMessage().toString();
        }
// DEBUG 的异常不打印
//        ThrowableProxy info = (ThrowableProxy) event.getThrowableProxy();
//        if (info != null) {
//            data = data + '\n' + this.buildExceptionStack(info.getThrowable());
//            Cat.logError(data, info.getThrowable());
//            return;
//        }
        Cat.logEvent(type, name, "0", formatShowData(data));
    }

    /**
     * 根据打印出来的内容进行格式化,按照长度进行换行
     *
     * @param msg
     * @return
     */
    public String formatShowData(String msg) {
        int length = msg.length();

        if (length < lineLength) {
            return msg;
        }

        int maxSplit = length / lineLength;
        int mo = length % lineLength;
        if (length % lineLength > 0) {
            maxSplit++;
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < maxSplit; i++) {
            int index = i * lineLength;
            if (maxSplit == (i + 1)) {
                sb.append(msg.substring(index, index + mo) + "\n");
            } else {
                sb.append(msg.substring(index, index + lineLength) + "\n");
            }
        }
        return sb.toString();
    }

}
