|
|
@@ -1,16 +1,28 @@ |
|
|
|
package com.xkcoding.log.aop.aspectj; |
|
|
|
|
|
|
|
import cn.hutool.core.util.ArrayUtil; |
|
|
|
import cn.hutool.json.JSONUtil; |
|
|
|
import com.google.common.collect.Maps; |
|
|
|
import eu.bitwalker.useragentutils.UserAgent; |
|
|
|
import lombok.AllArgsConstructor; |
|
|
|
import lombok.Builder; |
|
|
|
import lombok.Data; |
|
|
|
import lombok.NoArgsConstructor; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.aspectj.lang.JoinPoint; |
|
|
|
import org.aspectj.lang.ProceedingJoinPoint; |
|
|
|
import org.aspectj.lang.annotation.*; |
|
|
|
import org.aspectj.lang.Signature; |
|
|
|
import org.aspectj.lang.annotation.Around; |
|
|
|
import org.aspectj.lang.annotation.Aspect; |
|
|
|
import org.aspectj.lang.annotation.Pointcut; |
|
|
|
import org.aspectj.lang.reflect.MethodSignature; |
|
|
|
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.net.InetAddress; |
|
|
|
import java.net.UnknownHostException; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Objects; |
|
|
|
|
|
|
@@ -20,14 +32,13 @@ import java.util.Objects; |
|
|
|
* </p> |
|
|
|
* |
|
|
|
* @author yangkai.shen |
|
|
|
* @author chen qi |
|
|
|
* @date Created in 2018-10-01 22:05 |
|
|
|
*/ |
|
|
|
@Aspect |
|
|
|
@Component |
|
|
|
@Slf4j |
|
|
|
public class AopLog { |
|
|
|
private static final String START_TIME = "request-start"; |
|
|
|
|
|
|
|
/** |
|
|
|
* 切入点 |
|
|
|
*/ |
|
|
@@ -36,27 +47,6 @@ public class AopLog { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 前置操作 |
|
|
|
* |
|
|
|
* @param point 切入点 |
|
|
|
*/ |
|
|
|
@Before("log()") |
|
|
|
public void beforeLog(JoinPoint point) { |
|
|
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
|
|
|
|
|
|
|
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); |
|
|
|
|
|
|
|
log.info("【请求 URL】:{}", request.getRequestURL()); |
|
|
|
log.info("【请求 IP】:{}", request.getRemoteAddr()); |
|
|
|
log.info("【请求类名】:{},【请求方法名】:{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName()); |
|
|
|
|
|
|
|
Map<String, String[]> parameterMap = request.getParameterMap(); |
|
|
|
log.info("【请求参数】:{},", JSONUtil.toJsonStr(parameterMap)); |
|
|
|
Long start = System.currentTimeMillis(); |
|
|
|
request.setAttribute(START_TIME, start); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 环绕操作 |
|
|
|
* |
|
|
@@ -66,25 +56,123 @@ public class AopLog { |
|
|
|
*/ |
|
|
|
@Around("log()") |
|
|
|
public Object aroundLog(ProceedingJoinPoint point) throws Throwable { |
|
|
|
|
|
|
|
// 开始打印请求日志 |
|
|
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
|
|
|
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); |
|
|
|
|
|
|
|
// 打印请求相关参数 |
|
|
|
long startTime = System.currentTimeMillis(); |
|
|
|
Object result = point.proceed(); |
|
|
|
log.info("【返回值】:{}", JSONUtil.toJsonStr(result)); |
|
|
|
String header = request.getHeader("User-Agent"); |
|
|
|
UserAgent userAgent = UserAgent.parseUserAgentString(header); |
|
|
|
|
|
|
|
final Log l = Log.builder() |
|
|
|
.threadId(Long.toString(Thread.currentThread().getId())) |
|
|
|
.threadName(Thread.currentThread().getName()) |
|
|
|
.ip(getIp(request)) |
|
|
|
.url(request.getRequestURL().toString()) |
|
|
|
.classMethod(String.format("%s.%s", point.getSignature().getDeclaringTypeName(), |
|
|
|
point.getSignature().getName())) |
|
|
|
.httpMethod(request.getMethod()) |
|
|
|
.requestParams(getNameAndValue(point)) |
|
|
|
.result(result) |
|
|
|
.timeCost(System.currentTimeMillis() - startTime) |
|
|
|
.userAgent(header) |
|
|
|
.browser(userAgent.getBrowser().toString()) |
|
|
|
.os(userAgent.getOperatingSystem().toString()).build(); |
|
|
|
|
|
|
|
log.info("Request Log Info : {}", JSONUtil.toJsonStr(l)); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 后置操作 |
|
|
|
* 获取方法参数名和参数值 |
|
|
|
* @param joinPoint |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@AfterReturning("log()") |
|
|
|
public void afterReturning() { |
|
|
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
|
|
|
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); |
|
|
|
private Map<String, Object> getNameAndValue(ProceedingJoinPoint joinPoint) { |
|
|
|
|
|
|
|
Long start = (Long) request.getAttribute(START_TIME); |
|
|
|
Long end = System.currentTimeMillis(); |
|
|
|
log.info("【请求耗时】:{}毫秒", end - start); |
|
|
|
final Signature signature = joinPoint.getSignature(); |
|
|
|
MethodSignature methodSignature = (MethodSignature) signature; |
|
|
|
final String[] names = methodSignature.getParameterNames(); |
|
|
|
final Object[] args = joinPoint.getArgs(); |
|
|
|
|
|
|
|
String header = request.getHeader("User-Agent"); |
|
|
|
UserAgent userAgent = UserAgent.parseUserAgentString(header); |
|
|
|
log.info("【浏览器类型】:{},【操作系统】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header); |
|
|
|
if (ArrayUtil.isEmpty(names) || ArrayUtil.isEmpty(args)) { |
|
|
|
return Collections.emptyMap(); |
|
|
|
} |
|
|
|
if (names.length != args.length) { |
|
|
|
log.warn("{}方法参数名和参数值数量不一致", methodSignature.getName()); |
|
|
|
return Collections.emptyMap(); |
|
|
|
} |
|
|
|
Map<String, Object> map = Maps.newHashMap(); |
|
|
|
for (int i = 0; i < names.length; i++) { |
|
|
|
map.put(names[i], args[i]); |
|
|
|
} |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
private static final String UNKNOWN = "unknown"; |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取ip地址 |
|
|
|
*/ |
|
|
|
public static String getIp(HttpServletRequest request) { |
|
|
|
String ip = request.getHeader("x-forwarded-for"); |
|
|
|
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { |
|
|
|
ip = request.getHeader("Proxy-Client-IP"); |
|
|
|
} |
|
|
|
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { |
|
|
|
ip = request.getHeader("WL-Proxy-Client-IP"); |
|
|
|
} |
|
|
|
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { |
|
|
|
ip = request.getRemoteAddr(); |
|
|
|
} |
|
|
|
String comma = ","; |
|
|
|
String localhost = "127.0.0.1"; |
|
|
|
if (ip.contains(comma)) { |
|
|
|
ip = ip.split(",")[0]; |
|
|
|
} |
|
|
|
if (localhost.equals(ip)) { |
|
|
|
// 获取本机真正的ip地址 |
|
|
|
try { |
|
|
|
ip = InetAddress.getLocalHost().getHostAddress(); |
|
|
|
} catch (UnknownHostException e) { |
|
|
|
log.error(e.getMessage(), e); |
|
|
|
} |
|
|
|
} |
|
|
|
return ip; |
|
|
|
} |
|
|
|
|
|
|
|
@Data |
|
|
|
@Builder |
|
|
|
@NoArgsConstructor |
|
|
|
@AllArgsConstructor |
|
|
|
static class Log { |
|
|
|
// 线程id |
|
|
|
private String threadId; |
|
|
|
// 线程名称 |
|
|
|
private String threadName; |
|
|
|
// ip |
|
|
|
private String ip; |
|
|
|
// url |
|
|
|
private String url; |
|
|
|
// http方法 GET POST PUT DELETE PATCH |
|
|
|
private String httpMethod; |
|
|
|
// 类方法 |
|
|
|
private String classMethod; |
|
|
|
// 请求参数 |
|
|
|
private Object requestParams; |
|
|
|
// 返回参数 |
|
|
|
private Object result; |
|
|
|
// 接口耗时 |
|
|
|
private Long timeCost; |
|
|
|
// 操作系统 |
|
|
|
private String os; |
|
|
|
// 浏览器 |
|
|
|
private String browser; |
|
|
|
// user-agent |
|
|
|
private String userAgent; |
|
|
|
} |
|
|
|
} |