153 votes

Comment faire pour que la sortie de la journalisation java apparaisse sur une seule ligne ?

Actuellement, une entrée par défaut ressemble à quelque chose comme ceci :

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

Comment faire pour qu'il fasse ça ?

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

Clarification : j'utilise java.util.logging.

96voto

Trevor Robinson Points 3657

À partir de Java 7, java.util.logging.SimpleFormatter soutient l'obtention de son format à partir d'une propriété du système, donc ajouter quelque chose comme ceci à la ligne de commande de la JVM provoquera l'impression sur une seule ligne :

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

Vous pouvez également ajouter ceci à votre 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 votes

Vrai à partir de Java7. Il n'y a aucune mention de cela dans les documents de Java6.

1 votes

Aussi dans IDEA, fonctionne avec des guillemets doubles. @jbruni Cela ne fonctionne pas dans Java6.

1 votes

Cela fonctionne avec des guillemets simples dans Eclipse pour moi.

78voto

Ondra Žižka Points 8262

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

Java 7 prend en charge une propriété dont le nom est java.util.Formatter syntaxe de la chaîne de format.

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

Voir aquí .

Mon préféré est :

-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

ce qui donne des résultats comme :

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

2) S'adresser aux IDE

Les IDE vous permettent généralement de définir les propriétés du système pour un projet. Par exemple, dans NetBeans, au lieu d'ajouter -D...=... quelque part, ajoutez la propriété dans le dialogue d'action, sous la forme de java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-... - sans guillemets. L'IDE devrait s'en rendre compte.

3) Mettre cela à Maven - Surefire

Pour votre commodité, voici comment le mettre à 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) Fait à la main

J'ai une bibliothèque avec quelques java.util.logging cours connexes . Parmi eux, il y a SingleLineFormatter . Bocal téléchargeable aquí .

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

0 votes

Consommation de mémoire plus agréable que l'autre solution.

0 votes

J'ai essayé cela - mais cela me donne le journal en XML - qu'est-ce que je fais de mal ? stackoverflow.com/questions/16030578/

0 votes

S'il s'agit de XML au lieu du format que vous attendiez - cela signifie que le paramètre dans votre fichier de propriétés n'a pas trouvé votre classe de formateur, vous pouvez faire 2 choses : 1. assurez-vous que votre classe est dans un package et définissez la propriété de formateur à cette classe et ce package 2. assurez-vous que votre classe a un nom unique comme "MyFormatter", enfin : assurez-vous que tous les handlers ont le formateur que vous vouliez (java.util.logging.ConsoleHandler.formatter=my.package.MyFormatter et aussi : java.util.logging.FileHandler.formatter=my.package.MyFormatter)

38voto

Bno Points 5688

Comme Obediah Stane l'a dit, il est nécessaire de créer votre propre format méthode. Mais je changerais certaines choses :

  • Créer une sous-classe directement dérivée de Formatter et non de SimpleFormatter . Le site SimpleFormatter n'a plus rien à ajouter.

  • Faites attention à la création d'un nouveau Date objet ! Vous devez vous assurer de représenter la date du LogRecord . Lors de la création d'une nouvelle Date avec le constructeur par défaut, il représentera la date et l'heure à laquelle l'élément Formatter traite les LogRecord et non la date à laquelle le LogRecord a été créé.

La classe suivante peut être utilisé comme formateur dans un Handler qui, à son tour, peut être ajouté à la Logger . Notez qu'il ignore toutes les informations relatives aux classes et aux méthodes disponibles dans le fichier 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();
    }
}

0 votes

J'ai essayé cela - mais cela me donne le journal en XML - qu'est-ce que je fais de mal ? stackoverflow.com/questions/16030578/

0 votes

S'il s'agit de XML au lieu du format que vous attendiez - cela signifie que le paramètre dans votre fichier de propriétés n'a pas trouvé votre classe de formateur, vous pouvez faire 2 choses : 1. assurez-vous que votre classe est dans un package et définissez la propriété de formateur à cette classe et ce package 2. assurez-vous que votre classe a un nom unique comme "MyFormatter", enfin : assurez-vous que tous les handlers ont le formateur que vous vouliez (java.util.logging.ConsoleHandler.formatter=my.package.MyFormatter et aussi : java.util.logging.FileHandler.formatter=my.package.MyFormatter)

10voto

rupweb Points 158

Eclipse config

Selon la capture d'écran, dans Eclipse, sélectionnez "run as" puis "Run Configurations..." et ajoutez la réponse de Trevor Robinson avec des guillemets au lieu de guillemets. Si vous oubliez les guillemets, vous obtiendrez l'erreur "could not find or load main class".

2 votes

Conformément à la réponse précédente, cela fonctionne en Java 7. Java 6 ne dispose pas de cette fonctionnalité.

5voto

Obediah Stane Points 2278

J'ai trouvé un moyen qui fonctionne. Vous pouvez sous-classer SimpleFormatter et surcharger la méthode de formatage.

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

Je suis un peu surpris par cette API. J'aurais pensé que plus de fonctionnalités/flexibilité auraient été fournies d'emblée.

0 votes

Tout le monde devrait utiliser formatMessage(record) plutôt que record.getMessage() . Les porte-places n'ont pas changé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X