SpringBoot+log4j2+MDC+AOP记录requestId

前言

在AOP切面注入RequestId,拦截Controller、Service方法,打印入参出参耗时等,方便排查问题。

可以在服务上通过RequestId查询一次调用链日志:

SpringBoot+log4j2+MDC+AOP记录requestId

可以使用 Linux grep 命令查询日志:

grep 命令用于查找文件里符合条件的字符串。

日志文件太大无法直接 cat 查看,可以用grep

常用参数:

  • -A
  • -C
  • -E : 将样式为延伸的正则表达式来使用。

eg:

查询 包含 trainSegment/detail 的字符串的前后10行

grep -C 10 trainSegment/detail webapi-info-VM-130-116-centos.log

正则

grep -E -C 30 “keyword1. keyword2. ” webapi-info-VM-130-116-centos.log

代码

Controller

/**
 * @author lihaoyang
 * @date 2021/3/17
 */
@RestController
public class HiController {

    @Autowired
    HiServiceImpl hiService;

    @GetMapping("get")
    public String get(String msg) {
        String rs = hiService.getHi(msg);
        return rs;
    }

}

Service

@Service
public class HiServiceImpl {

    public String getHi(String msg) {
        return "service:  >>>>> " + msg;
    }

}

切面类

RequestId切面

@Aspect
@Component
@Slf4j
@Order(-10)
public class ControllerRequestIdAspect {

    @Pointcut("execution(public * com.nb.log.controller..*.*(..))")
    public void controllerPoint() {
    }

    @Around("controllerPoint()")
    public Object doControllerPointAround(ProceedingJoinPoint joinPoint) throws Throwable {
        String requestId = UUID.randomUUID().toString();
        MDC.put("requestId", requestId);
        Object result = null;
        try {
            result = joinPoint.proceed();
        } finally {
            MDC.remove("requestId");
        }
        return result;
    }
}

Controller切面

package com.nb.log.aop;

import com.alibaba.fastjson.JSONObject;
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.springframework.core.annotation.Order;
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.Arrays;

/**
 * controller切面
 */
@Aspect
@Slf4j
@Component
@Order(0)
public class ControllerLogAspect {

    @Pointcut("execution(public * com.nb.log.controller..*.*(..))")
    public void controllerPoint() {}

    @Around("controllerPoint()")
    public Object doControllerAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        Object result = null;
        try {
            HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            Object[] params = joinPoint.getArgs();
            log.info("Controller层 className={}, methodName={}, params={},url={},ip={}",
                joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
                Arrays.toString(params), request.getRequestURL(), IpUtil.getIpAddr(request));
            result = joinPoint.proceed();
        } finally {
            log.info("Controller层 耗时={}(ms), className={}, methodName={}, result={}",
                System.currentTimeMillis() - startTime, joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(), JSONObject.toJSONString(result));
        }
        return result;
    }
}

Service切面

package com.nb.log.aop;

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.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * service层切面日志
 */
@Aspect
@Slf4j
@Order(0)
@Component
public class ServiceLogAspect {

    @Pointcut("execution(public * com.nb.log.service..*ServiceImpl.*(..))")
    public void servicePoint() {
    }

    @Around("servicePoint()")
    public Object doServiceAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            Object[] params = joinPoint.getArgs();
            log.info("Service层 className={}, methodName={}, params={}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), Arrays.toString(params));
            result = joinPoint.proceed();
        }
        finally {
            log.info("Service层 耗时={}(ms), className={}, methodName={}", System.currentTimeMillis() - startTime, joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        }
        return result;
    }
}

log4j2.xml

xml version="1.0" encoding="UTF-8"?>

<configuration status="warn" monitorInterval="30">
    <Properties>
        <property name="log_pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%level] -%X{filter} <%t|%C{1.}.%M(%L)> -%X{requestId} %m%n%exproperty>
        <property name="project">remix-collectorproperty>
        <property name="basePath">D:/log/${project}/property>

        <property name="rolling_file_name">${basePath}/%d{yyyy-MM-dd}-%iproperty>

        <property name="every_file_size">500 MBproperty>
    Properties>

    <appenders>

        <console name="Console" target="SYSTEM_OUT">

            <PatternLayout pattern="${log_pattern}"/>
        console>

        <RollingFile name="RollingFile" fileName="${basePath}/${project}-info-${hostName}.log" filePattern="${basePath}/${project}-info-${hostName}-%d{yyyy-MM-dd}-%i.log">
            <Filters>

                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
                <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            Filters>
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${every_file_size}"/>
            Policies>

            <DefaultRolloverStrategy>
                <Delete basePath="${basePath}" maxDepth="1">
                    <IfFileName glob="*.log" />
                    <IfLastModified age="3d">

                    IfLastModified>
                Delete>
            DefaultRolloverStrategy>
        RollingFile>

        <RollingFile name="RollingFileWarn"
                     fileName="${basePath}/${project}-warn-${hostName}.log"
                     filePattern="${rolling_file_name}-warn-${hostName}-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            Filters>
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy modulate="true" interval="24"/>
                <SizeBasedTriggeringPolicy/>
            Policies>

            <DefaultRolloverStrategy max="20"/>
        RollingFile>

        <RollingFile name="RollingFileError"
                     fileName="${basePath}/${project}-error-${hostName}.log"
                     filePattern="${rolling_file_name}-error-${hostName}-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY" />
            Filters>
            <PatternLayout pattern="${log_pattern}"/>
            <SizeBasedTriggeringPolicy size="${every_file_size}"/>
        RollingFile>

    appenders>

    <loggers>

        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="druidSqlAppender"/>
            <AppenderRef ref="invokeAppender"/>
        logger>
        <logger name="druid.sql.ResultSet" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="druidSqlAppender"/>
            <AppenderRef ref="invokeAppender"/>
        logger>
        <logger name="com.nb.log.controller" level="INFO">
        logger>

        <root level="info">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFile"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
        root>
    loggers>

configuration>

maven pom.xml

xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <groupId>com.nbgroupId>
    <artifactId>nb-logartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>nb-logname>
    <description>Demo project for Spring Bootdescription>

    <properties>
        <java.version>1.8java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASEspring-boot.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-starter-loggingartifactId>
                exclusion>
            exclusions>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-log4j2artifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-aopartifactId>
        dependency>

        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>1.2.75version>
        dependency>

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.18version>
            <scope>providedscope>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintagegroupId>
                    <artifactId>junit-vintage-engineartifactId>
                exclusion>
            exclusions>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.8.1version>
                <configuration>
                    <source>1.8source>
                    <target>1.8target>
                    <encoding>UTF-8encoding>
                configuration>
            plugin>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>2.3.7.RELEASEversion>
                <configuration>
                    <mainClass>com.nb.log.NbLogApplicationmainClass>
                configuration>
                <executions>
                    <execution>
                        <id>repackageid>
                        <goals>
                            <goal>repackagegoal>
                        goals>
                    execution>
                executions>
            plugin>
        plugins>
    build>

project>

完整代码

https://gitee.com/haoyangli/mdc-log.git

Original: https://www.cnblogs.com/lihaoyang/p/15612808.html
Author: 我俩绝配
Title: SpringBoot+log4j2+MDC+AOP记录requestId

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/541013/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球