2015-04-21 15 views
12

Mam aplikację, która jest prosta networked knock-knock joke app. Dołączyłem do niego log4J (wersja 2). Oto klasa server:Jak sprawić, aby rejestracja Apache Log4J w tej aplikacji była przydatna?

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

I po to plik 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> 

Co chciałbym zrobić, to dowiedzieć się, jak zrobić zalogowaniu nieco bardziej użyteczne. Dodajesz w specjalnych instrukcjach if, aby zdecydować, czy coś zarejestrować (tj. Jeśli użytkownik wejdzie w "zamknij", mogę zrobić w tym celu specjalny dziennik).

Czy istnieje sposób włączenia danych o wydajności do rejestrowania? Byłoby to dla mnie bardzo przydatne. Moim celem jest, aby kod demonstrował coś, co może pomóc w późniejszym udostępnieniu funkcji odpornych na awarie (tj. Być może moglibyśmy użyć dzienników do ponownego uruchomienia strony klienta, gdyby została przerwana).

dzięki

+0

Ok wzorzysty się tak z pliku XML: ' Coffee

Odpowiedz

3

jeden pomysł centralne wielu ram rejestrowania jest to, że nie zdecydować, co zrobić w aplikacji, ale w konfiguracji. więc, w zasadzie, twoja aplikacja rejestruje wszystko, a twoja konfiguracja "filtruje" i wysyła dane wyjściowe we właściwe miejsce (tj. różne pliki, syslog, a nawet całkowicie je ignorując)

ogólnie, w środowisku programistycznym, chcesz więcej rejestrować, możesz ustawić wszystko na "DEBUG", a podczas produkcji ustawić na "INFO".

czasami może to być korzystne, aby zrobić wzór taki jak ten:

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

uniknąć wykonując formatowanie (w tym przypadku) i rzuca ją zaraz potem.

Twój układ wzór jest również nieco problematyczne - na przykład, pobieranie numer wiersza jest zawodna (to w zasadzie zależy od kodu jest skompilowany z debug = true) i bardzo drogie (to musi odzyskać StackTrace i wyodrębnić linię informacje z niego).

dla rzeczywistych miar czasu realizacji, może chcesz szukać gdzie indziej - doskonałą bibliotekę, która zapewnia liczników i pomiary czasowe w tym max, min, średnia itp jest metryka-core:

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

a jeśli „re za pomocą sprężyny, można zajrzeć do mojego aspekcie oparte na tej biblioteki:

https://github.com/rmalchow/metrics

4

po pierwsze, Twój kod nie kompiluje. Pierwsze wywołanie logger.info() musi znajdować się wewnątrz statycznego bloku {} lub przeniesione do main(); I twoja pętla while() zostanie zakończona za pierwszym razem - potrzebujesz {} nawiasów wokół instrukcji debugowania i przerwania.

Ale muszę stwierdzić, moje uprzedzenia :)

  1. Osobiście uważam, że niewiele pożytku logger.debug() wywołuje. Nowoczesne IDE (używam Eclipse) zapewniają doskonałą obsługę debugowania bez zaśmiecania kodu za pomocą instrukcji logger.debug()[email protected] zwrócił już uwagę na wady niepotrzebnych instrukcji debugowania - widziałem przypadek, w którym wydajność wzrosła o ponad 100%, gdy tylko kilka instrukcji zostało umieszczonych wokół wywołań logger.debug().
  2. Więc w moim świecie logowanie jest dla systemów produkcyjnych, których nie mogę debugować za pomocą IDE. Przynosi to szereg obowiązków.
  3. Połączenia z System.err() należy zastąpić wywołaniami logger.error(). Domyślnie przejdą one do System.err, ale możesz przekierować w razie potrzeby.
  4. Jeśli nie możesz dodać wartości, pozwól, aby wyjątki uległy przesiąknięciu. Mam tendencję do przekształcania ich w RuntimeExceptions, ale niektórzy puryści nienawidzą tego.
  5. Gdy możesz dodać wartość, nie połykaj śladu stosu. Na przykład twój logger.fatal powinien być logger.fatal (".. msg ...", wyjątek). Pozwoli to zaoszczędzić wiele szczęśliwych godzin kodowania grepping.

Jeśli chodzi o dane, zawsze możesz przetasować własne - np. czas trwania połączenia typu back-end, aby zakończyć i zalogować się na poziomie informacji. Nie mam konkretnych sugestii dotyczących przydatnych ram, ale inni mogą.

2

Dla twojej aplikacji, myślę, że to, co zrobiłeś, jest wystarczające. nie potrzebujesz więcej.

Debugowanie w celu debugowania/Błąd wyjątków i błędów. Może być dodana informacja dla serwera start i stop.

Teraz, jeśli mieli większą aplikację należy to zrobić:

  1. Zmień Log4J dla Logback zobaczyć logback vs log4j
  2. parametry przekazywane debugowania i zwracane wartości każdej metody wykorzystującej AOP .To pozwoli zaoszczędzić wiele czasu podczas rozwoju. Osobiście używam Jcabi loggable.
1

Można użyć AOP (programowanie zorientowane na aspekt) w celu uzyskania lepszego doświadczenia podczas logowania. Jeśli chcesz bardzo dokładnego rejestrowania, powinieneś skorzystać z Aspectj. Ale żeby zacząć uczyć się AOP na wiosnę, jeśli dobrze. Oto przykład sprężynowy AOP proporcji:

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

}