一、 Java 日志框架发展历程
- 1996年,欧洲安全电子市场项目组编写了自己的程序跟踪API,后发展成为 log 4j,并成为Apache基金会项目成员;
- 2002年Java1.4,Sun推出Java Util Loggin(JUL),模仿了Log4j的实现;
- 2002年Apache推出Jakarta Commons Logging(JCL),定义了一套日志接口和简单的Simple Log实现,支持运行时动态加载日志组件。从官网看,2014年1.2版本后就没在更新了。
- 2006年,Ceki Gülcü创建了slf4j和Logback(也是Log4j的作者);
- 2012年,Apache开发Log4j 2,其与Log4j1不兼容。
二、一些基本概念
1. 接口与实现
- Commons Logging和Slf4j定义的是接口,需要给出具体的实现再使用;
- 一般Slf4j与Logback组合使用,Commons Logging与Log4j组合使用。
2. 日志信息输出目的地
- 控制台
- 打印到文件
- 打印到网络
- 写入数据库
三、Jakarta Commons Logging(JCL)
1. 框架结构
JCL由Apache提供的一个通用日志API,包名: org.apache.commons.logging ,有两个抽象类:
- Log:基本记录器
- LogFactory:负责创建Log实例
2. LogFactory查找日志工具的顺序
- 寻找当前factory中名叫 org.apache.commons.logging.Log 配置属性的值;
- 寻找系统中属性中名叫 org.apache.commons.logging.Log 的值;
- 如果应用程序的classpath中有log4j,则使用相关的包装(wrapper)类(Log4JLogger);
- 如果应用程序运行在jdk1.4的系统中,使用相关的包装类(Jdk14Logger);
- 使用简易日志包装类(SimpleLog)。
3. 日志严重性排序
// 非常严重的错误
log.fatal(Object message);
log.fatal(Object message, Throwable t);
// 一般运行期间错误
log.error(Object message);
log.error(Object message, Throwable t);
// 警告性错误
log.warn(Object message);
log.warn(Object message, Throwable t);
// 有意义的日志信息
log.info(Object message);
log.info(Object message, Throwable t);
// 调试信息
log.debug(Object message);
log.debug(Object message, Throwable t);
// 更完整的跟踪链信息
log.trace(Object message);
log.trace(Object message, Throwable t);
4. 基本使用示例
3.4.1 maven引用
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>.2</version>
</dependency>
3.4.2 java示例
// 引用
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
// 创建日志对象
// 没有其它日志实现的时候,会自动实现jdk自带的日志JUL
private static Log log = LogFactory.getLog(Test.class);
// 调用,建议调用日志时都使用is...Enabled进行判断
if (log.isDebugEnabled()) {
log.debug("debug test");
}
3.4.3 运行结果
5. 使用JCL+Log4j
3.5.1 maven引用
<!-- -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>.2</version>
</dependency>
<dependency>
<groupId>logj</groupId>
<artifactId>logj</artifactId>
<version>.2.17</version>
</dependency>
3.5.2 创建commons-loggin.properties文件
org.apache.commons.logging.Log = org.apache.commons.logging.impl.LogJLogger
3.5.3 创建log4j.properties
#配置根 Loggers控制日志的输出级别与日志是否输出
logj.rootLogger=trace,console
#配置输出到控制台 Appenders是指定日志的输出方式
logj.appender.console=org.apache.log4j.ConsoleAppender
#指定输出控制台
logj.appender.console.Target = System.out
#指定布局,输出日志的格式
logj.appender.console.layout=org.apache.log4j.PatternLayout
#指定布局的参数
logj.appender.console.layout.ConversionPattern=[%-10p] %r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
3.5.4 java示例
@Test
public void test() throws Exception{
// 获取log日志记录器对象
Log log = LogFactory.getLog(JCLTest.class);
if(log.isInfoEnabled()){
log.info("hello jcl");
}
}
3.5.5 运行结果
四、slf4j
1. 功能介绍
slf4j类似JCL提供日志接口,可以选用的实现有:NLOG4J、SimpleLogger、logback、log4j等,也可以通过slf4j提供的API实现来开发相应的适配器,如:Log4jLoggerAdapter、JDK14LoggerAdapter。
2. 使用slf4j+log4j
log4j是apache实现的一个开源日志组件。(Wrapped implementations)
4.2.1 maven引用
<dependencies>
<dependency>
<groupId>org.slfj</groupId>
<artifactId>slfj-log4j12</artifactId>
<version>.7.25</version>
</dependency>
</dependencies>
4.2.2 java示例
import org.slfj.Logger;
import org.slfj.LoggerFactory;
/**
* @author Cade on-10-14
*/public class test {
private static final Logger logger = LoggerFactory.getLogger(test.class);
public static void main(String[] args){
if(logger.isInfoEnabled()){
logger.info("hello");
}
}
}
4.2.3 运行结果
3. slf4j+log4j 日志写mysql数据库
4.3.1 maven引用
<dependencies>
<dependency>
<groupId>org.slfj</groupId>
<artifactId>slfj-log4j12</artifactId>
<version>.7.25</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>.1.18</version>
</dependency>
</dependencies>
4.3.2 log4j.properties
# 日记级别(单个级别) 文件/控制台
logj.rootLogger=debug, stdout, file ,datasource
# Redirect log messages to console
logj.appender.stdout=org.apache.log4j.ConsoleAppender
logj.appender.stdout.Target=System.out
logj.appender.stdout.layout=org.apache.log4j.PatternLayout
logj.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Rirect log messages to a log file
logj.appender.file=org.apache.log4j.RollingFileAppender
logj.appender.file.File=test.log
logj.appender.file.MaxFileSize=5MB
logj.appender.file.MaxBackupIndex=10
logj.appender.file.layout=org.apache.log4j.PatternLayout
logj.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
#下面是配置将日志信息插入数据库,
#配置输出目标为数据库(假如要将日志在控制台输出,配置为logj.appender. stdout =org.apache.log4j.ConsoleAppender;将日志写入文件,配置为log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
#这样的配置在许多地方都要有,需要可查有关资料),当然你也可以自己扩展org.apache.logj.jdbc.JDBCAppender这个类,只需要在这里配置就可以了例如我们配置我自己扩展的MyJDBCAppender,配置为#log4j.appender.db=com.neam.commons.MyJDBCAppender
logj.appender.datasource=org.apache.log4j.jdbc.JDBCAppender
logj.appender.datasource.layout=org.apache.log4j.PatternLayout
logj.appender.datasource.driver=com.mysql.jdbc.Driver
#定义什么级别的错误将写入到数据库中
logj.appender.datasource.BufferSize=1
#设置缓存大小,就是当有条日志信息是才忘数据库插一次,我设置的数据库名和表名均为user
logj.appender.datasource.URL=jdbc:mysql://数据库ip:3306/数据库名称?characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull
logj.appender.datasource.user=数据库账号
logj.appender.datasource.password=数据库密码
logj.appender.datasource.sql=insert into logs (class,method,create_time,log_ level ,log_line,msg) values ('%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%l','%m')
4.3.3 数据库建表
CREATE TABLE `logs` (
`class` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`method` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`create_time` datetime() NULL DEFAULT NULL,
`log_level` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`log_line` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`msg` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf COLLATE = utf8_general_ci ROW_FORMAT = Compact;
4.3.4 java代码
//注意导入的包都是slfj的包
import org.slfj.Logger;
import org.slfj.LoggerFactory;
public class test {
private static final Logger log = LoggerFactory.getLogger(test.class);
public static void main(String[] args) {
if(log.isInfoEnabled()){
log.info("logback的--info日志--输出了");
}
}
}
4.3.5 运行结果
4. 使用slf4j+logback
logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架。是slf4j的原生实现。(Native implementations)
logback特点:
- 更快的执行速度
- 充分的测试
- 自动重新载入配置文件
- 优雅地从I/O错误中恢复
- 自动清除旧的日志归档文件
- 自动压缩归档日志文件
- …
4.4.1 maven引用
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>.1.2</version>
</dependency>
4.4.2 配置文件logback.xml
<?xml version=".0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod=" seconds" debug="false">
<!-- 定义日志的根目录 -->
<property name="LOG_HOME" value="/app/log" />
<!-- 定义日志文件名称 -->
<property name="appName" value="netty"></property>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<Encoding>UTF-</Encoding>
<!--
日志输出格式:%d表示日期时间,%thread表示线程名,%-level:级别从左显示5个字符宽度
%logger{} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
</layout>
</appender>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Encoding>UTF-</Encoding>
<!-- 指定日志文件的名称 -->
<file>${LOG_HOME}/${appName}.log</file>
<!--
当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
%i:当文件大小超过maxFileSize时,按照i进行文件滚动
-->
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
且maxHistory是,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
那些为了归档而创建的目录也会被删除。
-->
<MaxHistory></MaxHistory>
<!--
当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!--
日志输出格式:%d表示日期时间,%thread表示线程名,%-level:级别从左显示5个字符宽度 %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-level ] [ %logger{50} : %line ] - %msg%n</pattern>
</layout>
</appender>
<!--
logger主要用于存放日志对象,也可以定义日志类型、级别
name:表示匹配的logger类型前缀,也就是包的前半部分
level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,false:表示只用当前logger的appender-ref,true:表示当前logger的appender-ref和rootLogger的appender-ref都有效
-->
<!-- hibernate logger -->
<logger name="org.hibernate" level="error" />
<!-- Spring framework logger -->
<logger name="org.springframework" level="error" additivity="false"></logger>
<logger name="com.creditease" level="info" additivity="true">
<appender-ref ref="appLogAppender" />
</logger>
<!--
root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。
-->
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="appLogAppender" />
</root>
</configuration>
4.4.3 java代码
//注意导入的包都是slfj的包
import org.slfj.Logger;
import org.slfj.LoggerFactory;
public class test {
private static final Logger LOGGER = LoggerFactory.getLogger(test.class);
public static void main(String[] args) {
if(LOGGER.isInfoEnabled()){
LOGGER.info("logback的--info日志--输出了");
}
}
}
4.4.4 运行结果
五、日志组件冲突
如果在引用的项目里使用了log4j,如: zookeeper 使用了log4j,在pom中解决冲突:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>.4.9</version>
<exclusions>
<exclusion>
<groupId>org.slfj</groupId>
<artifactId>slfj-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>logj</groupId>
<artifactId>logj</artifactId>
</exclusion>
</exclusions>
</dependency>
可以使用
mvn dependecy:tree
查看依赖情况,或者在idea 的Maven窗口可以方便地看到引用情况。
六、Spring中使用Log4j
在 web.xml 设置:
<!-- 设置根目录 -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webapp.root</param-value>
</context-param>
<context-param>
<param-name>logjConfigLocation</param-name>
<param-value>/WEB-INF/classes/logj.properties</param-value>
</context-param>
<!--表示 开一条watchdog线程每60秒扫描一下配置文件的变化;这样便于日志存放位置的改变 -->
<context-param>
<param-name>logjRefreshInterval</param-name>
<param-value></param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.LogjConfigListener</listener-class>
</listener>
七、SpringBoot2 使用 logback
1. 引用
<?xml version=".0" encoding="UTF-8"?>
<project xmlns="#;
xmlns:xsi="#;
xsi:schemaLocation=" #;>
<modelVersion>.0.0</modelVersion>
<groupId>com.xundh</groupId>
<artifactId>javalearn</artifactId>
<version>.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>.0.0.RELEASE</version>
</dependency>
</dependencies>
</project>
添加Springboot的引用后,可以在idea中查看已经包含了log的几个组件:
2. 创建logback.xml
<?xml version=".0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod=" seconds">
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="./logs" />
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<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:-%p}) %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="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<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为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
<charset>UTF-</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory></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}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
<charset>UTF-</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory></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}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
<charset>UTF-</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory></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}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
<charset>UTF-</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory></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,
还有一个特俗值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="com.xundh.view" level="debug"/>
</springProfile>
<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" />
</root>
<!--生产环境:输出到文件-->
<!--<springProfile name="pro">-->
<!--<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>
3. 运行效果
六、Lombok 日志注解
Lombok可以用来创建 slf4j+logback的日志
1. 使用方法
6.1.1 maven引用
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>.1.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>.18.14</version>
<scope>provided</scope>
</dependency>
</dependencies>
6.1.2 java代码
//注意导入的包都是slfj的包
import lombok.extern.slfj.Slf4j;
@Slfj
public class test {
public static void main(String[] args) {
if(log.isInfoEnabled()){
log.info("logback的--info日志--输出了");
}
}
}
其它配置与slf4j+logback类似。
6.1.3 运行效果
八、logback+redis
1. 依赖
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>.1.1</version>
</dependency>
<dependency>
<groupId>com.cwbase</groupId>
<artifactId>logback-redis-appender</artifactId>
<version>.1.5</version>
</dependency>
2. logback.xml
<configuration>
<property name="type.name" value="" />
<appender name="TEST" class="com.cwbase.logback.RedisAppender">
<source>test-application</source>
<!--type 可定为项目类型-->
<type>${type.name}</type>
<!--redis ip-->
<host>你的redis ip</host>
<!--redis存放的key-->
<key>logstash:redis</key>
<tags>test-</tags>
<mdc>true</mdc>
<location>true</location>
<callerStackIndex></callerStackIndex>
<!--additionalField添加附加字段 用于head插件显示-->
<additionalField>
<key>MyKey</key>
<value>MyValue</value>
</additionalField>
<additionalField>
<key>MySecondKey</key>
<value>MyOtherValue</value>
</additionalField>
</appender>
<!--日志输出-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--日志回滚周期天-->
<maxHistory></maxHistory>
</rollingPolicy>
<!-- <encoder>
<pattern>%logger{} - %message%n%xException{5}</pattern>
</encoder>-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-relative [%thread] %-5level %logger{35} %caller{3} - %msg%n%xException{5}</pattern>
</encoder>
</appender>
<logger name="application" level="DEBUG" />
<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="TEST" />
</root>
</configuration>
九、logback+logstash
可以在第七条基础上,让logstash从redis获取数据,或直接使用logstash-logback插件。
1. 依赖
<!-- Logstash encoder -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>.4</version>
</dependency>
2. logback.xml添加内容
<?xml version=".0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are by default assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<param name="Encoding" value="UTF-"/>
<remoteHost>logstash ip</remoteHost>
<port></port>
<!-- encoder is required -->
<encoder class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<root level="info">
<appender-ref ref="logstash" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
十、日志上 阿里云
使用阿里云的日志服务,可以避免自行搭建ELK的复杂配置。对于云上分布式的应用来说,使用阿里云是一个比较好的选择方案。
文档地址:
1. 申请阿里云日志服务
- 按提示申请服务后,创建Project
- 按提示创建logstore
- 点击logstore、数据接入后的加号,可以看到有很多接入方式,这里选择logback-sdk写入:
2. 添加依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>.5.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.openservices</groupId>
<artifactId>aliyun-log-logback-appender</artifactId>
<version>.1.15</version>
</dependency>
3. logback.xml配置文件
<!--为了防止进程退出时,内存中的数据丢失,请加上此选项-->
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<appender name="aliyun" class="com.aliyun.openservices.log.logback.LoghubAppender">
<!--必选项-->
<!-- 账号及网络配置 -->
<endpoint>your project endpoint</endpoint>
<accessKeyId>your accesskey id</accessKeyId>
<accessKeySecret>your accesskey</accessKeySecret>
<!-- sls 项目配置 -->
<project>your project</project>
<logStore>your logStore</logStore>
<!--必选项 (end)-->
<!-- 可选项 -->
<topic>your topic</topic>
<source>your source</source>
<!-- 可选项 详见 '参数说明'-->
<totalSizeInBytes></totalSizeInBytes>
<maxBlockMs></maxBlockMs>
<ioThreadCount></ioThreadCount>
<batchSizeThresholdInBytes></batchSizeThresholdInBytes>
<batchCountThreshold></batchCountThreshold>
<lingerMs></lingerMs>
<retries></retries>
<baseRetryBackoffMs></baseRetryBackoffMs>
<maxRetryBackoffMs></maxRetryBackoffMs>
<!-- 可选项 通过配置 encoder 的 pattern 自定义 log 的格式 -->
<encoder>
<pattern>%d %-level [%thread] %logger{0}: %msg</pattern>
</encoder>
<!-- 可选项 设置 time 字段呈现的格式 -->
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
<!-- 可选项 设置 time 字段呈现的时区 -->
<timeZone>UTC</timeZone>
</appender>
<!-- 可用来获取StatusManager中的状态
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
-->
4. java代码
package com.aliyun.openservices.log.logback.example;
import org.slfj.Logger;
import org.slfj.LoggerFactory;
import org.slfj.MDC;
/**
* Created by brucewu on/1/8.
*/public class LogbackAppenderExample {
private static final Logger LOGGER = LoggerFactory.getLogger(LogbackAppenderExample.class);
public static void main(String[] args) {
MDC.put("MDC_KEY","MDC_VALUE");
MDC.put("THREAD_ID", String.valueOf(Thread.currentThread().getId()));
LOGGER.trace("trace log");
LOGGER.debug("debug log");
LOGGER.info("info log");
LOGGER.warn("warn log");
LOGGER.error("error log");
}
}
5. 查询示例
十一、idea 彩色日志插件
1. 安装插件Grep Console
2. 运行效果