151

At the moment a default entry looks something like this:

Oct 12, 2008 9:45:18 AM myClassInfoHere
INFO: MyLogMessageHere

How do I get it to do this?

Oct 12, 2008 9:45:18 AM myClassInfoHere - INFO: MyLogMessageHere

Clarification I'm using java.util.logging

Obediah Stane
  • 15,471
  • 14
  • 39
  • 28
  • I landed here because of adding Tomcat server to Eclipse. It seems Tomcat ignores the logging.properties so all answers below, except setting VM argument, failed. Actually this problem is answered here: https://stackoverflow.com/questions/44198899/tomcat-ignores-logging-properties-when-started-from-eclipse . Hope it helps someone :-) – Jose Manuel Gomez Alvarez Apr 04 '22 at 19:24

10 Answers10

94

As of Java 7, java.util.logging.SimpleFormatter supports getting its format from a system property, so adding something like this to the JVM command line will cause it to print on one line:

-Djava.util.logging.SimpleFormatter.format='%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n'

Alternatively, you can also add this to your logger.properties:

java.util.logging.SimpleFormatter.format='%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n'
Trevor Robinson
  • 15,694
  • 5
  • 73
  • 72
78

Similar to Tervor, But I like to change the property on runtime.

Note that this need to be set before the first SimpleFormatter is created - as was written in the comments.

    System.setProperty("java.util.logging.SimpleFormatter.format", 
            "%1$tF %1$tT %4$s %2$s %5$s%6$s%n");
Guy L
  • 2,824
  • 2
  • 27
  • 37
  • 7
    Note that this need to be set before the first SimpleFormatter is created - for example before getting global logger's handlers. – Sheepy Jul 06 '16 at 16:43
  • 5
    This is the quickest way to force your logs to write out to a single line without adding any other startup parameters to the JVM. But make sure you set this property before you make your call to 'new SimpleFormatter()' in your code. – Salvador Valencia Aug 02 '16 at 19:29
  • 1
    FYI this pattern generates messages like this: `2022-03-16 13:40:04 INFORMATION org.apache.coyote.AbstractProtocol start Starting ProtocolHandler ["http-bio-8080"] ` – Grim Mar 16 '22 at 12:40
77

1) -Djava.util.logging.SimpleFormatter.format

Java 7 supports a property with the java.util.Formatter format string syntax.

-Djava.util.logging.SimpleFormatter.format=... 

See here.

My favorite is:

-Djava.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n

which makes output like:

2014-09-02 16:44:57 SEVERE org.jboss.windup.util.ZipUtil unzip: Failed to load: foo.zip

2) Putting it to IDEs

IDEs typically let you set system properties for a project. E.g. in NetBeans, instead of adding -D...=... somewhere, add the property in the action dialog, in a form of java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-... - without any quotes. The IDE should figure out.

3) Putting that to Maven - Surefire

For your convenience, Here is how to put it to Surefire:

<!-- Surefire -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.17</version>
    <configuration>
        <systemPropertyVariables>
            <!-- Set JUL Formatting -->
            <java.util.logging.SimpleFormatter.format>%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n</java.util.logging.SimpleFormatter.format>
        </systemPropertyVariables>
    </configuration>
</plugin>

4) Hand-made

I have a library with few java.util.logging related classes. Amongst them, it's SingleLineFormatter. Downloadable jar here.

public class SingleLineFormatter extends Formatter {

  Date dat = new Date();
  private final static String format = "{0,date} {0,time}";
  private MessageFormat formatter;
  private Object args[] = new Object[1];

  // Line separator string.  This is the value of the line.separator
  // property at the moment that the SimpleFormatter was created.
  //private String lineSeparator = (String) java.security.AccessController.doPrivileged(
  //        new sun.security.action.GetPropertyAction("line.separator"));
  private String lineSeparator = "\n";

  /**
   * Format the given LogRecord.
   * @param record the log record to be formatted.
   * @return a formatted log record
   */
  public synchronized String format(LogRecord record) {

    StringBuilder sb = new StringBuilder();

    // Minimize memory allocations here.
    dat.setTime(record.getMillis());    
    args[0] = dat;


    // Date and time 
    StringBuffer text = new StringBuffer();
    if (formatter == null) {
      formatter = new MessageFormat(format);
    }
    formatter.format(args, text, null);
    sb.append(text);
    sb.append(" ");


    // Class name 
    if (record.getSourceClassName() != null) {
      sb.append(record.getSourceClassName());
    } else {
      sb.append(record.getLoggerName());
    }

    // Method name 
    if (record.getSourceMethodName() != null) {
      sb.append(" ");
      sb.append(record.getSourceMethodName());
    }
    sb.append(" - "); // lineSeparator



    String message = formatMessage(record);

    // Level
    sb.append(record.getLevel().getLocalizedName());
    sb.append(": ");

    // Indent - the more serious, the more indented.
    //sb.append( String.format("% ""s") );
    int iOffset = (1000 - record.getLevel().intValue()) / 100;
    for( int i = 0; i < iOffset;  i++ ){
      sb.append(" ");
    }


    sb.append(message);
    sb.append(lineSeparator);
    if (record.getThrown() != null) {
      try {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        record.getThrown().printStackTrace(pw);
        pw.close();
        sb.append(sw.toString());
      } catch (Exception ex) {
      }
    }
    return sb.toString();
  }
}
tomerpacific
  • 4,704
  • 13
  • 34
  • 52
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
  • nicer memory consumption than the other solution. – Tim Williscroft Sep 23 '11 at 00:36
  • I tried this - but it gives me the log in XML - what am I doing wrong - http://stackoverflow.com/questions/16030578/subclassing-java-util-logging-formatter-always-prints-xml – user93353 Apr 16 '13 at 06:58
  • if it turns XML instead of the format you expected - that means the setting in your properties file did not found your formatter class, you can do 2 things: 1. make sure your class is in a package and set the formatter property to that class and package 2. make sure your class has a unique name like "MyFormatter", last: make sure all handlers have the formatter you wanted (java.util.logging.ConsoleHandler.formatter=my.package.MyFormatter and also: java.util.logging.FileHandler.formatter=my.package.MyFormatter) – Shaybc Mar 29 '14 at 10:56
  • Thanks for sharing. I shared a Formatter I wrote in [response to another question](http://stackoverflow.com/a/19991351/249623). Its performed alright for me. I like seeing the tricks other developers come up with for making code smaller and faster. – Ryan Jul 11 '14 at 17:02
  • 1
    @ondra-Žižka For what its worth I just sent you a patch on your google code repo. – Ryan Jul 11 '14 at 17:24
  • The google repo is off now... I'll be moving that to github.com/OndraZizka – Ondra Žižka Mar 29 '16 at 04:43
  • Don't forget to use double quotes (at least in IntellIJ) when setting the formatter in the vm options. – Displee Dec 28 '16 at 15:06
  • @OndraŽižka Thank you very much, I customized your formatter a little bit so I'm not using your repo, but it's very didactic – Alvaro Pedraza Jan 24 '20 at 12:36
  • How about the log level? – Raffi Khatchadourian Jul 03 '23 at 16:53
38

Like Obediah Stane said, it's necessary to create your own format method. But I would change a few things:

  • Create a subclass directly derived from Formatter, not from SimpleFormatter. The SimpleFormatter has nothing to add anymore.

  • Be careful with creating a new Date object! You should make sure to represent the date of the LogRecord. When creating a new Date with the default constructor, it will represent the date and time the Formatter processes the LogRecord, not the date that the LogRecord was created.

The following class can be used as formatter in a Handler, which in turn can be added to the Logger. Note that it ignores all class and method information available in the LogRecord.

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;

public final class LogFormatter extends Formatter {

    private static final String LINE_SEPARATOR = System.getProperty("line.separator");

    @Override
    public String format(LogRecord record) {
        StringBuilder sb = new StringBuilder();

        sb.append(new Date(record.getMillis()))
            .append(" ")
            .append(record.getLevel().getLocalizedName())
            .append(": ")
            .append(formatMessage(record))
            .append(LINE_SEPARATOR);

        if (record.getThrown() != null) {
            try {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                record.getThrown().printStackTrace(pw);
                pw.close();
                sb.append(sw.toString());
            } catch (Exception ex) {
                // ignore
            }
        }

        return sb.toString();
    }
}
Benno Richters
  • 15,378
  • 14
  • 42
  • 45
  • I tried this - but it gives me the log in XML - what am I doing wrong - http://stackoverflow.com/questions/16030578/subclassing-java-util-logging-formatter-always-prints-xml – user93353 Apr 16 '13 at 06:59
  • if it turns XML instead of the format you expected - that means the setting in your properties file did not found your formatter class, you can do 2 things: 1. make sure your class is in a package and set the formatter property to that class and package 2. make sure your class has a unique name like "MyFormatter", last: make sure all handlers have the formatter you wanted (java.util.logging.ConsoleHandler.formatter=my.package.MyFormatter and also: java.util.logging.FileHandler.formatter=my.package.MyFormatter) – Shaybc Mar 29 '14 at 10:55
12

This is what I'm using.

public class VerySimpleFormatter extends Formatter {

    private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

    @Override
    public String format(final LogRecord record) {
        return String.format(
                "%1$s %2$-7s %3$s\n",
                new SimpleDateFormat(PATTERN).format(
                        new Date(record.getMillis())),
                record.getLevel().getName(), formatMessage(record));
    }
}

You'll get something like...

2016-08-19T17:43:14.295+09:00 INFO    Hey~
2016-08-19T17:43:16.068+09:00 SEVERE  Seriously?
2016-08-19T17:43:16.068+09:00 WARNING I'm warning you!!!
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
  • How could we have this formatter output exception information, such as its stacktrace? – fegemo Apr 24 '20 at 15:42
  • 1
    @fegemo I think you can print the starcktrace like this. `ofNullable(record.getThrown()).ifPresent(v -> v.printStackTrace());` just before return the formatted message. – Jin Kwon Apr 30 '20 at 03:57
9

Eclipse config

Per screenshot, in Eclipse select "run as" then "Run Configurations..." and add the answer from Trevor Robinson with double quotes instead of quotes. If you miss the double quotes you'll get "could not find or load main class" errors.

rupweb
  • 3,052
  • 1
  • 30
  • 57
5

I've figured out a way that works. You can subclass SimpleFormatter and override the format method

    public String format(LogRecord record) {
        return new java.util.Date() + " " + record.getLevel() + " " + record.getMessage() + "\r\n";
    }

A bit surprised at this API I would have thought that more functionality/flexibility would have been provided out of the box

Obediah Stane
  • 15,471
  • 14
  • 39
  • 28
  • Anyone should use `formatMessage(record)` rather than `record.getMessage()`. Place holders won't changed. – Jin Kwon Aug 19 '16 at 08:44
-2

If you log in a web application using tomcat add:

-Djava.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter

On VM arguments

Mohammad Irfan
  • 101
  • 3
  • 12
-3

This logging is specific to your application and not a general Java feature. What application(s) are you running?

It might be that this is coming from a specific logging library that you are using within your own code. If so, please post the details of which one you are using.

Leigh Caldwell
  • 10,426
  • 4
  • 25
  • 31
-3

if you're using java.util.logging, then there is a configuration file that is doing this to log contents (unless you're using programmatic configuration). So, your options are
1) run post -processor that removes the line breaks
2) change the log configuration AND remove the line breaks from it. Restart your application (server) and you should be good.

anjanb
  • 12,999
  • 18
  • 77
  • 106