我在oracle adf 12c应用程序中使用log4j2。
我们客户的需求之一是为不同的登录用户提供不同的日志级别,并且为用户动态地更改日志级别。此外,管理员应该有一个控制来停止所有的日志记录。
即假设“用户A”需要跟踪日志级别,“用户B”需要错误日志级别。如果两个用户同时登录,应用程序应该为“用户A”登录跟踪级别,为“用户B”登录错误级别。如果“用户B”想要登录FATAL级别,他应该能够动态更改配置。
以下是log4j2配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace">
<MapFilter onMatch="ACCEPT" operator="or">
<KeyValuePair key="$${ctx:LOGLEVELYN}" value="Y"/>
</MapFilter>
<Appenders>
<File name="file" fileName="./adfAppCustomLogs/TestLog4j2.log">
<PatternLayout>
<Pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} %-5level %class %L %M - %msg%xEx%n</Pattern>
</PatternLayout>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
<Routing name="AppRouting">
<Routes pattern="$${ctx:LOGGEDSESSIONID}">
<!-- This route is chosen if ThreadContext has no value for key ROUTINGKEY. -->
<Route key="$${ctx:LOGGEDSESSIONID}">
<RollingFile name="Rolling-ALL" fileName="./adfAppCustomLogs/DefaultAll.log"
filePattern="./adfAppCustomLogs/archive/${date:yyyy-MM}/DefaultAll-%d{MM-dd-yyyy}-%i.txt.gz">
<PatternLayout>
<Pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} %-5level %t %msg%xEx%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="6" modulate="true"/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
</RollingFile>
</Route>
<!-- This route is chosen if ThreadContext has value 'user' for key ROUTINGKEY. -->
<Route>
<RollingFile name="Rolling-OTHER-${ctx:LOGGEDSESSIONID}"
fileName="./adfAppCustomLogs/${ctx:LOGINID}-${ctx:LOGGEDSESSIONID}.log"
filePattern="./adfAppCustomLogs/archive/${date:yyyy-MM}/${ctx:LOGINID}-%d{MM-dd-yyyy}-%i.txt.gz">
<PatternLayout>
<Pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} %-5level %t %msg%xEx%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="6" modulate="true"/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<!-- <DefaultRolloverStrategy max="100"/> -->
</RollingFile>
</Route>
</Routes>
</Routing>
<Async name="async" bufferSize="1000" includeLocation="true">
<AppenderRef ref="AppRouting"/>
</Async>
</Appenders>
<Loggers>
<Root level="trace">
<!--<AppenderRef ref="file" level="DEBUG"/> -->
<AppenderRef ref="async"/>
<!-- Uncomment the following if you want the log to be printed in weblogic console -->
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
我试着创建多个日志记录器,每个都有不同的日志级别,但是没有成功。
如果你能给我一些指点或提示,那就太好了。
我们客户的要求之一是为不同的登录用户提供不同的日志级别,并为一个用户动态更改日志级别。管理员还应该控制停止所有日志记录。
这需要为每个用户设置一个单独的记录器,我假设这意味着每个Thread
。显然,您不可能提前配置所有这些记录器,因为您不知道在运行时会有多少用户。因此,您需要在运行时动态创建记录器并调用log4j2 API。您可以参考log4j2手册了解完整的详细信息。
此外,您需要创建管理控件,以允许访问log4j2配置,并提供在运行时修改配置的能力。
以下是一个小示例,说明如何实现每个Thread
拥有一个记录器的目标以及如何在运行时更改日志级别:
这是log4j2.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="example" level="trace">
<AppenderRef ref="STDOUT" />
</Logger>
<Root level="WARN">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
以下是java代码:
package example;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
public class LogLvlByThreadMain {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable(){
public void run() {
addLogger(Thread.currentThread().getName());
Logger log = LogManager.getLogger(Thread.currentThread().getName());
log.info("here's the first thread");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("some debug in first thread");
log.info("finishing first thread");
}}, "Thread1");
Thread t2 = new Thread(new Runnable(){
public void run() {
addLogger(Thread.currentThread().getName());
Logger log = LogManager.getLogger(Thread.currentThread().getName());
log.info("here's the second thread");
changeLogLevel(Thread.currentThread().getName(), Level.DEBUG);
log.debug("some debug in second thread");
}}, "Thread2");
t1.start();
t2.start();
}
public static synchronized void addLogger(String name){
AppenderRef ref = AppenderRef.createAppenderRef("STDOUT", null, null);
AppenderRef[] refs = new AppenderRef[] {ref};
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = LoggerConfig.createLogger("false", Level.INFO, name,
"true", refs, null, config, null );
loggerConfig.addAppender(config.getAppender("STDOUT"), null, null);
config.addLogger(name, loggerConfig);
ctx.updateLoggers();
}
public static synchronized void changeLogLevel(String loggerName, Level lvl){
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerCfg = config.getLoggerConfig(loggerName);
loggerCfg.setLevel(lvl);
ctx.updateLoggers();
}
}
请注意,您将不得不考虑多个线程动态更改日志配置的同步问题-请注意上面更改配置的两个方法是如何同步的。
上述代码的输出:
here's the second thread
here's the first thread
some debug in second thread
finishing first thread
这证明这两个线程具有不同的日志级别,因为如果我们同时更改了它们,我们将看到两个“调试”日志,而不仅仅是第二个线程中的日志。
我想做的很直截了当: 我只希望在控制台追加器上显示重要的消息,而我希望将详细的消息路由到文件追加器。 我还尝试向添加一个ThresholdFilter,但这也不能过滤它。
在log4j2文档log4j2 java配置中,默认配置为: 根本就不在那里。它仍将只打印出错误日志。 问题 是否有其他人遇到此问题? 有人能复制它吗? 有人知道怎么修吗?我几乎要给别人一块钱。不过,我肯定会把他们的答案标成绿色。 我的最终目标是让特定的记录器发送SMTP请求。我很确定我知道怎么做,我只是在和这个小问题作斗争
SLF4J具有以下日志级别 JDK日志记录具有以下日志级别 如果我想将日志级别设置为DEBUG,那么该级别在JDK日志中不可用。谁能解释一下在这种情况下我们如何获得调试级别的日志记录。对于这种情况,我们需要做什么额外的配置吗? 已更新 这是我的属性文件配置 请让我知道我哪里错了。
是的,我已经阅读了所有相关的问题。我正在使用log4j2(尝试了2.4版和更新到最新的2.6.2版)。 我有一个面向客户的小型实用程序。我渴望将暴露的配置保持在最低限度。但对于有问题的情况,我还想添加一个标志,以便在运行时启用调试日志。 这是我启用调试日志记录的代码 但它实际上并不适用于这些情况: 实用程序通常在30秒内完成,因此更改应该是即时的。这是log4j2。xml 使用AppenderRe
我正在尝试创建基于不同级别的“不同”附加器,但到目前为止,我找不到一种隔离日志级别的方法。。。。 我需要一种方法,能够土地只有INFO优先排序的日志被追加。因为INFO级别的日志记录也会显示DEBUG标记的日志记录器...这对我没有帮助。 另一件事是,对于“相同”包,我无法定义不同的日志附加器: 在这里,我得到了如下错误:
现在,问题是,当我以以下方式进行日志记录时: 尽管根记录器级别被设置为“错误”,但日志条目仍然存在于两个日志文件中。然而,当我去掉“it.pkg.testpkg.service”记录器(通过注释或删除它)时,条目停止进入根记录器。我不太清楚这是怎么回事。 目前,我已经找到了一个临时解决方案,方法是在“root_file_appender”中添加以下条目: 谢了。