关于Java的日志输出
1. 日志门面库
在log4j之后,标准的java.util.logging被创建了,但是由于log4j更易于使用,它并不完全普及。
因此需要一个不依赖于特定日志库的接口。
当每个库都有不同的日志库时,将日志记录到一个文件变得很困难,所以基本上最好使用SLF4J。
1-1. SLF4J(简单日志外观 for Java)
SLF4J + logback或SLF4J + Log4j2的配置似乎很常见。
这似乎是为了解决不易使用的Commons Logging而创建的,如果没有使用SLF4J的理由,似乎使用它是个不错的选择。
这个许可证是MIT?
必备的JAR
API (必须):slf4j-api-*.jar
日志实现的绑定(任选其一)
Log4j:slf4j-log4j12-*.jar
Log4j2:log4j-slf4j-impl-*.jar
Logback:logback-classic-*.jar
java.util.logging:slf4j-jdk14-*.jar
1-1-1. 适配器、桥接器
jcl代表着Jakarta Commons Logging,jul代表着java.util.logging。
1-1-2. 可参考的网站。
1-2. 公共日志记录
Commons Logging和JDK标准的日志记录示例
一对一导引
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
1-2-2. 属性文件
handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler
.level=FINEST
# FileHandlerの設定
java.util.logging.FileHandler.pattern=C:/sample/sample.log
java.util.logging.FileHandler.limit=500000
java.util.logging.FileHandler.count=3
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s\r\n
level可以设置如下内容。
严重 (最高值):故障
警告 (警告):潜在问题
信息:消息信息
配置:静态配置消息
良好:跟踪信息
较好:相当详细的跟踪消息
最好 (最低值):非常详细的跟踪消息
还有全选和关闭选项。
认为只使用以下三个级别会更容易理解:
错误:严重
信息:信息
调试:最详细
1-2-3。源代码 (Yī-èr-.
private static Log _log = LogFactory.getLog(Sample.class);
_log.debug("デバッグメッセージ");
_log.info("インフォメッセージ");
_log.error("エラーメッセージ");
一二四。用法。
在启动时,指定参数“-Djava.util.logging.config.file=文件路径”。
1-2-5.疑难解答
在标准输出中没有输出调试信息。
需要添加”java.util.logging.ConsoleHandler.level=FINEST”。
在文件中进行追加→添加”java.util.logging.FileHandler.append=true”。
我只想为特定的课程指定详细日志。
→请在「1-2-6」中记录。
1-2-6. 我只想为特定的类指定详细日志。
package logtest.sub1;
public class Sub1 {
private static Log _log = LogFactory.getLog(Sub1.class);
由于在每个源文件上指定了自己的类,因此应将属性文件中的类设置为以下所示。
logtest.sub1.Sub1.level=WARNING
logtest.sub1.Sub1.handlers=java.util.logging.ConsoleHandler
1-3. JBoss 日志记录
2. 日志输出库
2-1. Java的util.logging
有关2-1-1.logging.properties的信息
以下是参数内容:
1. 日期
2. 表示调用方的字符串。包含包名和类名+方法名
3. 记录器的名称,包含包名和类名
4. 日志级别
5. 消息
6. 抛出异常
参考链接:https://docs.oracle.com/javase/jp/8/docs/api/java/util/logging/SimpleFormatter.html
2-2. Log4j
2-2. 日志记录工具Log4j
建议停止支持,更好使用log4j2。
2-2-1.进行安装。
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2-2-2. 设置文件
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p %c{1} - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=log/log4j.log
log4j.appender.file.Append=true
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %5p %c{1} - %m%n
log4j.rootLogger=debug, stdout, file
关于 ConversionPattern
· 类名:”%C”。使用”%C{1}”可省略包名。
· 方法名:%M
· 进程ID 不支持
· 线程ID 不支持
将日志文件分成多个文件
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%C{1} %M %t %d %5p %c{1} - %m%n
### direct messages to file mylog.log ###
log4j.appender.file1=org.apache.log4j.FileAppender
log4j.appender.file1.File=log/log4j1.log
log4j.appender.file1.Append=true
log4j.appender.file1.layout=org.apache.log4j.PatternLayout
log4j.appender.file1.layout.ConversionPattern=%d %5p %c{1} - %m%n
### direct messages to file mylog.log ###
log4j.appender.file2=org.apache.log4j.FileAppender
log4j.appender.file2.File=log/log4j2.log
log4j.appender.file2.Append=true
log4j.appender.file2.layout=org.apache.log4j.PatternLayout
log4j.appender.file2.layout.ConversionPattern=%d %5p %c{1} - %m%n
#
log4j.logger.kero.domain=debug, file1
log4j.logger.kero.view=debug, file2
log4j.logger.kero.infrastructure=debug, file2
log4j.rootLogger=debug, stdout
2-2-3. 指定属性文件
在Java的启动选项中指定如下。
- プロパティファイル
将以下内容以中文翻译并改写为:
-Dlog4j.configuration=file:/C:/tmp/mylog4j.properties
-Dlog4j.configuration=file:/C:/tmp/mylog4j.properties 可以改写为:-Dlog4j配置=文件:/C:/tmp/mylog4j.properties
- XMLファイル
-Dlog4j.configuration=file:/C:/tmp/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator
-使用以下方式配置log4j:-Dlog4j.configuration=file:/C:/tmp/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator
2-3. Log4j2
2-3. Log4j2
2-3-1. 安装
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
2-3-2. 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration>
<Configuration status="OFF">
<Properties>
<Property name="ptn">%d{yyyy-MM-dd HH:mm:ss.SSS} p=%-5p c=%c t=%t C=%C F=%F M=%M L=%L m=%m %n</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${ptn}" />
</Console>
<RollingFile name="file" fileName="log/log4j2.log"
filePattern="log/%d{yyyyMM}/log4j2_%d{yyyyMMdd}_%i.log">
<PatternLayout pattern="${ptn}" />
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="2 MB" />
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingFile>
</Appenders>
<Loggers>
<Root level="all">
<AppenderRef ref="console" />
<AppenderRef ref="file" />
</Root>
</Loggers>
</Configuration>
只需要一个选项:
酱料
package ml.kerotori.log4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Test1 {
static Logger logger = LogManager.getLogger(Test1.class);
public static void main(String[] args) {
logger.trace("Test1のmainメソッド");
}
}
2-4. Logback -> 2-4. Logback
2-4-1. 安装
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.3</version>
</dependency>
↑這並不是必要的。只需使用logback-classic就可以了。
↑上面是錯誤的。slf4j是必需的。在源代碼中,無法使用SLF4J的介面……。
2-4-2 设定文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss} [%thread] %level %logger{0} - %msg \(%file:%line\)%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/logback.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log.tar.gz</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - %m%n</pattern>
</encoder>
</appender>
<root level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
2-4-3。醬料
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test2 {
private static Logger log = LoggerFactory.getLogger(Test2.class);
public static void main(String[] args) {
log.debug("Test2のmainメソッド");
}
}
只需要一个选项,以下是参考的中文释义:
对于初学者来说,简要了解Java日志库的历史与现状。
3. SLF4J+logback 的中文表达:
3-1. 安装
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
需要「slf4j-api」「logback-core」「logback-classic」这三个库,其中「logback-classic」还依赖其他库。但是,如果不安装SLF4J,源代码中就不能使用SLF4J的接口。
3-2. 使用方法
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Sample {
private static final Logger log = LoggerFactory.getLogger(Sample.class);
public static void main(String[] args) {
log.trace("traceです。");
log.error("errorです。");
}
由于SLF4J是一个接口,而Logback是其实现,因此需要使用import语句import SLF4J。
如果要使用Lombok的话
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Sample {
public static void main(String[] args) {
log.trace("traceです。");
log.error("errorです。");
3-4. 设定文件
3-4-1. 设定文件的存放位置
将 logback.xml 文件放置在 “/src/main/resources” 路径下。
对于 Web 应用程序,将其放置在 “/WEB-INF/classes” 路径下。(将其放置在 WEB-INF 的直接子文件夹或 lib 文件夹下,但无法加载。)
通过指定 -Dlogback.configurationFile 可以读取任意位置的文件。
3-4-2. 在Maven的模块结构中的属性文件。
如果在Maven中有多个子项目存在于模块化结构中,如何将配置文件进行共享。
将”logback.xml”文件放置在父项目的src/main/resources目录下,并在父项目的pom.xml文件中进行以下的配置。
<build>
<resources>
<resource>
<directory>${project.basedir}/../src/main/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
・・・省略
3-5. 定制化配置文件
输出进程ID为3-5-1。
输出3-5-2的方法名称
可以使用「%M」。请查看以下网站获取详细信息:
http://logback.qos.ch/manual/layouts_zh_CN.html
3-5-3模式例子
示例代码
package log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogOut {
private static final Logger log = LoggerFactory.getLogger(LogOut.class);
public static String Message() {
log.trace("traceです。");
log.error("errorです。");
System.out.println("標準出力です");
return "Messageです";
}
}



3-5-4. 不生成特定类别的日志。
3-6.解决问题
在Maven中运行测试时出现错误。
■现象
在执行Maven时,会输出以下错误日志。
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/pleiades/eclipse/plugins/org.eclipse.m2e.maven.runtime.slf4j.simple_1.16.0.20200610-1735/jars/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [file:/C:/pleiades/eclipse/configuration/org.eclipse.osgi/7/0/.cp/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/pleiades/eclipse/plugins/org.eclipse.m2e.maven.runtime.slf4j.simple_1.16.0.20200610-1735/jars/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [file:/C:/pleiades/eclipse/configuration/org.eclipse.osgi/7/0/.cp/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
执行测试时会出现以下错误。
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[WARNING] Corrupted STDOUT by directly writing to native stream in forked JVM 1. See FAQ web page and the dump file C:\Users\けろ\git\javaUtils2\Domain\target\surefire-reports\2021-01-17T12-39-22_446-jvmRun1.dumpstream
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for javaUtils 0.0.1-SNAPSHOT:
[INFO]
[INFO] javaUtils .......................................... SUCCESS [ 0.515 s]
[INFO] Domain ............................................. FAILURE [ 0.835 s]
[INFO] Infrastructure ..................................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.449 s
[INFO] Finished at: 2021-01-17T12:39:22+09:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test (default-test) on project Domain: There are test failures.
[ERROR]
[ERROR] Please refer to C:\Users\けろ\git\javaUtils2\Domain\target\surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was cmd.exe /X /C "C:\pleiades\java\11\bin\java -javaagent:C:\\Users\\けろ\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.8.3\\org.jacoco.agent-0.8.3-runtime.jar=destfile=C:\\Users\\けろ\\git\\javaUtils2\\Domain\\target\\jacoco.exec -jar C:\Users\けろ\AppData\Local\Temp\surefire10670104236856242318\surefirebooter7391686314887198056.jar C:\Users\けろ\AppData\Local\Temp\surefire10670104236856242318 2021-01-17T12-39-22_446-jvmRun1 surefire16778607688627256100tmp surefire_012236412007154186616tmp"
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was cmd.exe /X /C "C:\pleiades\java\11\bin\java -javaagent:C:\\Users\\けろ\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.8.3\\org.jacoco.agent-0.8.3-runtime.jar=destfile=C:\\Users\\けろ\\git\\javaUtils2\\Domain\\target\\jacoco.exec -jar C:\Users\けろ\AppData\Local\Temp\surefire10670104236856242318\surefirebooter7391686314887198056.jar C:\Users\けろ\AppData\Local\Temp\surefire10670104236856242318 2021-01-17T12-39-22_446-jvmRun1 surefire16778607688627256100tmp surefire_012236412007154186616tmp"
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:669)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:282)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1183)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1011)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:857)
[ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR] at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR] at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR] at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
[ERROR] at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
[ERROR] at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <args> -rf :Domain
# Created at 2021-01-17T12:29:56.634
Corrupted STDOUT by directly writing to native stream in forked JVM 1. Stream 'FATAL ERROR in native method: processing of -javaagent failed, appending to system class path failed'.
■对应方法
所使用的开发环境是「pleiades-2020-06-java-win-64bit-jre_20200702.zip」。
上述模块存在错误吗?
https://stackoverflow.com/questions/63755390/multiple-slf4j-bindings-with-m2e-in-eclipse-2020-06
暫時先試試看使用「pleiades-2020-12-java-win-64bit-jre_20201222.zip」。雖然一開始會出現相同的警告,但沒有發生錯誤,測試也成功執行了。
3-6-2.logback.xml文件的内容未能反映(Web应用程序)。
修改logback.xml文件后,Tomcat没有反应。
在Tomcat启动时,会出现以下日志。
情報: CATALINA_BASE: D:\pleiades-2020-12-java-win-64bit-jre_20201222\pleiades\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0
打开该位置并进行调查后,发现logback.xml文件位于以下位置:
D:\pleiades-2020-12-java-win-64bit-jre_20201222\pleiades\workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\WebSample\WEB-INF\classes
确认直接编辑该文件会反映出效果。
3-6-3. 输出相对路径的目标位置未知。
当将文件输出路径设为”log/logback.txt”时,我不知道输出的位置,所以进行了调查。以下是输出的位置:
D:\pleiades-2020-12-java-win-64bit-jre_20201222\pleiades\eclipse\logs