Как я могу получить вывод журнала Java в одну строку?

На данный момент запись по умолчанию выглядит примерно так:

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

Как мне заставить это сделать?

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

Уточнение Я использую java.util.logging

10 ответов

Начиная с Java 7, java.util.logging.SimpleFormatter поддерживает получение его формата из системного свойства, поэтому добавление чего-либо подобного в командную строку JVM приведет к тому, что оно будет печататься в одной строке:

-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'

Кроме того, вы также можете добавить это к вашему 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'

Похож на Tervor, но мне нравится менять свойство во время выполнения.

Обратите внимание, что это необходимо установить до создания первого SimpleFormatter - как было написано в комментариях.

    System.setProperty("java.util.logging.SimpleFormatter.format", 
            "%1$tF %1$tT %4$s %2$s %5$s%6$s%n");

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

Java 7 поддерживает свойство с java.util.Formatter синтаксис форматной строки.

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

Смотрите здесь.

Мой любимый:

-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

который делает вывод как:

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

2) Помещение в IDE

Среды IDE обычно позволяют устанавливать системные свойства для проекта. Например, в NetBeans вместо добавления -D...=... где-нибудь добавьте свойство в диалоге действий в форме java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-... - без кавычек. IDE должен выяснить.

3) Положить это в Maven - Surefire

Для вашего удобства вот как это сделать в 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) Ручная работа

У меня есть библиотека с несколькими java.util.logging связанные классы. Среди них это SingleLineFormatter, Скачать банку можно здесь.

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();
  }
}

Как сказал Обедия Стейн, необходимо создать свой собственный format метод. Но я бы изменил несколько вещей:

  • Создайте подкласс, непосредственно полученный из Formatterне из SimpleFormatter, SimpleFormatter больше нечего добавить

  • Будьте осторожны с созданием нового Date объект! Вы должны обязательно указать дату LogRecord, При создании нового Date с конструктором по умолчанию, он будет представлять дату и время Formatter обрабатывает LogRecord, а не дата, когда LogRecord был создан.

Следующий класс можно использовать в качестве средства форматирования в Handlerкоторый, в свою очередь, может быть добавлен к Logger, Обратите внимание, что он игнорирует всю информацию о классе и методе, доступную в 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();
    }
}

Это то, что я использую.

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));
    }
}

Вы получите что-то вроде...

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!!!

Eclipse config

На скриншоте в Eclipse выберите "Запустить как", затем "Запустить конфигурации..." и добавьте ответ Тревора Робинсона с двойными кавычками вместо кавычек. Если вы пропустите двойные кавычки, вы получите ошибки "не удалось найти или загрузить основной класс".

Я понял, как это работает. Вы можете создать подкласс SimpleFormatter и переопределить метод формата

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

Немного удивленный этим API, я бы подумал, что больше функциональности / гибкости было бы обеспечено из коробки

Это ведение журнала относится к вашему приложению, а не является общей функцией Java. Какие приложения вы используете?

Возможно, это происходит из определенной библиотеки журналов, которую вы используете в своем собственном коде. Если это так, пожалуйста, опубликуйте информацию о том, какой из них вы используете.

Если вы входите в веб-приложение с помощью tomcat, добавьте:

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

На ВМ аргументы

Если вы используете java.util.logging, то есть файл конфигурации, который делает это для регистрации содержимого (если вы не используете программную конфигурацию). Итак, ваши варианты
1) запустить постпроцессор, который удаляет разрывы строк
2) изменить конфигурацию журнала и удалить из него разрывы строк. Перезапустите свое приложение (сервер) и у вас все получится.

Другие вопросы по тегам