使用AOP或Interceptor分别实现日志采集

在微服务架构中,使用面向切面编程(Aspect-Oriented Programming, AOP)来实现接口的日志采集是一种常见的做法。AOP 允许开发者将横切关注点(如日志记录、性能监控等)从业务逻辑中分离出来,使得业务代码更加简洁、可维护。

对于微服务中的接口日志采集,可以通过以下几种方式来实现:

1. 使用 Spring AOP

1.1 添加依赖

首先确保你的项目中包含了Spring AOP和日志框架的依赖。以SLF4J和Logback为例,可以在Maven的构建文件中添加如下依赖:

<!-- Maven -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
    </dependency>
</dependencies>

1.2 配置日志

src/main/resources目录下添加logback.xml文件来配置日志输出:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

1.3 创建AOP切面

接下来创建一个AOP切面类来记录日志:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

    @Pointcut("execution(* com.example.service..*(..))")
    public void logPointCut() {}

    @Before("logPointCut()")
    public void logBefore(JoinPoint joinPoint) {
        logger.info("Entering method: {} with arguments: {}", 
                    joinPoint.getSignature().getName(), 
                    joinPoint.getArgs());
    }

    @AfterReturning(pointcut = "logPointCut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        logger.info("Exiting method: {} with result: {}", 
                    joinPoint.getSignature().getName(), 
                    result);
    }
}

2. 使用框架提供的支持

除了 Spring AOP 外,许多微服务框架也提供了自己的 AOP 实现。例如,在 Dubbo 或者 gRPC 中,可以利用它们提供的拦截器机制来记录日志。

示例:Dubbo 拦截器

import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.RpcResult;

@Service
public class UserServiceImpl implements UserService {

    // ... service implementation

    @Override
    public String getUserInfo(String userId) {
        RpcContext.getContext().setAttachment("userId", userId);
        // ... business logic
    }
}

// 日志拦截器
public class LoggingInterceptor implements Interceptor {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long start = System.currentTimeMillis();
        try {
            logger.info("Entering " + invocation.getMethodName());
            Result result = invoker.invoke(invocation);
            logger.info("Exiting " + invocation.getMethodName() + " in " + (System.currentTimeMillis() - start) + "ms");
            return result;
        } catch (RpcException e) {
            logger.error("Error in " + invocation.getMethodName(), e);
            throw e;
        }
    }
}