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.
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)
Since we're using a custom Layout class to begin with, actually outputting the information is not an issue, but finding it is.
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.