`
gdfloyd
  • 浏览: 73525 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Logback 日志隔离 -把日志输出到不同目标

 
阅读更多

最近研究了一下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">
 测试代码如下。 

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Test {
    public static void main(String[] args) {
		
	Logger domainLogger1 = 
			LoggerFactory.getLogger("xxx.yyy.zzz.domain1");
	Logger domainLogger2 = 
			LoggerFactory.getLogger("xxx.yyy.zzz.domain2");	
	Logger domainLogger3 = 
			LoggerFactory.getLogger("xxx.yyy.zzz.domain3");
		
	domainLogger1.info("test logger message is specified here");
	domainLogger1.warn("warn logger message is specified here");

	domainLogger2.info("test logger message is specified here");
	domainLogger2.warn("warn logger message is specified here");

	domainLogger3.info("test logger message is specified here");
	domainLogger3.warn("warn logger message is specified here");

 

 

可以改变myAppDomain.properties文件中的值来查看日志输出文件到不同的文件。

 

 

Ddbmonitor.aspect.aspect2.log.path=c:\logback\test\aspect2.log
-Ddbmonitor.aspect.log.defaultSingleLog=True
  

 

最后提一下的timeout属性。这个属性用来管理Appender的生命周期。对于根据不同user来划分日志的web服务器具有意义。海量用户数量意味着需要销毁长时间不用的Appender以释放资源。对于这个demo意义不大,又不存在永不过时的设定,便设定为一个很长的时间(十天)来代替。

分享到:
评论

相关推荐

    logback-classic-1.2.3-API文档-中英对照版.zip

    赠送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-classic-1.2.3.jar

    logback-core-1.2.11.jar

    logback-core-1.2.11.jar

    logback-cfca-jdk1.6-3.1.0.0.jar

    logback-cfca-jdk1.6-3.1.0.0.jar

    logback-classic-1.2.10-API文档-中文版.zip

    赠送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.2.6-API文档-中文版.zip

    赠送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

    logback-classic-1.2.11.jar

    logback-core-1.2.3-API文档-中英对照版.zip

    赠送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文档-中文(简体)-...

    logback-ext-spring-0.1.1

    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去下载。 注意:...

    logback-classic-1.2.3-API文档-中文版.zip

    赠送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; 包含翻译后...

    logback-core-1.2.3-API文档-中文版.zip

    赠送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

    logback-classic-1.1.2.jar 资源共享,有需要其他jar包的可以在评论留言,看到后我会陆续上传。

    logback-core-1.2.9.jar

    logback-core-1.2.9.jar

    logback-core-1.2.10-API文档-中英对照版.zip

    赠送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文档...

    logback-core-1.2.10-API文档-中文版.zip

    赠送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文档...

    logback-classic-1.2.10-API文档-中英对照版.zip

    赠送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-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-core-1.1.11.jar

    logback-android-1.1.1-2

    logback-android-1.1.1-2

    logback-core-1.2.6-API文档-中文版.zip

    赠送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文档:...

Global site tag (gtag.js) - Google Analytics