我想动态确定调用哪个类的主方法,以便更容易理解组合日志文件。
目前,单个(旋转)日志文件聚合来自多个守护进程的所有日志输出,但没有明显的方法来确定日志条目来自哪个守护进程,因为所有守护进程都使用共享代码库,和记录器是用log4j的getLogger(Something.class)
创建的由于我们开始使用自定义布局类,实际输出信息不是问题,但找到它是。
可以作为后备的一种方法是在调用时定义属性并读取该属性。
java -cp ... -Dmain.program=<WHATEVER> MainProgram
但是,如果该功能已存在,则无需创建新约定。
更新:就我的目的而言,以下似乎工作正常:
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;
}
}
感谢您的建议!
答案 0 :(得分:2)
如果您只需要执行此操作,则可以遍历异常堆栈并查看最后一个类/方法调用。
StackTraceElement[] elem = new Exception().getStackTrace();
elem[elem.length - 1].getClassName();
但是容易出错。如果我通过反射加载你的课程,你会在顶部看到一个完全不同的方法。
您可以尝试M. Jessup变体(匹配主方法签名),但如果我也从代码中调用main方法,它将失败。
答案 1 :(得分:1)
有点hackish,但你可以使用静态方法Thread.getAllStackTraces()。这将为您获取VM中每个活动线程的堆栈跟踪,并假设启动应用程序的线程仍处于活动状态,您可以检查跟踪并查找其方法签名与main匹配的底部元素(String [] args)。 / p>
答案 2 :(得分:0)
Veera Sundar撰写了两篇关于如何使用Log4j
的映射诊断上下文(Servlet过滤器的源代码)http://veerasundar.com/blog/2009/11/log4j-mdc-mapped-diagnostic-context-example-code/的文章,这些文章可能会对您的用例进行修改。
让你的应用程序类(使用main方法)将其类名添加为可以写入日志文件的变量。
它是否比在运行时添加属性更少工作?不,不是真的,但更优雅