還是直接上代碼
@Slf4j 這玩意 默認(rèn)支持 不用引入
yml 配置文件
# 日志配置 如果配置了xml 這個(gè)就不生效了 xml優(yōu)先級最高
#logging:
# file:
# path: /home/logs # 日志目錄地址
# name: /home/logs/skeleton.log
# max-size: 1KB # 設(shè)置日志大小的最大大小 1KB 用于演示 單位包括 KB、MB、GB
# max-history: 3 # 默認(rèn)存儲(chǔ)最近7天
# total-size-cap: 3KB #日志文檔的總大小:當(dāng)日志文檔總大小超過該閾值會(huì)刪除備份
# level:
# root: info #全局的日志等級 哪些日志輸出
下面分享 xml 方式
在 資源目錄下創(chuàng)建 logback-spring.xml 粘貼走 即可 重啟 看控制臺(tái)變化 還有磁盤 有沒有寫入
坑 :
我在創(chuàng)建的時(shí)候 發(fā)現(xiàn) xml 沒有生效 排查了半天 發(fā)現(xiàn) 在創(chuàng)建 logback-spring.xml 這個(gè)文件的時(shí)候
我不是手打的 是復(fù)制的 文件名 前面多了個(gè)空格 導(dǎo)致不生效
所以如果有小伙伴 和我一樣 復(fù)制的文件名 一定要小心 文件名兩邊不要復(fù)制多了 空格
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<!-- 日志級別從低到高分為TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果設(shè)置為WARN,則低于WARN的信息都不會(huì)輸出 -->
<!-- scan:當(dāng)此屬性設(shè)置為true時(shí),配置文件如果發(fā)生改變,將會(huì)被重新加載,默認(rèn)值為true -->
<!-- scanPeriod:設(shè)置監(jiān)測配置文件是否有修改的時(shí)間間隔,如果沒有給出時(shí)間單位,默認(rèn)單位是毫秒。當(dāng)scan為true時(shí),此屬性生效。默認(rèn)的時(shí)間間隔為1分鐘。 -->
<!-- debug:當(dāng)此屬性設(shè)置為true時(shí),將打印出logback內(nèi)部日志信息,實(shí)時(shí)查看logback運(yùn)行狀態(tài)。默認(rèn)值為false。 -->
<contextName>logback</contextName>
<!-- name的值是變量的名稱,value的值時(shí)變量定義的值。通過定義的值會(huì)被插入到logger上下文中。定義變量后,可以使“${}”來使用變量。 -->
<!-- 日志輸出位置-->
<property name="log.path" value="/home/logs/xx-skeleton" />
<!-- 按照日期一個(gè)文件夾-->
<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)"/>
<!--輸出到控制臺(tái)-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是為開發(fā)使用,只配置最底級別,控制臺(tái)輸出的日志級別是大于或等于此級別的日志信息-->
<!-- 例如:如果此處配置了INFO級別,則后面其他位置即使配置了DEBUG級別的日志,也不會(huì)被輸出 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 設(shè)置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--輸出到文件-->
<!-- 時(shí)間滾動(dòng)輸出 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>
<!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
<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>
<!--日志文件保留天數(shù)-->
<maxHistory>7</maxHistory>
</rollingPolicy>
<!-- 此日志文件只記錄info級別的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 時(shí)間滾動(dòng)輸出 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> <!-- 此處設(shè)置字符集 -->
</encoder>
<!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
<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>
<!--日志文件保留天數(shù)-->
<maxHistory>7</maxHistory>
</rollingPolicy>
<!-- 此日志文件只記錄warn級別的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 時(shí)間滾動(dòng)輸出 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> <!-- 此處設(shè)置字符集 -->
</encoder>
<!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
<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>
<!--日志文件保留天數(shù)-->
<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>用來設(shè)置某一個(gè)包或者具體的某一個(gè)類的日志打印級別、以及指定<appender>。
<logger>僅有一個(gè)name屬性,
一個(gè)可選的level和一個(gè)可選的addtivity屬性。
name:用來指定受此logger約束的某一個(gè)包或者具體的某一個(gè)類。
level:用來設(shè)置打印級別,大小寫無關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
如果未設(shè)置此屬性,那么當(dāng)前l(fā)ogger將會(huì)繼承上級的級別。
-->
<!--
使用mybatis的時(shí)候,sql語句是debug下才會(huì)打印,而這里我們只配置了info,所以想要查看sql語句的話,有以下兩種操作:
第一種把<root level="INFO">改成<root level="DEBUG">這樣就會(huì)打印sql,不過這樣日志那邊會(huì)出現(xiàn)很多其他消息
第二種就是單獨(dú)給mapper下目錄配置DEBUG模式,代碼如下,這樣配置sql語句會(huì)打印,其他還是正常DEBUG級別:
-->
<!--開發(fā)環(huán)境:打印控制臺(tái)-->
<springProfile name="dev">
<!--可以輸出項(xiàng)目中的debug日志,包括mybatis的sql日志-->
<logger name="com.xx" level="INFO" />
<!--
root節(jié)點(diǎn)是必選節(jié)點(diǎn),用來指定最基礎(chǔ)的日志輸出級別,只有一個(gè)level屬性
level:用來設(shè)置打印級別,大小寫無關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默認(rèn)是DEBUG
可以包含零個(gè)或多個(gè)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>
<!--生產(chǎn)環(huán)境:輸出到文件-->
<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>
測試文章來源:http://www.zghlxwxcb.cn/news/detail-855776.html
@RestController
@RequestMapping("/test-cg")
@Slf4j
public class TestCgController extends BaseController {
@GetMapping("index14")
@ApiOperation(value = "日志測試")
@PassToken
public R index14(){
log.trace("我是trace");
log.debug("我是 debug");
log.info("我是info");
log.warn("我是warn");
log.error("我是error");
return R.success();
}
}
最后再送 一個(gè) 定時(shí)任務(wù) 刪除過期 日志文件 防止刪除失敗
定時(shí)任務(wù) 用的 xxl-job 不太清除這個(gè)定時(shí)任務(wù)插件 可百度文章來源地址http://www.zghlxwxcb.cn/news/detail-855776.html
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系統(tǒng)的日志目錄
private static final String LOG_DIRECTORY_LINUX = "/home/logs/"; // Linux系統(tǒng)的日志目錄
//jobHandler 必須唯一 每天凌晨3點(diǎn)13分0秒觸發(fā) 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("===========清空緩存日志文件開始執(zhí)行==========");
if (clearCacheDay == null) {
//從nacos里讀,讀不到就設(shè)置為7天。
clearCacheDay = 7;
}
cleanupLogs(clearCacheDay);
log.info("===========清空緩存日志文件結(jié)束執(zhí)行==========");
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() {
// 根據(jù)運(yùn)行環(huán)境確定日志目錄
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;
}
}
//獲取過期文件夾 不會(huì)遞歸著找 只會(huì)找當(dāng)前目錄下的 文件夾格式是 : 2024-04-18 會(huì)根據(jù)文件夾檢索
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 directories
log.error("獲取過期文件夾報(bào)錯(cuò):" + e.getMessage());
}
});
} catch (Exception e) {
e.printStackTrace();
}
return oldFolders;
}
//刪除過期文件夾 linux 注意 jar是否有 刪除文件夾的權(quán)限 未測 linux
private 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("刪除過期文件夾報(bào)錯(cuò):" + e.getMessage());
}
});
}
}
到了這里,關(guān)于springboot日志使用 SLF4J+Logback 實(shí)現(xiàn)(springboot默認(rèn)的日志實(shí)現(xiàn)),日志打印到控制臺(tái)及日志輸出到指定文件的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!