2016-02-01 21 views
6

Ho il seguente problema: Voglio utilizzare lo java.util.logging.Logger. No ho trovato risorse diverse 1, 2, 3, come si può modificare il comportamento del registratore.Come inizializzare i logger correttamente?

Soprattutto nella domanda di 2 a (a mio parere) viene data una buona struttura per inizializzare i logger in base al nome della classe. Ciò consente anche di modificare la verbosità a livello di pacchetto per il debug, se necessario.

Dopo aver scavato un po 'nel problema ho scoperto che il logger globale e il logger "vuoto" (con il nome "") non sono gli stessi. Vedi anche l'esempio qui sotto. Ho appena creato un logger foo.Bar, che è ancorato al logger vuoto invece del logger chiamato foo. Solo se prima creo il logger bar, il logger bar.Baz è ancorato ad esso correttamente.

Ciò rende l'approccio in this question principalmente inutile poiché non è possibile presupporre che i logger principali vengano creati prima. Uno deve analizzare il nome della classe e creare i logger secondo necessità, per quanto vedo.

Sono corretto che devo aggiungere del codice static {...} per inizializzare i logger in modo ricorsivo prima che il proprio logger possa essere inizializzato? Questo ha un effetto negativo se più classi chiamano il metodo Logger.getLogger(String) per i logger del pacchetto (risultanti in più chiamate complessive, ad esempio sia bar.Baz e bar.FooBaz ottenere il logger bar)?

import java.util.Enumeration; 
import java.util.logging.LogManager; 
import java.util.logging.Logger; 
public class TestLogger 
{ 
    public static void main(String[] args) 
    { 
     // Create the logger directly 
     Logger.getLogger("foo.Bar"); 
     // Create the logger objects step-by-step 
     Logger.getLogger("bar"); 
     Logger.getLogger("bar.Baz"); 
     // Put the available loggers to output 
     Enumeration<String> e = LogManager.getLogManager().getLoggerNames(); 
     while(e.hasMoreElements()) 
     { 
      String s = e.nextElement(); 
      Logger l = Logger.getLogger(s); 
      String p = (l.getParent() == null ? "none" : "'" + l.getParent().getName() + "'"); 
      System.out.println("'" + s + "': " + p); 
     } 
    } 
} 

L'output del programma è

'bar': '' 
'global': '' 
'foo.bar': '' 
'bar.baz': 'bar' 
'': none 
+0

'java.utils.Logger's può essere complicato. Sebbene io non comprenda appieno quale sia la vera domanda, una (probabilmente) importante nota a margine: i logger possono essere raccolti. Quando scrivi 'Logger.getLogger (" foo "). SetLevel (x)' nel tuo metodo 'main', e poi ottieni un logger con' Logger.getLogger ("foo") 'da qualche altra parte, ** può ** sii un'istanza diversa! Il logger che hai ottenuto nel file 'main' potrebbe essere già stato raccolto e la seconda chiamata' getLogger ("pippo") 'creerà quindi una nuova istanza. – Marco13

risposta

1

Un effetto negativo di avere Logger.getLogger(String) in ogni classe è che non sarà in grado di prendere in giro (o passare un logger speciale) per le prove.

Esempio: Diciamo che è necessario testare la seguente classe C:

package a.b; 
class C { 
    private Logger logger; 
    private int capacity; 
    private int size; 
    C(int capacity) { 
    this.logger = Logger.getLogger("a.b.C"); 
    this.capacity = capacity; 
    size = 0; 
    } 
    void add(int item) { 
    if (size >= capacity) { 
     logger.log("You already reached the capacity: " + capacity); 
    } 
    //... 
    } 
} 

è un requisito che aggiungono i registri, se viene raggiunta la capacità. Ora devi testarlo. E 'molto difficile e hacky per fare un test che verifica questo:

public void testCapacityReachedLogs() { 
    C c = new C(2); 
    c.add(1); 
    c.add(2); 
    // verify that c logged the exact string: "You already reached the capacity: 2" 
} 

Tuttavia, se si dispone di:

package a.b; 
class D { 
    private Logger logger; 
    private int capacity; 
    private int size; 
    D(Logger logger, int capacity) { 
    this.logger = logger; 
    this.capacity = capacity; 
    size = 0; 
    } 
    void add(int item) { 
    if (size >= capacity) { 
     logger.log("You already reached the capacity: " + capacity); 
    } 
    //... 
    } 
} 

Ora si può deridere Logger:

public void testCapacityReachedLogs() { 
    Logger logger = getMock(Logger.class); 
    D d = new D(logger, 2); 
    d.add(1); 
    d.add(2); 
    verify(logger).log("You already reached the capacity: 2"); 
} 

Annotare il "finto "Il codice correlato non segue necessariamente la sintassi di un framework, è solo per esempio.

+0

Cosa intendi con "deriderlo"? Puoi spiegarci un po '? –

+0

@ChristianWolf Ho aggiunto un esempio con "simulato" – Gavriel

+0

Ah, capisco. Grazie per aver spiegato. –