How do you usually Tag log entries? (android)

橙三吉。 提交于 2019-12-18 10:03:17

问题


I assume most of you are aware of android.util.Log All logging methods accept 'String tag' as a first argument.

And my question is How do you usually tag your logs in your applications? I've seen some hardcode like this:

public class MyActivity extends Activity {
    private static final String TAG = "MyActivity";
    //...
    public void method () {
        //...
        Log.d(TAG, "Some logging");
    }
}

This doesn't look nice because of many reasons:

  • You can tell me this code doesn't have hardcode, but it does.
  • My application could have any number of classes in different packages with the same name. So it would be hard to read the log.
  • It isn't flexible. You always have put a private field TAG into your class.

Is there any neat way to get a TAG for a class?


回答1:


I use a TAG, but I initialise it like this:

private static final String TAG = MyActivity.class.getName();

This way when I refactor my code the tag will also change accordingly.




回答2:


I usually create an App class that sits in a different package and contains useful static methods. One of the method is a getTag() method, this way I can get the TAG everywhere.
App class looks like this:

EDIT: Improved per br mob comment ( Thanks :) )

public class App {

    public static String getTag() {
        String tag = "";
        final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
        for (int i = 0; i < ste.length; i++) {
            if (ste[i].getMethodName().equals("getTag")) {
                tag = "("+ste[i + 1].getFileName() + ":" + ste[i + 1].getLineNumber()+")";
            }
        }
        return tag;
    }

}

And when I want to use it:

Log.i(App.getTag(), "Your message here");

The output of the getTag method is the name of the caller class (with the package name), and the line number where the getTag is called from, for easy debuging.




回答3:


Go to Android Studio -> preference -> Live Templates -> AndroidLog then select Log.d(TAG, String).

In Template text replace

android.util.Log.d(TAG, "$METHOD_NAME$: $content$");

with

android.util.Log.d("$className$", "$METHOD_NAME$: $content$");

Then click Edit variables and enter className() in the Expression column next to the className Name column.

Now when you type the shortcut logd it will put

Log.d("CurrentClassName", "currentMethodName: ");

You dont need to define a TAG anymore.




回答4:


I like to improve Yaniv answer if you have the log in this format (filename.java:XX) xx line number you can link the shortcut the same way gets linked when there's an error, this way I can get direct to the line in question just by click on the logcat

I put this inside my extended Application so i can use in every other file

public static String getTag() {
    String tag = "";
    final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
    for (int i = 0; i < ste.length; i++) {
        if (ste[i].getMethodName().equals("getTag")) {
            tag = "("+ste[i + 1].getFileName() + ":" + ste[i + 1].getLineNumber()+")";
        }
    }
    return tag;
}

Screenshot:




回答5:


I have created a class of Static variables, methods and classes named as S.

The following is the logging method:

public static void L(Context ctx, Object s) {
    Log.d("CCC " + ctx.getClass().getName().replace(ctx.getPackageName(), ""), s.toString());
}

It is called in any class as S.L(this, whaterver_object); The getClass().getName() also appends the package name, hence, I am removing it out to avoid making the tag unnecessarily long.

Advantages:

  1. Shorter than Log.d(TAG,
  2. No need to convert int values to their string. Infact no need to type toString
  3. Won't forget to delete Log.d ever as I just have to delete the method and the locations of all logs get marked red.
  4. No need to define TAG at the top of the activity as it takes the name of the class.
  5. The TAG has a prefix of CCC (a short, easy to type string) so that it is easy to list only your logs in android monitor in Android Studio. Sometimes you are running services or other classes simultaneously. If you have to search by activity name alone then you cannot see exactly when a service response was obtained and then an action from your activity has occurred. A prefix like CCC helps as it gives you logs chronologically with the activity in which it occured



回答6:


At the expense of updating these strings when I move code between methods or rename methods, I like doing the following. Philosophically it also seems to be better to keep "location" or "context" in the tag, not the message.

public class MyClass {

    // note this is ALWAYS private...subclasses should define their own
    private static final LOG_TAG = MyClass.class.getName();

    public void f() {
        Log.i(LOG_TAG + ".f", "Merry Christmas!");
    }

}

The benefit here is that you can filter out a single method even if the content isn't static, e.g.

Log.i(LOG_TAG + ".f", String.valueOf(new Random().nextInt()));

The only drawback is that when I rename f() to g() I need to keep that string in mind. Also, automatic IDE refactoring won't catch these.

For a while I was a fan of using the short class name, I mean LOG_TAG = MyClass.class.getSimpleName(). I found them harder to filter in the logs because there was less to go on.




回答7:


AndroidStudio has a logt template by default (you can type logtand press tab to have it expand to a sinppet of code) . I recommend using this to avoid copy pasting the TAG definition from another class and forgetting to change the class you're referring to. The template expands by default to

private static final String TAG = "$CLASS_NAME$"

To avoid using the old class name after refactoring you could change that to

private static final String TAG = $CLASS_NAME$.class.getSimpleName();

Remember to check the "Edit variables" button and make sure that the CLASS_NAME variable is defined to use the className() Expression and has "Skip if defined" checked.




回答8:


You could use this.toString() to get a unique identifer for the specific class in which you print to the log.




回答9:


It is a very old question, but even thought an updated answer for July 2018 it is more preferable to use Timber. In order to Log the correct logging, errors and warns can be send to third party crash libraries, such as Firebase or Crashlytics.

In the class that implements Application you should add this:

@Override
public void onCreate() {
    super.onCreate();
    if (BuildConfig.DEBUG) {
        Timber.plant(new Timber.DebugTree());
    } else {
        Timber.plant(new CrashReportingTree());
    }
}

/** A tree which logs important information for crash reporting. */
private static class CrashReportingTree extends Timber.Tree {
    @Override protected void log(int priority, String tag, String message, Throwable t) {
        if (priority == Log.VERBOSE || priority == Log.DEBUG) {
            return;
        }

        FakeCrashLibrary.log(priority, tag, message);

        if (t != null) {
            if (priority == Log.ERROR) {
                FakeCrashLibrary.logError(t);
            } else if (priority == Log.WARN) {
                FakeCrashLibrary.logWarning(t);
            }
        }
    }
}

Do not forget Timber dependency.

implementation 'com.jakewharton.timber:timber:4.7.1'



回答10:


For those users that visit this question:

private val TAG:String = this.javaClass.simpleName;



回答11:


they use Timber for the IOsched app 2019 to show debug info:

implementation 'com.jakewharton.timber:timber:4.7.1'

class ApplicationController: Application() {

override fun onCreate() {  
    super.onCreate()
    if(BuildConfig.DEBUG){
        Timber.plant(Timber.DebugTree())
    }
}   
// enables logs for every activity and service of the application
// needs to be registered in manifest like:  
 <application
    android:label="@string/app_name"
    android:name=".ApplicationController"
    ... >

usage

  Timber.e("Error Message") 
  // will print ->  D/MainActivity: Error Message

  Timber.d("Debug Message");
  Timber.tag("new tag").e("error message");

note that this makes the Logs available only during DEBUG state and facilitates you the task of removing them manually for the launch on Google Play -

when release the app on the play store, we need to remove all Log statement from the app, so that none of the application data such as user information, hidden application data, auth-tokens are available to user in logcat as plain text

check out this article https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d




回答12:


I usually use the method name as the tag but from Thread

String TAG = Thread.currentThread().getStackTrace()[1].getMethodName();

This avoids the new Exception.




回答13:


private static final String TAG = new RuntimeException().getStackTrace()[0].getClassName();


来源:https://stackoverflow.com/questions/8355632/how-do-you-usually-tag-log-entries-android

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!