Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使此应用程序中的apachelog4j日志记录变得有用?_Java_Logging_Log4j - Fatal编程技术网

Java 如何使此应用程序中的apachelog4j日志记录变得有用?

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

我有一个简单的应用程序。我在其中加入了一些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 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语句周围需要{}括号

但我需要陈述我的偏见:)

  • 就我个人而言,我发现logger.debug()调用没有什么用处。现代IDE(我使用Eclipse)提供了出色的调试支持,不会让logger.debug()语句扰乱代码@rmalchow已经指出了不必要的调试语句的缺点——我曾经看到过这样一种情况:如果在logger.debug()调用中使用一些if语句,性能会提高100%以上
  • 所以在我的世界里,日志记录是针对生产系统的,我无法用IDE调试。这带来了许多责任
  • 对System.err()的调用应替换为logger.error()调用。默认情况下,这些将转到System.err,但如果需要,可以重定向
  • 如果你不能增加价值,就让异常渗透进来吧。我倾向于将它们转换为运行时异常,但一些纯粹主义者讨厌这样
  • 当您可以添加值时,不要吞下堆栈跟踪。例如,logger.fatal应该是logger.fatal(“…msg…”,异常)。这将节省许多快乐的格雷普代码小时

  • 至于指标,您可以随时滚动自己的时间-例如,完成后端呼叫和在信息级别登录所需的时间。对于一个有用的框架,我没有具体的建议,但其他人可能会提供。

    对于您的应用程序,我认为您所做的已经足够了。你不需要更多

    调试用于调试/异常和错误的错误。可能需要为启动和停止服务器添加信息

    现在,如果您有一个更大的应用程序,您应该这样做:

  • 将Log4J更改为Logback,请参见
  • 调试传递的参数并返回使用的每个方法的值。这将在开发过程中节省大量时间。我个人用
  • 您可以使用AOP(面向方面编程)来获得更好的日志记录体验。如果您想要非常细粒度的日志记录,您应该使用Aspectj。但对于开始学习AOP的春季AOP来说,如果可以的话。下面是spring aop方面的一个示例:

    @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文件的方法: