Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure logback to append special prefix for each object?

I have a class that takes string parameter in its constructor which represents it.

And i want to append this string as prefix at log messages. How can I do it in logback ?

For example;

MyClass classA = new MyClass("0999445454");

MyClass classB = new MyClass("0999446464");

classA.doSomething();
classB.doSomething();

The method of MyClass ;

public void doSomething()  {
     logger.info("Doing Something...");

     //Do something
}

So i want to see log messages like that ;

[INFO] [0999445454]: Doing Something...
[INFO] [0999446464]: Doing Something...
like image 509
Jman Avatar asked Jul 24 '14 11:07

Jman


People also ask

How do I change the Logback configuration file?

Setting the location of the configuration file via a system property. You may specify the location of the default configuration file with a system property named "logback. configurationFile" . The value of this property can be a URL, a resource on the class path or a path to a file external to the application.

What is Appender in Logback?

Appenders place log messages in their final destinations. A Logger can have more than one Appender. We generally think of Appenders as being attached to text files, but Logback is much more potent than that. Layout prepares messages for outputting.


1 Answers

I don't know how you currently instantiate your logger, but you can use your "string parameter which represents" your object to name this logger:

logger = LoggerFactory.getLogger("0999445454");

For example, if this string identifier is stored in an attribute id, you can do that:

Logger logger = null;

public MyClass(String id) {
    logger = org.slf4j.LoggerFactory.getLogger(id);
    // ...
}

public void doSomething()  {
    logger.info("Doing Something...");
    // Do something
}

You will then need to use the following Pattern in your Logback configuration file:

<appender name="..." class="...Appender">
    <encoder>
        <pattern>[%level] [%logger]: %msg%n</pattern>
    </encoder>
</appender>

Because %logger is the logger name, which is the parameter given to org.slf4j.LoggerFactory.getLogger()


If you want to avoid creating a Logger for each ID, you can also use Mapped Diagnostic Context (MDC):

logger = LoggerFactory.getLogger(MyClass.class);
org.slf4j.MDC.put("id", "your ID");
logger.info("Doing Something...");

You shall then add field %mdc in your Pattern (i.e. Logback configuration file):

<pattern>[%level] [%mdc{id}]: %msg%n</pattern>

So you shall call MDC.put() before a log each time you want to log with a different ID. What you could do in your case is something like:

public class MyClass {
    private Logger logger = LoggerFactory.getLogger(MyClass.class);
    private final String id;
    private static final Object MDC_MUTEX = new Object();

    public MyClass(String id) {
        this.id = id;
        // ...
    }

    public void doSomething()  {
        log("Doing Something...");
        // Do something...
    }

    private void log(String message) {
        synchronized(MDC_MUTEX) {
            MDC.put("id", id);
            logger.info(message);
        }
    }
}
like image 96
xav Avatar answered Sep 18 '22 12:09

xav