日志的做用是用来追踪和记录咱们的程序运行中的信息,咱们能够利用日志很快定位问题,追踪分析。java
首先要知道日志级别是干什么用的,日志级别是当你使用不一样的方式运行的时候,根据你运行的方式和你设置的日志打印级别来肯定哪些信息须要输出。
规定:日志只会打印设置的优先级及比本身高优先级的内容。
日志级别优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALLweb
Sun公司的日志框架,原生的日志框架,优势是使用很是简单,直接在 JDK 中就可使用。但 JDKLog 功能比较太过于简单,不支持占位符显示,拓展性比较差,因此如今用的人也不多。
示例:apache
import java.util.logging.Logger; /**** ** JDKLog Demo **/ public class JDKLog { public static void main( String[] args ) { Logger logger = Logger.getLogger("JDKLog"); logger.info("Hello World."); } }
Apache的日志框架,有多个分级(DEBUG/INFO/WARN/ERROR)记录级别,能够很好地将不一样日志级别的日志分开记录,极大地方便了日志的查看。api
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 输出DEBUG 级别以上的日志到=E://logs/error.log ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = E://logs/log.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 输出ERROR 级别以上的日志到=E://logs/error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =E://logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
Log4j升级版,2.x的版本在架构上进行了一些升级,配置文件也发生了一些变化。架构
<!-- Log4J --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.6.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.6.2</version> </dependency>
注:log4j和log4j2的依赖包路径是不同的,这是为了区分log4j和log4j2,开发者专门设置的。app
<?xml version="1.0" encoding="UTF-8"?> <configuration status="error"> <!-- 先定义全部的appender --> <appenders> <!-- 这个输出控制台的配置 --> <Console name="Console" target="SYSTEM_OUT"> <!-- 控制台只输出level及以上级别的信息(onMatch),其余的直接拒绝(onMismatch) --> <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/> <!-- 这个都知道是输出日志的格式 --> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> </Console> <!-- 文件会打印出全部信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 --> <!-- append为TRUE表示消息增长到指定文件中,false表示消息覆盖指定的文件内容,默认值是true --> <File name="log" fileName="log/test.log" append="false"> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> <!-- 添加过滤器ThresholdFilter,能够有选择的输出某个级别以上的类别 onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,不然直接拒绝 --> <File name="ERROR" fileName="logs/error.log"> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> <!-- 这个会打印出全部的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份创建的文件夹下面并进行压缩,做为存档 --> <RollingFile name="RollingFile" fileName="logs/web.log" filePattern="logs/$${date:yyyy-MM}/web-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> <SizeBasedTriggeringPolicy size="2MB"/> </RollingFile> </appenders> <!-- 而后定义logger,只有定义了logger并引入的appender,appender才会生效 --> <loggers> <!-- 创建一个默认的root的logger --> <root level="trace"> <appender-ref ref="RollingFile"/> <appender-ref ref="Console"/> <appender-ref ref="ERROR" /> <appender-ref ref="log"/> </root> </loggers> </configuration>
日志门面,支持运行时动态加载日志组件实现。也就是说,在应用代码中,只须要调用commons logging的接口,底层实现能够是log4j,也能够是Java Util Logging。框架
与Commons Logging对立的阵营,这是接口,实现是Logback。工具
Slf4J的实现。性能
Slf4j实现机制:Slf4j在编译期间,静态绑定本地的LOG库,所以能够在OSGi中正常使用。它是经过查找类路径下org.slf4j.impl.StaticLoggerBinder,而后绑定工做都在这类里面进。测试
Slf4j实现机制决定Slf4j限制较少,使用范围更广。因为Slf4j在编译期间,静态绑定本地的LOG库使得通用性要比Commons logging要好。
Logback拥有更好的性能。Logback声称:某些关键操做,好比断定是否记录一条日志语句的操做,其性能获得了显著的提升。这个操做在Logback中须要3纳秒,而在Log4J中则须要30纳秒。LogBack建立记录器(logger)的速度也更快:13毫秒,而在Log4J中须要23毫秒。更重要的是,它获取已存在的记录器只需94纳秒,而Log4J须要2234纳秒,时间减小到了1/23。跟JUL相比的性能提升也是显著的。
if(log.isDebugEnabled()){ log.debug("User name: " + user.getName() + " buy goods id :" + good.getId()); }
在Slf4j阵营,你只需这么作:
log.debug("User name:{} ,buy goods id :{}", user.getName(),good.getId());
也就是说,slf4j把构建日志的开销放在了它确认须要显示这条日志以后,减小内存和cup的开销,使用占位符号,代码也更为简洁。
Logback文档免费。Logback的全部文档是全面免费提供的,不象Log4J那样只提供部分免费文档而须要用户去购买付费文档。
jar包名 | 说明 |
---|---|
slf4j-log4j12-1.7.13.jar | log4j1.2版本的桥接器,你须要将log4j.jar加入classpath。 |
slf4j-jdk14-1.7.13.jar | java.util.logging的桥接器,JDK原生日志框架。 |
slf4j-nop-1.7.13.jar | NOP桥接器,默默丢弃一切日志。 |
slf4j-simple-1.7.13.jar | 一个简单实现的桥接器,该实现输出全部事件到System.err. 只有INFO以及高于该级别的消息被打印,在小型应用中它也许是有用的。 |
slf4j-jcl-1.7.13.jar | Jakarta Commons Logging 的桥接器. 这个桥接器将SLF4j全部日志委派给JCL。 |
logback-classic-1.0.13.jar(requires logback-core-1.0.13.jar) | slf4j的原生实现,logback直接实现了slf4j的接口,所以使用slf4j与 logback的结合使用也意味更小的内存与计算开销 |
具体接入方式以下:
在使用不一样的框架的时候,可能别人集成的框架不同。好比Spring Framework集成的是Commons Logging,而XSocket依赖的是Java Util Logging。如今咱们须要解决不一样框架中的不一样日志组件都统一为Slf4J。SLF4J会根据绑定器把日志交给具体的日志实现工具。Slf4J带有几个桥接模块,能够重定向log4j,JCL和Java.util.logging中的api到Slf4J。
jar包名 | 做用 |
---|---|
log4j-over-slf4j-version.jar | 将log4j重定向到slf4j |
jcl-over-slf4j-version.jar | 将commons logging里的Simple Logger重定向到slf4j |
jul-to-slf4j-version.jar | 将Java Util Logging 重定向到slf4j |
桥接方式参考下图:
在使用slf4j桥接时要注意避免造成死循环,在项目依赖的jar包中不要存在如下状况:
多个日志jar包造成死循环的条件 | 产生缘由 |
---|---|
log4j-over-slf4j.jar和slf4j-log4j12.jar同时存在 | 因为slf4j-log4j12.jar的存在会将全部日志调用委托给log4j。但因为同时因为log4j-over-slf4j.jar的存在,会将全部对log4j api的调用委托给相应等值的slf4j,因此log4j-over-slf4j.jar和slf4j-log4j12.jar同时存在会造成死循环 |
jul-to-slf4j.jar和slf4j-jdk14.jar同时存在 | 因为slf4j-jdk14.jar的存在会将全部日志调用委托给jdk的log。但因为同时jul-to-slf4j.jar的存在,会将全部对jul api的调用委托给相应等值的slf4j,因此jul-to-slf4j.jar和slf4j-jdk14.jar同时存在会造成死循环。 |