Bagaimana cara membuat keluaran pencatatan java muncul dalam satu baris?


124

Saat ini entri default terlihat seperti ini:

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

Bagaimana saya membuatnya melakukan ini?

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

Klarifikasi Saya menggunakan java.util.logging

Jawaban:


81

Mulai Java 7, java.util.logging.SimpleFormatter mendukung mendapatkan formatnya dari properti sistem, jadi menambahkan sesuatu seperti ini ke baris perintah JVM akan membuatnya dicetak pada satu baris:

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

Atau, Anda juga dapat menambahkan ini ke 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'

4
Benar seperti Java7. Ini tidak disebutkan dalam dokumen Java6.
jbruni

1
Juga di IDEA, berfungsi dengan tanda kutip ganda. @jbruni Ini tidak bekerja di Java6.
Joshua Davis

1
Bekerja dengan tanda kutip tunggal di Eclipse untuk saya.
kaya

1
Alih-alih% 1 $ tY-% 1 $ tm-% 1 $ td% 1 $ tH:% 1 $ tM:% 1 $ tS Anda dapat menulis% 1 $ tF% 1 $ tT. Membuatnya sedikit lebih pendek. Saya tidak tahu apakah itu lebih cepat.
Bruno Eberhard

1
... atau logging.properties, dengan adaptasi berdasarkan saran oleh @BrunoEberhard dan nama penebang yang dipersingkat: java.util.logging.SimpleFormatter.format=%1$tF %1$tT %4$.1s %2$s %5$s%6$s%n
Kariem

73

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

Java 7 mendukung properti dengan java.util.Formattersintaks format string.

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

Lihat disini .

Favorit saya adalah:

-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

yang menghasilkan keluaran seperti:

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

2) Menempatkannya ke IDE

Biasanya IDE memungkinkan Anda menyetel properti sistem untuk suatu proyek. Misalnya di NetBeans, alih-alih menambahkan -D ... = ... di suatu tempat, tambahkan properti di dialog tindakan, dalam bentuk java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-...- tanpa tanda kutip. IDE harus mencari tahu.

3) Menempatkan itu ke Maven - Pasti

Untuk kenyamanan Anda, Berikut adalah cara memasukkannya ke 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) Buatan tangan

Saya memiliki perpustakaan dengan beberapa java.util.loggingkelas terkait . Di antara mereka, itu SingleLineFormatter. Jar yang dapat diunduh di sini .

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

konsumsi memori yang lebih baik daripada solusi lainnya.
Tim Williscroft

Saya mencoba ini - tetapi memberi saya log in XML - apa yang saya lakukan salah - stackoverflow.com/questions/16030578/…
user93353

jika ternyata XML bukan format yang Anda harapkan - itu berarti setelan di file properti Anda tidak menemukan kelas pemformat Anda, Anda dapat melakukan 2 hal: 1. pastikan kelas Anda ada dalam paket dan setel properti pemformat ke kelas itu dan paket 2. pastikan kelas Anda memiliki nama unik seperti "MyFormatter", terakhir: pastikan semua penangan memiliki formatter yang Anda inginkan (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter dan juga: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc

Terima kasih telah berbagi. Saya membagikan Formatter yang saya tulis sebagai tanggapan atas pertanyaan lain . Ini dilakukan dengan baik untuk saya. Saya suka melihat trik yang dibuat oleh pengembang lain untuk membuat kode lebih kecil dan lebih cepat.
Ryan

1
@ ondra-Žižka Untuk apa nilainya, saya baru saja mengirimi Anda tambalan di repo kode google Anda.
Ryan

61

Mirip dengan Tervor, Tapi saya suka mengubah properti saat runtime.

Perhatikan bahwa ini perlu disetel sebelum SimpleFormatter pertama dibuat - seperti yang tertulis di komentar.

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

6
Perhatikan bahwa ini perlu disetel sebelum SimpleFormatter pertama dibuat - misalnya sebelum mendapatkan penangan logger global.
Sheepy

5
Ini adalah cara tercepat untuk memaksa log Anda menulis ke satu baris tanpa menambahkan parameter startup lainnya ke JVM. Tapi pastikan Anda menyetel properti ini sebelum membuat panggilan ke 'new SimpleFormatter ()' di kode Anda.
Salvador Valencia

36

Seperti yang dikatakan Obediah Stane, Anda perlu membuat formatmetode Anda sendiri . Tetapi saya akan mengubah beberapa hal:

  • Buat subclass yang diturunkan langsung dari Formatter, bukan dari SimpleFormatter. Tidak SimpleFormatterada lagi yang ditambahkan.

  • Hati-hati saat membuat Dateobjek baru ! Anda harus memastikan untuk mewakili tanggal LogRecord. Saat membuat baru Datedengan konstruktor default, itu akan mewakili tanggal dan waktu Formatterproses LogRecord, bukan tanggal LogRecorddibuat.

Kelas berikut dapat digunakan sebagai pemformat di a Handler, yang pada gilirannya dapat ditambahkan ke Logger. Perhatikan bahwa ini mengabaikan semua informasi kelas dan metode yang tersedia di 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();
    }
}

Saya mencoba ini - tetapi memberi saya log in XML - apa yang saya lakukan salah - stackoverflow.com/questions/16030578/…
user93353

jika ternyata XML bukan format yang Anda harapkan - itu berarti setelan dalam file properti Anda tidak menemukan kelas pemformat Anda, Anda dapat melakukan 2 hal: 1. pastikan kelas Anda ada dalam paket dan setel properti pemformat ke kelas itu dan paket 2. pastikan kelas Anda memiliki nama unik seperti "MyFormatter", terakhir: pastikan semua penangan memiliki formatter yang Anda inginkan (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter dan juga: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc

10

Inilah yang saya gunakan.

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

Anda akan mendapatkan sesuatu seperti ...

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

Bagaimana kita bisa memiliki informasi pengecualian keluaran formatter ini, seperti stacktrace?
fegemo

1
@fegemo Saya rasa Anda dapat mencetak starcktrace seperti ini. ofNullable(record.getThrown()).ifPresent(v -> v.printStackTrace());tepat sebelum mengembalikan pesan yang telah diformat.
Jin Kwon

7

Konfigurasi Eclipse

Per screenshot, di Eclipse pilih "run as" lalu "Run Configurations ..." dan tambahkan jawaban dari Trevor Robinson dengan tanda kutip ganda, bukan tanda kutip. Jika Anda melewatkan tanda kutip ganda, Anda akan mendapatkan kesalahan "tidak dapat menemukan atau memuat kelas utama".


2
Sesuai jawaban sebelumnya, ini berfungsi di Java 7. Java 6 tidak memiliki fitur ini.
Joshua Davis

5

Saya telah menemukan cara yang berhasil. Anda dapat membuat subkelas SimpleFormatter dan mengganti metode format

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

Sedikit terkejut dengan API ini, saya mengira bahwa lebih banyak fungsionalitas / fleksibilitas akan disediakan di luar kotak


Siapapun harus menggunakan formatMessage(record)daripada record.getMessage(). Placeholder tidak akan berubah.
Jin Kwon

-2

Pencatatan log ini khusus untuk aplikasi Anda dan bukan fitur Java umum. Aplikasi apa yang Anda jalankan?

Mungkin ini berasal dari perpustakaan logging tertentu yang Anda gunakan dalam kode Anda sendiri. Jika demikian, harap posting detail mana yang Anda gunakan.


3
Ini bukan aplikasi logger acak. Ini milik javajava.util.logging.Logger
André C. Andersen

-2

Jika Anda masuk ke aplikasi web menggunakan tomcat tambahkan:

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

Tentang argumen VM


-3

jika Anda menggunakan java.util.logging, maka ada file konfigurasi yang melakukan ini untuk mencatat konten (kecuali Anda menggunakan konfigurasi program). Jadi, pilihan Anda adalah
1) jalankan pasca-prosesor yang menghapus jeda baris
2) ubah konfigurasi log DAN hapus jeda baris darinya. Restart aplikasi Anda (server) dan Anda akan baik-baik saja.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.