[英]How can I determine which class's `main` method was invoked at runtime?
I'd like to dynamically determine which class's main method was invoked, in order to allow for an easier to digest combined log file. 我想动态确定哪个类的main方法被调用,以使摘要日志组合更容易消化。
Currently, a single (rotated) log file aggregates all the log output from a number of daemons, but there is no obvious way to determine which daemon the log entry originated from, as all of the daemons use a shared code base, and loggers are created with log4j's getLogger(Something.class) 当前,单个(循环的)日志文件聚合了多个守护程序的所有日志输出,但是没有明显的方法来确定日志条目源自哪个守护程序,因为所有守护程序都使用共享的代码库,并且记录器是使用log4j的getLogger(Something.class)创建
Since we're using a custom Layout class to begin with, actually outputting the information is not an issue, but finding it is. 由于我们使用的是自定义Layout类,因此实际输出信息不是问题,但找到它是一个问题。
One approach that could work as a fallback is defining a property at invocation time and reading that property. 可以作为备用的一种方法是在调用时定义属性并读取该属性。
java -cp ... -Dmain.program=<WHATEVER> MainProgram
However, there's no need to create a new convention if the ability already exists. 但是,如果该功能已经存在,则无需创建新约定。
Update: For my purposes, the following seems to work fine: 更新:就我而言,以下似乎可以正常工作:
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
public class MyLayout extends PatternLayout {
private static String _mainClass = null;
public String format( LoggingEvent event ) {
String mesg = super.format( event );
if (mesg.indexOf("$main") > -1) {
mesg = mesg.replaceAll("\\$main", getMainClass());
}
return mesg;
}
private static String getMainClass() {
if (_mainClass == null) {
StackTraceElement[] elem = new Exception().getStackTrace();
int offset = elem.length - 1;
if (elem[offset].getMethodName().equals("main")) {
_mainClass = elem[offset].getClassName();
}
else {
_mainClass = "<Unknown_Main_Class>";
}
}
return _mainClass;
}
}
Thanks for the suggestions! 感谢您的建议!
If you only need to do it once you can walk the exception stack and look at the last class/method call. 如果只需要执行一次,则可以遍历异常堆栈并查看最后的类/方法调用。
StackTraceElement[] elem = new Exception().getStackTrace();
elem[elem.length - 1].getClassName();
But is error prone. 但是容易出错。 If i load your class via reflection you will see a completely different method at the top. 如果我通过反射加载您的课程,您将在顶部看到完全不同的方法。
You can try M. Jessup variant ( matching a main method signature ) but it will fail if I call a main method from the code too. 您可以尝试M. Jessup变体(匹配主方法签名),但是如果我也从代码中调用主方法,它将失败。
It is a bit hackish, but you could use the static method Thread.getAllStackTraces(). 它有点黑,但是您可以使用静态方法Thread.getAllStackTraces()。 This will get you the stack trace for every live thread in the VM, and assuming the thread that started the application is still alive you could inspect the traces and look for a bottom element whose method signature matched main(String[] args). 这将为您提供VM中每个活动线程的堆栈跟踪,并假设启动应用程序的线程仍然处于活动状态,则可以检查跟踪并查找其方法签名与main(String [] args)相匹配的底部元素。
Veera Sundar has written two articles on how to use Log4j
's Mapped Diagnostic Context (source code for Servlet Filters) http://veerasundar.com/blog/2009/11/log4j-mdc-mapped-diagnostic-context-example-code/ that might be possible modify for your use case. Veera Sundar已经撰写了两篇有关如何使用Log4j
的映射诊断上下文(Servlet过滤器的源代码)的文章, 网址为http://veerasundar.com/blog/2009/11/log4j-mdc-mapped-diagnostic-context-example-code /可能会针对您的用例进行修改。
Let your application classes (with the main method) add its class name as a variable which can be written to the log files. 让您的应用程序类(使用main方法)将其类名称添加为可以写入日志文件的变量。
Is it less work than adding a property at runtime? 它比在运行时添加属性要少吗? No, not really but, more elegant 不,不是,但是,更优雅
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.