Log4j2:日志未发送到控制台,其中日志到文件工作正常
Log4j2: Logs not sent to Console where as logs to file works fine
我是 log4j 的新手。我的 log4j 配置没有将日志写入控制台,而文件的日志工作正常。尽管参考了之前的帖子,但我无法解决此问题。
我有两个附加程序 - 一个用于控制台,另一个用于文件。我打算将 ERROR 和 FATAL 写入文件,因此使用 level=ERROR。我打算将所有日志写入控制台,因此对控制台使用 level=TRACE。
我的代码只包含一个名为 'parallel' 的包,有一个名为 ClassA 的包 class 以及一种记录所有类型日志的方法。
如果我在 Root 标记中同时指定了控制台和文件附加程序,那么我的期望就满足了。如果我将 File appender 移到 Root 之外并在 Logger 标签下提及它,那么只有 File appender 可以工作,而 Console appender 不起作用。所有appender都必须放在Root标签下吗?
package parallel;
public class ClassA {
private final Logger log = LogManager.getLogger(ClassA.class);
@Test
public void testLogs() {
log.info("info");
log.debug("debug");
log.warn("warn");
log.error("error");
log.fatal("fatal");
log.trace("trace");
}
}
<Configuration status="INFO">
<Properties>
<Property name="basePath" value="./logs" />
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</Pattern>
</PatternLayout>
</Console>
<File name="fileLogger" fileName="${basePath}/error.log">
<PatternLayout>
<Pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss} [%t] %c{1} - %msg%n
</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root name="parallel">
<AppenderRef ref="console" level="trace" />
</Root>
<Logger name="parallel" level="warn" additivity="false">
<AppenderRef ref="fileLogger" />
</Logger>
</Loggers>
部分解决.....
我在 Logger 标记中添加了 Additivity="true" ,这使得日志在控制台和文件中打印。但是,ERROR 的日志级别同时应用于控制台和文件。我的实际要求是 Console 具有 TRACE 和 File 具有 ERROR 级别。
我无法从 log4j2 官方文档中理解可加性的概念。任何能解释这个概念的人都会有很大帮助。
据我了解,您的目标是完成这些项目:
I intend to write ERROR and FATAL to file hence using level=ERROR. I
intend to write all logs to console hence using level=TRACE for
Console.
请在最终选择您将在代码中实现的内容之前阅读整个答案。
您可以通过如下配置您的记录器来做到这一点:
<Loggers>
<Root>
<AppenderRef ref="console"/>
</Root>
<Logger name="parallel" level="ALL" additivity="true">
<AppenderRef ref="fileLogger" level="ERROR"/>
</Logger>
</Loggers>
每个 logger 将根据记录器名称和事件级别接受记录事件。例如,如果您调用 log.error(...)
,则会生成 ERROR
级别事件。如果 log
是通过 LogManager.getLogger(ClassA.class)
获得的,那么 log4j 将在其配置中搜索名为 "parallel.ClassA" 的记录器。如果它没有找到这样的记录器,它将 up the hierarchy 转到一个不太具体的记录器 - "parallel"。如果此记录器不存在,它将转到根记录器。
一旦记录器被识别,log4j 必须确定事件是否被该记录器接受。这基于记录器的级别设置。由于 "parallel" 记录器设置为 ALL
级别,它将接受任何级别的事件。
记录器接受事件后,其附加程序也必须接受该事件。与 "parallel" 记录器的文件附加程序关联的级别是 ERROR
,因此此附加程序将只接受 ERROR
和 FATAL
级别的事件。
由于 "parallel" 记录器的可加性是 true
,只要它接受一个事件,它就会将该事件传递给 as well (unless one of them breaks the chain by specifying additivity false
- see log4j2 architecture page 以获取详细信息)。因此,"parallel" 接受的任何事件都将转到与根记录器关联的控制台附加程序。
这种方法有一个问题,如果日志事件以 ERROR 或 FATAL 级别到达根记录器,它将不会写入您的日志文件。日志将 "leak" 发送到控制台。如果您不小心写了一些错误的代码,或者如果您在添加一些新代码后不小心忘记更新配置文件,就会发生这种情况。
下面是一些示例代码来说明问题:
package parallel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ClassA {
private static final Logger log = LogManager.getLogger(ClassA.class);
public static void main(String[] args) {
log.info("info");
log.debug("debug");
log.warn("warn");
log.error("error");
log.fatal("fatal");
log.trace("trace");
// See the mistake here?
// The wrong logger name was used in the code,
// now the error event goes to the root logger!
final Logger log2 = LogManager.getLogger("foo");
log2.error("Woops an error!");
}
}
上面使用答案开头的配置的控制台输出是:
[INFO ] 2019-05-05 12:48:31.410 [main] ClassA - info
[DEBUG] 2019-05-05 12:48:31.411 [main] ClassA - debug
[WARN ] 2019-05-05 12:48:31.411 [main] ClassA - warn
[ERROR] 2019-05-05 12:48:31.411 [main] ClassA - error
[FATAL] 2019-05-05 12:48:31.412 [main] ClassA - fatal
[TRACE] 2019-05-05 12:48:31.412 [main] ClassA - trace
[ERROR] 2019-05-05 12:48:31.413 [main] foo - Woops an error!
错误日志文件只显示:
[ERROR] 2019-05-05 12:48:31 [main] ClassA - error
[FATAL] 2019-05-05 12:48:31 [main] ClassA - fatal
最简单的修复方法是将所有附加程序移动到根记录器,如下所示:
<Loggers>
<Root level="ALL">
<AppenderRef ref="console"/>
<AppenderRef ref="fileLogger" level="ERROR"/>
</Root>
</Loggers>
现在所有事件都被根记录器和控制台附加器接受,但文件附加器只接受错误和致命事件。现在,即使代码不正确,日志事件也会转到正确的位置。
控制台输出:
[INFO ] 2019-05-05 12:59:32.419 [main] ClassA - info
[DEBUG] 2019-05-05 12:59:32.421 [main] ClassA - debug
[WARN ] 2019-05-05 12:59:32.421 [main] ClassA - warn
[ERROR] 2019-05-05 12:59:32.421 [main] ClassA - error
[FATAL] 2019-05-05 12:59:32.421 [main] ClassA - fatal
[TRACE] 2019-05-05 12:59:32.421 [main] ClassA - trace
[ERROR] 2019-05-05 12:59:32.422 [main] foo - Woops an error!
错误日志文件:
[ERROR] 2019-05-05 12:59:32 [main] ClassA - error
[FATAL] 2019-05-05 12:59:32 [main] ClassA - fatal
[ERROR] 2019-05-05 12:59:32 [main] foo - Woops an error!
其他可能有用的链接:
希望对您有所帮助!
我是 log4j 的新手。我的 log4j 配置没有将日志写入控制台,而文件的日志工作正常。尽管参考了之前的帖子,但我无法解决此问题。 我有两个附加程序 - 一个用于控制台,另一个用于文件。我打算将 ERROR 和 FATAL 写入文件,因此使用 level=ERROR。我打算将所有日志写入控制台,因此对控制台使用 level=TRACE。 我的代码只包含一个名为 'parallel' 的包,有一个名为 ClassA 的包 class 以及一种记录所有类型日志的方法。
如果我在 Root 标记中同时指定了控制台和文件附加程序,那么我的期望就满足了。如果我将 File appender 移到 Root 之外并在 Logger 标签下提及它,那么只有 File appender 可以工作,而 Console appender 不起作用。所有appender都必须放在Root标签下吗?
package parallel;
public class ClassA {
private final Logger log = LogManager.getLogger(ClassA.class);
@Test
public void testLogs() {
log.info("info");
log.debug("debug");
log.warn("warn");
log.error("error");
log.fatal("fatal");
log.trace("trace");
}
}
<Configuration status="INFO">
<Properties>
<Property name="basePath" value="./logs" />
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</Pattern>
</PatternLayout>
</Console>
<File name="fileLogger" fileName="${basePath}/error.log">
<PatternLayout>
<Pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss} [%t] %c{1} - %msg%n
</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root name="parallel">
<AppenderRef ref="console" level="trace" />
</Root>
<Logger name="parallel" level="warn" additivity="false">
<AppenderRef ref="fileLogger" />
</Logger>
</Loggers>
部分解决..... 我在 Logger 标记中添加了 Additivity="true" ,这使得日志在控制台和文件中打印。但是,ERROR 的日志级别同时应用于控制台和文件。我的实际要求是 Console 具有 TRACE 和 File 具有 ERROR 级别。 我无法从 log4j2 官方文档中理解可加性的概念。任何能解释这个概念的人都会有很大帮助。
据我了解,您的目标是完成这些项目:
I intend to write ERROR and FATAL to file hence using level=ERROR. I intend to write all logs to console hence using level=TRACE for Console.
请在最终选择您将在代码中实现的内容之前阅读整个答案。
您可以通过如下配置您的记录器来做到这一点:
<Loggers>
<Root>
<AppenderRef ref="console"/>
</Root>
<Logger name="parallel" level="ALL" additivity="true">
<AppenderRef ref="fileLogger" level="ERROR"/>
</Logger>
</Loggers>
每个 logger 将根据记录器名称和事件级别接受记录事件。例如,如果您调用 log.error(...)
,则会生成 ERROR
级别事件。如果 log
是通过 LogManager.getLogger(ClassA.class)
获得的,那么 log4j 将在其配置中搜索名为 "parallel.ClassA" 的记录器。如果它没有找到这样的记录器,它将 up the hierarchy 转到一个不太具体的记录器 - "parallel"。如果此记录器不存在,它将转到根记录器。
一旦记录器被识别,log4j 必须确定事件是否被该记录器接受。这基于记录器的级别设置。由于 "parallel" 记录器设置为 ALL
级别,它将接受任何级别的事件。
记录器接受事件后,其附加程序也必须接受该事件。与 "parallel" 记录器的文件附加程序关联的级别是 ERROR
,因此此附加程序将只接受 ERROR
和 FATAL
级别的事件。
由于 "parallel" 记录器的可加性是 true
,只要它接受一个事件,它就会将该事件传递给 false
- see log4j2 architecture page 以获取详细信息)。因此,"parallel" 接受的任何事件都将转到与根记录器关联的控制台附加程序。
这种方法有一个问题,如果日志事件以 ERROR 或 FATAL 级别到达根记录器,它将不会写入您的日志文件。日志将 "leak" 发送到控制台。如果您不小心写了一些错误的代码,或者如果您在添加一些新代码后不小心忘记更新配置文件,就会发生这种情况。
下面是一些示例代码来说明问题:
package parallel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ClassA {
private static final Logger log = LogManager.getLogger(ClassA.class);
public static void main(String[] args) {
log.info("info");
log.debug("debug");
log.warn("warn");
log.error("error");
log.fatal("fatal");
log.trace("trace");
// See the mistake here?
// The wrong logger name was used in the code,
// now the error event goes to the root logger!
final Logger log2 = LogManager.getLogger("foo");
log2.error("Woops an error!");
}
}
上面使用答案开头的配置的控制台输出是:
[INFO ] 2019-05-05 12:48:31.410 [main] ClassA - info
[DEBUG] 2019-05-05 12:48:31.411 [main] ClassA - debug
[WARN ] 2019-05-05 12:48:31.411 [main] ClassA - warn
[ERROR] 2019-05-05 12:48:31.411 [main] ClassA - error
[FATAL] 2019-05-05 12:48:31.412 [main] ClassA - fatal
[TRACE] 2019-05-05 12:48:31.412 [main] ClassA - trace
[ERROR] 2019-05-05 12:48:31.413 [main] foo - Woops an error!
错误日志文件只显示:
[ERROR] 2019-05-05 12:48:31 [main] ClassA - error
[FATAL] 2019-05-05 12:48:31 [main] ClassA - fatal
最简单的修复方法是将所有附加程序移动到根记录器,如下所示:
<Loggers>
<Root level="ALL">
<AppenderRef ref="console"/>
<AppenderRef ref="fileLogger" level="ERROR"/>
</Root>
</Loggers>
现在所有事件都被根记录器和控制台附加器接受,但文件附加器只接受错误和致命事件。现在,即使代码不正确,日志事件也会转到正确的位置。
控制台输出:
[INFO ] 2019-05-05 12:59:32.419 [main] ClassA - info
[DEBUG] 2019-05-05 12:59:32.421 [main] ClassA - debug
[WARN ] 2019-05-05 12:59:32.421 [main] ClassA - warn
[ERROR] 2019-05-05 12:59:32.421 [main] ClassA - error
[FATAL] 2019-05-05 12:59:32.421 [main] ClassA - fatal
[TRACE] 2019-05-05 12:59:32.421 [main] ClassA - trace
[ERROR] 2019-05-05 12:59:32.422 [main] foo - Woops an error!
错误日志文件:
[ERROR] 2019-05-05 12:59:32 [main] ClassA - error
[FATAL] 2019-05-05 12:59:32 [main] ClassA - fatal
[ERROR] 2019-05-05 12:59:32 [main] foo - Woops an error!
其他可能有用的链接:
希望对您有所帮助!