Понимание ведения журнала

В этой статье рассматривается процесс ведения журнала, включая стандарты журналирования, рекомендации по уровням, классы, цели и многостековые приближения.

Стандарты журналов

Вход в систему Android сложен из-за множества используемых стандартов, объединенных в logcat . Основные используемые стандарты подробно описаны ниже:

Источник Примеры Руководство по уровню стека
RFC 5424 (стандарт syslog ) Ядро Linux, множество приложений Unix Ядро, системные демоны
android.util.Log Платформа Android + журналирование приложений Платформа Android и системное приложение
java.util.logging.Level Общий вход в Java несистемное приложение

Рисунок 1: Стандарты уровня журнала.

Хотя каждый из этих стандартов имеет схожую структуру уровней, они различаются по степени детализации. Приблизительные эквиваленты для всех стандартов следующие:

Уровень RFC 5424 RFC 5424 Серьезность RFC 5424 Описание android.util.Log java.util.logging.Level
0 Чрезвычайная ситуация Система непригодна для использования Log.e / Log.wtf SEVERE
1 Тревога Действия должны быть приняты немедленно Log.e / Log.wtf SEVERE
2 Критический Критические условия Log.e / Log.wtf SEVERE
3 Ошибка Условия ошибки Log.e SEVERE
4 Предупреждение Условия предупреждения Log.w WARNING
5 Уведомление Нормально, но существенно Log.w WARNING
6 Информация Информационные сообщения Log.i INFO
7 Отлаживать Сообщения уровня отладки Log.d CONFIG , FINE
- - Подробные сообщения Log.v FINER / FINEST

Рисунок 2. Уровни ведения журнала syslog , Android и Java.

Рекомендации по уровню журнала

Для каждого стандарта бревен существуют существующие рекомендации. Выбранный уровень журнала соответствует соответствующему используемому стандарту, например, использованию стандарта syslog для разработки ядра.

Порядок уровня журнала, от меньшего к большему, показан на трех рисунках ниже:

ERROR Эти журналы сохраняются всегда.
WARN Эти журналы сохраняются всегда.
INFO Эти журналы сохраняются всегда.
DEBUG Эти журналы компилируются, но удаляются во время выполнения.
VERBOSE Эти журналы никогда не компилируются в приложение, кроме как во время разработки.

Рисунок 3: android.util.Log

CONFIG Уровень сообщений для сообщений статической конфигурации
FINE Уровень сообщения, предоставляющий информацию для отслеживания
FINER Указывает на довольно подробное сообщение отслеживания.
FINEST Обозначает очень подробное сообщение отслеживания.
INFO Уровень сообщений для информационных сообщений
SEVERE Уровень сообщения, указывающий на серьезный сбой
WARNING Уровень сообщения, указывающий на потенциальную проблему

Рисунок 4: java.util.Logging.Level .

0 Чрезвычайная ситуация Система непригодна для использования
1 Тревога Действия должны быть приняты немедленно
2 Критический Критические условия
3 Ошибка Условия ошибки
4 Предупреждение Условия предупреждения
5 Уведомление Нормальное, но значимое состояние
6 Информационный Информационные сообщения
7 Отлаживать Сообщения уровня отладки

Рисунок 5: RFC 5424 — раздел 6.2.1 .

Ведение журнала приложений

Выборочное ведение журнала выполняется с помощью TAG класса android.util.Log с использованием Log#isLoggable , как показано ниже:

if (Log.isLoggable("FOO_TAG", Log.VERBOSE)) {
 Log.v("FOO_TAG", "Message for logging.");
}

Журналы можно настроить во время выполнения, чтобы обеспечить выбранный уровень ведения журнала, как показано ниже:

adb shell setprop log.tag.FOO_TAG VERBOSE

Свойства log.tag.* сбрасываются при перезагрузке. Существуют постоянные варианты, которые сохраняются и после перезагрузки. См. ниже:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

Проверки Log#isLoggable оставляют следы журнала в коде приложения. Логические флаги DEBUG обходят трассировку журнала, используя оптимизацию компилятора, для которой установлено значение false , как показано ниже:

private final static boolean DEBUG = false;

… If (DEBUG) { Log.v("FOO_TAG", "Extra debug logging."); }

Ведение журнала можно удалить для каждого APK-файла с помощью наборов правил ProGuard с помощью R8 во время компиляции. В следующем примере удаляется все, что ниже уровня ведения журнала INFO для android.util.Log :

# This allows proguard to strip isLoggable() blocks containing only <=INFO log
# code from release builds.
-assumenosideeffects class android.util.Log {
  static *** i(...);
  static *** d(...);
  static *** v(...);
  static *** isLoggable(...);
}
-maximumremovedandroidloglevel 4

Это полезно для обработки нескольких типов сборок приложений (например, сборок разработки и сборок выпуска), где ожидается, что базовый код будет одинаковым, но разрешенные уровни журнала разные. Для приложений (особенно системных приложений) необходимо установить и соблюдать явную политику, чтобы решить, как типы сборок и ожидаемые версии влияют на выходные данные журнала.

Системное журналирование в среде выполнения Android (ART)

Существует несколько доступных классов для системных приложений и сервисов:

Сорт Цель
android.telephony.Rlog Радиозапись
android.util.Log Общая регистрация приложений
android.util.EventLog Регистрация событий диагностики системного интегратора
android.util.Slog Ведение журнала платформы платформы

Рисунок 6: Доступные классы и цели системного журнала.

Хотя android.util.Log и android.util.Slog используют одни и те же стандарты уровня журнала, Slog — это класс @hide , используемый только платформой. Уровни EventLog сопоставляются с записями в файле event.logtags в /system/etc/event-log-tags .

Собственная регистрация

Регистрация в C/C++ соответствует стандарту syslog : syslog (2) соответствует syslog ядра Linux, который управляет буфером printk , а syslog (3) соответствует общему системному регистратору. Android использует библиотеку liblog для общего ведения журнала системы.

liblog предоставляет оболочки для групп поджурналов, используя следующую форму макроса:

[Sublog Buffer ID] LOG [Log Level ID]

RLOGD , например, соответствует [Radio log buffer ID] LOG [Debug Level] . Основные оболочки liblog следующие:

Класс-оболочка Примеры функций
log_main.h ALOGV , ALOGW
log_radio.h RLOGD , RLOGE
log_system.h SLOGI , SLOGW

Рисунок 7: оболочки liblog .

Android имеет интерфейсы более высокого уровня для ведения журналов, которые предпочтительнее прямого использования liblog , как показано ниже:

Библиотека Применение
async_safe Библиотека только для ведения журналов из сред, безопасных для асинхронных сигналов.
libbase Библиотека ведения журналов, предоставляющая потоковый интерфейс C++ для ведения журналов, аналогичный ведению журналов в стиле Google (glog). libbase можно использовать как во внешних проектах, так и в приложениях, использующих libbase_ndk .

Рисунок 8: Библиотеки журналов более высокого уровня.

Многостековые аппроксимации

Из-за различий в степени детализации и назначении уровней не существует четкого или точного соответствия различным стандартам ведения журналов. Например, уровни java.util.logging.Level и android.util.Log для журналов ошибок не совпадают 1:1:

java.util.Logging.Level android.util.Log
СЕРЬЕЗНЫЙ Log.wtf
СЕРЬЕЗНЫЙ Log.e

Рисунок 9. Уровень ошибок при стандартном ведении журнала Java по сравнению с ведением журнала Android.

В подобных случаях используйте индивидуальный стандарт, чтобы определить, какой уровень применять.

При разработке системы с несколькими компонентами уровня стека следуйте рис. 1, чтобы определить, какой стандарт использовать для каждого компонента. Примерное руководство по обмену сообщениями на уровне приведено на рисунке 2.

Безопасность и конфиденциальность

Не регистрируйте личную информацию (PII). Сюда входят такие детали, как:

  • Адрес электронной почты
  • Телефонные номера
  • Имена

Аналогичным образом, некоторые данные считаются конфиденциальными, даже если они не позволяют явно идентифицировать личность.

Например, хотя информация о часовом поясе не считается личной, она дает представление о приблизительном местоположении пользователя.

Политика ведения журналов и допустимые сведения должны рассматриваться как часть проверки безопасности и конфиденциальности перед выпуском.

Журналы устройств

Доступ ко всем журналам устройства, в том числе с использованием android.permission.READ_LOGS , ограничен:

  • Если приложение в фоновом режиме запрашивает доступ ко всем журналам устройства, запрос автоматически отклоняется, если только приложение:
    • разделяет системный UID.
    • использует собственный системный процесс ( UID < APP_UID ).
    • использует DropBoxManager .
    • обращается только к буферу журнала событий.
    • использует API EventLog .
    • использует инструментальные тесты.
  • Если приложение на переднем плане с READ_LOGS запрашивает доступ к журналам устройства, система предлагает пользователю утвердить или отклонить запрос на доступ.