Frage

I'm writing my own logging Handler for Java and I'd like to insert the line number of the log message to my output.

Here's my current attempt without the line number:

public class ConsoleHandler extends Handler {

    private static final String SEVERE = "SEVERE";

    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Override
    public void publish(LogRecord record) {
        StringBuilder output = new StringBuilder();

        // Add time and location of the message
        Date d = new Date(record.getMillis());
        String time = new SimpleDateFormat(DATE_TIME_FORMAT).format(d);

        output.append(time + ": " + record.getSourceClassName() + "."
                + record.getSourceMethodName() + "\t\t\t");

        output.append(record.getLevel() + ": " + record.getMessage());

        switch (record.getLevel().getName()) {
        case SEVERE:
            System.err.println(output);
            break;
        default:
            System.out.println(output);
        }
    }
    public void flush() {}
    public void close() throws SecurityException {}
}

I searched the interface of LogRecord but could not find out in which line the message was logged.

Edit: I adapted the code linked in jmehrens' answer; this method returns the stack frame of the logging class from which I can get the line number and the file name:

private StackTraceElement getCallerStackFrame(final String callerName) {
    StackTraceElement callerFrame = null;

    final StackTraceElement stack[] = new Throwable().getStackTrace();
    // Search the stack trace to find the calling class
    for (int i = 0; i < stack.length; i++) {
        final StackTraceElement frame = stack[i];
        if (callerName.equals(frame.getClassName())) {
            callerFrame = frame;
            break;
        }
    }

    return callerFrame;
}

Usage:

final StackTraceElement callerFrame = getCallerStackFrame(record.getSourceClassName());

if (callerFrame != null) {
    final String fileName = callerFrame.getFileName();
    final int lineNumber = callerFrame.getLineNumber();
    // This creates a link to the line when used in Eclipse
    output.append("(" + fileName + ":" + lineNumber + ")");
}
War es hilfreich?

Lösung

There is no LogRecord (JDK1.4 - JDK1.7) method to get the line number. If no thread handoff is occurring in your handler or upstream you can create a new Throwable().getStackTrace() and use the java.lang.StackTraceElement API to get the line number.

Example code can be found in the JavaMail API at MailLogger.inferCaller()/isLoggerImplFrame(). If you have to deal with thread handoffs, then you would have to log the line number as a log record parameter. Keep in mind that computing the callsite is expensive in terms of performance.

Andere Tipps

You can get it using this code:

StackTraceElement e = Thread.currentThread().getStackTrace()[2];
e.getLineNumber();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top