How do I get java logging output to appear on a single line?
Asked Answered
B

10

153

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

Backset answered 11/10, 2008 at 22:51 Comment(1)
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: #44199399 . Hope it helps someone :-)Freedafreedman
E
96

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'
Eclipse answered 22/5, 2012 at 16:20 Comment(8)
True as of Java7. There is no mention of this in the Java6 docs.Andesine
Also in IDEA, works with double quotes. @Andesine This does not work in Java6.Ambsace
Works with single quotes in Eclipse for me.Gainless
Instead of %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS you can write %1$tF %1$tT . Makes it a little bit shorter. I don't know if it's even faster.Pensioner
... or in logging.properties, with adaptation based on the suggestion by @BrunoEberhard and a shortened logger name: java.util.logging.SimpleFormatter.format=%1$tF %1$tT %4$.1s %2$s %5$s%6$s%nUnbelieving
If you use IntellIJ, you need to use double quotes. Single quotes didn't work for me.Hobbyhorse
Works better without quotes in logger.properties.Cullum
Trying to set this programmatically, I get this error "The field SimpleFormatter.format is not visible".Angleworm
V
80

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");
Viburnum answered 11/12, 2015 at 17:53 Comment(3)
Note that this need to be set before the first SimpleFormatter is created - for example before getting global logger's handlers.Negation
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.Condor
FYI this pattern generates messages like this: 2022-03-16 13:40:04 INFORMATION org.apache.coyote.AbstractProtocol start Starting ProtocolHandler ["http-bio-8080"] Rosenberger
C
78

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();
  }
}
Colmar answered 9/5, 2011 at 14:0 Comment(9)
nicer memory consumption than the other solution.Nosology
I tried this - but it gives me the log in XML - what am I doing wrong - #16031078Organ
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)Divulgence
Thanks for sharing. I shared a Formatter I wrote in response to another question. Its performed alright for me. I like seeing the tricks other developers come up with for making code smaller and faster.Plump
@ondra-Žižka For what its worth I just sent you a patch on your google code repo.Plump
The google repo is off now... I'll be moving that to github.com/OndraZizkaAlible
Don't forget to use double quotes (at least in IntellIJ) when setting the formatter in the vm options.Hobbyhorse
@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 didacticSalivation
How about the log level?Parnas
A
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();
    }
}
Algy answered 13/10, 2008 at 12:10 Comment(2)
I tried this - but it gives me the log in XML - what am I doing wrong - #16031078Organ
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)Divulgence
B
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!!!
Brno answered 19/8, 2016 at 8:49 Comment(2)
How could we have this formatter output exception information, such as its stacktrace?Leilani
@Leilani I think you can print the starcktrace like this. ofNullable(record.getThrown()).ifPresent(v -> v.printStackTrace()); just before return the formatted message.Brno
B
10

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.

Baronetcy answered 20/3, 2013 at 16:55 Comment(2)
As per the previous answer, this works in Java 7. Java 6 doesn't have this feature.Ambsace
Thank you, it had to be this way, the logging.properties does not work for Eclipse console, for some reason!Freedafreedman
B
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

Backset answered 12/10, 2008 at 6:13 Comment(1)
Anyone should use formatMessage(record) rather than record.getMessage(). Place holders won't changed.Brno
W
-2

If you log in a web application using tomcat add:

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

On VM arguments

Wimer answered 3/10, 2016 at 8:39 Comment(0)
S
-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.

Simba answered 11/10, 2008 at 22:56 Comment(1)
It's not some random logger application. It's java's own java.util.logging.LoggerPrimer
H
-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.

Harper answered 12/10, 2008 at 1:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.