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

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

Стандарты бревен

Логирование в 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.Уровень
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 запрашивает доступ к журналам устройства, система предлагает пользователю одобрить или отклонить запрос на доступ.