`
gdfloyd
  • 浏览: 74170 次
  • 性别: 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意义不大,又不存在永不过时的设定,便设定为一个很长的时间(十天)来代替。

分享到:
评论

相关推荐

    采用slf4j+logback输出日志

    它的核心思想是通过接口隔离日志记录的逻辑,避免与具体实现耦合。 2. **Logback介绍** Logback是针对性能优化的日志记录工具,其设计目标是在保持高性能的同时提供更多的功能。相比于Log4j,Logback具有更快的...

    Java日志学习一:Log4j和commons-logging的关系

    使用commons-logging可以隔离日志实现的依赖,使得替换或升级日志框架变得更加容易。而Log4j由于其强大的功能和广泛的支持,常被选作commons-logging的默认实现。 在实践中,我们需要注意以下几点: 1. 配置:正确...

    slf4j-1.5.8.rar Hibernate日志接口

    SLF4J(Simple Logging Facade for Java)是Java中一个重要的日志抽象层,它为各种日志框架,如Log4j、java.util.logging、Logback等提供了一个统一的API,使得开发者可以在运行时选择具体使用的日志实现。...

    springboot395疫情隔离酒店管理系统的开发--论文pf.zip

    6. 日志记录:集成Logback日志框架,记录系统运行日志,便于问题排查。 五、系统测试与部署 系统开发完成后,需进行功能测试、性能测试和安全测试,确保系统稳定可靠。部署时,可选择Docker容器化部署,提高系统的...

    Logger.rar

    2. 日志隔离:不同模块或服务使用独立的logger,避免信息混淆。 3. 性能考虑:大量日志可能影响性能,生产环境通常只保留ERROR和WARN级别的日志。 4. 审计日志:对于安全和合规性要求高的应用,需要记录审计日志,...

    commons-logging-1.zip Spring必备Jar包

    `commons-logging`是Apache软件基金会提供的一个日志抽象层,它的主要目的是为Java应用程序提供一个简单、一致的日志接口,从而隔离底层的日志实现。通过`commons-logging`,开发者无需关心具体的日志实现,如log4j...

    slf4j-api-1.7.12.jar slf4j-log4j12-1.7.12.jar

    4. **模块化**:在大型项目中,SLF4J可以帮助隔离日志实现,使得各个模块可以独立选择日志系统。 然而,要注意的是,使用SLF4J时,你需要避免类路径中的“类装载器争抢”问题,即多个SLF4J绑定同时存在的情况,这会...

    slf4j jar包

    SLF4J的核心思想是通过使用接口来隔离日志实现,允许开发人员在部署时动态插入所需的日志系统。在运行时,SLF4J会自动查找类路径上可用的绑定,并加载相应的日志实现。例如,如果类路径上有`slf4j-log4j12.jar`,...

    打印日志和存储,单列式网络请求

    这些框架提供了多种级别(如DEBUG、INFO、WARN、ERROR)的日志记录,便于控制不同环境下的日志输出量。在实践中,我们应遵循良好的日志编写规范,包括清晰的时间戳、线程信息、调用堆栈等,以提高日志的可读性和分析...

    Springboot 示例代码

    Logback 提供了高效且功能丰富的日志解决方案,包括实时日志级别调整、日志输出格式自定义以及多种日志目标(如文件、控制台、SMTP 邮件等)。 异常处理在 SpringBoot 应用程序中通常是通过 Spring 的面向切面编程...

    12年老java程序员整理收集的面试题合集

    - 日志框架:Log4j,SLF4J,Logback等。 - 极限测试:压力测试工具JMeter的使用。 以上知识点涵盖了从Java基础到高级特性的方方面面,对于准备Java面试的程序员来说,这些都是需要深入理解和掌握的内容。通过这些...

    spring-boot-中文参考指南

    - **日志框架**:支持多种日志框架,如 Logback、Log4j2 等。 - **日志配置**:可以通过配置文件进行自定义。 - **日志级别**:控制日志记录的详细程度。 **4.5 开发 Web 应用** - **Spring Web MVC**:构建 ...

    seata-server-1.3.0.tar.gz

    - **日志配置**:可以通过调整conf/logback.xml配置日志级别和输出位置,便于调试和问题定位。 综上,"seata-server-1.3.0.tar.gz"是Seata分布式事务框架的服务器端组件,包含了部署和运行Seata Server所需的所有...

    spring-boot-elk-docker:使用ELK Stack,Slf4J和Spring-Boot进行日志聚合

    同时,可以编写一个Logstash配置文件,通过Logstash的JDBC输入插件连接到Spring-Boot应用的日志数据库,实现日志的实时收集。 6. **日志格式**:为了更好地利用ELK Stack,我们需要确保日志格式符合Logstash的解析...

    cloud技术点

    - Logback 是一个日志记录框架,用于记录应用程序的日志信息。 2. **Jenkins** - Jenkins 是一个持续集成工具,用于自动化构建和测试过程。 3. **Druid** - Druid 是一个高性能的数据库连接池管理工具。 4. **...

    阿里巴巴Java开发手册v1.2.0

    - **日志框架**:推荐使用成熟的日志框架如SLF4J和Logback,便于日志管理和聚合。 - **日志内容**:日志信息应包含必要的上下文信息,方便问题排查。 5. **性能优化** - **对象初始化**:避免在循环体内创建对象...

    alibbJava开发手册高清最新版.rar

    - 使用SLF4J与Logback/Log4j等日志框架,统一日志输出。 10. **性能优化**: - 深入理解JVM内存模型,合理设置堆大小,避免内存溢出。 - 代码性能分析,使用Profiler工具找出瓶颈。 - 调整GC策略,避免频繁Full...

    spring-boot-easy-pay-demo-master.zip

    8. **日志管理**:Spring Boot集成了日志框架,如Logback或Log4j,用于记录系统日志和支付操作日志。 9. **错误处理与异常处理**:在支付场景中,可能会涉及到各种错误和异常情况,项目可能有优雅的错误处理机制。 ...

    基于SpringBoot+Mybatis的学生信息查看与管理系统.zip

    - **Logback**:常用的日志框架,可以方便地配置日志级别和输出格式。 - **SLF4J**:简单日志门面,提供统一的日志API。 9. 版本控制: - **Git**:用于版本控制,协同开发。 这个项目不仅涵盖了SpringBoot的...

    spring整合mybatis(非springMVC)

    3. **日志级别**: 可以根据需要设置不同级别的日志输出,如DEBUG、INFO、WARN、ERROR等,以便调试或监控应用状态。 通过以上步骤,我们可以实现Spring和MyBatis的整合,同时配置事务管理和日志输出,从而构建出一个...

Global site tag (gtag.js) - Google Analytics