fix bugs
This commit is contained in:
50
blade-starter-log/pom.xml
Normal file
50
blade-starter-log/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>BladeX-Tool</artifactId>
|
||||
<groupId>org.springblade</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>blade-starter-log</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${project.parent.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!--Blade-->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-cloud</artifactId>
|
||||
</dependency>
|
||||
<!--Mybatis-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus</artifactId>
|
||||
</dependency>
|
||||
<!-- Logstash -->
|
||||
<dependency>
|
||||
<groupId>net.logstash.logback</groupId>
|
||||
<artifactId>logstash-logback-encoder</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.janino</groupId>
|
||||
<artifactId>janino</artifactId>
|
||||
</dependency>
|
||||
<!-- validator -->
|
||||
<dependency>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
</dependency>
|
||||
<!-- Auto -->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-auto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 操作日志注解
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ApiLog {
|
||||
|
||||
/**
|
||||
* 日志描述
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
String value() default "日志记录";
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springblade.core.log.annotation.ApiLog;
|
||||
import org.springblade.core.log.publisher.ApiLogPublisher;
|
||||
|
||||
/**
|
||||
* 操作日志使用spring event异步入库
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
public class ApiLogAspect {
|
||||
|
||||
@Around("@annotation(apiLog)")
|
||||
public Object around(ProceedingJoinPoint point, ApiLog apiLog) throws Throwable {
|
||||
//获取类名
|
||||
String className = point.getTarget().getClass().getName();
|
||||
//获取方法
|
||||
String methodName = point.getSignature().getName();
|
||||
// 发送异步日志事件
|
||||
long beginTime = System.currentTimeMillis();
|
||||
//执行方法
|
||||
Object result = point.proceed();
|
||||
//执行时长(毫秒)
|
||||
long time = System.currentTimeMillis() - beginTime;
|
||||
//记录日志
|
||||
ApiLogPublisher.publishEvent(methodName, className, apiLog, time);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.aspect;
|
||||
|
||||
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.springblade.core.log.utils.LogTraceUtil;
|
||||
|
||||
/**
|
||||
* 为异步方法添加traceId
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Aspect
|
||||
public class LogTraceAspect {
|
||||
|
||||
@Pointcut("@annotation(org.springframework.scheduling.annotation.Async)")
|
||||
public void logPointCut() {
|
||||
}
|
||||
|
||||
@Around("logPointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
try {
|
||||
LogTraceUtil.insert();
|
||||
return point.proceed();
|
||||
} finally {
|
||||
LogTraceUtil.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.aspect;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
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.reflect.MethodSignature;
|
||||
import org.springblade.core.launch.log.BladeLogLevel;
|
||||
import org.springblade.core.log.props.BladeRequestLogProperties;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springblade.core.tool.utils.ClassUtil;
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.io.InputStreamSource;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Spring boot 控制器 请求日志,方便代码调试
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@AutoConfiguration
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnProperty(value = BladeLogLevel.REQ_LOG_PROPS_PREFIX + ".enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class RequestLogAspect {
|
||||
|
||||
private final BladeRequestLogProperties properties;
|
||||
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
|
||||
|
||||
/**
|
||||
* AOP 环切 控制器 R 返回值
|
||||
*
|
||||
* @param point JoinPoint
|
||||
* @return Object
|
||||
* @throws Throwable 异常
|
||||
*/
|
||||
@Around(
|
||||
"execution(!static org.springblade.core.tool.api.R *(..)) && " +
|
||||
"(@within(org.springframework.stereotype.Controller) || " +
|
||||
"@within(org.springframework.web.bind.annotation.RestController))"
|
||||
)
|
||||
public Object aroundApi(ProceedingJoinPoint point) throws Throwable {
|
||||
BladeLogLevel level = properties.getLevel();
|
||||
// 不打印日志,直接返回
|
||||
if (BladeLogLevel.NONE == level) {
|
||||
return point.proceed();
|
||||
}
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
String requestUrl = Objects.requireNonNull(request).getRequestURI();
|
||||
String requestMethod = request.getMethod();
|
||||
|
||||
// 放行的接口不打印日志
|
||||
if (isSkip(requestUrl)) {
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
// 构建成一条长 日志,避免并发下日志错乱
|
||||
StringBuilder beforeReqLog = new StringBuilder(300);
|
||||
// 日志参数
|
||||
List<Object> beforeReqArgs = new ArrayList<>();
|
||||
beforeReqLog.append("\n\n================ Request Start ================\n");
|
||||
// 打印路由
|
||||
beforeReqLog.append("===> {}: {}");
|
||||
beforeReqArgs.add(requestMethod);
|
||||
beforeReqArgs.add(requestUrl);
|
||||
// 打印请求参数
|
||||
logIngArgs(point, beforeReqLog, beforeReqArgs);
|
||||
// 打印请求 headers
|
||||
logIngHeaders(request, level, beforeReqLog, beforeReqArgs);
|
||||
beforeReqLog.append("================ Request End ================\n");
|
||||
|
||||
// 打印执行时间
|
||||
long startNs = System.nanoTime();
|
||||
log.info(beforeReqLog.toString(), beforeReqArgs.toArray());
|
||||
// aop 执行后的日志
|
||||
StringBuilder afterReqLog = new StringBuilder(200);
|
||||
// 日志参数
|
||||
List<Object> afterReqArgs = new ArrayList<>();
|
||||
afterReqLog.append("\n\n=============== Response Start ================\n");
|
||||
try {
|
||||
Object result = point.proceed();
|
||||
// 打印返回结构体
|
||||
if (BladeLogLevel.BODY.lte(level)) {
|
||||
afterReqLog.append("===Result=== {}\n");
|
||||
afterReqArgs.add(JsonUtil.toJson(result));
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
|
||||
afterReqLog.append("<=== {}: {} ({} ms)\n");
|
||||
afterReqArgs.add(requestMethod);
|
||||
afterReqArgs.add(requestUrl);
|
||||
afterReqArgs.add(tookMs);
|
||||
afterReqLog.append("=============== Response End ================\n");
|
||||
log.info(afterReqLog.toString(), afterReqArgs.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 激励请求参数
|
||||
*
|
||||
* @param point ProceedingJoinPoint
|
||||
* @param beforeReqLog StringBuilder
|
||||
* @param beforeReqArgs beforeReqArgs
|
||||
*/
|
||||
public void logIngArgs(ProceedingJoinPoint point, StringBuilder beforeReqLog, List<Object> beforeReqArgs) {
|
||||
MethodSignature ms = (MethodSignature) point.getSignature();
|
||||
Method method = ms.getMethod();
|
||||
Object[] args = point.getArgs();
|
||||
// 请求参数处理
|
||||
final Map<String, Object> paraMap = new HashMap<>(16);
|
||||
// 一次请求只能有一个 request body
|
||||
Object requestBodyValue = null;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
// 读取方法参数
|
||||
MethodParameter methodParam = ClassUtil.getMethodParameter(method, i);
|
||||
// PathVariable 参数跳过
|
||||
PathVariable pathVariable = methodParam.getParameterAnnotation(PathVariable.class);
|
||||
if (pathVariable != null) {
|
||||
continue;
|
||||
}
|
||||
RequestBody requestBody = methodParam.getParameterAnnotation(RequestBody.class);
|
||||
String parameterName = methodParam.getParameterName();
|
||||
Object value = args[i];
|
||||
// 如果是body的json则是对象
|
||||
if (requestBody != null) {
|
||||
requestBodyValue = value;
|
||||
continue;
|
||||
}
|
||||
// 处理 参数
|
||||
if (value instanceof HttpServletRequest) {
|
||||
paraMap.putAll(((HttpServletRequest) value).getParameterMap());
|
||||
continue;
|
||||
} else if (value instanceof WebRequest) {
|
||||
paraMap.putAll(((WebRequest) value).getParameterMap());
|
||||
continue;
|
||||
} else if (value instanceof HttpServletResponse) {
|
||||
continue;
|
||||
} else if (value instanceof MultipartFile) {
|
||||
MultipartFile multipartFile = (MultipartFile) value;
|
||||
String name = multipartFile.getName();
|
||||
String fileName = multipartFile.getOriginalFilename();
|
||||
paraMap.put(name, fileName);
|
||||
continue;
|
||||
} else if (value instanceof MultipartFile[]) {
|
||||
MultipartFile[] arr = (MultipartFile[]) value;
|
||||
if (arr.length == 0) {
|
||||
continue;
|
||||
}
|
||||
String name = arr[0].getName();
|
||||
StringBuilder sb = new StringBuilder(arr.length);
|
||||
for (MultipartFile multipartFile : arr) {
|
||||
sb.append(multipartFile.getOriginalFilename());
|
||||
sb.append(StringPool.COMMA);
|
||||
}
|
||||
paraMap.put(name, StringUtil.removeSuffix(sb.toString(), StringPool.COMMA));
|
||||
continue;
|
||||
} else if (value instanceof List) {
|
||||
List<?> list = (List<?>) value;
|
||||
AtomicBoolean isSkip = new AtomicBoolean(false);
|
||||
for (Object o : list) {
|
||||
if ("StandardMultipartFile".equalsIgnoreCase(o.getClass().getSimpleName())) {
|
||||
isSkip.set(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isSkip.get()) {
|
||||
paraMap.put(parameterName, "此参数不能序列化为json");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 参数名
|
||||
RequestParam requestParam = methodParam.getParameterAnnotation(RequestParam.class);
|
||||
String paraName = parameterName;
|
||||
if (requestParam != null && StringUtil.isNotBlank(requestParam.value())) {
|
||||
paraName = requestParam.value();
|
||||
}
|
||||
if (value == null) {
|
||||
paraMap.put(paraName, null);
|
||||
} else if (ClassUtil.isPrimitiveOrWrapper(value.getClass())) {
|
||||
paraMap.put(paraName, value);
|
||||
} else if (value instanceof InputStream) {
|
||||
paraMap.put(paraName, "InputStream");
|
||||
} else if (value instanceof InputStreamSource) {
|
||||
paraMap.put(paraName, "InputStreamSource");
|
||||
} else if (JsonUtil.canSerialize(value)) {
|
||||
// 判断模型能被 json 序列化,则添加
|
||||
paraMap.put(paraName, value);
|
||||
} else {
|
||||
paraMap.put(paraName, "此参数不能序列化为json");
|
||||
}
|
||||
}
|
||||
// 请求参数
|
||||
if (paraMap.isEmpty()) {
|
||||
beforeReqLog.append("\n");
|
||||
} else {
|
||||
beforeReqLog.append(" Parameters: {}\n");
|
||||
beforeReqArgs.add(JsonUtil.toJson(paraMap));
|
||||
}
|
||||
if (requestBodyValue != null) {
|
||||
beforeReqLog.append("====Body===== {}\n");
|
||||
beforeReqArgs.add(JsonUtil.toJson(requestBodyValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录请求头
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
* @param level 日志级别
|
||||
* @param beforeReqLog StringBuilder
|
||||
* @param beforeReqArgs beforeReqArgs
|
||||
*/
|
||||
public void logIngHeaders(HttpServletRequest request, BladeLogLevel level,
|
||||
StringBuilder beforeReqLog, List<Object> beforeReqArgs) {
|
||||
// 打印请求头
|
||||
if (BladeLogLevel.HEADERS.lte(level)) {
|
||||
Enumeration<String> headers = request.getHeaderNames();
|
||||
while (headers.hasMoreElements()) {
|
||||
String headerName = headers.nextElement();
|
||||
String headerValue = request.getHeader(headerName);
|
||||
beforeReqLog.append("===Headers=== {}: {}\n");
|
||||
beforeReqArgs.add(headerName);
|
||||
beforeReqArgs.add(headerValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSkip(String path) {
|
||||
return properties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.config;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.log.error.BladeErrorAttributes;
|
||||
import org.springblade.core.log.error.BladeErrorController;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
|
||||
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
||||
import org.springframework.boot.web.servlet.error.ErrorController;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
import jakarta.servlet.Servlet;
|
||||
|
||||
/**
|
||||
* 统一异常处理
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@ConditionalOnWebApplication
|
||||
@AutoConfiguration(before = ErrorMvcAutoConfiguration.class)
|
||||
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
|
||||
public class BladeErrorMvcAutoConfiguration {
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
|
||||
public DefaultErrorAttributes errorAttributes() {
|
||||
return new BladeErrorAttributes();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
|
||||
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
|
||||
return new BladeErrorController(errorAttributes, serverProperties.getError());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.config;
|
||||
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.launch.props.BladePropertySource;
|
||||
import org.springblade.core.launch.server.ServerInfo;
|
||||
import org.springblade.core.log.aspect.ApiLogAspect;
|
||||
import org.springblade.core.log.aspect.LogTraceAspect;
|
||||
import org.springblade.core.log.event.ApiLogListener;
|
||||
import org.springblade.core.log.event.ErrorLogListener;
|
||||
import org.springblade.core.log.event.UsualLogListener;
|
||||
import org.springblade.core.log.feign.ILogClient;
|
||||
import org.springblade.core.log.filter.LogTraceFilter;
|
||||
import org.springblade.core.log.logger.BladeLogger;
|
||||
import org.springblade.core.log.props.BladeRequestLogProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
|
||||
/**
|
||||
* 日志工具自动配置
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnWebApplication
|
||||
@EnableConfigurationProperties(BladeRequestLogProperties.class)
|
||||
@BladePropertySource(value = "classpath:/blade-log.yml")
|
||||
public class BladeLogToolAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public ApiLogAspect apiLogAspect() {
|
||||
return new ApiLogAspect();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LogTraceAspect logTraceAspect() {
|
||||
return new LogTraceAspect();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BladeLogger bladeLogger() {
|
||||
return new BladeLogger();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<LogTraceFilter> logTraceFilterRegistration() {
|
||||
FilterRegistrationBean<LogTraceFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
registration.setFilter(new LogTraceFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("LogTraceFilter");
|
||||
registration.setOrder(Ordered.LOWEST_PRECEDENCE);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "apiLogListener")
|
||||
public ApiLogListener apiLogListener(ILogClient logService, ServerInfo serverInfo, BladeProperties bladeProperties) {
|
||||
return new ApiLogListener(logService, serverInfo, bladeProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "errorEventListener")
|
||||
public ErrorLogListener errorEventListener(ILogClient logService, ServerInfo serverInfo, BladeProperties bladeProperties) {
|
||||
return new ErrorLogListener(logService, serverInfo, bladeProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "usualEventListener")
|
||||
public UsualLogListener usualEventListener(ILogClient logService, ServerInfo serverInfo, BladeProperties bladeProperties) {
|
||||
return new UsualLogListener(logService, serverInfo, bladeProperties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.constant;
|
||||
|
||||
/**
|
||||
* 事件常量
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface EventConstant {
|
||||
|
||||
/**
|
||||
* log
|
||||
*/
|
||||
String EVENT_LOG = "log";
|
||||
/**
|
||||
* request
|
||||
*/
|
||||
String EVENT_REQUEST = "request";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.error;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.log.publisher.ErrorLogPublisher;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.api.ResultCode;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springframework.boot.web.error.ErrorAttributeOptions;
|
||||
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
public class BladeErrorAttributes extends DefaultErrorAttributes {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
|
||||
String requestUri = this.getAttr(webRequest, "jakarta.servlet.error.request_uri");
|
||||
Integer status = this.getAttr(webRequest, "jakarta.servlet.error.status_code");
|
||||
Throwable error = getError(webRequest);
|
||||
R result;
|
||||
if (error == null) {
|
||||
log.error("URL:{} error status:{}", requestUri, status);
|
||||
result = R.fail(ResultCode.FAILURE, "系统未知异常[HttpStatus]:" + status);
|
||||
} else {
|
||||
log.error(String.format("URL:%s error status:%d", requestUri, status), error);
|
||||
result = R.fail(status, error.getMessage());
|
||||
}
|
||||
//发送服务异常事件
|
||||
ErrorLogPublisher.publishEvent(error, requestUri);
|
||||
return BeanUtil.toMap(result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> T getAttr(WebRequest webRequest, String name) {
|
||||
return (T) webRequest.getAttribute(name, RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.error;
|
||||
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springframework.boot.autoconfigure.web.ErrorProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
|
||||
import org.springframework.boot.web.error.ErrorAttributeOptions;
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 更改html请求异常为ajax
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class BladeErrorController extends BasicErrorController {
|
||||
|
||||
public BladeErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {
|
||||
super(errorAttributes, errorProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
|
||||
boolean includeStackTrace = isIncludeStackTrace(request, MediaType.ALL);
|
||||
Map<String, Object> body = getErrorAttributes(request, (includeStackTrace) ? ErrorAttributeOptions.of(ErrorAttributeOptions.Include.STACK_TRACE) : ErrorAttributeOptions.defaults());
|
||||
HttpStatus status = getStatus(request);
|
||||
response.setStatus(status.value());
|
||||
MappingJackson2JsonView view = new MappingJackson2JsonView();
|
||||
view.setObjectMapper(JsonUtil.getInstance());
|
||||
view.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
return new ModelAndView(view, body);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.error;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.log.props.BladeRequestLogProperties;
|
||||
import org.springblade.core.log.publisher.ErrorLogPublisher;
|
||||
import org.springblade.core.secure.exception.SecureException;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.api.ResultCode;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.UrlUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
import jakarta.servlet.Servlet;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 未知异常转译和发送,方便监听,对未知异常统一处理。Order 排序优先级低
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Order
|
||||
@RequiredArgsConstructor
|
||||
@AutoConfiguration
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
|
||||
@RestControllerAdvice
|
||||
public class BladeRestExceptionTranslator {
|
||||
|
||||
private final BladeProperties bladeProperties;
|
||||
private final BladeRequestLogProperties requestLogProperties;
|
||||
|
||||
@ExceptionHandler(ServiceException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleError(ServiceException e) {
|
||||
log.error("业务异常", e);
|
||||
return R.fail(e.getResultCode(), e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(SecureException.class)
|
||||
@ResponseStatus(HttpStatus.UNAUTHORIZED)
|
||||
public R handleError(SecureException e) {
|
||||
log.error("认证异常", e);
|
||||
return R.fail(e.getResultCode(), e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Throwable.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public R handleError(Throwable e) {
|
||||
log.error("服务器异常", e);
|
||||
if (requestLogProperties.getErrorLog()) {
|
||||
//发送服务异常事件
|
||||
ErrorLogPublisher.publishEvent(e, UrlUtil.getPath(Objects.requireNonNull(WebUtil.getRequest()).getRequestURI()));
|
||||
}
|
||||
// 生产环境屏蔽具体异常信息返回
|
||||
if (bladeProperties.isProd()) {
|
||||
return R.fail(ResultCode.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
return R.fail(ResultCode.INTERNAL_SERVER_ERROR, (Func.isEmpty(e.getMessage()) ? ResultCode.INTERNAL_SERVER_ERROR.getMessage() : e.getMessage()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.error;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hibernate.validator.internal.engine.path.PathImpl;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.api.ResultCode;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
import jakarta.servlet.Servlet;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 全局异常处理,处理可预见的异常,Order 排序优先级高
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
@AutoConfiguration
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
|
||||
@RestControllerAdvice
|
||||
public class RestExceptionTranslator {
|
||||
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleError(MissingServletRequestParameterException e) {
|
||||
log.warn("缺少请求参数", e.getMessage());
|
||||
String message = String.format("缺少必要的请求参数: %s", e.getParameterName());
|
||||
return R.fail(ResultCode.PARAM_MISS, message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleError(MethodArgumentTypeMismatchException e) {
|
||||
log.warn("请求参数格式错误", e.getMessage());
|
||||
String message = String.format("请求参数格式错误: %s", e.getName());
|
||||
return R.fail(ResultCode.PARAM_TYPE_ERROR, message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleError(MethodArgumentNotValidException e) {
|
||||
log.warn("参数验证失败", e.getMessage());
|
||||
return handleError(e.getBindingResult());
|
||||
}
|
||||
|
||||
@ExceptionHandler(BindException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleError(BindException e) {
|
||||
log.warn("参数绑定失败", e.getMessage());
|
||||
return handleError(e.getBindingResult());
|
||||
}
|
||||
|
||||
private R handleError(BindingResult result) {
|
||||
FieldError error = result.getFieldError();
|
||||
String message = String.format("%s:%s", error.getField(), error.getDefaultMessage());
|
||||
return R.fail(ResultCode.PARAM_BIND_ERROR, message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleError(ConstraintViolationException e) {
|
||||
log.warn("参数验证失败", e.getMessage());
|
||||
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
|
||||
ConstraintViolation<?> violation = violations.iterator().next();
|
||||
String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName();
|
||||
String message = String.format("%s:%s", path, violation.getMessage());
|
||||
return R.fail(ResultCode.PARAM_VALID_ERROR, message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoHandlerFoundException.class)
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public R handleError(NoHandlerFoundException e) {
|
||||
log.error("404没找到请求:{}", e.getMessage());
|
||||
return R.fail(ResultCode.NOT_FOUND, e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleError(HttpMessageNotReadableException e) {
|
||||
log.error("消息不能读取:{}", e.getMessage());
|
||||
return R.fail(ResultCode.MSG_NOT_READABLE, e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
|
||||
public R handleError(HttpRequestMethodNotSupportedException e) {
|
||||
log.error("不支持当前请求方法:{}", e.getMessage());
|
||||
return R.fail(ResultCode.METHOD_NOT_SUPPORTED, e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
|
||||
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
|
||||
public R handleError(HttpMediaTypeNotSupportedException e) {
|
||||
log.error("不支持当前媒体类型:{}", e.getMessage());
|
||||
return R.fail(ResultCode.MEDIA_TYPE_NOT_SUPPORTED, e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
|
||||
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
|
||||
public R handleError(HttpMediaTypeNotAcceptableException e) {
|
||||
String message = e.getMessage() + " " + StringUtil.join(e.getSupportedMediaTypes());
|
||||
log.error("不接受的媒体类型:{}", message);
|
||||
return R.fail(ResultCode.MEDIA_TYPE_NOT_SUPPORTED, message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统日志事件
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ApiLogEvent extends ApplicationEvent {
|
||||
|
||||
public ApiLogEvent(Map<String, Object> source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.event;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.launch.server.ServerInfo;
|
||||
import org.springblade.core.log.constant.EventConstant;
|
||||
import org.springblade.core.log.feign.ILogClient;
|
||||
import org.springblade.core.log.model.LogApi;
|
||||
import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 异步监听日志事件
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class ApiLogListener {
|
||||
|
||||
private final ILogClient logService;
|
||||
private final ServerInfo serverInfo;
|
||||
private final BladeProperties bladeProperties;
|
||||
|
||||
|
||||
@Async
|
||||
@Order
|
||||
@EventListener(ApiLogEvent.class)
|
||||
public void saveApiLog(ApiLogEvent event) {
|
||||
Map<String, Object> source = (Map<String, Object>) event.getSource();
|
||||
LogApi logApi = (LogApi) source.get(EventConstant.EVENT_LOG);
|
||||
LogAbstractUtil.addOtherInfoToLog(logApi, bladeProperties, serverInfo);
|
||||
logService.saveApiLog(logApi);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.event;
|
||||
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 错误日志事件
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ErrorLogEvent extends ApplicationEvent {
|
||||
|
||||
public ErrorLogEvent(Map<String, Object> source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.event;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.launch.server.ServerInfo;
|
||||
import org.springblade.core.log.constant.EventConstant;
|
||||
import org.springblade.core.log.feign.ILogClient;
|
||||
import org.springblade.core.log.model.LogError;
|
||||
import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 异步监听错误日志事件
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class ErrorLogListener {
|
||||
|
||||
private final ILogClient logService;
|
||||
private final ServerInfo serverInfo;
|
||||
private final BladeProperties bladeProperties;
|
||||
|
||||
@Async
|
||||
@Order
|
||||
@EventListener(ErrorLogEvent.class)
|
||||
public void saveErrorLog(ErrorLogEvent event) {
|
||||
Map<String, Object> source = (Map<String, Object>) event.getSource();
|
||||
LogError logError = (LogError) source.get(EventConstant.EVENT_LOG);
|
||||
LogAbstractUtil.addOtherInfoToLog(logError, bladeProperties, serverInfo);
|
||||
logService.saveErrorLog(logError);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统日志事件
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class UsualLogEvent extends ApplicationEvent {
|
||||
|
||||
public UsualLogEvent(Map<String, Object> source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.event;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.launch.server.ServerInfo;
|
||||
import org.springblade.core.log.constant.EventConstant;
|
||||
import org.springblade.core.log.feign.ILogClient;
|
||||
import org.springblade.core.log.model.LogUsual;
|
||||
import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 异步监听日志事件
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class UsualLogListener {
|
||||
|
||||
private final ILogClient logService;
|
||||
private final ServerInfo serverInfo;
|
||||
private final BladeProperties bladeProperties;
|
||||
|
||||
@Async
|
||||
@Order
|
||||
@EventListener(UsualLogEvent.class)
|
||||
public void saveUsualLog(UsualLogEvent event) {
|
||||
Map<String, Object> source = (Map<String, Object>) event.getSource();
|
||||
LogUsual logUsual = (LogUsual) source.get(EventConstant.EVENT_LOG);
|
||||
LogAbstractUtil.addOtherInfoToLog(logUsual, bladeProperties, serverInfo);
|
||||
logService.saveUsualLog(logUsual);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springblade.core.tool.api.IResultCode;
|
||||
import org.springblade.core.tool.api.ResultCode;
|
||||
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ServiceException extends RuntimeException {
|
||||
private static final long serialVersionUID = 2359767895161832954L;
|
||||
|
||||
@Getter
|
||||
private final IResultCode resultCode;
|
||||
|
||||
public ServiceException(String message) {
|
||||
super(message);
|
||||
this.resultCode = ResultCode.FAILURE;
|
||||
}
|
||||
|
||||
public ServiceException(IResultCode resultCode) {
|
||||
super(resultCode.getMessage());
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public ServiceException(IResultCode resultCode, Throwable cause) {
|
||||
super(cause);
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提高性能
|
||||
*
|
||||
* @return Throwable
|
||||
*/
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Throwable doFillInStackTrace() {
|
||||
return super.fillInStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.feign;
|
||||
|
||||
import org.springblade.core.launch.constant.AppConstant;
|
||||
import org.springblade.core.log.model.LogApi;
|
||||
import org.springblade.core.log.model.LogUsual;
|
||||
import org.springblade.core.log.model.LogError;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
/**
|
||||
* Feign接口类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@FeignClient(
|
||||
value = AppConstant.APPLICATION_LOG_NAME,
|
||||
fallback = LogClientFallback.class
|
||||
)
|
||||
public interface ILogClient {
|
||||
|
||||
String API_PREFIX = "/log";
|
||||
|
||||
/**
|
||||
* 保存错误日志
|
||||
*
|
||||
* @param log
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(API_PREFIX + "/saveUsualLog")
|
||||
R<Boolean> saveUsualLog(@RequestBody LogUsual log);
|
||||
|
||||
/**
|
||||
* 保存操作日志
|
||||
*
|
||||
* @param log
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(API_PREFIX + "/saveApiLog")
|
||||
R<Boolean> saveApiLog(@RequestBody LogApi log);
|
||||
|
||||
/**
|
||||
* 保存错误日志
|
||||
*
|
||||
* @param log
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(API_PREFIX + "/saveErrorLog")
|
||||
R<Boolean> saveErrorLog(@RequestBody LogError log);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.feign;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.log.model.LogApi;
|
||||
import org.springblade.core.log.model.LogError;
|
||||
import org.springblade.core.log.model.LogUsual;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 日志fallback
|
||||
*
|
||||
* @author jiang
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LogClientFallback implements ILogClient {
|
||||
|
||||
@Override
|
||||
public R<Boolean> saveUsualLog(LogUsual log) {
|
||||
return R.fail("usual log send fail");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<Boolean> saveApiLog(LogApi log) {
|
||||
return R.fail("api log send fail");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<Boolean> saveErrorLog(LogError log) {
|
||||
return R.fail("error log send fail");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.filter;
|
||||
|
||||
import org.springblade.core.log.utils.LogTraceUtil;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 日志追踪过滤器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class LogTraceFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
boolean flag = LogTraceUtil.insert();
|
||||
try {
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
if (flag) {
|
||||
LogTraceUtil.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.launch;
|
||||
|
||||
import org.springblade.core.auto.service.AutoService;
|
||||
import org.springblade.core.launch.service.LauncherService;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 日志启动配置类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@AutoService(LauncherService.class)
|
||||
public class LogLauncherServiceImpl implements LauncherService {
|
||||
@Override
|
||||
public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) {
|
||||
Properties props = System.getProperties();
|
||||
props.setProperty("logging.config", "classpath:log/logback-" + profile + ".xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.listener;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.spi.LoggerContextListener;
|
||||
import ch.qos.logback.core.Context;
|
||||
import ch.qos.logback.core.spi.ContextAwareBase;
|
||||
import ch.qos.logback.core.spi.LifeCycle;
|
||||
import org.springblade.core.log.utils.ElkPropsUtil;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
/**
|
||||
* logback监听类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class LoggerStartupListener extends ContextAwareBase implements LoggerContextListener, LifeCycle {
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Context context = getContext();
|
||||
context.putProperty("ELK_MODE", "FALSE");
|
||||
context.putProperty("STDOUT_APPENDER", "STDOUT");
|
||||
context.putProperty("INFO_APPENDER", "INFO");
|
||||
context.putProperty("ERROR_APPENDER", "ERROR");
|
||||
context.putProperty("DESTINATION", "127.0.0.1:9000");
|
||||
String destination = ElkPropsUtil.getDestination();
|
||||
if (StringUtil.isNotBlank(destination)) {
|
||||
context.putProperty("ELK_MODE", "TRUE");
|
||||
context.putProperty("STDOUT_APPENDER", "STDOUT_LOGSTASH");
|
||||
context.putProperty("INFO_APPENDER", "INFO_LOGSTASH");
|
||||
context.putProperty("ERROR_APPENDER", "ERROR_LOGSTASH");
|
||||
context.putProperty("DESTINATION", destination);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResetResistant() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(LoggerContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReset(LoggerContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(LoggerContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLevelChange(Logger logger, Level level) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.logger;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.log.publisher.UsualLogPublisher;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
/**
|
||||
* 日志工具类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
public class BladeLogger implements InitializingBean {
|
||||
|
||||
@Value("${spring.application.name}")
|
||||
private String serviceId;
|
||||
|
||||
public void info(String id, String data) {
|
||||
UsualLogPublisher.publishEvent("info", id, data);
|
||||
}
|
||||
|
||||
public void debug(String id, String data) {
|
||||
UsualLogPublisher.publishEvent("debug", id, data);
|
||||
}
|
||||
|
||||
public void warn(String id, String data) {
|
||||
UsualLogPublisher.publishEvent("warn", id, data);
|
||||
}
|
||||
|
||||
public void error(String id, String data) {
|
||||
UsualLogPublisher.publishEvent("error", id, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
log.info(serviceId + ": BladeLogger init success!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.model;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* logApi、logError、logUsual父类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class LogAbstract implements Serializable {
|
||||
|
||||
protected static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
protected Long id;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
private String tenantId;
|
||||
/**
|
||||
* 服务ID
|
||||
*/
|
||||
protected String serviceId;
|
||||
/**
|
||||
* 服务器 ip
|
||||
*/
|
||||
protected String serverIp;
|
||||
/**
|
||||
* 服务器名
|
||||
*/
|
||||
protected String serverHost;
|
||||
/**
|
||||
* 环境
|
||||
*/
|
||||
protected String env;
|
||||
/**
|
||||
* 操作IP地址
|
||||
*/
|
||||
protected String remoteIp;
|
||||
/**
|
||||
* 用户代理
|
||||
*/
|
||||
protected String userAgent;
|
||||
/**
|
||||
* 请求URI
|
||||
*/
|
||||
protected String requestUri;
|
||||
/**
|
||||
* 操作方式
|
||||
*/
|
||||
protected String method;
|
||||
/**
|
||||
* 方法类
|
||||
*/
|
||||
protected String methodClass;
|
||||
/**
|
||||
* 方法名
|
||||
*/
|
||||
protected String methodName;
|
||||
/**
|
||||
* 操作提交的数据
|
||||
*/
|
||||
protected String params;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
protected String createBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
protected Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.model;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 实体类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@TableName("blade_log_api")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LogApi extends LogAbstract {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 日志类型
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 日志标题
|
||||
*/
|
||||
private String title;
|
||||
/**
|
||||
* 执行时间
|
||||
*/
|
||||
private String time;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.model;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 服务 异常
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@TableName("blade_log_error")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LogError extends LogAbstract {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 堆栈信息
|
||||
*/
|
||||
private String stackTrace;
|
||||
/**
|
||||
* 异常名
|
||||
*/
|
||||
private String exceptionName;
|
||||
/**
|
||||
* 异常消息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 代码行数
|
||||
*/
|
||||
private Integer lineNumber;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.model;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 实体类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@TableName("blade_log_usual")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LogUsual extends LogAbstract {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 日志级别
|
||||
*/
|
||||
private String logLevel;
|
||||
/**
|
||||
* 日志业务id
|
||||
*/
|
||||
private String logId;
|
||||
/**
|
||||
* 日志数据
|
||||
*/
|
||||
private String logData;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.props;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springblade.core.launch.log.BladeLogLevel;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 日志配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(BladeLogLevel.REQ_LOG_PROPS_PREFIX)
|
||||
public class BladeRequestLogProperties {
|
||||
|
||||
/**
|
||||
* 是否开启请求日志
|
||||
*/
|
||||
private Boolean enabled = true;
|
||||
|
||||
/**
|
||||
* 是否开启异常日志推送
|
||||
*/
|
||||
private Boolean errorLog = true;
|
||||
|
||||
/**
|
||||
* 日志级别配置,默认:BODY
|
||||
*/
|
||||
private BladeLogLevel level = BladeLogLevel.BODY;
|
||||
|
||||
/**
|
||||
* 放行url
|
||||
*/
|
||||
private List<String> skipUrl = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.publisher;
|
||||
|
||||
import org.springblade.core.log.annotation.ApiLog;
|
||||
import org.springblade.core.log.constant.EventConstant;
|
||||
import org.springblade.core.log.event.ApiLogEvent;
|
||||
import org.springblade.core.log.model.LogApi;
|
||||
import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.utils.SpringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* API日志信息事件发送
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ApiLogPublisher {
|
||||
|
||||
public static void publishEvent(String methodName, String methodClass, ApiLog apiLog, long time) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
LogApi logApi = new LogApi();
|
||||
logApi.setType(BladeConstant.LOG_NORMAL_TYPE);
|
||||
logApi.setTitle(apiLog.value());
|
||||
logApi.setTime(String.valueOf(time));
|
||||
logApi.setMethodClass(methodClass);
|
||||
logApi.setMethodName(methodName);
|
||||
LogAbstractUtil.addRequestInfoToLog(request, logApi);
|
||||
Map<String, Object> event = new HashMap<>(16);
|
||||
event.put(EventConstant.EVENT_LOG, logApi);
|
||||
SpringUtil.publishEvent(new ApiLogEvent(event));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.publisher;
|
||||
|
||||
import org.springblade.core.log.constant.EventConstant;
|
||||
import org.springblade.core.log.event.ErrorLogEvent;
|
||||
import org.springblade.core.log.model.LogError;
|
||||
import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springblade.core.tool.utils.Exceptions;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.SpringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 异常信息事件发送
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ErrorLogPublisher {
|
||||
|
||||
public static void publishEvent(Throwable error, String requestUri) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
LogError logError = new LogError();
|
||||
logError.setRequestUri(requestUri);
|
||||
if (Func.isNotEmpty(error)) {
|
||||
logError.setStackTrace(Exceptions.getStackTraceAsString(error));
|
||||
logError.setExceptionName(error.getClass().getName());
|
||||
logError.setMessage(error.getMessage());
|
||||
StackTraceElement[] elements = error.getStackTrace();
|
||||
if (Func.isNotEmpty(elements)) {
|
||||
StackTraceElement element = elements[0];
|
||||
logError.setMethodName(element.getMethodName());
|
||||
logError.setMethodClass(element.getClassName());
|
||||
logError.setFileName(element.getFileName());
|
||||
logError.setLineNumber(element.getLineNumber());
|
||||
}
|
||||
}
|
||||
LogAbstractUtil.addRequestInfoToLog(request, logError);
|
||||
Map<String, Object> event = new HashMap<>(16);
|
||||
event.put(EventConstant.EVENT_LOG, logError);
|
||||
SpringUtil.publishEvent(new ErrorLogEvent(event));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.publisher;
|
||||
|
||||
import org.springblade.core.log.constant.EventConstant;
|
||||
import org.springblade.core.log.event.UsualLogEvent;
|
||||
import org.springblade.core.log.model.LogUsual;
|
||||
import org.springblade.core.log.utils.LogAbstractUtil;
|
||||
import org.springblade.core.tool.utils.SpringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* BLADE日志信息事件发送
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class UsualLogPublisher {
|
||||
|
||||
public static void publishEvent(String level, String id, String data) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
LogUsual logUsual = new LogUsual();
|
||||
logUsual.setLogLevel(level);
|
||||
logUsual.setLogId(id);
|
||||
logUsual.setLogData(data);
|
||||
Thread thread = Thread.currentThread();
|
||||
StackTraceElement[] trace = thread.getStackTrace();
|
||||
if (trace.length > 3) {
|
||||
logUsual.setMethodClass(trace[3].getClassName());
|
||||
logUsual.setMethodName(trace[3].getMethodName());
|
||||
}
|
||||
LogAbstractUtil.addRequestInfoToLog(request, logUsual);
|
||||
Map<String, Object> event = new HashMap<>(16);
|
||||
event.put(EventConstant.EVENT_LOG, logUsual);
|
||||
SpringUtil.publishEvent(new UsualLogEvent(event));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.utils;
|
||||
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Elk配置工具
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ElkPropsUtil {
|
||||
|
||||
/**
|
||||
* 获取elk服务地址
|
||||
*
|
||||
* @return 服务地址
|
||||
*/
|
||||
public static String getDestination() {
|
||||
Properties props = System.getProperties();
|
||||
return props.getProperty("blade.log.elk.destination", StringPool.EMPTY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.log.utils;
|
||||
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springblade.core.launch.server.ServerInfo;
|
||||
import org.springblade.core.log.model.LogAbstract;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Log 相关工具
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class LogAbstractUtil {
|
||||
|
||||
/**
|
||||
* 向log中添加补齐request的信息
|
||||
*
|
||||
* @param request 请求
|
||||
* @param logAbstract 日志基础类
|
||||
*/
|
||||
public static void addRequestInfoToLog(HttpServletRequest request, LogAbstract logAbstract) {
|
||||
if (ObjectUtil.isNotEmpty(request)) {
|
||||
logAbstract.setTenantId(Func.toStrWithEmpty(AuthUtil.getTenantId(), BladeConstant.ADMIN_TENANT_ID));
|
||||
logAbstract.setRemoteIp(WebUtil.getIP(request));
|
||||
logAbstract.setUserAgent(request.getHeader(WebUtil.USER_AGENT_HEADER));
|
||||
logAbstract.setRequestUri(UrlUtil.getPath(request.getRequestURI()));
|
||||
logAbstract.setMethod(request.getMethod());
|
||||
logAbstract.setParams(WebUtil.getRequestContent(request));
|
||||
logAbstract.setCreateBy(AuthUtil.getUserAccount(request));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向log中添加补齐其他的信息(eg:blade、server等)
|
||||
*
|
||||
* @param logAbstract 日志基础类
|
||||
* @param bladeProperties 配置信息
|
||||
* @param serverInfo 服务信息
|
||||
*/
|
||||
public static void addOtherInfoToLog(LogAbstract logAbstract, BladeProperties bladeProperties, ServerInfo serverInfo) {
|
||||
logAbstract.setServiceId(bladeProperties.getName());
|
||||
logAbstract.setServerHost(serverInfo.getHostName());
|
||||
logAbstract.setServerIp(serverInfo.getIpWithPort());
|
||||
logAbstract.setEnv(bladeProperties.getEnv());
|
||||
logAbstract.setCreateTime(DateUtil.now());
|
||||
if (logAbstract.getParams() == null) {
|
||||
logAbstract.setParams(StringPool.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.log.utils;
|
||||
|
||||
import org.slf4j.MDC;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
/**
|
||||
* 日志追踪工具类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class LogTraceUtil {
|
||||
private static final String UNIQUE_ID = "traceId";
|
||||
|
||||
/**
|
||||
* 获取日志追踪id格式
|
||||
*/
|
||||
public static String getTraceId() {
|
||||
return StringUtil.randomUUID();
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入traceId
|
||||
*/
|
||||
public static boolean insert() {
|
||||
MDC.put(UNIQUE_ID, getTraceId());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除traceId
|
||||
*/
|
||||
public static boolean remove() {
|
||||
MDC.remove(UNIQUE_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
3
blade-starter-log/src/main/resources/blade-log.yml
Normal file
3
blade-starter-log/src/main/resources/blade-log.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
#配置日志地址
|
||||
logging:
|
||||
config: classpath:log/logback-${blade.env}.xml
|
||||
113
blade-starter-log/src/main/resources/log/logback-dev.xml
Normal file
113
blade-starter-log/src/main/resources/log/logback-dev.xml
Normal file
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="false" debug="false">
|
||||
<!-- 自定义参数监听 -->
|
||||
<contextListener class="org.springblade.core.log.listener.LoggerStartupListener"/>
|
||||
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
|
||||
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
|
||||
<conversionRule conversionWord="wex"
|
||||
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
|
||||
<conversionRule conversionWord="wEx"
|
||||
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN"
|
||||
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>utf8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<if condition='property("ELK_MODE").toUpperCase().contains("TRUE")'>
|
||||
<then>
|
||||
<!-- 推送日志至elk -->
|
||||
<appender name="STDOUT_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
|
||||
<destination>${DESTINATION}</destination>
|
||||
<!-- 日志输出编码 -->
|
||||
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
|
||||
<providers>
|
||||
<timestamp>
|
||||
<timeZone>UTC</timeZone>
|
||||
</timestamp>
|
||||
<pattern>
|
||||
<pattern>
|
||||
{
|
||||
"traceId": "%X{traceId}",
|
||||
"requestId": "%X{requestId}",
|
||||
"accountId": "%X{accountId}",
|
||||
"tenantId": "%X{tenantId}",
|
||||
"logLevel": "%level",
|
||||
"serviceName": "${springAppName:-SpringApp}",
|
||||
"pid": "${PID:-}",
|
||||
"thread": "%thread",
|
||||
"class": "%logger{40}",
|
||||
"line":"%L",
|
||||
"message": "%message"
|
||||
}
|
||||
</pattern>
|
||||
</pattern>
|
||||
<mdc/>
|
||||
<stackTrace/>
|
||||
</providers>
|
||||
</encoder>
|
||||
</appender>
|
||||
</then>
|
||||
</if>
|
||||
|
||||
<!-- 日志输出级别 -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="${STDOUT_APPENDER}"/>
|
||||
</root>
|
||||
|
||||
<logger name="net.sf.ehcache" level="INFO"/>
|
||||
<logger name="druid.sql" level="INFO"/>
|
||||
|
||||
|
||||
<!-- MyBatis log configure -->
|
||||
<logger name="com.apache.ibatis" level="INFO"/>
|
||||
<logger name="org.mybatis.spring" level="INFO"/>
|
||||
<logger name="java.sql.Connection" level="INFO"/>
|
||||
<logger name="java.sql.Statement" level="INFO"/>
|
||||
<logger name="java.sql.PreparedStatement" level="INFO"/>
|
||||
|
||||
<!-- 减少部分debug日志 -->
|
||||
<logger name="druid.sql" level="INFO"/>
|
||||
<logger name="org.apache.shiro" level="INFO"/>
|
||||
<logger name="org.mybatis.spring" level="INFO"/>
|
||||
<logger name="org.springframework" level="INFO"/>
|
||||
<logger name="org.springframework.context" level="WARN"/>
|
||||
<logger name="org.springframework.beans" level="WARN"/>
|
||||
<logger name="com.baomidou.mybatisplus" level="INFO"/>
|
||||
<logger name="org.apache.ibatis.io" level="INFO"/>
|
||||
<logger name="org.apache.velocity" level="INFO"/>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="io.undertow" level="INFO"/>
|
||||
<logger name="org.xnio.nio" level="INFO"/>
|
||||
<logger name="org.thymeleaf" level="INFO"/>
|
||||
<logger name="springfox.documentation" level="INFO"/>
|
||||
<logger name="org.hibernate.validator" level="INFO"/>
|
||||
<logger name="com.netflix.loadbalancer" level="INFO"/>
|
||||
<logger name="com.netflix.hystrix" level="INFO"/>
|
||||
<logger name="com.netflix.zuul" level="INFO"/>
|
||||
<logger name="de.codecentric" level="INFO"/>
|
||||
<!-- cache INFO -->
|
||||
<logger name="net.sf.ehcache" level="INFO"/>
|
||||
<logger name="org.springframework.cache" level="INFO"/>
|
||||
<!-- cloud -->
|
||||
<logger name="org.apache.http" level="INFO"/>
|
||||
<logger name="com.netflix.discovery" level="INFO"/>
|
||||
<logger name="com.netflix.eureka" level="INFO"/>
|
||||
<!-- 业务日志 -->
|
||||
<Logger name="org.springblade" level="INFO"/>
|
||||
<Logger name="org.springblade.core.tenant" level="INFO"/>
|
||||
<Logger name="org.springblade.core.version" level="INFO"/>
|
||||
|
||||
<!-- 减少nacos日志 -->
|
||||
<logger name="com.alibaba.nacos" level="ERROR"/>
|
||||
|
||||
|
||||
</configuration>
|
||||
151
blade-starter-log/src/main/resources/log/logback-prod.xml
Normal file
151
blade-starter-log/src/main/resources/log/logback-prod.xml
Normal file
@@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="false" debug="false">
|
||||
<!-- 自定义参数监听 -->
|
||||
<contextListener class="org.springblade.core.log.listener.LoggerStartupListener"/>
|
||||
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
|
||||
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
|
||||
<conversionRule conversionWord="wex"
|
||||
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
|
||||
<conversionRule conversionWord="wEx"
|
||||
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN"
|
||||
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>utf8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 生成日志文件 -->
|
||||
<appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件输出的文件名 -->
|
||||
<FileNamePattern>target/blade/log/info-%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 生成日志文件 -->
|
||||
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件输出的文件名 -->
|
||||
<FileNamePattern>target/blade/log/error-%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<if condition='property("ELK_MODE").toUpperCase().contains("TRUE")'>
|
||||
<then>
|
||||
<!-- 推送日志至elk -->
|
||||
<appender name="INFO_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
|
||||
<destination>${DESTINATION}</destination>
|
||||
<!-- 日志输出编码 -->
|
||||
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
|
||||
<providers>
|
||||
<timestamp>
|
||||
<timeZone>UTC</timeZone>
|
||||
</timestamp>
|
||||
<pattern>
|
||||
<pattern>
|
||||
{
|
||||
"traceId": "%X{traceId}",
|
||||
"requestId": "%X{requestId}",
|
||||
"accountId": "%X{accountId}",
|
||||
"tenantId": "%X{tenantId}",
|
||||
"logLevel": "%level",
|
||||
"serviceName": "${springAppName:-SpringApp}",
|
||||
"pid": "${PID:-}",
|
||||
"thread": "%thread",
|
||||
"class": "%logger{40}",
|
||||
"line":"%L",
|
||||
"message": "%message"
|
||||
}
|
||||
</pattern>
|
||||
</pattern>
|
||||
<mdc/>
|
||||
<stackTrace/>
|
||||
</providers>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 推送日志至elk -->
|
||||
<appender name="ERROR_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
|
||||
<destination>${DESTINATION}</destination>
|
||||
<!-- 日志输出编码 -->
|
||||
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
|
||||
<providers>
|
||||
<timestamp>
|
||||
<timeZone>UTC</timeZone>
|
||||
</timestamp>
|
||||
<pattern>
|
||||
<pattern>
|
||||
{
|
||||
"traceId": "%X{traceId}",
|
||||
"requestId": "%X{requestId}",
|
||||
"accountId": "%X{accountId}",
|
||||
"tenantId": "%X{tenantId}",
|
||||
"logLevel": "%level",
|
||||
"serviceName": "${springAppName:-SpringApp}",
|
||||
"pid": "${PID:-}",
|
||||
"thread": "%thread",
|
||||
"class": "%logger{40}",
|
||||
"line":"%L",
|
||||
"message": "%message"
|
||||
}
|
||||
</pattern>
|
||||
</pattern>
|
||||
<mdc/>
|
||||
<stackTrace/>
|
||||
</providers>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
</then>
|
||||
</if>
|
||||
|
||||
<!-- 日志输出级别 -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="${INFO_APPENDER}"/>
|
||||
<appender-ref ref="${ERROR_APPENDER}"/>
|
||||
</root>
|
||||
|
||||
<logger name="net.sf.ehcache" level="INFO"/>
|
||||
<logger name="druid.sql" level="INFO"/>
|
||||
|
||||
<!-- 减少nacos日志 -->
|
||||
<logger name="com.alibaba.nacos" level="ERROR"/>
|
||||
|
||||
</configuration>
|
||||
151
blade-starter-log/src/main/resources/log/logback-test.xml
Normal file
151
blade-starter-log/src/main/resources/log/logback-test.xml
Normal file
@@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="false" debug="false">
|
||||
<!-- 自定义参数监听 -->
|
||||
<contextListener class="org.springblade.core.log.listener.LoggerStartupListener"/>
|
||||
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
|
||||
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
|
||||
<conversionRule conversionWord="wex"
|
||||
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
|
||||
<conversionRule conversionWord="wEx"
|
||||
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN"
|
||||
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>utf8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 生成日志文件 -->
|
||||
<appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件输出的文件名 -->
|
||||
<FileNamePattern>target/blade/log/info-%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 生成日志文件 -->
|
||||
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件输出的文件名 -->
|
||||
<FileNamePattern>target/blade/log/error-%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<if condition='property("ELK_MODE").toUpperCase().contains("TRUE")'>
|
||||
<then>
|
||||
<!-- 推送日志至elk -->
|
||||
<appender name="INFO_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
|
||||
<destination>${DESTINATION}</destination>
|
||||
<!-- 日志输出编码 -->
|
||||
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
|
||||
<providers>
|
||||
<timestamp>
|
||||
<timeZone>UTC</timeZone>
|
||||
</timestamp>
|
||||
<pattern>
|
||||
<pattern>
|
||||
{
|
||||
"traceId": "%X{traceId}",
|
||||
"requestId": "%X{requestId}",
|
||||
"accountId": "%X{accountId}",
|
||||
"tenantId": "%X{tenantId}",
|
||||
"logLevel": "%level",
|
||||
"serviceName": "${springAppName:-SpringApp}",
|
||||
"pid": "${PID:-}",
|
||||
"thread": "%thread",
|
||||
"class": "%logger{40}",
|
||||
"line":"%L",
|
||||
"message": "%message"
|
||||
}
|
||||
</pattern>
|
||||
</pattern>
|
||||
<mdc/>
|
||||
<stackTrace/>
|
||||
</providers>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 推送日志至elk -->
|
||||
<appender name="ERROR_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
|
||||
<destination>${DESTINATION}</destination>
|
||||
<!-- 日志输出编码 -->
|
||||
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
|
||||
<providers>
|
||||
<timestamp>
|
||||
<timeZone>UTC</timeZone>
|
||||
</timestamp>
|
||||
<pattern>
|
||||
<pattern>
|
||||
{
|
||||
"traceId": "%X{traceId}",
|
||||
"requestId": "%X{requestId}",
|
||||
"accountId": "%X{accountId}",
|
||||
"tenantId": "%X{tenantId}",
|
||||
"logLevel": "%level",
|
||||
"serviceName": "${springAppName:-SpringApp}",
|
||||
"pid": "${PID:-}",
|
||||
"thread": "%thread",
|
||||
"class": "%logger{40}",
|
||||
"line":"%L",
|
||||
"message": "%message"
|
||||
}
|
||||
</pattern>
|
||||
</pattern>
|
||||
<mdc/>
|
||||
<stackTrace/>
|
||||
</providers>
|
||||
</encoder>
|
||||
<!-- 打印日志级别 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
</then>
|
||||
</if>
|
||||
|
||||
<!-- 日志输出级别 -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="${INFO_APPENDER}"/>
|
||||
<appender-ref ref="${ERROR_APPENDER}"/>
|
||||
</root>
|
||||
|
||||
<logger name="net.sf.ehcache" level="INFO"/>
|
||||
<logger name="druid.sql" level="INFO"/>
|
||||
|
||||
<!-- 减少nacos日志 -->
|
||||
<logger name="com.alibaba.nacos" level="ERROR"/>
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user