Come faccio a visualizzare l'output di registrazione java su una singola riga?


124

Al momento una voce predefinita è simile a questa:

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

Come posso ottenerlo per farlo?

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

Chiarimento sto usando java.util.logging

Risposte:


81

A partire da Java 7, java.util.logging.SimpleFormatter supporta il recupero del suo formato da una proprietà di sistema, quindi l'aggiunta di qualcosa di simile alla riga di comando JVM farà sì che venga stampato su una riga:

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

In alternativa, puoi anche aggiungerlo a 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
Vero a partire da Java7. Non si fa menzione di questo nei documenti Java6.
jbruni

1
Anche in IDEA, funziona con virgolette doppie. @jbruni Questo non funziona in Java6.
Joshua Davis

1
Funziona con virgolette singole in Eclipse per me.
ricco

1
Invece di% 1 $ tY-% 1 $ tm-% 1 $ td% 1 $ tH:% 1 $ tM:% 1 $ tS puoi scrivere% 1 $ tF% 1 $ tT. Lo rende un po 'più corto. Non so se sia ancora più veloce.
Bruno Eberhard

1
... o in logging.properties, con adattamento basato sul suggerimento di @BrunoEberhard e un nome abbreviato di java.util.logging.SimpleFormatter.format=%1$tF %1$tT %4$.1s %2$s %5$s%6$s%n
taglialegna

73

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

Java 7 supporta una proprietà con la java.util.Formattersintassi della stringa di formato.

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

Vedi qui .

Il mio preferito è:

-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

che produce output come:

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

2) Metterlo agli IDE

Gli IDE in genere consentono di impostare le proprietà di sistema per un progetto. Ad esempio in NetBeans, invece di aggiungere -D ... = ... da qualche parte, aggiungi la proprietà nella finestra di dialogo dell'azione, sotto forma di java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-...- senza virgolette. L'IDE dovrebbe capire.

3) Mettendolo a Maven - Surefire

Per tua comodità, ecco come metterlo su 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) Fatto a mano

Ho una libreria con poche java.util.loggingclassi correlate . Tra questi, è SingleLineFormatter. Vaso scaricabile qui .

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

consumo di memoria migliore rispetto all'altra soluzione.
Tim Williscroft

Ho provato questo - ma mi dà il registro in XML - cosa faccio di sbagliato - stackoverflow.com/questions/16030578/...
user93353

se trasforma XML invece del formato che ti aspettavi, significa che l'impostazione nel tuo file delle proprietà non ha trovato la tua classe di formattatore, puoi fare 2 cose: 1. assicurati che la tua classe sia in un pacchetto e imposta la proprietà del formattatore su quella classe e pacchetto 2. assicurati che la tua classe abbia un nome univoco come "MyFormatter", ultimo: assicurati che tutti i gestori abbiano il formattatore che desideri (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter e anche: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc

Grazie per la condivisione. Ho condiviso un formattatore che ho scritto in risposta a un'altra domanda . Va bene per me. Mi piace vedere i trucchi inventati da altri sviluppatori per rendere il codice più piccolo e veloce.
Ryan

1
@ ondra-Žižka Per quel che vale, ti ho appena inviato una patch sul tuo repository di codice Google.
Ryan

61

Simile a Tervor, ma mi piace cambiare la proprietà in fase di esecuzione.

Si noti che questo deve essere impostato prima della creazione del primo SimpleFormatter, come è stato scritto nei commenti.

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

6
Si noti che questo deve essere impostato prima della creazione del primo SimpleFormatter, ad esempio prima di ottenere i gestori del logger globale.
Sheepy

5
Questo è il modo più rapido per forzare la scrittura dei log su una singola riga senza aggiungere altri parametri di avvio alla JVM. Ma assicurati di impostare questa proprietà prima di effettuare la chiamata a "new SimpleFormatter ()" nel codice.
Salvador Valencia

36

Come ha detto Obediah Stane, è necessario creare il proprio formatmetodo. Ma cambierei alcune cose:

  • Crea una sottoclasse derivata direttamente da Formatter, non da SimpleFormatter. Non SimpleFormatterha più niente da aggiungere.

  • Fai attenzione quando crei un nuovo Dateoggetto! Assicurati di rappresentare la data del LogRecord. Quando si crea un nuovo Datecon il costruttore predefinito, rappresenterà la data e l'ora in cui vengono Formatterelaborati LogRecord, non la data in cui è LogRecordstato creato.

La seguente classe può essere utilizzata come formattatore in a Handler, che a sua volta può essere aggiunta al file Logger. Notare che ignora tutte le informazioni sulla classe e sul metodo disponibili nel file 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();
    }
}

Ho provato questo - ma mi dà il registro in XML - cosa faccio di sbagliato - stackoverflow.com/questions/16030578/...
user93353

se trasforma XML invece del formato che ti aspettavi, significa che l'impostazione nel tuo file delle proprietà non ha trovato la tua classe formattatore, puoi fare 2 cose: 1. assicurati che la tua classe sia in un pacchetto e imposta la proprietà del formattatore su quella classe e pacchetto 2. assicurati che la tua classe abbia un nome univoco come "MyFormatter", ultimo: assicurati che tutti i gestori abbiano il formattatore che desideri (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter e anche: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc

10

Questo è quello che sto usando.

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

Otterrai qualcosa come ...

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

Come potremmo avere questo formattatore di informazioni sull'eccezione di output, come il suo stacktrace?
fegemo

1
@fegemo Penso che tu possa stampare lo starcktrace in questo modo. ofNullable(record.getThrown()).ifPresent(v -> v.printStackTrace());appena prima di restituire il messaggio formattato.
Jin Kwon

7

Configurazione di Eclipse

Per screenshot, in Eclipse seleziona "Esegui come" quindi "Esegui configurazioni ..." e aggiungi la risposta di Trevor Robinson con virgolette doppie invece di virgolette. Se si dimenticano le virgolette doppie, verranno visualizzati gli errori "Impossibile trovare o caricare la classe principale".


2
Come per la risposta precedente, funziona in Java 7. Java 6 non ha questa funzione.
Joshua Davis

5

Ho scoperto un modo che funziona. È possibile creare una sottoclasse SimpleFormatter e sovrascrivere il metodo di formattazione

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

Un po 'sorpreso da questa API, avrei pensato che sarebbe stata fornita una maggiore funzionalità / flessibilità immediatamente


Chiunque dovrebbe usare formatMessage(record)piuttosto che record.getMessage(). I segnaposto non cambieranno.
Jin Kwon

-2

Questa registrazione è specifica per l'applicazione e non è una funzionalità Java generale. Quali applicazioni stai utilizzando?

Potrebbe essere che provenga da una libreria di registrazione specifica che stai utilizzando all'interno del tuo codice. In tal caso, inserisci i dettagli di quello che stai utilizzando.


3
Non è un'applicazione di registrazione casuale. È di proprietà di Javajava.util.logging.Logger
André C. Andersen

-2

Se accedi a un'applicazione web utilizzando Tomcat aggiungi:

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

Sugli argomenti della VM


-3

se stai usando java.util.logging, allora c'è un file di configurazione che lo fa per registrare i contenuti (a meno che tu non stia usando la configurazione programmatica). Quindi, le tue opzioni sono
1) esegui post-processore che rimuove le interruzioni di riga
2) modifica la configurazione del registro E rimuovi le interruzioni di riga da esso. Riavvia la tua applicazione (server) e dovresti essere bravo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.