还是直接上代码
@Slf4j 这玩意 默认支持 不用引入
yml 配置文件
# 日志配置 如果配置了xml 这个就不生效了 xml优先级最高
#logging:
# file:
# path: /home/logs # 日志目录地址
# name: /home/logs/skeleton.log
# max-size: 1KB # 设置日志大小的最大大小 1KB 用于演示 单位包括 KB、MB、GB
# max-history: 3 # 默认存储最近7天
# total-size-cap: 3KB #日志文档的总大小:当日志文档总大小超过该阈值会删除备份
# level:
# root: info #全局的日志等级 哪些日志输出
下面分享 xml 方式
在 资源目录下创建 logback-spring.xml 粘贴走 即可 重启 看控制台变化 还有磁盘 有没有写入
坑 :
我在创建的时候 发现 xml 没有生效 排查了半天 发现 在创建 logback-spring.xml 这个文件的时候
我不是手打的 是复制的 文件名 前面多了个空格 导致不生效
所以如果有小伙伴 和我一样 复制的文件名 一定要小心 文件名两边不要复制多了 空格
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds"><!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 --><!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true --><!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 --><!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --><contextName>logback</contextName><!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 --><!-- 日志输出位置--><property name="log.path" value="/home/logs/xx-skeleton" />
<!-- 按照日期一个文件夹--><timestamp key="datetime" datePattern="yyyy-MM-dd"/><!-- 彩色日志 --><!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 --><!-- magenta:洋红 --><!-- boldMagenta:粗红--><!-- cyan:青色 --><!-- white:白色 --><!-- magenta:洋红 --><property name="CONSOLE_LOG_PATTERN"value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/><!--输出到控制台--><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--><!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><encoder><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!--输出到文件--><!-- 时间滚动输出 level为 INFO 日志 --><appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/${datetime}/log_info.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 每天日志归档路径以及格式 --><fileNamePattern>${log.path}/${datetime}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>7</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}/${datetime}/log_warn.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/${datetime}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>7</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}/${datetime}/log_error.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/${datetime}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>7</maxHistory></rollingPolicy><!-- 此日志文件只记录ERROR级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。name:用来指定受此logger约束的某一个包或者具体的某一个类。level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,如果未设置此属性,那么当前logger将会继承上级的级别。--><!--使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:--><!--开发环境:打印控制台--><springProfile name="dev"><!--可以输出项目中的debug日志,包括mybatis的sql日志--><logger name="com.xx" level="INFO" /><!--root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG可以包含零个或多个appender元素。--><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="WARN_FILE" /><appender-ref ref="ERROR_FILE" /></root></springProfile><!--生产环境:输出到文件--><springProfile name="prd"><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="DEBUG_FILE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="ERROR_FILE" /><appender-ref ref="WARN_FILE" /></root></springProfile></configuration>
测试
@RestController
@RequestMapping("/test-cg")
@Slf4j
public class TestCgController extends BaseController {@GetMapping("index14")@ApiOperation(value = "日志测试")@PassTokenpublic R index14(){log.trace("我是trace");log.debug("我是 debug");log.info("我是info");log.warn("我是warn");log.error("我是error");return R.success();}
}
最后再送 一个 定时任务 删除过期 日志文件 防止删除失败
定时任务 用的 xxl-job 不太清除这个定时任务插件 可百度
package com.xxx.init.job;import com.xxx.api.out.R;
import com.xxx.init.aop.XxlJobTask;
import com.xxx.init.utils.BaseDataUtil;import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;import java.nio.file.*;import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;import java.util.List;/*** User:Json* Date: 2024/4/18**/
@Slf4j
@Component
public class RuntimeFileClearJob {@Value("${spring.application.name}")private String serviceName;private static final String LOG_DIRECTORY_WINDOWS = "home\\logs"; // Windows系统的日志目录private static final String LOG_DIRECTORY_LINUX = "/home/logs/"; // Linux系统的日志目录//jobHandler 必须唯一 每天凌晨3点13分0秒触发 0 13 3 * * ?@XxlJob("planRuntimeFileClearJava")@XxlJobTask(jobDesc = "日志文件的清空-Java", cron = "0 13 3 * * ?", jobHandler = "planRuntimeFileClearJava", routeStrategy = "ROUND")//自定义注解public R planRuntimeFileClearJava() {Integer clearCacheDay = BaseDataUtil.getSystemConfigNacos().getClearCacheDay();log.info("===========清空缓存日志文件开始执行==========");if (clearCacheDay == null) {//从nacos里读,读不到就设置为7天。clearCacheDay = 7;}cleanupLogs(clearCacheDay);log.info("===========清空缓存日志文件结束执行==========");return R.success();}public void cleanupLogs(Integer clearCacheDay) {String logDirectory = getLogDirectory();if (logDirectory == null) {log.error("日志文件 目录不能为空!");return;}List<String> oldFolders = getOldFolders(logDirectory, clearCacheDay);if (!CollectionUtils.isEmpty(oldFolders)) {deleteOldFolders(oldFolders);}}//获取日志根目录private String getLogDirectory() {// 根据运行环境确定日志目录String osName = System.getProperty("os.name").toLowerCase();if (osName.contains("windows")) {String drive = Paths.get("").toAbsolutePath().getRoot().toString();return drive + "\\" + LOG_DIRECTORY_WINDOWS + "\\" + serviceName;} else {return LOG_DIRECTORY_LINUX + "/" + serviceName;}}//获取过期文件夹 不会递归着找 只会找当前目录下的 文件夹格式是 : 2024-04-18 会根据文件夹检索private List<String> getOldFolders(String logDirectory, Integer clearCacheDay) {List<String> oldFolders = new ArrayList<>();LocalDate today = LocalDate.now();DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");try {Files.list(Paths.get(logDirectory)).filter(Files::isDirectory).forEach(dir -> {String dirName = dir.getFileName().toString();try {LocalDate folderDate = LocalDate.parse(dirName, formatter);if (folderDate.isBefore(today.minusDays(clearCacheDay))) {oldFolders.add(dir.toString());}} catch (Exception e) {// Ignore non-date directorieslog.error("获取过期文件夹报错:" + e.getMessage());}});} catch (Exception e) {e.printStackTrace();}return oldFolders;}//删除过期文件夹 linux 注意 jar是否有 删除文件夹的权限 未测 linuxprivate void deleteOldFolders(List<String> oldFolders) {oldFolders.forEach(folder -> {try {Files.walk(Paths.get(folder)).sorted((path1, path2) -> -path1.compareTo(path2)).forEach(path -> {try {Files.deleteIfExists(path);} catch (Exception e) {e.printStackTrace();}});} catch (Exception e) {e.printStackTrace();log.error("删除过期文件夹报错:" + e.getMessage());}});}
}