Java 如何使此应用程序中的apachelog4j日志记录变得有用?
我有一个简单的应用程序。我在其中加入了一些Log4J(版本2)。以下是服务器类:Java 如何使此应用程序中的apachelog4j日志记录变得有用?,java,logging,log4j,Java,Logging,Log4j,我有一个简单的应用程序。我在其中加入了一些Log4J(版本2)。以下是服务器类: 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 Thre
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();
}
}
以下是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>
我想做的是找出如何使日志记录更有用。您是否添加了特殊的if
语句来决定是否记录某些内容(即,如果用户输入“quit”,我可以对此进行特定的记录)
是否有一种方法可以将性能指标包括到日志中?这对我来说真的很有用。我的目标是让代码演示一些可能有助于使其稍后显示故障安全特性的东西(即,如果客户端被中止,我们可能会利用日志重新启动客户端)
感谢许多日志框架的核心思想是,您不需要决定在应用程序中做什么,而是在配置中。因此,基本上,应用程序会记录所有内容,配置“过滤”并将输出发送到正确的位置(即不同的文件、系统日志,甚至完全忽略它) 通常,在开发环境中,您需要记录更多日志,因此您可以将所有内容设置为“DEBUG”,而在生产环境中,您可以将其设置为“INFO” 有时,这样做可能是有益的:
if(log.isDebug()) {
log.debug("some formatting");
}
避免执行格式化(在本例中)并在之后立即将其丢弃
您的模式布局也有点问题-例如,检索行号不可靠(基本上取决于使用debug=true编译的代码),而且非常昂贵(它必须检索stacktrace并从中提取行信息)
对于实际的执行时间度量,您可能想看看其他地方-一个提供计数器和时间度量(包括最大值、最小值、平均值等)的优秀库是度量的核心:
如果您使用的是spring,您可能希望查看基于此库的我的方面:
首先,您的代码无法编译。第一个logger.info()调用需要位于静态{}块内,或者移动到main()中;您的while()循环将第一次通过退出-在debug和break语句周围需要{}括号 但我需要陈述我的偏见:)
至于指标,您可以随时滚动自己的时间-例如,完成后端呼叫和在信息级别登录所需的时间。对于一个有用的框架,我没有具体的建议,但其他人可能会提供。对于您的应用程序,我认为您所做的已经足够了。你不需要更多 调试用于调试/异常和错误的错误。可能需要为启动和停止服务器添加信息 现在,如果您有一个更大的应用程序,您应该这样做:
@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());
}
}好的,我找到了XML文件的方法: