38

I am currently working on a program wherein, I must write all output to a log file.

I need to write a log method, that should give an output with a level, a message, an object value, another message, an integer value, another message and another integer value, in the same order as I have specified. I can't seem to find a log method that does this. I am using Java.util.logging. Is this possible?

Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58
Gash87
  • 401
  • 1
  • 4
  • 4
  • Consider Log4J http://logging.apache.org/log4j/2.x/ – Mirco Apr 08 '13 at 13:40
  • 1
    @verbose-mode Why? java util logging does all that is required and and is simpler to use. As far as I see it your suggestion breaks the KISS (Keep it Simple S…) principle. – Martin Nov 12 '14 at 12:50

4 Answers4

40

I assume you need the log format in the below format FINE,Message1,object.GetValue(),Message2,1,Message3,2

You need to create an output message format

logger.log(Level.INFO, "{0},{1},{2},{3},{4},{5}",new Object[]{Message1,object.getValue(),Message2,1,Message3,2});

Now you need to create a custom formatter which by extending Formatter class

public class DataFormatter extends Formatter {

@Override
public synchronized String format(LogRecord record) {
    String formattedMessage = formatMessage(record);
    String throwable = "";
    String outputFormat = "%1$s, %2$s \n %3$s"; //Also adding for logging exceptions
    if (record.getThrown() != null) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        pw.println();
        record.getThrown().printStackTrace(pw);
        pw.close();
        throwable = sw.toString();
    }
    return String.format(outputFormat,record.getLevel().getName(),formattedMessage,throwable);
}
}

Now set the newly created formatter

    for(int i=0;i<logger.getHandlers().length;i++)
        logger.getHandlers()[i].setFormatter(new DataFormatter());
Rohit
  • 743
  • 4
  • 10
  • 2
    logger.info("Logging with id {} and cache : {} " ,id,cache ); – abhishek ringsia Apr 26 '18 at 07:21
  • 1
    This answer is correct. I have achieved the same by using `java.util.logging.Logger`'s method `public void log(Level level, String msg, Object params[])`. You just need to number the placeholders in the message like `{0}`, `{1}`, etc. and pass an array of parameters like shown above `new Object[] {parameter1, parameter2}`. – havryliuk Jan 03 '23 at 12:18
34

We used below code while using slf4j logger -

logger.error("Error while finding A from DB. a : {} and b : {}", a, b);
logger.info("Nothing found in db for A with a : {} and b : {}", a, b);
HoKy22
  • 4,057
  • 8
  • 33
  • 54
Sanchi Girotra
  • 1,232
  • 13
  • 13
20

It's a quite old topic, anyhow, my two cents, because I also prefer to use java.util.logging.Logger` in my projects where sufficient.

Lambdas make this boilerplate Formatter extension for multiple custom parameters more or less obsolete, unless you benefit from its application-wide reuse. In (my) simple scenarios, log messages are tailored to the code part where it is inserted, so String.format() is usually much easier and more flexible.

Before Java 8 and lambdas, the Formatter was the only possibility to postpone the message construction. The only alternative was, to construct the message to log in advance before the loggable check based on the Level took place.
With Java 8 lambdas, the String formatting can be postponed to after the loggable check, but still with access to the original method context. The only small downside is, that all accessed fields need to be final, due to the lambda restrictions.

Here a fairly simple snippet:

final String val1 = "lambda expression log message";
final Level level = Level.INFO;
Logger.getGlobal().log(level, () -> 
        String.format("Hello, I'm a %s, evaluated after %s loggable check.", val1, level)
);
Logger.getGlobal().log(level, new RuntimeException(), () -> 
        String.format("Hello, I'm a %s with a stack trace, evaluated after %s loggable check.", val1, level)
);

Hope this helps some of you who also want to use the built-in logging :-)

Cheers Ben

Ben Steinert
  • 1,309
  • 1
  • 11
  • 15
  • 1
    Disadvantage of this is that parameter formatting cannot be applied when they are inserted through `String.format` rather than `java.util.logging.Logger` itself. – Breina Nov 04 '19 at 10:59
0

A simple example that works for me:

Logger logger = java.util.logging.Logger.getLogger("MyLogger");
logger.log(java.util.logging.Level.INFO, "Test {0}, {1}", new Object[]{2, 3});

Result:

INFO: Test 2, 3
ceklock
  • 6,143
  • 10
  • 56
  • 78