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


96

대부분의 사용자가 android.util.Log를 알고 있다고 가정합니다. 모든 로깅 방법은 '문자열 태그'를 첫 번째 인수로 허용합니다.

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

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

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

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

수업 용 TAG를 얻을 수있는 깔끔한 방법이 있나요?


2
TAG 사용은 Android javadoc 에서 제안 하므로 런타임에 클래스 이름을 얻는 것보다 나쁘지 않다고 생각합니다
Vladimir

저는 GeneralConstants와 같은 특정 클래스를 만들고 여기에 내 TAG를 붙이는 것을 선호하며 원하는 모든 클래스에 접근 할 수 있습니다. GeneralConstans.MY_TAG
cagryInside 2011

6
클래스에 TAG를 정의하는 것이 가장 좋다고 생각합니다. 클래스 이름을 하드 코딩하는 것은 추악하지만 proguard로 작업하는 유일한 신뢰할 수있는 방법입니다. proguard를 사용하지 않는 경우 MyActivity.class.getName ()이 최상의 솔루션입니다. 중복 이름이 걱정되는 경우 패키지 이름을 포함하십시오. TAG 이름을 다른 위치에 두는 것은 유지 관리의 악몽이 될 것입니다.
Ralph Mueller

답변:


179

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

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

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


21
동일한 방식으로 TAG 상수를 정의하고 있습니다. 그러나 코드 난독 화 도구가 클래스 이름에 어떤 영향을 미치고 결과적으로이 상수의 값에 영향을 미칠지 궁금합니다.
Gumbit 2010 년

1
이번에는 수동으로 붙여 넣었습니다 "MyActivity.class.getName();". 저는 항상 "TAG"가 실제 Static변수가 아닌 Google 등의 예제에있는 자리 표시 자라고 생각했습니다 . 덕분에 훨씬 더 나은 솔루션입니다. :)
wired00

4
정적을 제거하고 this.getClass().getName()대신 사용하여 더 일반적으로 만드는 것은 어떻습니까?
theblang

11
TAG의 길이 제한을 피하기 위해 this.getClass (). getSimpleName ()을 시도 할 수 있습니다. IllegalArgumentException가 슬로우되는 경우 tag.length ()> 23
마이클 레비

14
Ralph Mueller가 언급했듯이 Proguard (대부분의 Android 프로젝트와 마찬가지로)를 사용하여 클래스 이름을 난독 화하는 경우이 기술이 작동하지 않습니다.
John Patterson

16

일반적으로 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쉽게 디버깅 할 수 있도록 호출자 클래스의 이름 (패키지 이름 포함) 과이 호출 된 행 번호 입니다.


6
나는 확실히 이것을하지 않을 것이다 .. 당신이 그렇게한다면 당신의 로그 진술은 큰 성능 타격을받을 것이다. 이렇게하면 프로 가드가 프로덕션 빌드에 대한 경고보다 적은 로그 메시지를 제거하도록 확실히하고 싶을 것입니다.
Matt Wolfe 2015

1
매트, 당신 말이 맞아요! 프로덕션에서 로그를 제거 / 제거하는 것이 좋습니다.- stackoverflow.com
2019563

2
태그 길이는 이제 23 자로 제한되어 있기 때문에이 아마 더 이상 권장
클라우디오 레디

어떻게 getStackTrace()작동 하는지 보여 주셔서 감사 합니다. 그러나 나는 그것의 비용 때문에 그것을 사용 실 거예요
BlueWizard

12

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

에서 템플릿 텍스트 교체

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를 정의 할 필요가 없습니다.


1
이것은 Android Studio의 정말 멋진 사용법이며 문제에 대한 흥미로운 접근 방식이지만 동시에 실제로 TAG 변수 대신 문자열을 입력하고 있습니다. 변경해야 할 경우 약간 번거로울 수 있습니다. 기능을 보여 주셔서 감사합니다.
Voy dec

3
나는 이런 방식을 좋아하지만 기존 항목을 수정하는 대신 새 로그 항목을 생성하고, 향후 업데이트 등에서 변경된 경우 안전한쪽에 있습니다.
Alaa

9

이 형식 (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;
}

스크린 샷 :


:) 그것을 사랑을 "도둑질"내 대답을 업데이트
Yaniv에게

4
태그 길이는 이제 23 자로 제한되어 있기 때문에이 아마 더 이상 권장
클라우디오 레디

3

AndroidStudio에는 logt기본적으로 템플릿이 있습니다 ( logt단일 코드로 확장되도록 입력 하고 탭을 누를 수 있음 ). 다른 클래스의 TAG 정의를 복사하여 붙여넣고 참조하는 클래스를 변경하는 것을 잊는 것을 방지하려면 이것을 사용하는 것이 좋습니다. 템플릿은 기본적으로 다음으로 확장됩니다.

private static final String TAG = "$CLASS_NAME$"

리팩토링 후 이전 클래스 이름을 사용하지 않으려면 다음과 같이 변경할 수 있습니다.

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

"변수 편집"버튼을 확인하고 CLASS_NAME변수가 className()표현식 을 사용하도록 정의되어 있고 "정의 된 경우 건너 뛰기"가 선택되어 있는지 확인하십시오.


2

다음과 같은 정적 변수, 메서드 및 클래스 클래스를 만들었습니다. S .

다음은 로깅 방법입니다.

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

모든 클래스에서 다음과 같이 호출됩니다 S.L(this, whaterver_object);.getClass().getName() 는 또한 패키지 이름을 추가하므로 되므로 태그가 불필요하게 길어지지 않도록 제거하고 있습니다.

장점 :

  1. 보다 짧은 Log.d(TAG,
  2. int 값을 문자열로 변환 할 필요가 없습니다. 사실 입력 할 필요가 없습니다.toString
  3. 삭제하는 것을 잊지 않습니다 Log.d방법을 삭제하고 모든 로그의 위치가 빨간색으로 표시되므로 삭제하는 것을 .
  4. 클래스 이름을 사용하므로 활동 상단에 TAG를 정의 할 필요가 없습니다.
  5. TAG에는 CCC(짧고 입력하기 쉬운 문자열) 접두사가 있으므로 Android Studio의 Android 모니터에 로그 만 쉽게 나열 할 수 있습니다. 때로는 서비스 또는 다른 클래스를 동시에 실행하고 있습니다. 활동 이름만으로 검색해야하는 경우 서비스 응답을 얻은 시점과 활동에서 조치가 발생한 시점을 정확히 알 수 없습니다. CCC와 같은 접두사는 로그가 발생한 활동과 함께 시간순으로 로그를 제공하므로 도움이됩니다.

1
훌륭한 솔루션! 내가 사용할 게! 하지만 교체 Context ctxObject ctxctx.getClass().getName().replace(ctx.getPackageName(), "")에 의해 ctx.getClass().getSimpleName(). 이렇게하면 S.L(Object, Object)어디서든 전화를 걸 수 있습니다 .FragmentContext 즉시 확장하지 않는 s ).
Antonio Vinicius Menezes Medei

1

this.toString()로그에 인쇄하는 특정 클래스에 대한 고유 식별자를 가져 오는 데 사용할 수 있습니다 .


이것은 무엇을 하느냐에 따라 비싸 질 수 toString()있습니다.
tar

1

메서드간에 코드를 이동하거나 메서드 이름을 바꿀 때 이러한 문자열을 업데이트하는 대신 다음을 수행하는 것이 좋습니다. 철학적으로 메시지가 아니라 태그에 "위치"또는 "컨텍스트"를 유지하는 것이 더 나은 것 같습니다.

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

}

여기서의 이점은 콘텐츠가 정적이 아닌 경우에도 단일 메서드를 필터링 할 수 있다는 것입니다.

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

유일한 단점은 이름 f()을 바꿀 때g() 해당 문자열을 염두에 두어야한다는 것입니다. 또한 자동 IDE 리팩토링은이를 포착하지 못합니다.

잠시 동안 나는 짧은 클래스 이름을 사용하는 팬이었습니다 LOG_TAG = MyClass.class.getSimpleName(). 할 일이 적기 때문에 로그에서 필터링하기가 더 어렵다는 것을 알았습니다.


1

매우 오래된 질문이지만 2018 년 7 월 업데이트 된 답변이라고 생각하더라도 Timber를 사용하는 것이 더 좋습니다. 올바른 로깅을 로깅하기 위해 오류 및 경고를 Firebase 또는 Crashlytics와 같은 타사 오류 라이브러리로 보낼 수 있습니다.

Application 을 구현하는 클래스에서 다음을 추가해야합니다.

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

목재 의존성을 잊지 마십시오.

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

0

이 질문을 방문하는 사용자의 경우 :

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

0

IOsched 앱 2019에 Timber를 사용하여 디버그 정보를 표시합니다.

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"
    ... >

용법

  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를 확인 하십시오.


-2

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

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

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


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

3
RuntimeException현재 클래스 이름을 가져 오기 위해 새 파일을 만드는 이유는 무엇 입니까? 아주 나쁜.
asgs apr.

이것이 내 로그 항목에 태그를 지정하는 방법이며, 프로젝트에서 다른 클래스로 클래스를 복사 할 때 적절하게 리팩토링 할 수있는 유일한 솔루션입니다. 더 좋고 편안한 아이디어가 있다면 제안을받을 수 있습니다.
Arise

1
이름을 바꾸지 않고 한 위치에서 다른 위치로 Java 클래스 파일을 복사하는 경우 @gianpi에서 제공하는 솔루션이 필요합니다. 그렇지 않으면, 당신은 할 수있는 this.getClass().getName()당신의 정적 범위 제거해야하지만TAG
asgs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.