Reputation: 33
Now I have problem with log4j2.
My goal is: Determine which file to log according to the value of "fileName" in the MDC map.
For example
public class A {
void test() {
//log in A.log
MDC.put("fileName", A);
//LoggerContext ctx = (LoggerContext)LoggerContext.getContext(false);
//ctx.reconfigure();
//Now, I want it log in A.log
log.info("aaa");
C c = new C();
c.test();
}
}
public class B {
void test() {
//log in B.log
MDC.put("fileName", B);
//LoggerContext ctx = (LoggerContext)LoggerContext.getContext(false);
//ctx.reconfigure();
//Now, I want it log in B.log
log.info("bbb");
C c = new C();
c.test();
}
}
public class C {
void test() {
log.info("cccc");
}
}
and my log4j2.xml is
<RollingFile name="rollingFile" fileName="/home/logs/${ctx:key}.log"
filePattern="/home/logs/application-${ctx:key}-i.log">
<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="2MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
if I uncomment reconfigure(), it works that When executing A.test(), "aaa", "cccc" log in A.log and when executing B.test(), "bbb", "cccc" log in B.log.
LoggerContext ctx = (LoggerContext)LoggerContext.getContext(false);
ctx.reconfigure();
But considering the high concurrency scenario, I am worried that frequent updates will cause performance problems such as IO resources.
In configurtion of log4j2, we can use %X{key} to get MDC map value in real time.
So is it possible that we do not need to execute reconfigure() every time when MDC map values change?
or is there any way to achieve my goal?
Upvotes: 0
Views: 434
Reputation: 9151
You want to use the RoutingAppender. You would use it as
<Routing name="Routing">
<Routes pattern="$${ctx:fileName}">
<Route>
<RollingFile name="rollingFile" fileName="/home/logs/${ctx:fileName}.log"
filePattern="/home/logs/application-${ctx:fileName}-i.log">
<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
<SizeBasedTriggeringPolicy size="2MB"/>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Route>
<Routes>
<Routing>
Note that this only configures a default Route so if fileName is not provided you will end up logging to a file literally named ${ctx:fileName}-n.log.
You also need to know that this should only be used when the possible values for fileName is limited. But if they are all known beforehand it is really better to directly declare them. If fileName is not well controlled you could end up running out of file handles.
Upvotes: 1