Comment faire apparaître la sortie de journalisation Java sur une seule ligne?

124

Pour le moment, une entrée par défaut ressemble à ceci:

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

Comment puis-je le faire faire?

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

Clarification J'utilise java.util.logging

Obediah Stane
la source

Réponses:

81

À partir de Java 7, java.util.logging.SimpleFormatter prend en charge l'obtention de son format à partir d'une propriété système, donc l'ajout de quelque chose comme ça à la ligne de commande JVM le fera imprimer sur une 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'
Trevor Robinson
la source
4
Vrai à partir de Java7. Il n'y a aucune mention de cela dans la documentation Java6.
jbruni
1
Également dans IDEA, fonctionne avec des guillemets doubles. @jbruni Cela ne fonctionne pas en Java6.
Joshua Davis
1
Fonctionne avec des guillemets simples dans Eclipse pour moi.
riche
1
Au lieu de% 1 $ tY-% 1 $ tm-% 1 $ td% 1 $ tH:% 1 $ tM:% 1 $ tS, vous pouvez écrire% 1 $ tF% 1 $ tT. Rend un peu plus court. Je ne sais pas si c'est encore plus rapide.
Bruno Eberhard
1
... ou en logging.properties, avec adaptation basée sur la suggestion de @BrunoEberhard et un nom abrégé de bûcheron: 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 prend en charge une propriété avec la java.util.Formattersyntaxe de chaîne de format.

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

Regardez ici .

Mon favori 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 rend la sortie comme:

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

2) Le mettre aux IDE

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

3) Mettre ça à Maven - Surefire

Pour votre commodité, voici comment l'appliquer à 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.loggingclasses connexes . Parmi eux, c'est SingleLineFormatter. Pot téléchargeable ici .

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();
  }
}
Ondra Žižka
la source
meilleure consommation de mémoire que l'autre solution.
Tim Williscroft
J'ai essayé ceci - mais cela me donne le journal en XML - qu'est-ce que je fais de mal - stackoverflow.com/questions/16030578/…
user93353
s'il transforme XML au lieu du format attendu - cela signifie que le paramètre de 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 sur cette classe et package 2. assurez-vous que votre classe a un nom unique comme "MyFormatter", dernier: assurez-vous que tous les gestionnaires ont le formateur que vous vouliez (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter et aussi: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc
Merci d'avoir partagé. J'ai partagé un formateur que j'ai écrit en réponse à une autre question . C'est bien pour moi. J'aime voir les astuces que d'autres développeurs proposent pour rendre le code plus petit et plus rapide.
Ryan le
1
@ ondra-Žižka Pour ce que ça vaut, je viens de vous envoyer un correctif sur votre repo de code google.
Ryan
61

Similaire à Tervor, mais j'aime changer la propriété à l'exécution.

Notez que cela doit être défini avant la création du premier SimpleFormatter - comme cela a été écrit dans les commentaires.

    System.setProperty("java.util.logging.SimpleFormatter.format", 
            "%1$tF %1$tT %4$s %2$s %5$s%6$s%n");
Guy L
la source
6
Notez que cela doit être défini avant la création du premier SimpleFormatter - par exemple avant d'obtenir les gestionnaires de l'enregistreur global.
Sheepy
5
C'est le moyen le plus rapide de forcer vos journaux à écrire sur une seule ligne sans ajouter d'autres paramètres de démarrage à la JVM. Mais assurez-vous de définir cette propriété avant de faire votre appel à «new SimpleFormatter ()» dans votre code.
Salvador Valencia
36

Comme l'a dit Obediah Stane, il est nécessaire de créer sa propre formatméthode. Mais je changerais quelques choses:

  • Créez une sous-classe directement dérivée de Formatter, pas de SimpleFormatter. Le SimpleFormattern'a plus rien à ajouter.

  • Soyez prudent avec la création d'un nouvel Dateobjet! Vous devez vous assurer de représenter la date du LogRecord. Lors de la création d'un nouveau Dateavec le constructeur par défaut, il représentera la date et l'heure du Formattertraitement LogRecord, et non la date de LogRecordcréation du.

La classe suivante peut être utilisée comme formateur dans a Handler, qui à son tour peut être ajoutée au Logger. Notez qu'il ignore toutes les informations de classe et de méthode disponibles dans le 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();
    }
}
Benno Richters
la source
J'ai essayé ceci - mais cela me donne le journal en XML - qu'est-ce que je fais de mal - stackoverflow.com/questions/16030578
...
s'il transforme XML au lieu du format attendu - cela signifie que le paramètre de 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 sur cette classe et package 2. assurez-vous que votre classe a un nom unique comme "MyFormatter", dernier: assurez-vous que tous les gestionnaires ont le formateur que vous vouliez (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter et aussi: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc
10

C'est ce que j'utilise.

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

Vous obtiendrez quelque chose comme ...

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!!!
Jin Kwon
la source
Comment pourrions-nous avoir ce formateur de sortie des informations d'exception, telles que son stacktrace?
fegemo le
1
@fegemo Je pense que vous pouvez imprimer le starcktrace comme ça. ofNullable(record.getThrown()).ifPresent(v -> v.printStackTrace());juste avant de renvoyer le message formaté.
Jin Kwon
7

Configuration de l'éclipse

Par capture d'écran, dans Eclipse sélectionnez "exécuter en tant que" puis "Exécuter les configurations ..." et ajoutez la réponse de Trevor Robinson avec des guillemets doubles au lieu de guillemets. Si vous manquez les guillemets doubles, vous obtiendrez des erreurs "Impossible de trouver ou de charger la classe principale".

rupweb
la source
2
Selon la réponse précédente, cela fonctionne dans Java 7. Java 6 n'a pas cette fonctionnalité.
Joshua Davis
5

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

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

Un peu surpris de cette API, j'aurais pensé que plus de fonctionnalités / flexibilité auraient été fournies hors de la boîte

Obediah Stane
la source
Tout le monde devrait utiliser formatMessage(record)plutôt que record.getMessage(). Les espaces réservés ne changeront pas.
Jin Kwon
-2

Cette journalisation est spécifique à votre application et non une fonctionnalité Java générale. Quelle (s) application (s) utilisez-vous?

Il se peut que cela provienne d'une bibliothèque de journalisation spécifique que vous utilisez dans votre propre code. Si tel est le cas, veuillez publier les détails de celui que vous utilisez.

Leigh Caldwell
la source
3
Ce n'est pas une application d'enregistrement aléatoire. C'est javajava.util.logging.Logger
André C. Andersen
-2

Si vous vous connectez à une application Web à l'aide de tomcat, ajoutez:

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

Sur les arguments VM

Mohammad Irfan
la source
-3

si vous utilisez java.util.logging, il existe un fichier de configuration qui le fait pour consigner le contenu (sauf si vous utilisez la configuration par programmation). Ainsi, vos options sont
1) exécuter le post-processeur qui supprime les sauts de ligne
2) modifier la configuration du journal ET supprimer les sauts de ligne. Redémarrez votre application (serveur) et vous devriez être bon.

Anjanb
la source