Как обычно вы регистрируете записи журнала? (Андроид)

Я предполагаю, что большинство из вас знают о 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 для класса?

Ответ 1

Я использую TAG, но я инициализирую его следующим образом:

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

Таким образом, когда я реорганизую свой код, тег также будет соответствующим образом изменяться.

Ответ 2

Обычно я создаю класс 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, для легкой отладки.

Ответ 3

Перейдите в Android Studio → предпочтение → Живые шаблоны → AndroidLog, затем выберите Log.d(TAG, String).

В текст шаблона замените

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

с

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

Изображение меню Android

Затем нажмите Изменить переменные и введите className() в столбце Выражение рядом с столбцом className Имя. изображение меню Android 2

Теперь, когда вы набираете ярлык logd, он помещает

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

Вам больше не нужно определять TAG.

Ответ 4

Мне нравится улучшать ответ Янива если у вас есть журнал в этом формате (filename.java:XX) номер строки xx, вы можете связать ярлык так же, как и связанный, когда есть ошибка, таким образом, я могу сразу перейти к рассматриваемой строке, просто нажав на 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;
}

Скриншот:

BUgeBL9.jpg

Ответ 5

Я создал класс статических переменных, методов и классов с именем 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() также добавляет имя пакета, поэтому я удаляю его, чтобы избежать ненужного тега.

<сильные > Преимущества:

  • Короче Log.d(TAG,
  • Не нужно преобразовывать значения int в свою строку. Infact не нужно вводить toString
  • Не забудьте удалить Log.d когда-либо, так как мне просто нужно удалить этот метод, а расположение всех журналов станет красным.
  • Не нужно определять TAG в верхней части действия, так как он принимает имя класса.
  • TAG имеет префикс CCC (короткая, простая в использовании строка), поэтому легко перечислять только ваши журналы на Android-мониторе в Android Studio. Иногда вы запускаете службы или другие классы одновременно. Если вам нужно искать только по имени активности, то вы не можете точно видеть, когда был получен ответ службы, а затем произошло действие из вашей активности. Префикс, такой как CCC, помогает, поскольку он дает вам журналы в хронологическом порядке с активностью, в которой он произошел.

Ответ 6

За счет обновления этих строк при перемещении кода между методами или переименовании мне нравится делать следующее. Философски также кажется, что лучше сохранить "местоположение" или "контекст" в теге, а не в сообщении.

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(). Я нашел их сложнее фильтровать в журналах, потому что было меньше, чтобы продолжить.

Ответ 7

AndroidStudio имеет шаблон logt по умолчанию (вы можете набрать logt и нажать вкладку, чтобы он был разворачиван до сильного кода). Я рекомендую использовать это, чтобы избежать копирования, вставляющего определение TAG из другого класса и забывая изменить класс, о котором вы говорите. Шаблон по умолчанию расширяется до

private static final String TAG = "$CLASS_NAME$"

Чтобы избежать использования старого имени класса после рефакторинга, вы можете изменить его на

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

Не забудьте проверить кнопку "Изменить переменные" и убедитесь, что переменная CLASS_NAME определена для использования выражения className() и имеет флажок "Пропустить, если определено".

Ответ 8

Вы можете использовать this.toString(), чтобы получить уникальный идентификатор для определенного класса, в котором вы печатаете в журнале.

Ответ 9

Это очень старый вопрос, но даже в обновленном ответе за июль 2018 года предпочтительнее использовать Timber. Для регистрации правильного ведения журнала ошибки и предупреждения можно отправлять сторонним библиотекам сбоев, таким как Firebase или Crashlytics.

В классе, который реализует приложение, вы должны добавить это:

@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'

Ответ 10

Для тех пользователей, которые посещают этот вопрос:

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

Ответ 11

они используют Timber для приложения IOsched 2019 для отображения отладочной информации:

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 Store, нам нужно удалить все операторы Log из приложения, чтобы никакие данные приложения, такие как информация о пользователе, скрытые данные приложения, токены авторизации, не были доступны пользователю в logcat в виде простого текста

проверить эту статью https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d

Ответ 12

Я обычно использую имя метода как тег, но из Thread

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

Это исключает новое исключение.

Ответ 13

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