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

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

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

Вход в 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.Журнал 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.wtf
СЕРЬЕЗНЫЙ Log.e

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

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

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

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

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

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

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

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

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