Generating multiple log-files with log4j2

I just wanted to do a small excourse into great log4j2-logging-framework, which, by the way, still is „only“ a release-candidate 2.0-rc, but brings a lot of features most developers are missing in log4j.
I decided to create a tiny generator that can generate a ton of logs. Maybe next weeks or months I will have time to take a look at logstash? We’ll see.

But back to the log-generator: The idea behind is to create a boilerplate-configuration where I can have a look at new features and basic log4j2-configuration with all the appenders and loggers.

So the setup is only a standard-maven-layout (maven 3.0.5 with jdk 1.8.0_05) with following pom.xml:

<project xmlns="" xmlns:xsi=""



The single class that produces the logs:

package org.jtaddeus.playground.loggenerator;

import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

 * This class represents a Generator for some logs. It will print out logs in form of "Logging in user <some userame>
 * with id <some id>.
 * Therefor it uses static lists of users and loggers.
 * @author christoph burmeister
public class LogGenerator {
    /** List of users. */
    private static final List<String> users = new ArrayList<String>();
    /** List of loggers. */
    private static final List<Logger> loggers = new ArrayList<Logger>();

    /** Some static initialization of users- and logger-lists. */
    static {

        // the loggers that will appear in the log4j2.xml

     * Entry-point.
     * @param args
     *            doesn't matter in this case
    public static void main(String[] args) {
        while (true) {
            int logLevel = getRandomNumber(0, 3); // 4 different log-levels
            int loggerId = getRandomNumber(0, loggers.size() - 1);
            Logger logger = loggers.get(loggerId);
            int userId = getRandomNumber(0, users.size() - 1);
            String user = users.get(userId);

            log(user, userId, logger, logLevel);

            try {
                long sleeptime = getRandomNumber(200, 500);
            } catch (InterruptedException e) {


     * Method to do the actual logging.
     * @param user
     *            the username
     * @param userId
     *            the user-id
     * @param logger
     *            the logger to use
     * @param logLevel
     *            the loglevel to use
    private static void log(String user, int userId, Logger logger, int logLevel) {
        switch (logLevel) {
        case 0:
            logger.error("Logging in user {} with id {} ", user, userId);
        case 1:
            logger.warn("Logging in user {} with id {} ", user, userId);
        case 2:
  "Logging in user {} with id {} ", user, userId);
        case 3:
            logger.debug("Logging in user {} with id {} ", user, userId);

     * Method to wrap random-mechanism. gets a random number in range of [min...max].
     * @param min
     *            the minium-value
     * @param max
     *            the maximum-value
     * @return the random int.
    private static int getRandomNumber(int min, int max) {
        int incMax = max + 1;
        int random = min + (int) (Math.random() * (incMax - min) + min);
        return random;

And, finally the log4j2.xml (take care of the „2“ in the filename!). There we have 5 appenders: one for the console, 2 file-appender for server1-logs (all and error) and 2 file-appender for server2-logs (again all and error). Then I configure 3 Loggers which refer to the appenders.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30" status="debug">
	<!-- monitorInterval: automatic reload every 30sec on changes -->
	<!-- status: log4j2 internal logging (not for the app) -->

	<!-- fantastic: properties within config-file finally in log4j2 🙂 -->
		<Property name="filename-server1-all">logs/server1-all.log</Property>
		<Property name="filename-server1-error">logs/server1-err.log</Property>
		<Property name="filename-server2-all">logs/server2-all.log</Property>
		<Property name="filename-server2-error">logs/server2-err.log</Property>

		<!-- the standard-console-appender -->
		<Console name="appender-Console-all" target="SYSTEM_OUT">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />

		<!-- the appenders for server 1 -->
		<File name="appender-server-1-all" fileName="${filename-server1-all}" append="true">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		<File name="appender-server-1-error" fileName="${filename-server1-error}" append="true">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />

		<!-- the appenders for server 2 -->
		<File name="appender-server-2-all" fileName="${filename-server2-all}" append="true">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		<File name="appender-server-2-error" fileName="${filename-server2-error}" append="true">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />

		<!-- Every configuration must have a root logger. If one is not configured the default root LoggerConfig is ERROR with Console appender attached. -->
		<Root level="DEBUG">
			<AppenderRef ref="appender-Console-all" />

		<!-- server1-loggers -->
		<!-- additivity means, that parent-logger (in every case the root-logger) will also get the chance to log this stuff -->
		<Logger name="org.jtaddeus.playground.loggenerator.Server1" additivity="TRUE" level="ALL">
			<AppenderRef ref="appender-server-1-all" level="ALL" />
			<AppenderRef ref="appender-server-1-error" level="ERROR" />

		<!-- server2-loggers -->
		<!-- additivity means, that parent-logger (in every case the root-logger) will also get the chance to log this stuff -->
		<Logger name="org.jtaddeus.playground.loggenerator.Server2" additivity="TRUE" level="ALL">
			<AppenderRef ref="appender-server-2-all" level="ALL" />
			<AppenderRef ref="appender-server-2-error" level="ERROR" />