日志打印 - 命令模式、模版方法模式

1. logback-spring.xml

    <appender name="monitorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
        <file>${logging.file.path}/smart.monitor.log</file>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--按时间保存日志 修改格式可以按小时、按天、月来保存-->
            <fileNamePattern>${logging.file.path}/smart.monitor.log.%d{yyyy-MM-dd}</fileNamePattern>
            <!--保存时长-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
    </appender>


    <!-- 自定义配置__web请求入参、反参、请求时常 -->
    <logger name="monitorLogger" additivity="false" level="info">
        <appender-ref ref="monitorAppender"/>
    </logger>

2. AbstractLogItem

package com.soyoung.ztdata.bi.api.model.log;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

/**
 * @program: bi-main
 * @description:
 * @author: Leon
 * @create: 2021-11-15 19:30
 **/
@Getter
@Setter
public abstract class AbstractLogItem implements Serializable {

    private static final long serialVersionUID = 9206074344981457062L;
    
    private String requestId;
    private String method;
    private String projectName;
    private String time;

    public AbstractLogItem(String requestId, String method, String projectName) {
        this.requestId = requestId;
        this.method = method;
        this.projectName = projectName;
    }
}

3. MonitorLogItem

package com.soyoung.ztdata.bi.api.model.log;

import lombok.Getter;
import lombok.Setter;

import java.util.Map;

/**
 * @program: bi-main
 * @description:
 * @author: Leon
 * @create: 2021-11-15 19:42
 **/
@Setter
@Getter
public class MonitorLogItem extends AbstractLogItem {


    public MonitorLogItem(String requestId, String method, String projectName) {
        super(requestId, method, projectName);
    }

    /**
     * 请求的 userName
     */
    private String userName;
    /**
     * 开始时间
     */
    private String startTime;
    /**
     * 结束时间戳
     */
    private String endTime;
    /**
     * 耗时
     */
    private Integer costTime;
    /**
     * params接口入参对象
     */
    private Map<String, String[]> params;
    /**
     * params接口入参对象
     */
    private Map<String, Object> nameAndValue;
    /**
     * result接口返回结果
     */
    private Object result;
}

4.LogCommand

package com.soyoung.ztdata.bi.api.model.log;

/**
 * @program: bi-main
 * @description:
 * @author: Leon
 * @create: 2021-11-12 16:58
 **/
public interface LogCommand {

    void execute();
}

5. AbstractLogCommand

package com.soyoung.ztdata.bi.api.model.log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @program: bi-main
 * @description:
 * @author: Leon
 * @create: 2021-11-12 21:26
 **/
@Slf4j
public abstract class AbstractLogCommand<LogItem extends AbstractLogItem> implements LogCommand {

    private Logger receiver;

    private LogItem logItem;

    public AbstractLogCommand(Logger receiver, LogItem logItem) {
        this.receiver = receiver;
        this.logItem = logItem;
    }

    /**
     * @desc: 打印入口
     */
    @Override
    public void execute() {
        try {
            obtainLog(logItem);
            /**
             * 日志打印的时间
             */
            logItem.setTime(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            String msg = JSON.toJSONString(logItem, SerializerFeature.DisableCircularReferenceDetect);
            receiver.info(msg);
        } catch (Exception e) {
            log.error("AbstractLogCommand execute error:{}, requestId:{}", e.getMessage(), logItem.getRequestId());
        }
    }

    protected abstract void obtainLog(LogItem t);
}

6. MonitorLogCommand

package com.soyoung.ztdata.bi.api.model.log;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @program: bi-main
 * @description:
 * @author: Leon
 * @create: 2021-11-12 21:32
 **/
@Slf4j
@Setter
@Getter
@Accessors(chain = true)
public class MonitorLogCommand extends AbstractLogCommand<MonitorLogItem> {

    public MonitorLogCommand(Logger receiver, String requestId, String method, String projectName) {
        super(receiver, new MonitorLogItem(requestId, method, projectName));
    }

    @Override
    protected void obtainLog(MonitorLogItem monitorLogItem) {
        monitorLogItem.setUserName(this.userName);
        monitorLogItem.setStartTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(this.startTime), ZoneId.systemDefault()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        monitorLogItem.setEndTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(this.endTime), ZoneId.systemDefault()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

        if (Objects.nonNull(this.startTime) && Objects.nonNull(this.endTime)) {
            monitorLogItem.setCostTime((int) (this.endTime - this.startTime));
        }

        Map<String, String[]> allParameterMap = new HashMap<>();

        if (!CollectionUtils.isEmpty(parameterMap)) {
            allParameterMap.putAll(parameterMap);
        }

        if (StringUtils.isNotBlank(queryString)) {
            Map<String, String[]> queryStringMap = Arrays.stream(queryString.split("&")).collect(Collectors.toMap(s -> s.split("=")[0], s -> new String[]{
                    s.split("=")[1]
            }));
            allParameterMap.putAll(queryStringMap);
        }

        monitorLogItem.setParams(allParameterMap);

        monitorLogItem.setNameAndValue(nameAndValue);

        monitorLogItem.setResult(result);
    }

    /**
     * 请求的 userName
     */
    private String userName;
    /**
     * 开始时间戳
     */
    private Long startTime;
    /**
     * 结束时间戳
     */
    private Long endTime;

    /**
     * params接口入参对象
     */
    private Map<String, String[]> parameterMap;
    /**
     * params接口入参对象
     */
    private String queryString;
    /**
     * params接口入参对象
     */
    private Map<String, Object> nameAndValue;
    /**
     * result接口返回结果
     */
    private Object result;

}

7. AsyncExecuteInvoker

package com.soyoung.ztdata.smart.common;

import com.soyoung.ztdata.bi.api.model.log.LogCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @program: bi-main
 * @description:
 * @author: Leon
 * @create: 2021-11-12 18:22
 **/
@Slf4j
@Component
public class AsyncExecuteInvoker {

    @Async
    public void invoke(LogCommand logCommand) {
        logCommand.execute();
    }

}

8. MonitorLogHandler

package com.soyoung.ztdata.smart.aop;

import com.soyoung.ztdata.bi.api.model.log.MonitorLogCommand;
import com.soyoung.ztdata.bi.core.enums.ResultCodeEnum;
import com.soyoung.ztdata.bi.core.result.OutputResult;
import com.soyoung.ztdata.bi.core.util.JsonUtil;
import com.soyoung.ztdata.smart.common.AsyncExecuteInvoker;
import com.soyoung.ztdata.smart.common.SsoHelper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.LoggerFactory;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: bi-main
 * @description:
 * @author: Leon
 * @create: 2021-11-12 17:45
 **/
@Slf4j
@Aspect
@Component
public class MonitorLogHandler {


    @Autowired
    private AsyncExecuteInvoker asyncExecuteInvoker;

    @Pointcut("execution(public * com.soyoung.ztdata.smart.controller.*.*.*(..))")
    private void controllerAspect() {
    }

    @Around("controllerAspect()")
    public Object invokeResourceWithInterceptor(ProceedingJoinPoint pjp) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        String requestId = null != request.getParameterMap().get("requestId") ? request.getParameterMap().get("requestId")[0] : null;
        MonitorLogCommand monitorLogCommand = new MonitorLogCommand(LoggerFactory.getLogger("monitorLogger"), requestId, request.getRequestURI(), "projectName");

        monitorLogCommand.setUserName(SsoHelper.getUserName());
        monitorLogCommand.setParameterMap(request.getParameterMap());
        monitorLogCommand.setQueryString(request.getQueryString());
        Map<String, Object> nameAndValue = getNameAndValue(pjp);
        monitorLogCommand.setNameAndValue(nameAndValue);

        try {
            monitorLogCommand.setStartTime(System.currentTimeMillis());
            Object proceed = pjp.proceed();
            monitorLogCommand.setEndTime(System.currentTimeMillis());

            monitorLogCommand.setResult(proceed);

            asyncExecuteInvoker.invoke(monitorLogCommand);
            return proceed;
        } catch (Throwable e) {
            log.error("拦截器拦截异常 msg:{}", JsonUtil.writeValueAsString(monitorLogCommand), e);
            return OutputResult.error(ResultCodeEnum.SYS_ERROR);
        }
    }

    private Map<String, Object> getNameAndValue(ProceedingJoinPoint pjp) {
        Map<String, Object> result = new HashMap<>();
        final String[] parameterNames = ((CodeSignature) pjp.getSignature()).getParameterNames();
        final Object[] args = pjp.getArgs();
        for (int i = 0; i < parameterNames.length; i++) {
            result.put(parameterNames[i], args[i]);
        }
        return result;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值