Как я могу получить вывод журнала 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 выберите "Запустить как", затем "Запустить конфигурации..." и добавьте ответ Тревора Робинсона с двойными кавычками вместо кавычек. Если вы пропустите двойные кавычки, вы получите ошибки "не удалось найти или загрузить основной класс".
Я понял, как это работает. Вы можете создать подкласс 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) изменить конфигурацию журнала и удалить из него разрывы строк. Перезапустите свое приложение (сервер) и у вас все получится.