your programing

일반적으로 로그 항목에 태그를 어떻게 지정합니까?

lovepro 2020. 10. 4. 12:56
반응형

일반적으로 로그 항목에 태그를 어떻게 지정합니까? (기계적 인조 인간)


대부분의 사용자가 android.util.Log를 알고 있다고 가정합니다. 모든 로깅 메서드는 'String tag'를 첫 번째 인수로 허용합니다.

제 질문은 일반적으로 애플리케이션에서 로그에 태그를 어떻게 지정합니까? 다음과 같은 하드 코드를 보았습니다.

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

여러 가지 이유로보기 좋지 않습니다.

  • 이 코드에는 하드 코드가 없다고 말할 수 있지만 실제로 있습니다.
  • 내 응용 프로그램은 동일한 이름을 가진 다른 패키지에 여러 클래스를 가질 수 있습니다. 따라서 로그를 읽기가 어려울 것입니다.
  • 유연하지 않습니다. 항상 개인 필드 TAG를 수업에 넣었습니다.

수업에 대한 TAG를 얻을 수있는 깔끔한 방법이 있습니까?


TAG를 사용하지만 다음과 같이 초기화합니다.

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

이렇게하면 코드를 리팩터링 할 때 태그도 그에 따라 변경됩니다.


일반적으로 App다른 패키지에 있고 유용한 정적 메서드를 포함 하는 클래스를 만듭니다 . 방법 중 하나는 방법입니다. getTag()이렇게하면 어디서나 TAG를 얻을 수 있습니다.
App클래스는 다음과 같습니다.

편집 : br mob 코멘트에 따라 개선되었습니다 (감사합니다 :))

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;
    }

}

그리고 그것을 사용하고 싶을 때 :

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

getTag메서드 의 출력은 getTag쉽게 디버깅 할 수 있도록 호출자 클래스의 이름 (패키지 이름 포함) 과이 호출 된 행 번호 입니다.


로 이동 안드로이드 스튜디오 -> 환경 설정 -> 라이브 템플릿 -> AndroidLog은 다음 선택 Log.d (TAG, 문자열) .

에서 템플릿 텍스트 교체

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

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

Android 메뉴 이미지

그런 다음 변수 편집을 클릭 하고 className Name에있는 Expression 열에 className ()을 입력 합니다.Android 메뉴 2 이미지

바로 가기를 입력 할 때 지금 logd은 둘 것이다

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

더 이상 TAG를 정의 할 필요가 없습니다.


이 형식 (filename.java:XX) xx 줄 번호로 로그가 있으면 Yaniv 답변을 개선하고 싶습니다. 오류가있을 때 동일한 방식으로 연결되는 바로 가기를 연결할 수 있습니다.이 방법으로 문제의 줄로 직접 갈 수 있습니다. logcat을 클릭하기 만하면

다른 모든 파일에서 사용할 수 있도록 확장 응용 프로그램에 넣었습니다.

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;
}

스크린 샷 :


라는 이름의 정적 변수, 메서드 및 클래스 클래스를 만들었습니다 S.

다음은 로깅 방법입니다.

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

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.


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.


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


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'

For those users that visit this question:

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

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");

이렇게하면 DEBUG 상태에서만 로그를 사용할 수 있으며 Google Play에서 시작하기 위해 로그를 수동으로 제거 할 수 있습니다.

Play 스토어에서 앱을 출시 할 때 사용자 정보, 숨겨진 애플리케이션 데이터, 인증 토큰과 같은 애플리케이션 데이터가 logcat의 사용자에게 일반 텍스트로 제공되지 않도록 앱에서 모든 Log 문을 제거해야합니다.

이 기사 https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d를 확인 하십시오.


일반적으로 메소드 이름을 태그로 사용하지만 Thread에서

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

이것은 새로운 예외를 피합니다.


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

참고 URL : https://stackoverflow.com/questions/8355632/how-do-you-usually-tag-log-entries-android

반응형