我们如何在java中将行号打印到日志中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/115008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:25:45  来源:igfitidea点击:

How can we print line numbers to the log in java

javalogging

提问by Bobby Kumar

How to print line numbers to the log. Say when outputting some information to the log, I also want to print the line number where that output is in the source code. As we can see in the stack trace, it displays the line number where the exception has occurred. Stack trace is available on the exception object.

如何将行号打印到日志中。假设在向日志输出一些信息时,我还想打印该输出在源代码中的行号。正如我们在堆栈跟踪中看到的那样,它显示了发生异常的行号。堆栈跟踪在异常对象上可用。

Other alternative could be like manually including the line number when printing to the log. Is there any other way?

其他替代方法可能是在打印到日志时手动包含行号。有没有其他办法?

回答by Simon Buchan

From Angsuman Chakraborty:

来自Angsuman Chakraborty

/** Get the current line number.
 * @return int - Current line number.
 */
public static int getLineNumber() {
    return Thread.currentThread().getStackTrace()[2].getLineNumber();
}

回答by UberAlex

You can't guarantee line number consistency with code, especially if it is compiled for release. I would not recommend using line numbers for that purpose anyway, it would be better to give a payload of the place where the exception was raised (the trivial method being to set the message to include the details of the method call).

你不能保证行号与代码的一致性,特别是如果它是为发布而编译的。无论如何,我不建议为此目的使用行号,最好给出引发异常的位置的有效负载(简单的方法是将消息设置为包含方法调用的详细信息)。

You might like to look at exception enrichment as a technique to improve exception handling http://tutorials.jenkov.com/java-exception-handling/exception-enrichment.html

您可能希望将异常丰富视为一种改进异常处理的技术 http://tutorials.jenkov.com/java-exception-handling/exception-enrichment.html

回答by Ron Tuffin

The code posted by @simon.buchan will work...

@simon.buchan 发布的代码将起作用...

Thread.currentThread().getStackTrace()[2].getLineNumber()

But if you call it in a method it will always return the line number of the line in the method so rather use the code snippet inline.

但是,如果您在方法中调用它,它将始终返回该方法中该行的行号,因此请使用内联代码片段。

回答by GBa

If it's been compiled for release this isn't possible. You might want to look into something like Log4J which will automatically give you enough information to determine pretty closely where the logged code occurred.

如果它是为发布而编译的,则这是不可能的。您可能想要研究类似 Log4J 的东西,它会自动为您提供足够的信息来非常准确地确定记录的代码发生的位置。

回答by James A Wilson

I am compelled to answer by not answering your question. I'm assuming that you are looking for the line number solely to support debugging. There are better ways. There are hackish ways to get the current line. All I've seen are slow. You are better off using a logging framework like that in java.util.logging package or log4j. Using these packages you can configure your logging information to include context down to the class name. Then each log message would be unique enough to know where it came from. As a result, your code will have a 'logger' variable that you call via

我是被迫不回答你的问题来回答的。我假设您正在寻找行号只是为了支持调试。有更好的方法。有一些hackish 方法可以获取当前行。我所看到的都是缓慢的。您最好使用 java.util.logging 包或log4j中的日志框架。使用这些包,您可以配置日志信息以将上下文包含到类名中。然后每条日志消息都足够独特,可以知道它来自哪里。因此,您的代码将有一个“记录器”变量,您可以通过该变量调用

logger.debug("a really descriptive message")

logger.debug("a really descriptive message")

instead of

代替

System.out.println("a really descriptive message")

System.out.println("a really descriptive message")

回答by James A Wilson

I would recommend using a logging toolkit such as log4j. Logging is configurable via properties files at runtime, and you can turn on / off features such as line number / filename logging.

我建议使用日志工具包,例如log4j。日志记录可在运行时通过属性文件进行配置,您可以打开/关闭诸如行号/文件名日志记录等功能。

Looking at the javadoc for the PatternLayoutgives you the full list of options - what you're after is %L.

查看PatternLayout的 javadoc 为您提供了完整的选项列表 - 您所追求的是 %L。

回答by Jim Kiley

Log4J allows you to include the line number as part of its output pattern. See http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.htmlfor details on how to do this (the key element in the conversion pattern is "L"). However, the Javadoc does include the following:

Log4J 允许您将行号作为其输出模式的一部分。有关如何执行此操作的详细信息,请参阅http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html(转换模式中的关键元素是“L”)。但是,Javadoc 确实包括以下内容:

WARNING Generating caller location information is extremely slow. It's use should be avoided unless execution speed is not an issue.

警告生成呼叫者位置信息非常慢。除非执行速度不是问题,否则应避免使用它。

回答by VonC

first the general method (in an utility class, in plain old java1.4 code though, you may have to rewrite it for java1.5 and more)

首先是通用方法(在一个实用程序类中,虽然在普通的旧 java1.4 代码中,您可能需要为 java1.5 和更高版本重写它)

/**
 * Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils" and aclass. <br />
 * Allows to get past a certain class.
 * @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils. 
 * @return "[class#method(line)]: " (never empty, because if aclass is not found, returns first class past StackTraceUtils)
 */
public static String getClassMethodLine(final Class aclass)  {
    final StackTraceElement st = getCallingStackTraceElement(aclass);
    final String amsg = "[" + st.getClassName() + "#" + st.getMethodName() + "(" + st.getLineNumber()
    +")] <" + Thread.currentThread().getName() + ">: ";
    return amsg;
}

Then the specific utility method to get the right stackElement:

然后是获取正确的stackElement的具体实用方法:

/**
   * Returns the first stack trace element of the first class not equal to "StackTraceUtils" or "LogUtils" and aClass. <br />
   * Stored in array of the callstack. <br />
   * Allows to get past a certain class.
   * @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils. 
   * @return stackTraceElement (never null, because if aClass is not found, returns first class past StackTraceUtils)
   * @throws AssertionFailedException if resulting statckTrace is null (RuntimeException)
   */
  public static StackTraceElement getCallingStackTraceElement(final Class aclass) {
    final Throwable           t         = new Throwable();
    final StackTraceElement[] ste       = t.getStackTrace();
    int index = 1;
    final int limit = ste.length;
    StackTraceElement   st        = ste[index];
    String              className = st.getClassName();
    boolean aclassfound = false;
    if(aclass == null) {
        aclassfound = true;
    }
    StackTraceElement   resst = null;
    while(index < limit) {
        if(shouldExamine(className, aclass) == true) {
            if(resst == null) {
                resst = st;
            }
            if(aclassfound == true) {
                final StackTraceElement ast = onClassfound(aclass, className, st);
                if(ast != null) {
                    resst = ast;
                    break;
                }
            }
            else
            {
                if(aclass != null && aclass.getName().equals(className) == true) {
                    aclassfound = true;
                }
            }
        }
        index = index + 1;
        st        = ste[index];
        className = st.getClassName();
    }
    if(isNull(resst))  {
        throw new AssertionFailedException(StackTraceUtils.getClassMethodLine() + " null argument:" + "stack trace should null"); //$NON-NLS-1$
    }
    return resst;
  }

  static private boolean shouldExamine(String className, Class aclass) {
      final boolean res = StackTraceUtils.class.getName().equals(className) == false && (className.endsWith(LOG_UTILS
        ) == false || (aclass !=null && aclass.getName().endsWith(LOG_UTILS)));
      return res;
  }

  static private StackTraceElement onClassfound(Class aclass, String className, StackTraceElement st) {
      StackTraceElement   resst = null;
      if(aclass != null && aclass.getName().equals(className) == false)
      {
          resst = st;
      }
      if(aclass == null)
      {
          resst = st;
      }
      return resst;
  }

回答by Michael Baltaks

We ended up using a custom class like this for our Android work:

我们最终在我们的 Android 工作中使用了这样的自定义类:

import android.util.Log;    
public class DebugLog {
 public final static boolean DEBUG = true;    
 public static void log(String message) {
  if (DEBUG) {
    String fullClassName = Thread.currentThread().getStackTrace()[2].getClassName();
    String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
    String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
    int lineNumber = Thread.currentThread().getStackTrace()[2].getLineNumber();

    Log.d(className + "." + methodName + "():" + lineNumber, message);
  }
 }
}

回答by Juan

Quick and dirty way:

快速而肮脏的方式:

System.out.println("I'm in line #" + 
    new Exception().getStackTrace()[0].getLineNumber());

With some more details:

更多细节:

StackTraceElement l = new Exception().getStackTrace()[0];
System.out.println(
    l.getClassName()+"/"+l.getMethodName()+":"+l.getLineNumber());

That will output something like this:

这将输出如下内容:

com.example.mytest.MyClass/myMethod:103