Логи в разработке очень полезны для дебага и ловли багов. Также они помогают отслеживать поведение вашего приложения, например при сетевых запросах.
Logcat. Уровни логирования.
Logcat — стандартный инструмент в Android, с помощью которого можно посмотреть dump логов с устройства или эмулятора. Скачать его можно как в составе Android Studio, так и отдельно. Для этого необходимо выкачать SDK platform tools, в которые входит утилита ADB (Android Device Bridge).
Logcat в Android studio
Открываете Android Studio и внизу видите возможность открыть Logcat.
Прелесть использования Logcat в Android Studio в том, что в случае крешей — место ошибки кликабельно. По нажатию на строку можно перейти в исходный код.
Все логи можно отфильтровать по тексту, процессу, который запускаете в режиме debug, по устройству, на котором запускаете приложение и т.д.
Hint: когда используете логи для отладки приложения, можно использовать заведомо уникальную последовательность символом. Такой подход позволит без проблем отфильтровать логи и увидеть только нужные вам строки. Я для этого использую строку «!@#» — ее легко написать (Shift + 1,2,3) и она точно уникальная в рамках Android.
Logcat в консоли
Если по каким-либо причинам вы не хотите открывать или устанавливать Android Studio, то logcat можно также запускать из командной строки (терминала). Для этого есть команда adb logcat
. Убедитесь, что путь до adb добавлен в переменные окружения, иначе система скажет что она не знает такой команды.
Запуск logcat из терминала также удобен для тестировщиков. Если есть баг или креш, который нужно зафиксировать, то можно
- Запустить команды
adb logcat > my_logs.txt
в консоли - Воспроизвести ошибку
- Остановить выполнения логирования (например по
ctrl + c
) - Скинуть логи из файлы my_logs.txt разработчикам.
Уровни логирования в Logcat
Для удобства выделены несколько возможных уровней логирования. В зависимости от важности и критичности вывода можно использовать те или иные приоритеты:
Log.e(String, String)
(ошибки)Log.w(String, String)
(предупреждения)Log.i(String, String)
(информация)Log.d(String, String)
(дебаг)Log.v(String, String)
(подробная информация)
Логирование как способ дебага
Иногда сложно используя только breakpoint воспроизвести странное поведение приложения. Часто такое встречается при работе с сетью, потоками и другими асинхронными вещами. В таком случае логи можно использовать для дебага.
Когда используете логи для отладки приложения, можно использовать заведомо уникальную последовательность символом. Такой подход позволит без проблем отфильтровать логи и увидеть только нужные вам строки. Я для этого использую строку «!@#» — ее легко написать (Shift + 1,2,3) и она точно уникальная в рамках Android.
Расставив по участку кода, в котором потенциально находится ошибка текст
Logs.e("!@#", "Some text, var, position")
можно проследить порядок выполнения кода и промежуточные результаты.
Логи обфусцированного приложения
Если приложение обфусцировано, то логи могут содержать непонятные строки вида a.a$b
. Для решения проблемы прочтения существую mapping файлы. Это специальные списки соответствия между обфусцированным кодом и исходниками. Такие файлы создаются автоматически на этапе компиляции и их можно найти в build
папке вашего приложения. Их можно загрузить в Google play developer console для деобфускации stacktrace.
Логирование сетевых запросов
В большинстве случаев современное приложение использует Retrofit для доступа к сети и выполнению запросов. Для целей логирования есть специальный класс HttpLoggingInterceptor. Он позволяет настроить вывод сетевых запросов. Обычной практикой является добавление всех логов в Debug режиме.
Если мы например используем Dagger, то можно данный interceptor создавать и использовать в вашем модуле сетевого слоя:
@Provides @Singleton @Named(LOG_INTERCEPTOR) fun provideLoggingInterceptor(): Interceptor = HttpLoggingInterceptor().apply { level = if (WHEN_TO_DISABLE_LOGS) HttpLoggingInterceptor.Level.NONE else HttpLoggingInterceptor.Level.BODY }
При создании OkHttpClient можно добавить данный Interceptor к клиенту. Важное замечание: если в вашем коде присутствуют другие интерсепторы, например, которые модифицируют заголовки, то loggingInterceptor логично использовать последним. В противном случае заголовки, которые будут добавлены в следующих звеньях цепочки вы не увидите в логах.
val client = OkHttpClient().newBuilder() .addInterceptor(connectionInterceptor) .addInterceptor(forceUpdateInterceptor) .addInterceptor(versionInterceptor) .addInterceptor(loggingInterceptor) .build()
Продвинутое логирование с Timber
В самом базовом случае обычного Android Logs будет достаточно. Когда вам перестанет хватать стандартного функционала (например захочется писать логи в разные места и в зависимости от внешней конфигурации) — присмотритесь к Timber. Это легкая, но мощная надстройка над стандартными логами. Она позволяет задавать на старте стратегию логирования. К примеру важные логи можно отправлять в Crashlytics или на ваш сторонний сервер:
public class App extends Application { @Override public void onCreate() { super.onCreate(); Timber.plant(BuildConfig.DEBUG ? new Timber.DebugTree() : new CrashReportingTree()); Fabric.with(this, new Crashlytics()); FirebaseAnalytics.getInstance(this); // other things... } private class CrashReportingTree extends Timber.Tree { private static final String CRASHLYTICS_KEY_PRIORITY = "priority"; private static final String CRASHLYTICS_KEY_TAG = "tag"; private static final String CRASHLYTICS_KEY_MESSAGE = "message"; @Override protected void log(int priority, String tag, String message, Throwable throwable) { if (priority == Log.VERBOSE || priority == Log.DEBUG) { return; } Throwable t = throwable != null ? throwable : new Exception(message); // Crashlytics Crashlytics.setInt(CRASHLYTICS_KEY_PRIORITY, priority); Crashlytics.setString(CRASHLYTICS_KEY_TAG, tag); Crashlytics.setString(CRASHLYTICS_KEY_MESSAGE, message); Crashlytics.logException(t); // Firebase Crash Reporting FirebaseCrash.logcat(priority, tag, message); FirebaseCrash.report(t); } } }
Логирование — мощный инструмент, который при правильном использовании заметно ускоряет и упрощает разработку. Также не стоит забывать и про профилирование приложения для оптимизации скорости работы. Да прибудут с вами безбажные и быстрые Android приложения!
1 комментарий
Только надо не забывать, что Crashlytics от Fabric всё. Надо использовать Firebase Crashlytics.