wangyunpeng 10 tuntia sitten
vanhempi
commit
0790bec876

+ 11 - 0
long-article-recommend-service/pom.xml

@@ -107,6 +107,17 @@
             <artifactId>aliyun-log-logback-appender</artifactId>
             <version>0.1.18</version>
         </dependency>
+        <dependency>
+            <groupId>com.tzld.commons</groupId>
+            <artifactId>aliyun-log-spring-boot-starter</artifactId>
+            <version>2.0.0</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>aliyun-log</artifactId>
+                    <groupId>com.aliyun.openservices</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-core</artifactId>

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/annotation/NoRequestLog.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 请求日志排除注解
+ * 标记在 controller 方法上,跳过 request-log 上报
+ *
+ * @author dyp
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface NoRequestLog {
+}

+ 45 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/IpUtil.java

@@ -0,0 +1,45 @@
+package com.tzld.longarticle.recommend.server.util;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * IP 工具类
+ *
+ * @author dyp
+ */
+public class IpUtil {
+
+    public static String getIpAddr(HttpServletRequest request) {
+        String ipAddress;
+        ipAddress = request.getHeader("x-forwarded-for");
+        if (ipAddress == null || ipAddress.length() == 0
+                || "unknown".equalsIgnoreCase(ipAddress)) {
+            ipAddress = request.getHeader("Proxy-Client-IP");
+        }
+        if (ipAddress == null || ipAddress.length() == 0
+                || "unknown".equalsIgnoreCase(ipAddress)) {
+            ipAddress = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ipAddress == null || ipAddress.length() == 0
+                || "unknown".equalsIgnoreCase(ipAddress)) {
+            ipAddress = request.getRemoteAddr();
+            if ("127.0.0.1".equals(ipAddress)) {
+                InetAddress inet;
+                try {
+                    inet = InetAddress.getLocalHost();
+                    ipAddress = inet.getHostAddress();
+                } catch (UnknownHostException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        // 对于通过多个代理的情况,取最后一跳 IP
+        if (ipAddress != null && ipAddress.indexOf(",") > 0) {
+            String[] ips = ipAddress.split(",");
+            ipAddress = ips[ips.length - 1].trim();
+        }
+        return ipAddress;
+    }
+}

+ 95 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/ControllerAspect.java

@@ -1,16 +1,27 @@
 package com.tzld.longarticle.recommend.server.web;
 
 import com.google.common.base.Stopwatch;
+import com.google.common.base.Strings;
+import com.tzld.commons.aliyun.log.AliyunLogManager;
+import com.tzld.longarticle.recommend.server.util.IpUtil;
 import com.tzld.longarticle.recommend.server.util.JSONUtils;
 import com.tzld.longarticle.recommend.server.util.TraceUtils;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 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.*;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * @author dyp
@@ -20,17 +31,46 @@ import java.util.concurrent.TimeUnit;
 @Slf4j
 public class ControllerAspect {
 
+    private final AliyunLogManager aliyunLogManager;
+
+    @Value("${aliyun.log.project:}")
+    private String project;
+    @Value("${aliyun.log.logstore.request:request-log}")
+    private String logStore;
+    @Value("${aliyun.log.topic:}")
+    private String topic;
+
+    @Autowired
+    public ControllerAspect(AliyunLogManager aliyunLogManager) {
+        this.aliyunLogManager = aliyunLogManager;
+    }
+
     @Around("execution(* com.tzld.longarticle.recommend.server.web..*Controller.*(..)) " +
-            "&& !execution(* com.tzld.longarticle.recommend.server.web.HealthCheckController.ok(..))")
+            "&& !execution(* com.tzld.longarticle.recommend.server.web.HealthCheckController.ok(..))" +
+            "&& !@annotation(com.tzld.longarticle.recommend.server.annotation.NoRequestLog)")
     public Object around(ProceedingJoinPoint pjp) throws Throwable {
         TraceUtils.setMDC();
 
         String className = pjp.getTarget().getClass().getSimpleName();
         MethodSignature signature = (MethodSignature) pjp.getSignature();
         Stopwatch stopwatch = Stopwatch.createStarted();
+        long startTime = System.currentTimeMillis();
+
         log.info("request className=[{}], method=[{}], param=[{}]", className, signature.getName(),
                 JSONUtils.toJson(pjp.getArgs()));
-        Object result = pjp.proceed();
+
+        Object result;
+        try {
+            result = pjp.proceed();
+        } catch (Throwable e) {
+            long elapsedTime = System.currentTimeMillis() - startTime;
+            sendRequestLog(pjp, e.toString(), elapsedTime);
+            TraceUtils.removeMDC();
+            throw e;
+        }
+
+        long elapsedTime = System.currentTimeMillis() - startTime;
+
         if (result != null && result instanceof String) {
             log.info("response className=[{}], method=[{}],  cost=[{}] param=[{}] result=[{}]", className,
                     signature.getName(), stopwatch.stop().elapsed(TimeUnit.MILLISECONDS),
@@ -41,7 +81,60 @@ public class ControllerAspect {
                     JSONUtils.toJson(pjp.getArgs()), JSONUtils.toJson(result));
         }
 
+        sendRequestLog(pjp, JSONUtils.toJson(result), elapsedTime);
+
         TraceUtils.removeMDC();
         return result;
     }
+
+    private void sendRequestLog(ProceedingJoinPoint pjp, String responseBody, long elapsedTime) {
+        try {
+            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+            if (attributes == null) {
+                return;
+            }
+            HttpServletRequest request = attributes.getRequest();
+
+            String query = request.getQueryString();
+            String uri = request.getRequestURI();
+            String url = Strings.isNullOrEmpty(query) ? uri : uri + "?" + query;
+
+            if (StringUtils.isNotBlank(url) && url.contains("/test")) {
+                return;
+            }
+
+            Map<String, Object> logMap = new HashMap<>(8);
+            logMap.put("url", url);
+            logMap.put("method", request.getMethod());
+            logMap.put("header", getHeaders(request));
+            logMap.put("elapsedTime", String.valueOf(elapsedTime));
+            logMap.put("clientIp", IpUtil.getIpAddr(request));
+            logMap.put("requestBody", getRequestBody(pjp.getArgs()));
+            logMap.put("traceId", Strings.nullToEmpty(TraceUtils.currentTraceId()));
+            logMap.put("responseBody", responseBody);
+
+            aliyunLogManager.sendLog(project, logStore, topic, logMap);
+        } catch (Exception e) {
+            log.error("log report request error", e);
+        }
+    }
+
+    private Object getRequestBody(Object[] args) {
+        try {
+            if (args == null || args.length == 0) {
+                return "";
+            }
+            return JSONUtils.toJson(args[0]);
+        } catch (Exception e) {
+            return args;
+        }
+    }
+
+    private String getHeaders(HttpServletRequest request) {
+        return Collections.list(request.getHeaderNames())
+                .stream()
+                .collect(Collectors.toMap(
+                        name -> name,
+                        request::getHeader)).toString();
+    }
 }