先引入相关依赖(当然很多包会间接依赖这些依赖)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
这里使用Slf4j的原因,市面上有很多日志框架,Slf4j可以看作一个接口或类似jdbc,将不同的日志框架整合起来,方便我们在一个项目中需要改变日志框架时,可以很好的进行维护。这里我们使用的是Slf4j + logback的方式。
另外,Slf4j 日志输出采用占位符{}的方式,相对于其他的日志框架可以避免很多字符串拼接而造成的性能问题。
接下来聊一聊关于logback配置文件的问题:
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:-->
<!-- 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。-->
<!-- scanPeriod:-->
<!-- 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。-->
<!-- debug:-->
<!-- 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<!-- 每隔10秒扫描一次xml文件,当发生改变时重新进行加载-->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>austin</contextName>
<!-- 设置日志输出路径 可以使“${}”来使用变量。 -->
<!-- 这里相当于是变量,后面可以根据name来获取value,即是将一些经常修改的数据提取出来·-->
<property name="log.path" value="logs"/>
<springProperty scope="context" name="grayLogIp" source="austin.business.graylog.ip"/>
<!-- 格式化输出 -->
<property name="LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5level][%t][%file:%line][%X{traceId}] -| %m%n"/>
<!-- 在一个configuration下可以有多个appender appender主要指定输出目的地 其中属性name用于指定自己定义的名字 class用于指定输出的目的地-->
<!-- ch.qos.logback.core.ConsoleAppender 输出的控制台-->
<!-- ch.qos.logback.core.rolling.RollingFileAppender 文件滚动输出:现将日志写到一个文件中,在特定的条件下,将某些日志输出到另一个文件-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- file日志输出的文件路径,可以是绝对路径也可以是相对路径-->
<!-- encoder格式化方式-->
<!-- rollingPolicy滚动策略 也是通过class来指定滚动策略-->
<!-- 最常见的滚动策略为 基于时间的滚动策略 ch.qos.logback.core.rolling.TimeBasedRollingPolicy-->
<!-- fileNamePattern用于指生产出来的滚动日志的文件名称格式-->
<!--时间滚动也即是生成的日志不仅仅会只打印在一个文件中,会根据一定的策略打印到不同的有一定顺序的文件中-->
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/austin-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}/logs/austin-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 当超过1000MB时,触发滚动策略-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1000MB</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为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/austin-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}/logs/austin-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1000MB</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="GELF" class="de.siegmar.logbackgelf.GelfUdpAppender">
<!-- Graylog服务的地址 -->
<graylogHost>${grayLogIp}</graylogHost>
<!-- UDP Input端口 -->
<graylogPort>12201</graylogPort>
<!-- 最大GELF数据块大小(单位:字节),508为建议最小值,最大值为65467 -->
<maxChunkSize>508</maxChunkSize>
<!-- 是否使用压缩 -->
<useCompression>true</useCompression>
<encoder class="de.siegmar.logbackgelf.GelfEncoder">
<!-- 是否发送原生的日志信息 -->
<includeRawMessage>false</includeRawMessage>
<includeMarker>true</includeMarker>
<includeMdcData>true</includeMdcData>
<includeCallerData>false</includeCallerData>
<includeRootCauseData>false</includeRootCauseData>
<!-- 是否发送日志级别的名称,否则默认以数字代表日志级别 -->
<includeLevelName>true</includeLevelName>
<shortPatternLayout class="ch.qos.logback.classic.PatternLayout">
<pattern>%m%nopex</pattern>
</shortPatternLayout>
<fullPatternLayout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d - [%thread] %-5level %logger{35} - %msg%n</pattern>
</fullPatternLayout>
<!-- 配置应用名称(服务名称),通过staticField标签可以自定义一些固定的日志字段 -->
<staticField>app_name:austin</staticField>
</encoder>
</appender>
<root level="info">
<!-- TODO console打印后面可以只针对dev环境的 -->
<appender-ref ref="CONSOLE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="GELF"/>
</root>
</configuration>
当spring加载时会自动去路径下找到logback.xml的名字的文件并加载配置
另一种写法:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义全局常量 -->
<!-- 配置默认的日志级别 -->
<property name="log.level" value="debug"/>
<!-- 配置文件存放的最大日期 30天-->
<property name="log.maxHistory" value="10" />
<!-- 配文件存放的路径 根目录下的logs-->
<property name="log.filePath" value="logs"/>
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- appender用于指定日志文件输出到什么地方,以及怎么输出,相当于定义一套规范 -->
<!-- 控制台日志 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<!-- 配置日志转化成字符串 -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- debug -->
<appender name="debugAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定文件路径 -->
<file>${log.filePath}/debug.log</file>
<!-- DEBUG日志 -->
<!-- 指定滚动策略 -->
<!-- 基于时间滚动的策略:常用 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 基于时间的文件名字格式 -->
<fileNamePattern>${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<!-- 除了指定策略外,一定要指定格式String -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
<!-- 本appender只记录debug信息 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- info -->
<appender name="infoAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定文件路径 -->
<file>${log.filePath}/info.log</file>
<!-- DEBUG日志 -->
<!-- 指定滚动策略 -->
<!-- 基于时间滚动的策略:常用 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 基于时间的文件名字格式 -->
<fileNamePattern>${log.filePath}/info/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<!-- 除了指定策略外,一定要指定格式String -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
<!-- 本appender只记录debug信息 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- error -->
<appender name="errorAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定文件路径 -->
<file>${log.filePath}/error.log</file>
<!-- DEBUG日志 -->
<!-- 指定滚动策略 -->
<!-- 基于时间滚动的策略:常用 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 基于时间的文件名字格式 -->
<fileNamePattern>${log.filePath}/error/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<!-- 除了指定策略外,一定要指定格式String -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
<!-- 本appender只记录debug信息 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- logger指定记录com.joofeel包下的日志,且只记录level以上水平的日志 -->
<!-- additivity表示将root中的appender-ref也加入到logger中 -->
<!-- 表示当com.joofeel.miniprogram包下有日志打印时,会采用该logger而不会采用root,如果没有在指定包的其他地方进行了日志-->
<!-- 则使用root而不是用logger。-->
<!-- 这里一定要将additivity指定为true,将root中的appeder弄到logger中,不然控制台就没有任何东西打印了-->
<logger name="com.joofeel.miniprogram" level="${log.level}" additivity="true">
<appender-ref ref="infoAppender"/>
<appender-ref ref="debugAppender"/>
<appender-ref ref="errorAppender"/>
</logger>
<root level="info">
<appender-ref ref="consoleAppender"/>
</root>
</configuration>
使用
@Slf4j
class UserServiceImpl{
public void deleteUser(int id){
log.info("传入id为{}",id);
}
}
@Slf4j是Lombok的注解,代替了一下语句
Logger log=LoggerFactory.getLogger();