2015-04-21 5 views
12

Ho un'applicazione che è un semplice networked knock-knock joke app. Ho incorporato alcuni Log4J (versione 2) che ci loggavano. Ecco la classe di server:Come posso rendere utile l'accesso a Apache Log4J in questa applicazione?

import org.apache.logging.log4j.LogManager; 
import org.apache.logging.log4j.Logger; 
import org.apache.logging.log4j.Level; 

import java.net.*; 
import java.io.*; 

public class MessageResponseServer extends Thread /* added in the T just now*/{ /* REPLACED */ 

    private static final Logger logger = LogManager.getLogger("MessageResponseServer"); 
     logger.info("MessageResponseServer.java : INFO message"); 
    public static void main(String[] args) throws IOException { 

     logger.debug("MessageResponseServer.java : DEBUG message"); 

     ServerSocket serverSocket = null; 
     try { 
      serverSocket = new ServerSocket(4444); 
     } catch (IOException e) { 
      System.err.println("Could not listen on port: 4444."); 
      logger.fatal("MessageResponseServer.java : FATAL message - Could not listen on port: 4444."); 

      System.exit(1); 
     } 

     Socket clientSocket = null; 
     try { 
      clientSocket = serverSocket.accept(); 
        logger.debug("MessageResponseServer.java : , debug message"); 
     } catch (IOException e) { 
      System.err.println("Accept failed."); 
      System.exit(1); 
     } 

     PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); 
     BufferedReader in = new BufferedReader(
       new InputStreamReader(
       clientSocket.getInputStream())); 
     String inputLine, outputLine; 
     MessageResponseProtocol mrp = new MessageResponseProtocol(); /* REPLACED */ 

     outputLine = mrp.processInput(null); 
     out.println(outputLine); 

     while ((inputLine = in.readLine()) != null) { 
      outputLine = mrp.processInput(inputLine); 
      out.println(outputLine); 
      if (outputLine.equals("Bye.")) 
      logger.debug("MessageResponseServer.java : , Exiting. DEBUG Message"); 
       break; 
     } 
     out.close(); 
     in.close(); 
     clientSocket.close(); 
     serverSocket.close(); 
    } 
} 

Ed il seguente è il file XML:

<?xml version="1.0" encoding="UTF-8"?> 


<Configuration status="WARN"> 
    <Appenders> 

    <Console name="Console" target="SYSTEM_OUT"> 
     <PatternLayout pattern="%d{HH:mm:ss} [%t] %-5level %logger{36} - %msg%n"/> 
    </Console> 
    <File name="MyFile" fileName="OutputLogFile.log" immediateFlush="false" append="true"> 
      <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> 
     </File> 

    </Appenders> 

    <Loggers> 
    <Root level="ALL"> 
     <Appender-Ref ref="Console"/> 
     <Appender-Ref ref="MyFile"/> 

    </Root> 


    </Loggers> 
</Configuration> 

Quello che mi piacerebbe fare è quello di capire come fare la registrazione un po 'più utile. Aggiungete speciali istruzioni if per decidere se registrare qualcosa (se l'utente inserisce "esci", posso creare un registro specifico).

C'è forse un modo per includere le metriche di prestazione nel logging? Questo sarebbe davvero utile per me. Il mio obiettivo è che il codice mostri qualcosa che possa aiutare a mostrare in seguito funzionalità fail-safe (ad esempio, forse potremmo utilizzare i log per riavviare il lato client se fosse stato abortito).

grazie

+0

Ok ho capito il modo con il file XML: '' – Coffee

risposta

3

un'idea centrale a molti dei quadri di registrazione è che non si decide cosa fare nella domanda, ma nella configurazione. quindi, in pratica, la tua applicazione registra tutto e la tua configurazione "filtra" e invia l'output nel posto giusto (cioè file diversi, il syslog o anche ignorandolo completamente)

in generale, in un ambiente di sviluppo, tu vuoi registrarti di più, così potresti impostare tutto su "DEBUG", mentre in produzione, lo imposti su "INFO".

volte, potrebbe essere utile fare un modello come questo:

if(log.isDebug()) { 
     log.debug("some formatting"); 
} 

per evitare di eseguire la formattazione (in questo caso) e buttare via subito dopo.

il layout del modello è anche un po 'problematico - ad esempio, il recupero del numero di riga è inaffidabile (dipende fondamentalmente dal codice compilato con debug = true) e molto costoso (deve recuperare lo stacktrace ed estrarre la linea informazioni da esso).

per le metriche attuali tempi di esecuzione, si consiglia di guardare altrove - un eccellente libreria che fornisce contatori e misure di tempo compreso max, min, media etc è metriche-core:

https://dropwizard.github.io/metrics/3.1.0/manual/core/

e se si 're utilizzando primavera, si consiglia di guardare il mio aspetto in base a questa libreria:

https://github.com/rmalchow/metrics

4

in primo luogo, il codice non viene compilato. La prima chiamata logger.info() deve essere all'interno di un blocco statico {} o spostata in main(); E il tuo ciclo while() sta per uscire la prima volta - hai bisogno di {} parentesi attorno alle istruzioni di debug e break.

ma ho bisogno di dichiarare i miei pregiudizi :)

  1. Personalmente, trovo poco per logger.debug() chiama. I moderni IDE (io uso Eclipse) forniscono un eccellente supporto per il debugging senza ingombrare il codice con le dichiarazioni logger.debug()[email protected] rmalchow ha già evidenziato gli svantaggi delle affermazioni di debug non necessarie: ho visto un caso in cui le prestazioni sono aumentate di oltre il 100% una volta che alcune dichiarazioni sono state messe in giro con chiamate logger.debug().
  2. Quindi nel mio mondo, la registrazione è per sistemi di produzione che non riesco a eseguire il debugging con l'IDE. Questo porta un numero di responsabilità.
  3. Le chiamate a System.err() devono essere sostituite da chiamate logger.error(). Per impostazione predefinita, questi andranno a System.err, ma è possibile reindirizzare se necessario.
  4. Se non è possibile aggiungere valore, lasciare che le eccezioni si moltiplichino. Tendo a trasformarli in RuntimeExceptions, ma alcuni puristi odiano questo.
  5. Quando è possibile aggiungere un valore, non ingerire la traccia dello stack. Ad esempio, il tuo logger.fatal dovrebbe essere logger.fatal ("..msg ...", eccezione). Ciò salverà molte ore felici di codice grepping.

Per quanto riguarda le metriche, puoi sempre eseguire il rollover - ad es. tempo per quanto tempo richiede una chiamata di back-end per completare e accedere a livello di informazioni. Non ho suggerimenti specifici per un quadro utile, ma altri potrebbero.

2

Per la tua applicazione, penso che quello che hai fatto sia abbastanza. non hai bisogno di più

Debug per il debug/Errore per eccezione ed errori. È possibile aggiungere informazioni per l'avvio e l'arresto del server.

Ora, se ha avuto un'applicazione più grande che si dovrebbe fare questo:

  1. Change Log4J per Logback vedere logback vs log4j
  2. parametri di debug passati e dei valori di ogni metodo che utilizza AOP .E farà risparmiare un sacco tornare di tempo durante lo sviluppo. Personalmente, uso Jcabi loggable.
1

È possibile utilizzare AOP (programmazione orientata all'aspetto) per ottenere un'esperienza di registrazione migliore. Se si desidera una registrazione a grana molto fine, si dovrebbe usare Aspectj. Ma per iniziare a imparare AOP molla a testa se va bene. Ecco un esempio della primavera-AOP Aspetto:

@Aspect 
public class CalculatorLoggingAspect { 

private Logger logger = Logger.getLogger(this.getClass()); 

@Before("execution(* ArithmeticCalculator.add(..))") 
public void logBefore(){ 
    logger.info("The method add() begins"); 
} 

@Before("execution(* *.*(..))") 
public void logBefore(JoinPoint joinPoint){ 
    logger.info("The method " + joinPoint.getSignature().getName() 
      + "() begins with " + Arrays.toString(joinPoint.getArgs())); 
} 

@After("execution(* *.*(..))") 
public void logAfter(JoinPoint joinPoint){ 
    logger.info("The method " + joinPoint.getSignature().getName() + "() ends."); 
} 

@AfterReturning("execution(* *.*(..))") 
public void logAfterReturning(JoinPoint joinPoint){ 
    logger.info("The method " + joinPoint.getSignature().getName() + "() ends successfully."); 
} 

@AfterReturning(pointcut="execution(* *.*(..))", returning="result") 
public void logAfterReturning(JoinPoint joinPoint, Object result){ 
    logger.info("The method " + joinPoint.getSignature().getName() + "() ends with "+result); 
} 

@AfterThrowing("execution(* *.*(..))") 
public void logAfterThrowing(JoinPoint joinPoint){ 
    logger.info("The method "+joinPoint.getSignature().getName()+"() throws an exception."); 
} 

@AfterThrowing(pointcut = "execution(* *.*(..))", throwing = "e") 
public void logAfterThrowing(JoinPoint joinPoint, Throwable e){ 
    logger.debug("The method "+joinPoint.getSignature().getName()+"() throws an exception : "+ e); 
} 

@Around("execution(* *.*(..))") 
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable{ 
    logger.info("The method "+joinPoint.getSignature().getName()+"() begins with " 
      +Arrays.toString(joinPoint.getArgs())); 
    try{ 
     Object result = joinPoint.proceed(); 
     logger.info("The method "+joinPoint.getSignature().getName() 
       +"() ends with "+result); 
     return result; 
    }catch(IllegalArgumentException e){ 
     logger.error("Illegal argument "+Arrays.toString(joinPoint.getArgs()) 
       +" in "+joinPoint.getSignature().getName()+"()"); 
     throw e; 
    } 
} 

@Before("execution(* *.*(..))") 
public void logJoinPoint(JoinPoint joinPoint){ 
    logger.info("Join point kind : "+joinPoint.getKind()); 
    logger.info("Signature declaring type : "+joinPoint.getSignature().getDeclaringTypeName()); 
    logger.info("Signature name : "+joinPoint.getSignature().getName()); 
    logger.info("Arguments : "+Arrays.toString(joinPoint.getArgs())); 
    logger.info("Target class : "+joinPoint.getTarget().getClass().getName()); 
    logger.info("This class : "+joinPoint.getThis().getClass().getName()); 
} 

}

Problemi correlati