views:

65

answers:

3

I am using System.out.println in my code to track the execution of a program and get some useful output. This creates results like this in the console:

Main function. Program starts.
Method getArea. Getting values
Method getSide. Side is 6
Method getArea. First value is 6
Method getSide. Side is 8
Method getArea. Second value is 8
Method getArea. Area is 48
Main function. The final area is 48

I would like to create tha method, which adds a space in front of the output every time the code goes deeper in the method call stack. For example, the same code but instead of using System.out.println, now with Misc.smartPrintln:

Main function. Program starts.
 Method getArea. Getting values
  Method getSide. Side is 6
 Method getArea. First value is 6
  Method getSide. Side is 8
 Method getArea. Second value is 8
 Method getArea. Area is 48
Main function. The final area is 48

The method would have this definition:

public static void smartPrintln(String string);

I don't know how to implement this functionality. Any ideas how to solve this? And, could the use of a logger offer this functionality?

+5  A: 

Create a temporary Throwable object. Use its getStackTrace() method to analyze the stack and determine the level. e.g.

public static void smartPrintln(String string) {
    Throwable t = new Throwable();
    StackTraceElement[] stackElements = t.getStackTrace();
    int level = stackElements.length - 1; // don't forget our function adds a level
    for (int i = 0; i < level; i++) {
        System.out.print(' '); // could probably make this more efficient
    }
    System.out.println(string);
}
ob1
Big +1 to ob1 - I never thought of this amazingly ugly but useful hack.
Little Bobby Tables
+1  A: 

Interesting question. A more condense implementation of @ob1's suggestion:

public static void smartPrintln(String string) {
    int i = new Throwable().getStackTrace().length - 1;
    System.out.printf("%"+i+"s%s%n", "", string);
}

Another solution would be to "add the functionality" directly to System.out.println calls like this:

System.setOut(new PrintStream(System.out) {
    public void println(String x) {
        printf("%"+(new Throwable().getStackTrace().length - 1)+"s", "");
        super.println(x);
    }
});

After this point, all calls to System.out.println(String) will be processed by our "filtering" PrintStream implementation.

aioobe
Nice. As an option, consider Thread.currentThread().getStackTrace() instead of new Throwable().getStackTrace() -- avoids the "ugly" throw-away throwable.
tucuxi
A: 

Use the Logger API or anyother third party API.

emeraldjava