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

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

стандарты логирования

Ведение логов в 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."); }

В R8 можно отключить запись логов для каждого APK-файла отдельно с помощью наборов правил ProGuard во время компиляции. Следующий пример удаляет все записи логов ниже уровня 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 для логов ошибок не совпадают один к одному:

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

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

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

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

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

Не регистрируйте персональные данные. Это включает в себя такие сведения, как:

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

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

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

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

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

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

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