Java程序员修炼之道 之 Logging(1/3) - Logback 配置

本文阐述了Java程序员为何需要重视日志,并选择了Logback作为日志框架,详细介绍了Logback的配置,包括依赖包导入、与遗留日志框架的兼容性处理,以及Logback配置文件的使用和编写策略。

写在前面的话:

作为《Java程序员修炼之道》博文的第一个主题Logging,我计划中按照如下三篇来写:

  1. Logback的简单介绍和配置
  2. 在Java代码中如何使用SLF4J来写日志以及写日志的要点
  3. 作为一个程序员,在日常工作中如何分析和挖掘Log。

PS:默认生成的目录不对,仔细检查过了,我的h1,h2,h3,h4用的都没错。

1. 缘起

写代码中的日志是一个除了用代码实现功能之外最基础最基础的一个技能了,是一个必须掌握的技能。但是目前为止,关于如何日志的文章和书籍还是不多。

1.1 写日志的必要性

碰到QA提的一个bug的时候,我见识过两种方式的答复:a)请给我重现步骤和重现数据;b)把当时的日志给我。答复前者的,一般需要花很多时间去找问题出现在那里,如果是别人开发的模块的话,花费的时间更多。答复后者的,一般能很快的找到出问题的点,然后就可以开始进入修复的流程。

从概念上来说:日志是一个可运行的、可维护的软件的基础组成部分;通过日志,我们可以了解软件系统在运行中的实时状态,历史状态和异常状态等。一个没有良好日志的软件是所有人的噩梦。想象一下,你开发中使用的框架,比如Spring之类的,如果没有日志的话,你还会用吗?(感谢@ix_fly网友的这个建议)

如果你不想给自己找麻烦,你还是把日志好好写写。

1.2 为什么选Logback?

原因有俩:

  1. 我最近几年用的都是Logback
  2. 在前几天Log4j 2.0出来之前,logback的Logger用得比较爽
不过不管是Logback、Log4j还是别的什么Log框架,后继文章里面的关于写Log的一些技巧和建议都是适用的。

2. 如何配置Logback

下面会简单介绍一下Logback的配置,适用于开始配置和开始入门,适用于一般情况下的使用,如果想了解更多的信息,建议看看Logback的官方文档,写得很不错的。 微笑 http://logback.qos.ch/manual/introduction.html

2.1 Logback简单介绍

简单来说就是Log4j 1流行了,发现有一些问题是无法解决的,于是又出来了Logback,在Log4j的基础上提升了性能,提高了功能等等。不过前几天有出来了Log4j 2,据说是相对于Logbak来说又提升了性能提高了功能。

2.2 关于SLF4J和Logback

SLF4J(slf4j.org)又称Simple Logging Facade for Java,是一个通用的logging接口,它试图一统Logging框架的天下,兼容了(Log4j 1, java.util.logging和Jakarta Commons Logging)这三个最流行的Logging框架。Logback就是SLF4J的默认实现。

2.3 依赖包导入

下文以Logback 1.1.2及slf4j1.7.6版本为例子。一般情况下,你按照我下面说的就可以了,如果不行的话,你可以去翻翻英文的文档:http://logback.qos.ch/setup.html。

2.3.1 一般程序

Maven版

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.2</version>
</dependency>

非Maven版

http://logback.qos.ch/dist/logback-1.1.2.zip下载下来之后,在其根目录下有logback-core-1.1.2.jarlogback-classic-1.1.2.jar这俩个Jar,在logback-examples\lib下有slf4j-api-1.7.6.jar这个jar,把这三个Jar添加到你的代码包路径中。

2.3.2 非独立运行程序

如果你做的是一个Lib或者API,那么你就不应该依赖于具体的slf4j实现。所以你对logback的依赖应该是在运行测试代码的时候,具体实现方式如下文所示:

Maven版

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.6</version>
</dependency>
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.1.2</version>
	<scope>test</scope>
</dependency>

当然了你是要把版本信息放在pom.xml中的<dependencies>还是<dependencyManagement>里面就你自己决定吧。

非Maven版

在发布的时候不要把只有Logback才用到jar打包进你的发布程序里面。(如果觉得绕口再多读两遍)

2.4 与遗留Logging框架兼容

目前行业除了Logback之外,广泛使用的还有其他四种Logging框架:

Log4j 2因为是刚出来的,目前SLF4J对其的兼容性还未知,对于其他的三种框架,SLF4J都提供了兼容性的支持。下面介绍了如何让Logbak兼容这些框架,另外,也可以阅读官方说明:http://www.slf4j.org/legacy.html

2.4.1 兼容Log4j 1和Apache Commons Logging

SLF4J对于Log4J 1和Apache commons Logging的支持方式是提供了实现Log4j和Apache commons Logging接口的SLF4J实现。使用方式是

  1. 去取对Log4J和Apache commons Logging的Jar包的引用
  2. 引入SLF4J的对应接口的实现包。

2.4.1.1 移除引用
如果你的系统是直接的使用了Log4j或者Apache commons Logging框架的话,你可以直接把对他们的引用去掉就可以了。如果是你所引用的第三方包里面引用了Log4j或者Apache commons Logging,可以使用<exclusions>标签去掉对他们的引用,如下所示:
<dependency>
  <groupId>org.springframework.ldap</groupId>
  <artifactId>spring-ldap-core</artifactId>
  <exclusions>
  	<exclusion>
  		<artifactId>commons-logging</artifactId>
  		<groupId>commons-logging</groupId>
  	</exclusion>
  </exclusions>
</dependency>

如何找到哪些第三方包引用了Log4j或者Apache commons Logging呢?有俩个方法:
  • 使用 mvn dependency:tree 命令,如下图所示,可以看出需要在org.springframework.ldap:spring-ldap-core中排除掉对Apache commons Logging的引用。

  • 第二种方式是使用Eclipse的m2e Maven插件。如下图所示,打开pom.xml文件后,选择Dependency Hierarchy标签,然后在Filter中输入logging或者log4j进行过滤,在左侧的Dependency Hierarchy中使用右键菜单就可以自动过滤了。

2.4.1.2 Maven导入对应的SLF4J实现包

<!-- Log4j 的SLF4J 实现 -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>log4j-over-slf4j</artifactId>
	<version>1.7.6</version>
</dependency>
<!-- Apache commons Logging 的SLF4J实现 -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jcl-over-slf4j</artifactId>
	<version>1.7.6</version>
</dependency>

2.4.1.3 非Maven版导入对应的SLF4J实现包

直接删除掉log4j-1.**.jar和commons-logging-1.**.jar文件,把http://slf4j.org/dist/slf4j-1.7.6.zip下载下来,把压缩包里的log4j-over-slf4j-1.7.6.jar或者(和)jcl-over-slf4j-1.7.6.jar文件放到classpath中。

2.4.2 兼容java.util.logging

SLF4J的jul-to-slf4j模块实现了一个java.util.logging handler,该handler会把对java.util.logging的调用都转化成对SLF4J实现的调用。所以需要以下俩个步骤:

  1. 导入jul-to-slf4j模块
  2. 启用jul-to-slf4j模块

2.4.2.1 导入jul-to-slf4j模块maven版

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jul-to-slf4j</artifactId>
	<version>1.7.6</version>
</dependency>
2.4.2.2 导入jul-to-slf4j模块非Maven版

http://slf4j.org/dist/slf4j-1.7.6.zip下载下来,把压缩包里的jul-to-slf4j-1.7.6.jar放到classpath中。

2.4.2.3 启用jul-to-slf4j模块

logging.properties中添加如下一行:

handlers = org.slf4j.bridge.SLF4JBridgeHandler

2.5 Logback 配置文件简介

2.5.1 Logback配置文件名称、位置和编写策略

Logback 会按照如下的顺序在classpath中读取配置文件,如果读取到任何一个,则停止继续寻找。

  1. logback.groovy 这个是使用groovy语法的配置文件
  2. logback.-test.xml
  3. logback.xml
如果以上三个文件都没能在classpath中找到,则会使用 默认配置。默认配置如下:
  • 输出格式
    %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
  • 输出方向:System.out
  • 输出级别:Debug
在我的经验中,基本上按照如下策略来配置Logback文件:
对于Maven项目
  • src/test/resources目录中放置logback-test.xml,该配置文件中log的输出是到输出到console,对于本应用的代码是debug级别,对于其他的是info级别。
  • src/main/resources目录中放置logback.xml,该配置文件中log的输出是输出到文件中,该文件每日滚动压缩打包备份,对于本应用的代码是info级别,对于其他的是warn级别。
对于非Maven项目
近10年里,我印象中没有做过非Maven的项目,所以提供不了经验,只能说说我知道的,供大家参考吧。
  • 对于web项目,logback.xml放置到WEB-INF/classes目录下,配置方式建议参考上面说的
  • 对于其他项目,放置到应用启动运行时的classpath根目录下

2.5.2 Logback配置文件示例

介绍Logback配置文件如何编写的有很多,我就不重复了,大家可以自己搜索一下。下面有两篇我觉得写得不错的,大家可以看一下:
当然了,写得最好的是官方文档:  http://logback.qos.ch/manual/introduction.html

公司项目的配置文件不方便贴出来,下面是我自己的个人项目中用的,加了一些注释,供大家参考。
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
	<!--Appendar详解: http://logback.qos.ch/manual/appenders.html#RollingFileAppender -->
	<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <!-- 当前Log文件名 -->
		<file>ldap-pwd.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!-- 非当天的Log文件压缩备份为 archive/ldap-pwd.2014-08-10.zip -->
			<fileNamePattern>archive/ldap-pwd.%d{yyyy-MM-dd}.zip</fileNamePattern>
			<!-- 超过30天的备份文件会被删除 -->
			<maxHistory>30</maxHistory>
		</rollingPolicy>

		<layout class="ch.qos.logback.classic.PatternLayout">
			<!-- 格式说明:http://logback.qos.ch/manual/layouts.html#ClassicPatternLayout -->
			<Pattern>%d [%thread] %-5level %40logger{40} - %msg%n</Pattern>
		</layout>
	</appender>

	<logger name="cn.justfly.training.logging" level="info" />

	<root level="warn">
		<appender-ref ref="FILE" />
	</root>
</configuration>
logback-test.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>%d [%thread] %-5level %40logger{40} - %msg%n</pattern>
		</encoder>
	</appender>
	<logger name="cn.justfly.training.logging" level="debug" />

	<root level="info">
		<appender-ref ref="Console" />
	</root>
</configuration>



/Users/dushaojun/Library/Java/JavaVirtualMachines/ms-17.0.15/Contents/Home/bin/java -Dproject.name=aidemo12345 -Ddruid.load.spifilter.skip=true -DlimitTime=100 -Dhsf.consumer.init.accumulate.timeout=3000 -Dspring.hsf.max-wait-address-time=-1 -Dserver.tomcat.additional-tld-skip-patterns=*.jar -Dconfigserver.client.timerpersist=false -Dconfigserver.client.timerpersist.initMins=1 -Dconfigserver.client.cacheDelayTime=1 -javaagent:/Users/dushaojun/.thub-tool/isimu-sandbox/boot/isimu-boot.jar=/Users/dushaojun/.thub-tool/isimu-sandbox/ -agentpath:/Users/dushaojun/.thub-tool/isimu-sandbox/native/libisimu-aarch64.dylib -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=56004:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/dushaojun/Desktop/aidemo12345/target/classes:/Users/dushaojun/.m2/repository/org/springframework/boot/spring-boot-starter-web/3.5.4/spring-boot-starter-web-3.5.4.jar:/Users/dushaojun/.m2/repository/org/springframework/boot/spring-boot-starter/3.5.4/spring-boot-starter-3.5.4.jar:/Users/dushaojun/.m2/repository/org/springframework/boot/spring-boot/3.5.4/spring-boot-3.5.4.jar:/Users/dushaojun/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/3.5.4/spring-boot-autoconfigure-3.5.4.jar:/Users/dushaojun/.m2/repository/org/springframework/boot/spring-boot-starter-logging/3.5.4/spring-boot-starter-logging-3.5.4.jar:/Users/dushaojun/.m2/repository/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar:/Users/dushaojun/.m2/repository/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar:/Users/dushaojun/.m2/repository/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar:/Users/dushaojun/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.24.3/log4j-to-slf4j-2.24.3.jar:/Users/dushaojun/.m2/repository/org/apache/logging/log4j/log4j-api/2.24.3/log4j-api-2.24.3.jar:/Users/dushaojun/.m2/repository/org/slf4j/jul-to-slf4j/2.0.17/jul-to-slf4j-2.0.17.jar:/Users/dushaojun/.m2/repository/j
07-31
<think>我们被要求生成一个Java应用程序启动命令,其中包含多个JVM参数和配置。这些参数可能用于调试、性能调优或启用特定功能。 常见的JVM参数包括: - 内存设置:如-Xms(初始堆大小)、-Xmx(最大堆大小) - 垃圾回收器设置:如-XX:+UseG1GC(使用G1垃圾回收器) - 调试参数:如-agentlib:jdwp(用于远程调试) - 系统属性:使用-D设置,如-Dkey=value - 其他性能调优参数:如-XX:+UseStringDeduplication(字符串去重)等 我们将构建一个示例命令,其中包含多个不同类型的参数。 注意:由于参数众多,我们只选择一些常用且具有代表性的参数进行演示。 示例命令: java -Xms512m -Xmx1024m -XX:+UseG1GC -XX:+UseStringDeduplication -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Dspring.profiles.active=dev -Dlog4j.configurationFile=/path/to/log4j2.xml -jar myapp.jar 解释: - -Xms512m: 设置初始堆大小为512MB - -Xmx1024m: 设置最大堆大小为1024MB - -XX:+UseG1GC: 使用G1垃圾回收器 - -XX:+UseStringDeduplication: 开启字符串去重(需要G1GC) - -agentlib:jdwp=...: 开启远程调试,监听5005端口,不挂起启动(suspend=n表示JVM启动后不等待调试器连接,suspend=y则等待) - -Dspring.profiles.active=dev: 设置系统属性spring.profiles.active为dev,用于Spring框架指定激活的配置文件 - -Dlog4j.configurationFile=/path/to/log4j2.xml: 设置log4j2的配置文件路径 - -jar myapp.jar: 运行可执行的jar包 注意:参数顺序通常没有严格要求,但有些参数可能有依赖关系(比如UseStringDeduplication需要先启用G1GC)。另外,如果使用模块化(Java 9+),可能需要额外的参数。 另外,如果需要启用JMX监控,可以添加: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false 但是注意,这样设置JMX是不安全的,仅建议在安全网络环境下使用。生产环境中应启用认证和SSL。 根据用户需求,可能还需要其他参数,如: - 设置时区:-Duser.timezone=GMT+08:00 - 设置编码:-Dfile.encoding=UTF-8 因此,我们可以组合这些参数来满足不同的需求。 最后,我们生成相关问题。</think>### Java应用程序启动命令(含多个JVM参数) 以下是包含调试、性能调优和功能启用的完整Java应用程序启动命令示例: ```bash java \ # 内存设置 -Xms512m -Xmx2048m -XX:MaxMetaspaceSize=512m \ # 垃圾回收配置 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ParallelRefProcEnabled \ # 调试参数 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \ # 性能监控 -Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=9010 \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.authenticate=false \ # 功能开关 -Dspring.profiles.active=prod \ -Dapp.feature.new_payment_gateway=true \ # 日志配置 -Dlogback.configurationFile=/etc/app/logback.xml \ # 系统级调优 -XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=/var/log/app/heapdump.hprof \ -XX:+UseStringDeduplication \ -XX:NativeMemoryTracking=summary \ # 应用入口 -jar /opt/app/application.jar \ # 应用参数 --db.host=mysql-prod \ --cache.enabled=true ``` #### 关键参数说明: 1. **内存配置** - `-Xms512m`:初始堆内存512MB - `-Xmx2048m`:最大堆内存2GB - `-XX:MaxMetaspaceSize=512m`:元空间上限 2. **垃圾回收优化** - `-XX:+UseG1GC`:启用G1垃圾收集器 - `-XX:MaxGCPauseMillis=200`:目标最大GC停顿时间 3. **调试支持** - `-agentlib:jdwp...`:启用远程调试(端口5005) - `-XX:+HeapDumpOnOutOfMemoryError`:OOM时自动生成堆转储 4. **性能监控** - JMX参数:启用JMX监控(端口9010) - `-XX:NativeMemoryTracking=summary`:跟踪本地内存使用 5. **功能开关** - `-Dspring.profiles.active=prod`:激活Spring生产环境配置 - `-Dapp.feature.new_payment_gateway=true`:功能标志位示例 #### 最佳实践建议: 1. 生产环境应启用JMX认证: ```bash -Dcom.sun.management.jmxremote.authenticate=true \ -Dcom.sun.management.jmxremote.password.file=/etc/jmx_pass ``` 2. 敏感参数(如密码)建议通过环境变量传递: ```bash -Ddb.password=${DB_PASSWORD} ``` 3. 使用工具验证参数有效性: ```bash java -XX:+PrintFlagsFinal -version | grep MaxHeapSize ``` > 注:参数顺序不影响功能,但建议按功能模块分组提高可读性[^1]。实际参数需根据具体应用需求调整,如高吞吐场景可考虑`-XX:+UseParallelGC`,低延迟场景建议`-XX:+UseZGC`。
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值