最近研究了一下Logback这个日志框架,有个功能我是看重的,应用程序能够根据自己的领域配置属性来加载配置Logback, 实现根据运行时信息,把不同日志的输出的目标地点。在Log4j下,要实现这个复杂功能需要自己扩展代码实现,而在logback下现在只需要简单扩展和配置一下便可以了。另外,Logback可以自动清理过期的归档的日志,而Log4j仅仅支持滚动,需要应用或者系统层面来进行额外清理工作。我自己做了一个还算复杂的demo, 实现如下的功能:
如果存在应用程序业务领域或者运行模块的的日志文件路径,则日志记录到这个独立的文件,否则日志记录默认日志路径。
默认日志文件根据配置,来划分是默认为所有业务领域所共享的单一文件,还是个业务领域独立的默认文件。
默认日志路径为当前位于当前运行用户下的OS的Home Path下.
把必须的jar包包含到classpath下,如果在maven下面,可以如下。Logback貌似绑定了SLF4J作为顶层日志API, 这样配置会自动加载SL4J这个Dependency.
<Project> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency> </dependencies> </project>
把logback.xml放置到classpath根目录下便可。这个默认加载路径与log4.xmlj类似。Logback仅仅支持XML或者goovy方式进行配置,像Log4j那种属性文件配置不能被logback直接使用。logback.xml配置如下。如果熟悉Log4j配置,这个Logback配置很容易看懂。
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"> <property file="src/main/java/xxx/yyy/zzz/myAppDomain/myAppDomain.properties" /> <define name="appDomaintDefaultSingleLogPath" class="xxx.yyy.zzz.appDomain.MyAppDoaminDefaultSingleLogPathPropertyDefiner"> <defaultSingleLog>${xxx.yyy.zzz.appDomain.defaultSingleLog}</defaultSingleLog> <singleLogPath>${xxx.yyy.zzz.appDomain.log.defaultSinglePath}</singleLogPath> <userHomePath>${user.home}</userHomePath> </define> <appender name="SIFT_APP_DOMAIN" class="ch.qos.logback.classic.sift.SiftingAppender" timeout="10 days"> <discriminator class="xxx.yyy.zzz.MyAppDomainLoggerNameBasedDiscriminator" /> <sift> <property name="myAppDomainLogPath" value="${xxx.yyy.zzz.${appDomainName}.log.path:-${appDomainDefaultSingleLogPath:-${user.home}/myAppDomain/${appDomainName}.log}}" /> <appender name="myAppDomain_ROLLING_FILE-${appDomainName}" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${myAppDomainLogPath}</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${myAppDomainLogPath}.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>${xxx.yyy.zzz.myAppDomain.log.retention:-5}</maxHistory> </rollingPolicy> <encoder> <pattern>${xxx.yyy.zzz.myAppDomain.${appDomainName}.log.outputPattern:-%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %c{0} - %m%n}</pattern> </encoder> </appender> </sift> </appender> <logger name ="xxx.yyy.zzz.myAppDomain" level="INFO"> <appender-ref ref="SIFT_APP_DOMAIN" /> </logger> </configuration>
下面解释一下XML配置的意思。
Configuration作为XML根节点包含所有的配置信息,其中debug属性打开后,如果配置有误,可以在Console中看到logback加载配置时候的一下重要指示信息,方便配置修改调试。
先来看property节点。Logback支持与Ant的build.xml类似的部分配置语法。可以在xml定义一些自定义的属性。在这里从外部导入外部业务领域的配置文件让logback加载到。在后面的xml中可以引用到,转化为logback的配置。可以看到,XML中使用${xxx}获取变量值的替换(value subsitution)。这个值首先从配置文件进行查找,如果找不到,会在上下文范围查找,最后会在系统属性中查找(详细解释参照这里:http://logback.qos.ch/manual/configuration.html#variableSubstitution)。
再来看define节点,我用自定义属性的封装了默认单一日志路径的获取逻缉。name属性指定该属性名,clas属性指定要实例化的类。在类中添加相应的子属性Set方法,Logback便可根据XML的子节点的值来加载自定义的属性类中去。主要是要实现其getPropertyValue的方法来告诉logback如何获得值。
import ch.qos.logback.core.PropertyDefinerBase; public class MyAppDoaminDefaultSingleLogPathPropertyDefiner extends PropertyDefinerBase { public static final String DEFAULT_SINGLE_LOGPATH = "myAppDomain/myAppDoamin.log"; private boolean defaultSingleLog = true; private String singleLogPath; private String userHomePath; public void setDefaultSingleLog(boolean defaultSingleLog) { this.defaultSingleLog = defaultSingleLog; } public void setSingleLogPath(String singleLogPath) { this.singleLogPath = singleLogPath; } public void setUserHomePath(String userHomePath) { this.userHomePath = userHomePath; } @Override public String getPropertyValue() { if (defaultSingleLog) { if (singleLogPath != null) { return singleLogPath; } if (userHomePath == null) { addError("The \"userHomePath\" property must be set."); return null; } return userHomePath + DEFAULT_SINGLE_LOGPATH; } return null; } }
接着来看Appender节点,这个是核心。详细参看官方文档(http://logback.qos.ch/manual/appenders.html#SiftingAppender)。默认是内置的MDCBasedDiscriminator,根据MDC来决定实际运行值,不是我所需要的,因此,自己扩展了一个区分器并在class属性中指定。区分器根据这个唯一的日志名称来划分不同的Appender,其实现相信用这个区分器返回的值来作为内部维护的HashMap的Key。getKey方法返回的是这个HashMap的唯一键,这个键可以在Appender的XML配置中作为变量替换的键。SiftingAppender根据这个区分器去确定不同的Appender实例,把日志事件派发到相应的Appender,并管理这些Appender的生命周期。每个Appener包含不同的日志文件路径,达到输出文件分离目的。在我的实现中getDiscriminatingValue是通过返回的日志名称最底层名字来作为区分值。
public class AppDomainLoggerNameBasedDiscriminator extends AbstractDiscriminator<ILoggingEvent> { public static final String KEY = "appDomainName"; public AspectLoggerNameBasedDiscriminator() { init(); } private void init() { .... // TODO } @Override public String getDiscriminatingValue(ILoggingEvent e) { String loggerName = e.getLoggerName(); int dotIndex = loggerName.lastIndexOf('.'); if (dotIndex != -1 && dotIndex < loggerName.length() - 1) { return loggerName.substring(dotIndex + 1); } return "xxx.yyy.zzz.myAppDomain.default"; } @Override public String getKey() { return KEY; } }
在sift节点下定义了业务领域的日志文件路径属性。这个属性根据区分器的值和业务领域配置组合进行评估。这里可以见到Logback配置的强大之处,支持嵌套配置和默认值。变量的键可以先变量替换来获得。“:-”表示如果当前键的计算结果为空的化,则返回默认值。
<property name="myAppDomainLogPath" value="${xxx.yyy.zzz.${myAppDomain}.log.path:-${appDomainDefaultSingleLogPath:-${user.home}/myAppDomain/${appDomainName}.log}}" /> <appender name="myAppDomain_ROLLING_FILE-${appDomainName}" class="ch.qos.logback.core.rolling.RollingFileAppender">测试代码如下。
相关推荐
赠送jar包:logback-classic-1.2.3.jar; 赠送原API文档:logback-classic-1.2.3-javadoc.jar; 赠送源代码:logback-classic-1.2.3-sources.jar; 包含翻译后的API文档:logback-classic-1.2.3-javadoc-API文档-...
logback-classic-1.2.3.jar
logback-core-1.2.11.jar
logback-cfca-jdk1.6-3.1.0.0.jar
赠送jar包:logback-classic-1.2.10.jar; 赠送原API文档:logback-classic-1.2.10-javadoc.jar; 赠送源代码:logback-classic-1.2.10-sources.jar; 赠送Maven依赖信息文件:logback-classic-1.2.10.pom; 包含...
赠送jar包:logback-classic-1.2.6.jar; 赠送原API文档:logback-classic-1.2.6-javadoc.jar; 赠送源代码:logback-classic-1.2.6-sources.jar; 赠送Maven依赖信息文件:logback-classic-1.2.6.pom; 包含翻译后...
logback-classic-1.2.11.jar
赠送jar包:logback-core-1.2.3.jar; 赠送原API文档:logback-core-1.2.3-javadoc.jar; 赠送源代码:logback-core-1.2.3-sources.jar; 包含翻译后的API文档:logback-core-1.2.3-javadoc-API文档-中文(简体)-...
https://github.com/qos-ch/logback-extensions/wiki/Spring https://github.com/qos-ch/logback-extensions/tree/master/spring/src/main/java/ch/qos/logback/ext/spring/web 你也可以自己用maven去下载。 注意:...
赠送jar包:logback-classic-1.2.3.jar; 赠送原API文档:logback-classic-1.2.3-javadoc.jar; 赠送源代码:logback-classic-1.2.3-sources.jar; 赠送Maven依赖信息文件:logback-classic-1.2.3.pom; 包含翻译后...
赠送jar包:logback-core-1.2.3.jar; 赠送原API文档:logback-core-1.2.3-javadoc.jar; 赠送源代码:logback-core-1.2.3-sources.jar; 赠送Maven依赖信息文件:logback-core-1.2.3.pom; 包含翻译后的API文档:...
logback-classic-1.1.2.jar 资源共享,有需要其他jar包的可以在评论留言,看到后我会陆续上传。
logback-core-1.2.9.jar
赠送jar包:logback-core-1.2.10.jar; 赠送原API文档:logback-core-1.2.10-javadoc.jar; 赠送源代码:logback-core-1.2.10-sources.jar; 赠送Maven依赖信息文件:logback-core-1.2.10.pom; 包含翻译后的API文档...
赠送jar包:logback-core-1.2.10.jar; 赠送原API文档:logback-core-1.2.10-javadoc.jar; 赠送源代码:logback-core-1.2.10-sources.jar; 赠送Maven依赖信息文件:logback-core-1.2.10.pom; 包含翻译后的API文档...
赠送jar包:logback-classic-1.2.10.jar; 赠送原API文档:logback-classic-1.2.10-javadoc.jar; 赠送源代码:logback-classic-1.2.10-sources.jar; 赠送Maven依赖信息文件:logback-classic-1.2.10.pom; 包含...
logback-classic-1.1.11.jar logback-classic-1.1.11.jar logback-classic-1.1.11.jar logback-classic-1.1.11.jar
logback-core-1.1.11.jar logback-core-1.1.11.jar logback-core-1.1.11.jar logback-core-1.1.11.jar
logback-android-1.1.1-2
赠送jar包:logback-core-1.2.6.jar; 赠送原API文档:logback-core-1.2.6-javadoc.jar; 赠送源代码:logback-core-1.2.6-sources.jar; 赠送Maven依赖信息文件:logback-core-1.2.6.pom; 包含翻译后的API文档:...