手写logback_LogBack入门实践

一、简介

LogBack是一个日志框架,它是Log4j作者Ceki的又一个日志组件。

LogBack,Slf4j,Log4j之间的关系

slf4j是The Simple Logging Facade for Java的简称,是一个简单日志门面抽象框架,它本身只提供了日志Facade API和一个简单的日志类实现,一般常配合Log4j,LogBack,java.util.logging使用。Slf4j作为应用层的Log接入时,程序可以根据实际应用场景动态调整底层的日志实现框架(Log4j/LogBack/JdkLog...);

LogBack和Log4j都是开源日记工具库,LogBack是Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。

LogBack官方建议配合Slf4j使用,这样可以灵活地替换底层日志框架。

LogBack的结构

LogBack分为3个组件,logback-core, logback-classic 和 logback-access。

其中logback-core提供了LogBack的核心功能,是另外两个组件的基础。

logback-classic则实现了Slf4j的API,所以当想配合Slf4j使用时,则需要引入这个包。

logback-access是为了集成Servlet环境而准备的,可提供HTTP-access的日志接口。

Log的行为级别

OFF、

FATAL、

ERROR、

WARN、

INFO、

DEBUG、

ALL

从下向上,当选择了其中一个级别,则该级别向下的行为是不会被打印出来。

举个例子,当选择了INFO级别,则INFO以下的行为则不会被打印出来。

二、slf4j与logback结合使用原理

我们从java代码最简单的获取logger开始

Logger logger = LoggerFactory.getLogger(xxx.class.getName());

LoggerFactory是slf4j的日志工厂,获取logger方法就来自这里。

public static Logger getLogger(String name) {

ILoggerFactory iLoggerFactory = getILoggerFactory();

return iLoggerFactory.getLogger(name);

}

这个方法里面有分为两个过程。

第一个过程是获取ILoggerFactory,就是真正的日志工厂。

第二个过程就是从真正的日志工厂中获取logger。

第一个过程又分为三个部分。

第一个部分加载org/slf4j/impl/StaticLoggerBinder.class文件

paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);//STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class"

第二部分随机选取一个StaticLoggerBinder.class来创建一个单例

当项目中存在多个StaticLoggerBinder.class文件时,运行项目会出现以下日志:

SLF4J: Class path contains multiple SLF4J bindings.

SLF4J: Found binding in [jar:file:/C:/Users/zhangheng5/.m2/repository/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: Found binding in [jar:file:/C:/Users/zhangheng5/.m2/repository/org/slf4j/slf4j-log4j12/1.7.12/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

最后会随机选择一个StaticLoggerBinder.class来创建一个单例

StaticLoggerBinder.getSingleton()

第三部分返回一个ILoggerFactory实例

StaticLoggerBinder.getSingleton().getLoggerFactory();

所以slf4j与其他实际的日志框架的集成jar包中,都会含有这样的一个org/slf4j/impl/StaticLoggerBinder.class类文件,并且提供一个ILoggerFactory的实现。

第二个过程就是每一个和slf4j集成的日志框架中实现ILoggerFactory方法getLogger()的实例所做的事了。

三、slf4j与logback结合使用实践

第一步引入jar包

slf4j-api

logback-core

logback-classic(含有对slf4j的集成包)

org.slf4j

slf4j-api

1.7.12

ch.qos.logback

logback-core

1.1.3

ch.qos.logback

logback-classic

1.1.3

第二步编写简单的logback配置文件

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

文件位置位于src/main/resources下,名字默认为logback.xml。

当然,logback也支持groovy格式的配置文件,如果你会用那更好。

接下来,自己随便写一个类调用一下logger

package log.test;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

/**

* @author jiangmitiao

* @date 2016/3/24

* @description TODO

*/

public class Foo {

public static void doIt(){

Logger logger = LoggerFactory.getLogger(Foo.class.getName());

logger.debug("let`s do it");

}

}

package log.test;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

/**

* @author jiangmitiao

* @date 2016/3/24

* @description TODO

*/

public class MyApp1 {

public static void main(String[] args) {

Logger logger = LoggerFactory.getLogger(MyApp1.class.getName());

logger.info("before");

Foo.doIt();

logger.info("after");

try {

int i = 10 / 0;

} catch (Exception e) {

logger.error("errorTest",e);

}

}

}

最后的结果是:

16:22:13.459 [main] INFO  log.test.MyApp1 - before

16:22:13.463 [main] DEBUG log.test.Foo - let`s do it

16:22:13.463 [main] INFO  log.test.MyApp1 - after

16:22:13.466 [main] ERROR log.test.MyApp1 - errorTest

java.lang.ArithmeticException: / by zero

at log.test.MyApp1.main(MyApp1.java:19) ~[classes/:na]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_25]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_25]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_25]

at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_25]

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) [idea_rt.jar:na]

配置规则简述

上边这么简单的配置当然是没有用的,下面这个就能够说明logback配置文件的编写规则了。

myApp1 contextName

debug

%-4d [%thread] %highlight%-5level %cyan%logger.%-10method - %message%n

${USER_HOME}/myApp1log-${bySecond}.log

%date %level [%thread] %logger{30} [%file:%line] %msg%n

debug

ACCEPT

DENY

%relative%thread%mdc%level%logger%msg

${USER_HOME}/test.html

true

${USER_HOME}/logFile.%d{yyyy-MM-dd}_%i.log

30

10KB

%-4date [%thread] %-5level %logger{35} - %msg%n%ex{full, DISPLAY_EX_EVAL}

四、过滤器的一些疑问

Logback的过滤器基于三值逻辑(ternary logic),允许把它们组装或成链,从而组成任意的复合过滤策略。过滤器很大程度上受到Linux的iptables启发。这里的所谓三值逻辑是说,过滤器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一个。

如果返回DENY,那么记录事件立即被抛弃,不再经过剩余过滤器;

如果返回NEUTRAL,那么有序列表里的下一个过滤器会接着处理记录事件;

如果返回ACCEPT,那么记录事件被立即处理,不再经过剩余过滤器。

写一个简单的过滤器大家就明白了。

package log.test;

import ch.qos.logback.classic.spi.ILoggingEvent;

import ch.qos.logback.core.filter.Filter;

import ch.qos.logback.core.spi.FilterReply;

public class SampleFilter extends Filter {

@Override

public FilterReply decide(ILoggingEvent event) {

if (event.getMessage().contains("let")) {

return FilterReply.ACCEPT;

} else {

return FilterReply.DENY;

}

}

}

可以选择任意几个输出源加入这个filter

最后的结果是,加入该filter的输出源只能输出Foo.doIt()中的日志了。

五、总结

logback配置比较简单,官网手册也是比较容易看懂的。除上边几种输出源之外,logback还支持输出到远程套接字服务器、 MySQL、 PostreSQL、Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等等。

第一次学习log方面的知识,如有错误,请不吝赐教。

相关资源:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值