This commit is contained in:
2021-08-29 23:16:35 +08:00
parent cc5cbc1ebb
commit 9d6a001b85
213 changed files with 1711 additions and 18656 deletions

60
budd-server/pom.xml Normal file
View File

@@ -0,0 +1,60 @@
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/>
</parent>
<artifactId>budd-server</artifactId>
<name>budd-server</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd-common</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,41 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
* @author ehlxr
* @since 2021-08-29 18:32.
*/
@SpringBootApplication
@ServletComponentScan("io.github.ehlxr.filter")
public class BuddServerApplication {
public static void main(String[] args) {
SpringApplication.run(BuddServerApplication.class, args);
}
}

View File

@@ -0,0 +1,141 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.aop;
import com.google.common.base.Strings;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.util.JsonUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 请求日志记录
*
* @author ehlxr
* @since 2021-08-17 22:03.
*/
@Aspect
@Component
public class LogRequestAop {
private static final Logger log = LoggerFactory.getLogger(LogRequestAop.class);
// private final AliyunLogManager aliyunLogManager;
// /**
// * aliyun log 配置
// */
// @Value("${aliyun.log.project:}")
// private String projcet;
// @Value("${aliyun.log.logstore.request:}")
// private String logStore;
// @Value("${aliyun.log.topic:}")
// private String topic;
// @Autowired
// public LogRequestAop(AliyunLogManager aliyunLogManager) {
// this.aliyunLogManager = aliyunLogManager;
// }
/**
* 切入点
*/
@Pointcut("execution(public * io.github.ehlxr.*Controller.*(..)) && !@annotation(io.github.ehlxr.annotations.NoRequestLog)")
// @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && !@annotation(com.tzld.piaoquan.incentive.annotations.NoRequestLog)")
public void requestLog() {
}
/**
* 前置操作
*/
@Before("requestLog()")
public void beforeLog() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
request.setAttribute(Constant.REQUEST_START_TIME, System.currentTimeMillis());
}
/**
* 后置操作
*/
@AfterReturning(pointcut = "requestLog()", returning = "returnValue")
public void afterReturning(JoinPoint point, Object returnValue) {
logRecord(point, JsonUtils.obj2String(returnValue));
}
@AfterThrowing(pointcut = "requestLog()", throwing = "ex")
public void afterThrowing(JoinPoint point, Exception ex) {
logRecord(point, ex.getMessage());
}
private void logRecord(JoinPoint point, String message) {
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
Long startTime = (Long) request.getAttribute(Constant.REQUEST_START_TIME);
if (Objects.isNull(startTime)) {
return;
}
String query = request.getQueryString();
String uri = request.getRequestURI();
Map<String, Object> logMap = new HashMap<>(8);
logMap.put("url", Strings.isNullOrEmpty(query) ? uri : uri + "?" + query);
logMap.put("method", request.getMethod());
logMap.put("header", getHeaders(request));
logMap.put("elapsedTime", String.valueOf(System.currentTimeMillis() - startTime));
logMap.put("clientIp", request.getRemoteAddr());
logMap.put("requestBody", JsonUtils.obj2String(point.getArgs()));
logMap.put(Constant.LOG_TRACE_ID, Strings.nullToEmpty(MDC.get(Constant.LOG_TRACE_ID)));
logMap.put("responseBody", message);
// aliyunLogManager.sendLog(projcet, logStore, topic, logMap);
} catch (Exception e) {
log.error("log report request error", e);
}
}
private String getHeaders(HttpServletRequest request) {
return Collections.list(request.getHeaderNames())
.stream()
.collect(Collectors.toMap(
name -> name,
request::getHeader)).toString();
}
}

View File

@@ -0,0 +1,72 @@
package io.github.ehlxr.config;
import io.github.ehlxr.util.SendAlarmUtil;
import io.github.ehlxr.util.Try;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 项目初始化
*
* @author ehlxr
* @since 2020/4/22.
*/
@Component
public class Initialization implements ApplicationRunner {
private static final Logger log = LoggerFactory.getLogger(Initialization.class);
@Value("${aliyun.oss.endpoint:}")
private String endpoint;
@Value("${aliyun.oss.accesskey.id:}")
private String accessKeyId;
@Value("${aliyun.oss.accesskey.secret:}")
private String accessKeySecret;
@Value("${aliyun.oss.bucket:}")
private String bucket;
@Value("${aliyun.oss.key-path:}")
private String keyPath;
@Value("${aliyun.oss.url-lifetime:0}")
private Long urlLifetime;
@Value("${lk.jmeter.cmd:}")
private String jmeterCmd;
@Value("${location:}")
private String location;
@Value("${lk.dingtalk-url:}")
private String dingtalkUrl;
@Override
public void run(ApplicationArguments args) {
// 初始化阿里云 OSS 配置信息
// AliyunOssConfig config = AliyunOssConfig.newBuilder()
// .endpoint(endpoint)
// .accessKeyId(accessKeyId)
// .accessKeySecret(accessKeySecret)
// .bucketName(bucket)
// .keyPath(keyPath)
// .urlLifetime(urlLifetime)
// .build();
// log.info("aliyun oss config {}", config);
// FileUploadUtil.init(config);
//
// if (!"develop".equals(location) && !"PRO2".equals(location)) {
// try {
// ExecShell.execShellCommand(jmeterCmd);
// } catch (Exception e) {
// log.error("exec jmeter cmd error {}", e.getMessage());
// }
// }
// 预警信息发送初始化
Try.of(() -> SendAlarmUtil.init(dingtalkUrl))
.trap(e -> log.warn("int SendAlarmUtil error: {}", e.getMessage()))
.run();
}
}

View File

@@ -0,0 +1,50 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author ehlxr
* @since 2021-08-29 18:45.
*/
@RestController
@Api(tags = "测试辅助接口")
public class IndexController {
/**
* 健康检测
*/
@ApiOperation(value = "健康检测", notes = "健康检测")
@GetMapping("/healthcheck")
public String healthcheck() {
return "ok";
}
}

View File

@@ -0,0 +1,42 @@
package io.github.ehlxr.filter;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.util.IdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* auth filter
*
* @author supeng
* @date 2020/08/31
*/
@Order(value = 1)
@WebFilter(filterName = "customFilter", urlPatterns = {"/api/*"})
public class CustomFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);
@Override
public void init(FilterConfig filterConfig) {
log.info("customFilter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
filterChain.doFilter(servletRequest, servletResponse);
MDC.remove(Constant.LOG_TRACE_ID);
}
@Override
public void destroy() {
log.info("customFilter destroy");
}
}

View File

@@ -0,0 +1,66 @@
package io.github.ehlxr.handler;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.common.Result;
import io.github.ehlxr.enums.CodeEnum;
import io.github.ehlxr.exception.ServiceDataException;
import org.assertj.core.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @author ehlxr
* @since 2020/4/20.
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(Exception.class)
@ResponseBody
public Result<?> defaultExceptionHandler(HttpServletRequest request, Exception e) {
log.error("request: {}, exception: ", request.getRequestURI(), e);
// SendAlarmUtil.send(String.format("未知异常 request: %s, exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
// (t, u) -> log.info("send exception message to dingtalk result {} ", t, u));
String msg = CodeEnum.UNKNOWN_EXCEPTION.getMessage();
String traceId = MDC.get(Constant.LOG_TRACE_ID);
if (!Strings.isNullOrEmpty(traceId)) {
msg = String.format("%s%s", msg, traceId);
}
return Result.of(CodeEnum.UNKNOWN_EXCEPTION.getCode(), null, msg);
}
@ExceptionHandler(ServiceDataException.class)
@ResponseBody
public Result<?> serviceDataExceptionHandler(HttpServletRequest request, ServiceDataException e) {
log.error("request: {} service exception: ", request.getRequestURI(), e);
// SendAlarmUtil.send(String.format("业务异常 request: %s, service exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
// (t, u) -> log.info("send service exception message to dingtalk result {} ", t, u));
String msg = e.getMessage();
String traceId = MDC.get(Constant.LOG_TRACE_ID);
if (!Strings.isNullOrEmpty(traceId)) {
msg = String.format("%s%s", msg, traceId);
}
return Result.of(e.getCode(), null, msg);
}
@ExceptionHandler(MultipartException.class)
public String handleError(MultipartException e, RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
return "redirect:/uploadStatus";
}
}

View File

@@ -0,0 +1,52 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.interceptor;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.util.IdUtil;
import org.slf4j.MDC;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 日志 traceid Interceptor
*
* @author ehlxr
* @since 2020-12-23 11:23.
*/
public class TraceInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
MDC.remove(Constant.LOG_TRACE_ID);
}
}

View File

@@ -0,0 +1,17 @@
server:
port: 8081
springfox:
documentation:
enabled: true
swagger:
base-package: io.github.ehlxr
base-path: /**
contact:
email: xrv@live.com
name: rtg
url: https://ehlxr.me
description: swagger of budd server
exclude-path: /error, /ops/**
title: budd swagger
version: 0.0.1-SNAPSHOT

View File

@@ -0,0 +1,18 @@
spring:
profiles:
active: dev
application:
name: budd
server:
tomcat:
uri-encoding: UTF-8
accept-count: 1000
connection-timeout: 30000
servlet:
context-path: /budd
session:
timeout: 60
logging:
file:
path: /Users/ehlxr/logs/${spring.application.name}

View File

@@ -0,0 +1,264 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL如果设置为WARN则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
<contextName>logback</contextName>
<!-- name的值是变量的名称value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后可以使“${}”来使用变量。 -->
<!-- <property name="LOG_PATH" value="${logging.file.path}" />-->
<springProperty name="LOG_PATH" source="logging.file.path"/>
<!--<springProperty name="ALIYUN_LOG_ENDPOINT" source="aliyun.log.endpoint"/>-->
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYID" source="aliyun.log.accessKeyId"/>-->
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYSECRET" source="aliyun.log.accessKeySecret"/>-->
<!--<springProperty name="ALIYUN_LOG_PROJECT" source="aliyun.log.project"/>-->
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_INFO" source="aliyun.log.logstore.info"/>-->
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_ERROR" source="aliyun.log.logstore.error"/>-->
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<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([%X{logTraceId}]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--<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([%X{√logTraceId}]){magenta} %clr(-&#45;&#45;){faint} %clr([%15.15t]){faint} %clr(at %class.%method){cyan} \\(%file:%line\\) %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>-->
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用只配置最底级别控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<appender name="ALIYUN_LOG_INFO" class="com.aliyun.openservices.log.logback.LoghubAppender">
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
<project>${ALIYUN_LOG_PROJECT}</project>
<logStore>${ALIYUN_LOG_LOGSTORE_INFO}</logStore>
<totalSizeInBytes>104857600</totalSizeInBytes>
<maxBlockMs>0</maxBlockMs>
<ioThreadCount>8</ioThreadCount>
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
<batchCountThreshold>4096</batchCountThreshold>
<lingerMs>2000</lingerMs>
<retries>10</retries>
<baseRetryBackoffMs>100</baseRetryBackoffMs>
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
<timeZone>Asia/Shanghai</timeZone>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
</filter>
<mdcFields>logTraceId</mdcFields>
</appender>
<appender name="ALIYUN_LOG_ERROR" class="com.aliyun.openservices.log.logback.LoghubAppender">
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
<project>${ALIYUN_LOG_PROJECT}</project>
<logStore>${ALIYUN_LOG_LOGSTORE_ERROR}</logStore>
<totalSizeInBytes>104857600</totalSizeInBytes>
<maxBlockMs>0</maxBlockMs>
<ioThreadCount>8</ioThreadCount>
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
<batchCountThreshold>4096</batchCountThreshold>
<lingerMs>2000</lingerMs>
<retries>10</retries>
<baseRetryBackoffMs>100</baseRetryBackoffMs>
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
<timeZone>Asia/Shanghai</timeZone>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<mdcFields>logTraceId</mdcFields>
</appender>
-->
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别大小写无关TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
还有一个特俗值INHERITED或者同义词NULL代表强制执行上级的级别。
如果未设置此属性那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--<logger name="org.springframework.web" level="info"/>-->
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
<!--
使用mybatis的时候sql语句是debug下才会打印而这里我们只配置了info所以想要查看sql语句的话有以下两种操作
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式代码如下这样配置sql语句会打印其他还是正常info级别
-->
<!--
root节点是必选节点用来指定最基础的日志输出级别只有一个level属性
level:用来设置打印级别大小写无关TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素标识这个appender将会添加到这个logger。
-->
<springProfile name="dev">
<logger name="io.github.ehlxr" level="debug"/>
</springProfile>
<!--<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="warn"/>-->
<!-- 可用来获取 StatusManager 中的状态 -->
<!--<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>-->
<!-- 解决 aliyun loghub debug模式下循环发送的问题 -->
<logger name="org.apache.http.impl.conn.Wire" level="WARN"/>
<!--aliyun loghub 为了防止进程退出时,内存中的数据丢失,请加上此选项-->
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<root level="info">
<appender-ref ref="CONSOLE"/>
<!--<appender-ref ref="DEBUG_FILE"/>-->
<!--<appender-ref ref="INFO_FILE"/>-->
<!--<appender-ref ref="WARN_FILE"/>-->
<!--<appender-ref ref="ERROR_FILE"/>-->
<!--<appender-ref ref="ALIYUN_LOG_INFO"/>-->
<!--<appender-ref ref="ALIYUN_LOG_ERROR"/>-->
</root>
</configuration>