SamuelTJackson
SamuelTJackson

Reputation: 1537

Log4j2 count messages

I want to count my messages. So the log message should look like this:

000001:Test:Service:23-05-2016:20-26-01:Message
000002:Test:Service:23-05-2016:20-26-01:Message
000003:Test:Service:23-05-2016:20-26-01:Message

I use the following log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF">
    <Appenders>
        <File name="logFile" filename="${sys:logDir}${sys:logFilename}">
            <PatternLayout pattern="${sys:logLevel}:Service:%d{dd-MM-yyyy:HH-mm-ss}:%msg%n" />
        </File>
    </Appenders>
    <Loggers>
        <Root level="${sys:logLvl}">
            <AppenderRef ref="logFile" />
        </Root>
    </Loggers>
</Configuration>

I can't find anything. Only something about %i for a rollover for a new logfile. I hope someone can help me!

Kindly Regards

EDIT:

I could solve the problem. Thanks to Carlitos Way and rgoers:

my new class SequenceNumberPatternConverterPaddedWithZeros:

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;

import java.util.concurrent.atomic.AtomicLong;

@Plugin(
        name = "SequenceNumberPaddedPatternConverter",
        category = "Converter"
)
@ConverterKeys({"snp", "sequenceNumberPadded"})
public final class SequenceNumberPatternConverterPaddedWithZeros extends LogEventPatternConverter {
    private String zeros;
    private static final AtomicLong SEQUENCE = new AtomicLong();

    private SequenceNumberPatternConverterPaddedWithZeros(String zeros) {

        super("Sequence Number Padded", "snp");
        this.zeros = zeros;
    }

    public static SequenceNumberPatternConverterPaddedWithZeros newInstance(String[] options) {
        if(options.length > 1 ||!StringUtils.isNumeric(options[0])) {
            LOGGER.error("Incorrect option on SequenceNumberPatternConverterPadded. Expected a number, received " + options.length);
            return null;
        }
        return new SequenceNumberPatternConverterPaddedWithZeros(options[0]);//INSTANCE;
    }

    public void format(LogEvent event, StringBuilder toAppendTo) {
        toAppendTo.append(String.format("%0"+this.zeros+"d",SEQUENCE.incrementAndGet()));
    }
}

So now you can just use it like this:

<PatternLayout pattern="%snp{6}:${sys:logLevel}:Service:%d{dd-MM-yyyy:HH-mm-ss}:%msg%n"/>

000010:Test:Service:24-05-2016:11-06-52:message

Upvotes: 1

Views: 1917

Answers (1)

Carlitos Way
Carlitos Way

Reputation: 3424

I believe that log4j does not have a built-in feature as the want that you describe... So, IMHO, your best options are:

  1. Use the log4j built-in MDC feature and generate your own message sequence through JAVA code (The sequence generator must be implemented as synchronized singleton)... Later, you should reconfigure your pattern as: %X{seqNextVal}${sys:logLevel}:Service:%d{dd-MM-yyyy:HH-mm-ss}:%msg%n" where seqNextVal the configured message sequence (example: MDC.put(seqNextVal, MessageSequenceGen.nextValue()).

  2. Define your own Appender (or PatternLayout) that includes (and hides) the message sequence generator logic for you. I believe this is is hardest but best option, because your encapsulate the logic of the sequence at the logj4 components and you don't need to modify your code in any place...

Beware, no matter the solution your implement, remember to persist your sequence somehow... otherwise, when your application start again, the message count will restart at "one" too...

UPDATE: Checking the log4j docs, I Found this: log4j layouts ... look for sequenceNumber at the Patterns section... May be this can help you....

Upvotes: 2

Related Questions