开发者

Is there any way to automatically log the method name in Android?

I'm using this kind of pattern:

public class FooProvider extends ContentProvider {
    private static final String TAG = FooProvider.class.getSimpleName(); 
    ...

    @Override
    public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
        l.v(TAG, TAG + ".update() Uri:" + uri.toString() + " " + db.getPath());

Where l is my wrapper round Androids Log.v which takes String... args. This gives logcat output like this:

FooProvider.update() Uri: foo bar etc

What I'm looking for is a way to log the method name, in this case update(), automatically 开发者_运维问答and in a way which survives refactoring the way TAG does. I've seen the class.getMethods() call but can't see a way to index the returned list with the current method at runtime.


You may want to wrap these statements in a constant, so they get compiled out for your published version (which won't be printing Log.v statements anyway), but you can do something like this:

private static final boolean FINAL_CONSTANT_IS_LOCAL = true;
private static final String TAG = FooProvider.class.getSimpleName();

private String getLogTagWithMethod() {
    if (FINAL_CONSTANT_IS_LOCAL) {
        Throwable stack = new Throwable().fillInStackTrace();
        StackTraceElement[] trace = stack.getStackTrace();
        return trace[0].getClassName() + "." + trace[0].getMethodName() + ":" + trace[0].getLineNumber();
    } else {
        return TAG;
    }
}

It will depend upon how you call it to determine which StackTraceElement index you'll want, just debug it or play around a few times to find it.

When you compile your published version, just set FINAL_CONSTANT_IS_LOCAL to false and that code block will go away, always returning TAG.


It seems expensive but you could use

String Method = Thread.currentThread().getStackTrace()[2].getMethodName();

The reason you use an index of 2, is that 0 = would return currentThread and 1 = getStackTrace. This works on Java 1.5 and above, I would wrap it in some kind of if (DEBUG) {} thing so it's not in production code

Of course you will need to adjust the depth if you put that inside a method etc.


I created a MethodLogger class that I instantiate at the beginning of a method.
It figures out the class name & method name.
It also has a handy elapsedTime logger that you access by calling methodLogger.end().

Usage - put this at the beginning of a method to log:

MethodLogger methodLogger = new MethodLogger();

To optionally log some debug messages:

methodLogger.d("optionally log some debug messages");

To log when a method ends and show the elapsed time since the method started:

methodLogger.end();

Results:

D/com.domain.app.MainActivity: onCreate()
D/com.domain.app.MainActivity: onCreate() optionally log some debug messages
D/com.domain.app.MainActivity: onCreate() finished in 0.123 seconds.

MethodLogger class:

public class MethodLogger {

    // Private Fields
    private String tag;
    private String methodName;
    private long startTime;


    // Constructor
    public MethodLogger() {
        if (BuildConfig.DEBUG) { // Avoid doing any processing nor debug logging when built for RELEASE.
            StackTraceElement callersStackTraceElement = Thread.currentThread().getStackTrace()[3];
            tag = callersStackTraceElement.getClassName();
            methodName = callersStackTraceElement.getMethodName() + "()";
            startTime = System.currentTimeMillis();
            Log.d(tag, this.methodName);
        }
    }


    // Public Methods
    public void e(String message) {
        Log.e(tag, methodName + " " + message);
    }

    public void i(String message) {
        Log.i(tag, methodName + " " + message);
    }

    public void d(String message) {
        if (BuildConfig.DEBUG) { // Avoid doing any debug logging when built for RELEASE.
            Log.d(tag, methodName + " " + message);
        }
    }

    public void end() {
        if (BuildConfig.DEBUG) { // Avoid doing any processing nor debug logging when built for RELEASE.
            long elapsedMillis = System.currentTimeMillis() - startTime;
            Log.d(tag, String.format("%s finished in %.3f seconds.", methodName, 0.001f * elapsedMillis));
        }
    }

}


I have a custom logger that wraps around android Log.

it will display class name, method name and line number.

http://www.hautelooktech.com/2011/08/15/android-logging/


you could make static methods like these and call them from the beginning and end of the methods you want to debug:

    public static void entry_log(String id) {
                Throwable stack = new Throwable().fillInStackTrace();
                StackTraceElement[] trace = stack.getStackTrace();

                    Log.v("ENTRY",
                            id + " - " + trace[1].getClassName() + "."
                                    + trace[1].getMethodName() + ":"
                                    + trace[1].getLineNumber());
                    break;

            }

And

public void exit_log(String id) {
            Throwable stack = new Throwable().fillInStackTrace();
            StackTraceElement[] trace = stack.getStackTrace();

                Log.v("EXIT",
                        id + " - " + trace[1].getClassName() + "."
                                + trace[1].getMethodName() + ":"
                                + trace[1].getLineNumber());
                break;

        }

I created this Logging utility for Android with a few more features,other than entry-exit logs. You might find it useful.


You only need addition message and input to this function to auto create log

private static String buildMsg(String msg) {
    StringBuilder buffer = new StringBuilder();

    if (DETAIL_ENABLE) {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[4];
        buffer.append("[ ");
        buffer.append(Thread.currentThread().getName());
        buffer.append(": ");
        buffer.append(stackTraceElement.getFileName());
        buffer.append(": ");
        buffer.append(stackTraceElement.getLineNumber());
        buffer.append(": ");
        buffer.append(stackTraceElement.getMethodName());
    }

    buffer.append("() ] _____ ");

    buffer.append(msg);

    return buffer.toString();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜