We have a java application connected to multiple services, for example email, DB etc. We'd like to still log everything into the same file just to be sure but we'd also like to route logs to certain files based onto the MDC keys that we set.
For example:
- I get a message from the DB, said message should be also in DB.log.
- I get an email that I should route to the email server and that should go into email.log
How can I achieve this? Is it possible just by setting the MDC keys and the appropriate log4j2.xml config?
[...]
<Property name="newPattern">%d %-5p %X{log-route} [%t]</Property>
[...]
<Routing name="RoutingAppender">
<Routes pattern="${ctx:log-route}">
<Route key="EMAIL">
<RollingRandomAccessFile
name="EMAILRollingFile"
fileName="log/email/email.log"
filePattern="log/email/email.log.%i">
<PatternLayout>
<Pattern>${newPattern}</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="50 MB"/>
</Policies>
<property name="createOnDemand">true</property>
<DefaultRolloverStrategy fileIndex="min" max="100"/>
</RollingRandomAccessFile>
</Route>
</Routes>
</Routing>
In java I do MDC.put("log-route","EMAIL");
I can see the correct log messages but all in the default file. The other files don't even get created.
We have a java application connected to multiple services, for example email, DB etc. We'd like to still log everything into the same file just to be sure but we'd also like to route logs to certain files based onto the MDC keys that we set.
For example:
- I get a message from the DB, said message should be also in DB.log.
- I get an email that I should route to the email server and that should go into email.log
How can I achieve this? Is it possible just by setting the MDC keys and the appropriate log4j2.xml config?
[...]
<Property name="newPattern">%d %-5p %X{log-route} [%t]</Property>
[...]
<Routing name="RoutingAppender">
<Routes pattern="${ctx:log-route}">
<Route key="EMAIL">
<RollingRandomAccessFile
name="EMAILRollingFile"
fileName="log/email/email.log"
filePattern="log/email/email.log.%i">
<PatternLayout>
<Pattern>${newPattern}</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="50 MB"/>
</Policies>
<property name="createOnDemand">true</property>
<DefaultRolloverStrategy fileIndex="min" max="100"/>
</RollingRandomAccessFile>
</Route>
</Routes>
</Routing>
In java I do MDC.put("log-route","EMAIL");
I can see the correct log messages but all in the default file. The other files don't even get created.
Share Improve this question asked Feb 7 at 16:06 Red--ManRed--Man 11 bronze badge 1 |1 Answer
Reset to default 0The <Routes>
element is similar to a switch
statement and you only specified the EMAIL
case. To specify a default
case, you need to create a <Route>
element without a key
attribute:
<Routing name="RoutingAppender">
<Routes pattern="$${ctx:log-route}">
<Route>
<RollingRandomAccessFile
name="${ctx:log-route:-MAIN}RollingFile"
fileName="log/${lower:${ctx:log-route:-MAIN}}/${lower:${ctx:log-route:-MAIN}}.log"
filePattern="log/${lower:${ctx:log-route:-MAIN}}/${lower:${ctx:log-route:-MAIN}}.log.%i">
<PatternLayout pattern="${newPattern}"/>
<Policies>
<OnStartupTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="50 MB"/>
</Policies>
<DefaultRolloverStrategy fileIndex="min" max="100"/>
</RollingRandomAccessFile>
</Route>
</Routes>
</Routing>
Note: if the assignment between log statements in your code and the categories is static, you might consider using markers instead of the thread context.
If you use the thread context to decide, which log file will be used, make sure that your code does not set thread context values from user data. For example some applications set thread context values from HTTP headers; in your case that would lead to a security issue.
/log/email/email.log
instead. – mahbad Commented Feb 7 at 16:16