You can use the Routing Appender, which you can find more info here https://logging.apache.org/log4j/2.x/manual/appenders.html#RoutingAppender and https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/appender/routing/RoutingAppender.html
I do have sample code using log4j2 Routing Appender in github here https://github.com/cdcentral/LoggingApp/pull/3/files
Here's some important snippets.
In the log4j2.xml file I have this in the Appenders
section:
<Routing name="Routing">
<Routes pattern="$${ctx:DYNAMIC_LOG}">
<Route>
<RollingFile name="routing_log" append="true" fileName="${logDirectory}/${ctx:DYNAMIC_LOG}_log.log"
filePattern="${logDirectory}/archive/${ctx:DYNAMIC_LOG}_Downlink-%d{MM-dd-yyyy}-%i.log">
<PatternLayout>
<pattern>%d{ISO8601} [%t] %p %c %L - %m%n</pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<!-- Deletes log files, with format *.log, older than 2 days -->
<DefaultRolloverStrategy>
<Delete basePath="${logDirectory}/" maxDepth="1">
<IfFileName glob="*_log.log" />
<IfLastModified age="2d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Route>
</Routes>
</Routing>
In the Loggers
section I did this Logger referencing the Appender
above:
<Logger name="RoutingLogger" level="info" additivity="false">
<appender-ref ref="Routing" level="DEBUG" />
</Logger>
In your java class where you have a reference to the RoutingLogger
you would have to put a ThreadContext.put('key', 'value');
line of code before the logging with the RoutingLogger, like this:
import static com.ancocentral.loggingapp.LogHelper.ROUTING_LOGGER;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
/**
*
* @author chris
*/
public class StartService implements Runnable {
private String instance = "";
public StartService (String instance) {
this.instance = instance;
}
@Override
public void run() {
connect();
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ThreadContext.put("DYNAMIC_LOG", instance);
ROUTING_LOGGER.fatal(instance + " Exception ->", ex);
}
disconnect();
}
private void connect() {
ThreadContext.put("DYNAMIC_LOG", instance);
ROUTING_LOGGER.info(instance + " is connecting.");
}
private void disconnect() {
ThreadContext.put("DYNAMIC_LOG", instance);
ROUTING_LOGGER.warn(instance + " is disconnecting.");
}
}
The DYNAMIC_LOG
text above is associated to the <Routing> -> <Routes pattern=
value in the log4j2.xml
The instance
variable is a parameter passed into the class above. The class is instantiated multiple times and a unique string id is passed in to it in the constructor and this unique string helps these log statements be written to different log files.
Here's how I instantiate this class in the main
method:
public static void main(String[] args) {
StartService ss = new StartService("Database_A");
Thread serviceThread = new Thread(ss);
serviceThread.start();
StartService ss2 = new StartService("Database_B");
Thread serviceThread2 = new Thread(ss2);
serviceThread2.start();
}
So the logs that will be generated after this is ran will be "Database_A_log.log" and a "Database_B_log.log"
To see the rest of the peripheral code in this app you can look at my github link above.