Adrian Genaid
Adrian Genaid

Reputation: 436

IDs for log messages when using SLF4J

I would like to add a unique identifier to log statements, so I am able to add documentation (externally, e.g. a wiki) to every log statement, so a user can quickly access the message related documentation using the id. The logging framework I would like to use is SLF4J/logback.

I was not able to find documentation about related approaches except for some bits regarding auditing frameworks.

There is the Marker concept which I thought could be usable for ID injection, or I could just add the ID to the message text itself.

How would I add IDs to the logging statements "the right way"? Are there possibilities I didn't think of?

EDIT

The term unique ID just states there should be an identifier per log statement. A developer e.g. adds such an ID to a table/enum/whatever manually, which could be done wrong. Such ID has to be stable, so documentation can be based on it. So the ID itself is not what I am wondering about.

My question is: what would be the right way of pushing the ID to the logger together with the message text? Would Markers be suited for this kind of requirement, should I embed the ID into the message text or is there some other possibility?

So, basically, would I use

logger.info(IDMarkers.DB_CONNECTION_FAILED, "no connection to the database");

or instead just

logger.info("[{}] no connection to the database", LogIDs.DB_CONNECTION_FAILED);

First approach has the advantage that showing the IDs is up to the logging system/its configuration.

Upvotes: 4

Views: 4737

Answers (2)

gavenkoa
gavenkoa

Reputation: 48753

Slf4j has http://www.slf4j.org/apidocs/org/slf4j/Marker.html

Unfortunately Markers are advertised for a different purpose. Still you can use them to uniquely mark logging statements.

More cumbersome solution is MDC:

MDC.put("MsgId", "EV-1234");
log.info()
MDC.remove("MsgId");

or with structural logging (requires v2.0.0):

logger.atDebug()
    .addKeyValue("MsgId", "EV-1234")
    .log("Temperature changed.");          

Upvotes: 1

Edwin Buck
Edwin Buck

Reputation: 70909

Unique is only unique within some scope. Eventually, even every int or long value will be used.

So think about what "uniqueness" means to you. Then use a wrapper that will ensure your logging is handled with that id inserted.

Note that with slf4j you are dealing with an interface which will make a number of logging APIs consistent. This means you probably won't have the option to sub-class or even inject your implementation of the interface to ensure your consistent logging. Therefore you will be constrained to techniques like wrapping your logging API (preferably through the "consistent" interface).

package mypackage.log;

public class LoggerWrapper implements org.log4j.Logger {

   private org.log4j.Logger logger;

   public LoggerWrapper(org.log4j.Logger logger) {
     this.logger = logger;
   }

   public String getUniqueId() {
     return ...;
   }

   public void info(String message, Object params...) {
     logger.info(String.format("[%d] %s", getUniqueId(), message), params));
   }

   ... implement all the other methods ...
}

And this means that you will have to make your own LoggerFactory interface too

public Logger getLogger(String name) {
  return new LoggerWrapper(org.sql4j.LoggerFactory(name));
}

While the code above has a few warts (not actually testing it); hopefully, it will give you an idea.

Upvotes: 0

Related Questions