最近研究了一下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">测试代码如下。
相关推荐
它的核心思想是通过接口隔离日志记录的逻辑,避免与具体实现耦合。 2. **Logback介绍** Logback是针对性能优化的日志记录工具,其设计目标是在保持高性能的同时提供更多的功能。相比于Log4j,Logback具有更快的...
使用commons-logging可以隔离日志实现的依赖,使得替换或升级日志框架变得更加容易。而Log4j由于其强大的功能和广泛的支持,常被选作commons-logging的默认实现。 在实践中,我们需要注意以下几点: 1. 配置:正确...
SLF4J(Simple Logging Facade for Java)是Java中一个重要的日志抽象层,它为各种日志框架,如Log4j、java.util.logging、Logback等提供了一个统一的API,使得开发者可以在运行时选择具体使用的日志实现。...
6. 日志记录:集成Logback日志框架,记录系统运行日志,便于问题排查。 五、系统测试与部署 系统开发完成后,需进行功能测试、性能测试和安全测试,确保系统稳定可靠。部署时,可选择Docker容器化部署,提高系统的...
2. 日志隔离:不同模块或服务使用独立的logger,避免信息混淆。 3. 性能考虑:大量日志可能影响性能,生产环境通常只保留ERROR和WARN级别的日志。 4. 审计日志:对于安全和合规性要求高的应用,需要记录审计日志,...
`commons-logging`是Apache软件基金会提供的一个日志抽象层,它的主要目的是为Java应用程序提供一个简单、一致的日志接口,从而隔离底层的日志实现。通过`commons-logging`,开发者无需关心具体的日志实现,如log4j...
4. **模块化**:在大型项目中,SLF4J可以帮助隔离日志实现,使得各个模块可以独立选择日志系统。 然而,要注意的是,使用SLF4J时,你需要避免类路径中的“类装载器争抢”问题,即多个SLF4J绑定同时存在的情况,这会...
SLF4J的核心思想是通过使用接口来隔离日志实现,允许开发人员在部署时动态插入所需的日志系统。在运行时,SLF4J会自动查找类路径上可用的绑定,并加载相应的日志实现。例如,如果类路径上有`slf4j-log4j12.jar`,...
这些框架提供了多种级别(如DEBUG、INFO、WARN、ERROR)的日志记录,便于控制不同环境下的日志输出量。在实践中,我们应遵循良好的日志编写规范,包括清晰的时间戳、线程信息、调用堆栈等,以提高日志的可读性和分析...
Logback 提供了高效且功能丰富的日志解决方案,包括实时日志级别调整、日志输出格式自定义以及多种日志目标(如文件、控制台、SMTP 邮件等)。 异常处理在 SpringBoot 应用程序中通常是通过 Spring 的面向切面编程...
- 日志框架:Log4j,SLF4J,Logback等。 - 极限测试:压力测试工具JMeter的使用。 以上知识点涵盖了从Java基础到高级特性的方方面面,对于准备Java面试的程序员来说,这些都是需要深入理解和掌握的内容。通过这些...
- **日志框架**:支持多种日志框架,如 Logback、Log4j2 等。 - **日志配置**:可以通过配置文件进行自定义。 - **日志级别**:控制日志记录的详细程度。 **4.5 开发 Web 应用** - **Spring Web MVC**:构建 ...
- **日志配置**:可以通过调整conf/logback.xml配置日志级别和输出位置,便于调试和问题定位。 综上,"seata-server-1.3.0.tar.gz"是Seata分布式事务框架的服务器端组件,包含了部署和运行Seata Server所需的所有...
同时,可以编写一个Logstash配置文件,通过Logstash的JDBC输入插件连接到Spring-Boot应用的日志数据库,实现日志的实时收集。 6. **日志格式**:为了更好地利用ELK Stack,我们需要确保日志格式符合Logstash的解析...
- Logback 是一个日志记录框架,用于记录应用程序的日志信息。 2. **Jenkins** - Jenkins 是一个持续集成工具,用于自动化构建和测试过程。 3. **Druid** - Druid 是一个高性能的数据库连接池管理工具。 4. **...
- **日志框架**:推荐使用成熟的日志框架如SLF4J和Logback,便于日志管理和聚合。 - **日志内容**:日志信息应包含必要的上下文信息,方便问题排查。 5. **性能优化** - **对象初始化**:避免在循环体内创建对象...
- 使用SLF4J与Logback/Log4j等日志框架,统一日志输出。 10. **性能优化**: - 深入理解JVM内存模型,合理设置堆大小,避免内存溢出。 - 代码性能分析,使用Profiler工具找出瓶颈。 - 调整GC策略,避免频繁Full...
8. **日志管理**:Spring Boot集成了日志框架,如Logback或Log4j,用于记录系统日志和支付操作日志。 9. **错误处理与异常处理**:在支付场景中,可能会涉及到各种错误和异常情况,项目可能有优雅的错误处理机制。 ...
- **Logback**:常用的日志框架,可以方便地配置日志级别和输出格式。 - **SLF4J**:简单日志门面,提供统一的日志API。 9. 版本控制: - **Git**:用于版本控制,协同开发。 这个项目不仅涵盖了SpringBoot的...
3. **日志级别**: 可以根据需要设置不同级别的日志输出,如DEBUG、INFO、WARN、ERROR等,以便调试或监控应用状态。 通过以上步骤,我们可以实现Spring和MyBatis的整合,同时配置事务管理和日志输出,从而构建出一个...