Java günlük çıktısının tek bir satırda görünmesini nasıl sağlayabilirim?


124

Şu anda varsayılan bir giriş şuna benzer:

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

Bunu yapmasını nasıl sağlayabilirim?

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

Açıklama java.util.logging kullanıyorum

Yanıtlar:


81

Java 7'den itibaren java.util.logging.SimpleFormatter , biçimini bir sistem özelliğinden almayı destekler , bu nedenle JVM komut satırına böyle bir şey eklemek, tek satırda yazdırılmasına neden olur:

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

Alternatif olarak, bunu aşağıdakilere de ekleyebilirsiniz 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
Java7 itibariyle doğrudur. Java6 belgelerinde bundan bahsedilmez.
jbruni

1
Ayrıca IDEA'da çift tırnakla çalışır. @jbruni Bu Java6'da çalışmaz.
Joshua Davis

1
Eclipse'de tek tırnakla benim için çalışıyor.
zengin

1
% 1 $ tY-% 1 $ tm-% 1 $ td% 1 $ tH:% 1 $ tM:% 1 $ tS yerine% 1 $ tF% 1 $ tT yazabilirsiniz. Biraz kısaltır. Daha hızlı mı bilmiyorum.
Bruno Eberhard

1
... ya da logging.properties@BrunoEberhard'ın önerisine ve kısaltılmış bir kaydedici adına göre uyarlama ile: 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, java.util.Formatterbiçim dizesi sözdizimine sahip bir özelliği destekler .

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

Buraya bakın .

Benim favorim:

-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

bu da çıktıyı şöyle yapar:

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

2) IDE'lere koymak

IDE'ler tipik olarak bir proje için sistem özelliklerini belirlemenize izin verir. Örneğin, NetBeans'te, bir yere -D ... = ... eklemek yerine, özelliği eylem iletişim kutusuna şu şekilde ekleyin:java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-... herhangi bir tırnak işareti olmadan - . IDE çözmeli.

3) Bunu Maven'e koymak - Surefire

Size kolaylık sağlamak için, Surefire'a şu şekilde aktarabilirsiniz:

        <!-- 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) El yapımı

Birkaç java.util.loggingilgili ders içeren bir kütüphanem var . Bunların arasında var SingleLineFormatter. İndirilebilir kavanoz burada .

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

diğer çözümden daha iyi bellek tüketimi.
Tim Williscroft

Bunu denedim - ama bana
XML'deki

Beklediğiniz format yerine XML'i döndürürse - bu, özellikler dosyanızdaki ayarın formatlayıcı sınıfınızı bulamadığı anlamına gelir, 2 şey yapabilirsiniz: 1. Sınıfınızın bir pakette olduğundan emin olun ve formatter özelliğini bu sınıfa ayarlayın ve paket 2. Sınıfınızın "MyFormatter" gibi benzersiz bir ada sahip olduğundan emin olun, son olarak: tüm işleyicilerin istediğiniz biçimlendiriciye sahip olduğundan emin olun (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter ve ayrıca: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc

Paylaşım için teşekkürler. Başka bir soruya yanıt olarak yazdığım bir Biçimlendiriciyi paylaştım . Benim için iyi yapıldı. Diğer geliştiricilerin kodu küçültmek ve hızlandırmak için bulduğu püf noktaları görmeyi seviyorum.
Ryan

1
@ ondra-Žižka Değeri ne olursa olsun, size google kod deponuzda bir yama gönderdim.
Ryan

62

Tervor'a benzer, ancak özelliği çalışma zamanında değiştirmeyi seviyorum.

Yorumlarda yazıldığı gibi bunun ilk SimpleFormatter oluşturulmadan önce ayarlanması gerektiğini unutmayın.

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

6
Bunun, ilk SimpleFormatter oluşturulmadan önce, örneğin global logger'ın işleyicilerini almadan önce ayarlanması gerektiğini unutmayın.
Sheepy

5
Bu, günlüklerinizi JVM'ye başka başlangıç ​​parametreleri eklemeden tek bir satıra yazmaya zorlamanın en hızlı yoludur. Ancak, kodunuzda 'new SimpleFormatter ()' çağrınızı yapmadan önce bu özelliği ayarladığınızdan emin olun.
Salvador Valencia

36

Obediah Stane'in dediği gibi, kendi formatyönteminizi oluşturmanız gerekiyor . Ama birkaç şeyi değiştirirdim:

  • Doğrudan türetilmiş bir alt sınıf oluşturun Formatter, buradan değil SimpleFormatter. SimpleFormatterArtık eklemek ilgisi yoktur.

  • Yeni bir Datenesne oluştururken dikkatli olun ! Tarihini temsil ettiğinizden emin olmalısınız LogRecord. DateVarsayılan kurucu ile bir yeni oluştururken, oluşturulduğu tarihi değil, Formatterişlemlerin tarih ve saatini temsil eder .LogRecordLogRecord

Aşağıdaki sınıf edilebilir biçimlendirici olarak kullanılan bir de Handlersırayla olabilir, ilave etmek Logger. .NET Framework içinde bulunan tüm sınıf ve yöntem bilgilerini yok saydığını unutmayın 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();
    }
}

Bunu denedim - ama bana
XML'deki

Beklediğiniz format yerine XML'i döndürürse - bu, özellikler dosyanızdaki ayarın formatlayıcı sınıfınızı bulamadığı anlamına gelir, 2 şey yapabilirsiniz: 1. Sınıfınızın bir pakette olduğundan emin olun ve formatter özelliğini bu sınıfa ayarlayın ve paket 2. Sınıfınızın "MyFormatter" gibi benzersiz bir ada sahip olduğundan emin olun, son olarak: tüm işleyicilerin istediğiniz biçimlendiriciye sahip olduğundan emin olun (java.util.logging.ConsoleHandler.formatter = my.package.MyFormatter ve ayrıca: java.util .logging.FileHandler.formatter = my.package.MyFormatter)
Shaybc

10

Ben bunu kullanıyorum.

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

Şöyle bir şey alacaksın ...

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

Bu biçimlendiricinin, yığın izi gibi istisna bilgisini çıktısına nasıl sahip olabiliriz?
fegemo

1
@fegemo Starcktrace'i bu şekilde yazdırabileceğinizi düşünüyorum. ofNullable(record.getThrown()).ifPresent(v -> v.printStackTrace());biçimlendirilmiş mesajı döndürmeden hemen önce.
Jin Kwon

7

Eclipse yapılandırması

Ekran görüntüsü başına, Eclipse'de "farklı çalıştır" ı ve ardından "Yapılandırmaları Çalıştır ..." ı seçin ve Trevor Robinson'dan gelen yanıtı tırnak yerine çift tırnaklarla ekleyin. Çift tırnak işaretlerini kaçırırsanız, "ana sınıfı bulamadı veya yükleyemedi" hatalarını alırsınız.


2
Önceki cevaba göre, bu Java 7'de çalışır. Java 6 bu özelliğe sahip değildir.
Joshua Davis

5

İşe yarayan bir yol buldum. SimpleFormatter'ı alt sınıflandırabilir ve format yöntemini geçersiz kılabilirsiniz

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

Bu API'ye biraz şaşırdım kutudan daha fazla işlevsellik / esneklik sağlanacağını düşünürdüm


Bunun formatMessage(record)yerine herkes kullanmalı record.getMessage(). Yer sahipleri değişmeyecek.
Jin Kwon

-2

Bu günlük kaydı, uygulamanıza özeldir ve genel bir Java özelliği değildir. Hangi uygulamaları çalıştırıyorsunuz?

Bu, kendi kodunuz içinde kullandığınız belirli bir günlük kitaplığından geliyor olabilir. Öyleyse, lütfen hangisini kullandığınızın ayrıntılarını gönderin.


3
Rastgele kaydedici bir uygulama değil. java.util.logging.Logger
André

-2

Tomcat kullanarak bir web uygulamasında oturum açarsanız şunu ekleyin:

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

Sanal makine argümanlarında


-3

java.util.logging kullanıyorsanız, içeriği günlüğe kaydetmek için bunu yapan bir yapılandırma dosyası vardır (programlı yapılandırmayı kullanmıyorsanız). Dolayısıyla, seçenekleriniz şunlardır:
1) satır sonlarını kaldıran son işlemciyi çalıştırın
2) günlük yapılandırmasını değiştirin VE satır sonlarını buradan kaldırın. Uygulamanızı (sunucunuzu) yeniden başlatın ve iyi olmalısınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.